wuhu-mail-notify/index.js
2025-03-12 16:27:01 +08:00

142 lines
5.9 KiB
JavaScript

import express from 'express'
import * as fs from "node:fs";
import nodemailer from "nodemailer";
import * as dotenv from "dotenv";
dotenv.config()
const app = express()
const PORT = parseInt(process.env.PORT) || 20123
const TIMEOUT = parseInt(process.env.TIMEOUT) || 60000
const SMTP_HOST = process.env.SMTP_HOST
const SMTP_PORT = parseInt(process.env.SMTP_PORT)
const SMTP_SECURE = process.env.SMTP_SECURE === 'true'
const SMTP_SENDER = process.env.SMTP_SENDER
const SMTP_PASS = process.env.SMTP_PASS
let stat = null
app.get('/', (req, res) => {
res.send(JSON.stringify(stat))
})
const configJson = fs.readFileSync('./data/config.json', 'utf8');
const configs = JSON.parse(configJson);
console.log('Read config successfully.');
const fetchData = (uid, key) => fetch(`https://api.torn.com/user/${uid}?selections=cooldowns,bars,travel&key=${key}`)
const transporter = nodemailer.createTransport({
host: SMTP_HOST,
port: SMTP_PORT,
secure: SMTP_SECURE, // true for port 465, false for other ports
auth: {
user: SMTP_SENDER,
pass: SMTP_PASS,
},
});
if (configs.length > 0) {
for (const config of configs) {
if (!config['apikey'] || typeof config['apikey'] !== 'string') {
throw new Error('配置文件apikey无效')
}
if (!config['email'] || typeof config['email'] !== 'string') {
throw new Error('配置文件email无效')
}
if (!config['uid'] || typeof config['uid'] !== 'string' || (config['uid'] | 0) === 0) {
throw new Error('配置文件uid无效')
}
const apikey = config['apikey']
const email = config['email']
const uid = config['uid']
// transporter.sendMail({
// from: `"Torn通知" <${SMTP_SENDER}>`, // sender address
// to: email, // list of receivers
// subject: "Torn通知测试", // Subject line
// text: "这是一封测试邮件 - Wuhu Mail Notify Project", // plain text body
// // html: "<b>Hello world?</b>", // html body
// }).catch(console.error);
const timeout = async () => {
try {
const apiData = await (await fetchData(uid, apikey)).json();
const date = new Date(); // ms
const timestamp = date.getTime() //ms
const serverTime = apiData?.server_time * 1000; // ms
const timeDiff = parseInt((timestamp - serverTime) / 1000 + ''); // sec
const drugCd = apiData?.cooldowns?.drug
const energyFull = apiData?.energy?.fulltime
const nerveFull = apiData?.nerve?.fulltime
const travelTimeLeft = apiData?.travel?.time_left
// cd
if (drugCd && typeof drugCd === 'number' && drugCd - timeDiff < 60 && drugCd - timeDiff > 0) {
console.log(`[${uid}]发送XAN通知`)
transporter.sendMail({
from: `"Torn通知" <${SMTP_SENDER}>`, // sender address
to: email, // list of receivers
subject: "到饭点了", // Subject line
text: "药CD即将结束 - Wuhu Mail Notify Project", // plain text body
// html: "<b>Hello world?</b>", // html body
}).catch(console.error);
} else {
console.log(`[${uid}]毒CD未到通知时间 ( 还需 ${drugCd - timeDiff}s ),跳过`)
}
// 体力满
if (energyFull && typeof energyFull === 'number' && energyFull - timeDiff < 60 && energyFull - timeDiff > 0) {
console.log(`[${uid}]发送体力通知`)
transporter.sendMail({
from: `"Torn通知" <${SMTP_SENDER}>`,
to: email,
subject: "体力已满",
text: "角色体力已满 - Wuhu Mail Notify Project",
}).catch(console.error);
} else {
console.log(`[${uid}]体力未满 ( 还需 ${energyFull - timeDiff}s ),跳过`)
}
// 精神满
if (nerveFull && typeof nerveFull === 'number' && nerveFull - timeDiff < 60 && nerveFull - timeDiff > 0) {
console.log(`[${uid}]发送精神通知`)
transporter.sendMail({
from: `"Torn通知" <${SMTP_SENDER}>`,
to: email,
subject: "精神已满",
text: "角色精神已满 - Wuhu Mail Notify Project",
}).catch(console.error);
} else {
console.log(`[${uid}]精神未满 ( 还需 ${nerveFull - timeDiff}s ),跳过`)
}
// 飞机落地
if (travelTimeLeft && typeof travelTimeLeft === 'number' && travelTimeLeft - timeDiff < 60 && travelTimeLeft - timeDiff > 0) {
console.log(`[${uid}]发送飞行通知`)
transporter.sendMail({
from: `"Torn通知" <${SMTP_SENDER}>`,
to: email,
subject: "飞行结束",
text: "角色即将落地 - Wuhu Mail Notify Project",
}).catch(console.error);
} else {
console.log(`[${uid}]飞机未到通知时间 ( 还需 ${travelTimeLeft - timeDiff}s ),跳过`)
}
} catch (e) {
console.error(e)
stat = {
stack: e.stack,
msg: e.message,
ts: Date.now(),
}
}
setTimeout(timeout, TIMEOUT)
}
timeout().catch(console.error)
}
} else {
throw new Error('配置文件列表为空')
}
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}`)
})