Skip to content

Instantly share code, notes, and snippets.

@imdong
Last active October 24, 2024 06:09
Show Gist options
  • Save imdong/f3fd44f43a6432bcc9d69f44ddf5ab7e to your computer and use it in GitHub Desktop.
Save imdong/f3fd44f43a6432bcc9d69f44ddf5ab7e to your computer and use it in GitHub Desktop.
/**
* Apple Store 专卖店库存监控
*
* Docker:
* 前台运行 $ docker run --rm -it -v $(pwd):/app --name="apple" node:alpine node /app/apple.js
* 后台运行 $ docker run --rm -it -d -v $(pwd):/app --name="apple" node:alpine node /app/apple.js
* 后台时实时查看日志 $ docker logs -f -n 100 apple
*
* 需先: npm i axios
*
* 作者:青石 https://www.qs5.org
*/
const axios = require('axios');
const fs = require('fs');
(function (products) {
let url = 'https://www.apple.com.cn/shop/fulfillment-messages',
parmas = {
mt: 'regular',
little: 'false',
store: 'R484', // 专卖店ID
// "parts.0": 'MLT83CH/A',
// "parts.1": 'MLT63CH/A'
},
bark_state = {};
Object.keys(products).forEach((product, index) => {
parmas['parts.' + index] = product;
});
axios.defaults.timeout = 10 * 1000;
function getInfo() {
let date = new Date();
console.log(date);
// 保存日志文件
let file = '/app/logs/' + date.toISOString() + '.txt';
axios.get(url, {
params: parmas
}).then(response => {
// console.log(response);
// 保存文件
fs.writeFileSync(file, JSON.stringify(response.data));
let productNames = {}, datas = {};
response.data.body.content.pickupMessage.stores.forEach(store => {
for (const product in store.partsAvailability) {
const productInfo = store.partsAvailability[product];
productNames[product] = productInfo.storePickupProductTitle;
datas[product] = {
'产品型号': productInfo.storePickupProductTitle,
'旗舰店取货': productInfo.pickupSearchQuote + ': ' + productInfo.storePickupQuote.replace(/<[^>]+>/g, ''),
};
// 如果有货 马上 提醒
if (productInfo.pickupSearchQuote.indexOf('不可取货') < 0 || productInfo.storePickupQuote.indexOf('不可') < 0) {
// 不要删除了
file = null;
// 检查是不是发过信息了 (30秒内 只发一次)
let now = new Date();
if (bark_state[product] && now - bark_state[product] < 30000) {
return;
}
bark_state[product] = now;
// 给列表的每个人发信息
products[product].forEach(bark_url => {
let bark_url_send = '';
if (bark_url.indexOf('api.day.app') > 0) {
// 发送信息的地址
bark_url_send = `${bark_url}/${encodeURIComponent(productInfo.storePickupProductTitle + ' ' + productInfo.pickupSearchQuote)}/${encodeURIComponent(productInfo.storePickupQuote.replace(/<[^>]+>/g, ''))}`;
} else {
let content = productInfo.storePickupProductTitle
+ ' ' + productInfo.pickupSearchQuote
+ "\n" + productInfo.storePickupQuote.replace(/<[^>]+>/g, '');
bark_url_send = `${bark_url}${encodeURIComponent(content)}`;
}
// 推送
axios.get(bark_url_send).catch(e => console.log(e)).then(response => {
// console.log(response);
});
});
}
}
});
// deliveryMessage 快递选项
// for (const product in response.data.body.content.deliveryMessage) {
// if (!products[product]) {
// continue;
// }
// const productInfo = response.data.body.content.deliveryMessage[product];
// datas[product] = datas[product] || {};
// // 捕捉这些不对的情况
// let orderByDeliveryBy = productInfo.orderByDeliveryBySuffix || productInfo.orderByDeliveryBy || null;
// if (!orderByDeliveryBy || Object.keys(datas[product]).length == 0) {
// file = null;
// }
// datas[product]['快递'] = orderByDeliveryBy.replace(/<[^>]+>/g, '') + productInfo.deliveryOptionMessages[0].displayName;
// }
console.table(datas);
// 保存日资
// datas.date = date;
fs.writeFileSync('/app/logs/run.log', `${date.toISOString()}\n\n` + JSON.stringify(datas) + "\n\n");
// 如果没有货 就删除文件
if (file) {
fs.unlinkSync(file);
}
// 延迟一秒再去查询
setTimeout(getInfo, 0);
}).catch(err => {
fs.writeFileSync('/app/logs/error.log', `${date.toISOString()}\n\n` + JSON.stringify(err) + "\n\n");
setTimeout(getInfo, 500);
});
}
// 每隔30秒执行一次
// setInterval(getInfo, 30000);
// 先查一次
getInfo();
})({
// Pro Max 远峰蓝 256G
'MLHC3CH/A': [
'https://api.day.app/xxxxx',
],
// Pro 远峰蓝 128G
'MLT83CH/A': [
'https://api.day.app/xxxxx',
],
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment