feat: 添加对TG bot的支持

This commit is contained in:
lyz05
2022-11-10 10:58:42 +08:00
parent 08ce841573
commit f50a177542
9 changed files with 1886 additions and 25 deletions

View File

@@ -12,8 +12,10 @@
- lib-qqwry: 纯真IP数据库
# 部署到fly.io
```
``` sh
curl -L https://fly.io/install.sh | sh
export FLYCTL_INSTALL="/home/codespace/.fly"
export PATH="$FLYCTL_INSTALL/bin:$PATH"
flyctl auth login
flyctl deploy
```

32
app.js
View File

@@ -4,7 +4,6 @@ const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
// 引入环境变量
require('dotenv').config();
@@ -12,8 +11,15 @@ require('dotenv').config();
const danmakuRouter = require('./routes/danmaku');
const ipinfoRouter = require('./routes/ipinfo');
const airportsubRouter = require('./routes/airportsub');
// 引入定时任务模块
const schedule = require('./schedule/schedule');
const DEBUG = process.env.DEBUG==="true" || false;
if (!DEBUG) {
console.log("PRODUCTION MODE!该模式下TG机器人与定时任务正常运行");
// 引入定时任务模块
const schedule = require('./schedule/schedule');
// 引入TG机器人
const tgbot = require('./tgbot/bot');
} else
console.log("DEBUG MODE!该模式下将关闭TG机器人和定时任务");
const app = express();
@@ -24,7 +30,7 @@ app.set('trust proxy', true)
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
@@ -33,19 +39,19 @@ app.use('/ipinfo', ipinfoRouter);
app.use('/sub', airportsubRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
app.use(function (req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;

1507
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -26,10 +26,12 @@
"moment": "^2.29.4",
"morgan": "~1.9.1",
"node-cron": "^3.0.2",
"node-telegram-bot-api": "^0.60.0",
"pako": "^1.0.11",
"whacko": "^0.19.1",
"xml-js": "^1.6.11",
"xml2js": "^0.4.23"
"xml2js": "^0.4.23",
"yaml": "^2.1.3"
},
"devDependencies": {
"chai": "^4.3.6",

View File

@@ -19,7 +19,7 @@ function subcache() {
cron.schedule('0 12 * * *', () => {
subcache();
});
//TODO 添加自动删除一个月前的日志
console.log('schedule.js loaded');
if (!module.parent) {
subcache();

19
tgbot/bot.js Normal file
View File

@@ -0,0 +1,19 @@
require('dotenv').config({path: '../.env'});
const memory = require('../utils/memory');
const hkaliyun = require('./bot/hkaliyun.js');
const airportsub = require('./bot/airportsub.js');
bots = [
hkaliyun(process.env.TELEGRAM_TOKEN_HKALIYUN),
airportsub(process.env.TELEGRAM_TOKEN_AIRPORTSUB),
];
console.log('bot.js loaded');
memory()
for (const bot of bots) {
bot.getMe().then((botInfo) => {
console.log('Bot info:', botInfo);
});
// bot.getWebHookInfo().then((webhookInfo) => {
// console.log('Webhook info:', webhookInfo);
// });
}

214
tgbot/bot/airportsub.js Normal file
View File

@@ -0,0 +1,214 @@
// Import modules
const whacko = require('whacko');
const YAML = require('yaml');
const TelegramBot = require('node-telegram-bot-api');
const goindex = require('./goindex');
const axios = require('axios');
const OSS = require('ali-oss');
// Environment variables
const OSS_OPTIONS = {
region: 'oss-cn-hongkong',
accessKeyId: process.env.OSS_ACCESS_KEY,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
bucket: 'hkosslog'
};
module.exports = (TOKEN) => {
let game = {};
const bot = new TelegramBot(TOKEN, {polling: true});
const client = new OSS(OSS_OPTIONS);
// Just to ping!
bot.on('message', msg => {
if (!msg.text) {
bot.sendMessage(msg.chat.id, 'I can only understand text messages!');
}
});
// 智能聊天机器人
bot.on('text', msg => {
if (msg.text.indexOf('/') === -1) {
bot.sendMessage(msg.chat.id, 'you said: ' + msg.text);
axios.get('https://api.qingyunke.com/api.php?key=free&appid=0&msg=' + encodeURI(msg.text)).then(res => {
console.log(res.data);
bot.sendMessage(msg.chat.id, res.data.content);
});
}
});
// 欢迎页面
bot.onText(/\/start/, (msg) => {
let name = [msg.from.first_name];
if (msg.from.last_name) {
name.push(msg.from.last_name);
}
name = name.join(" ");
bot.sendMessage(msg.chat.id, `Welcome, ${name}!`);
bot.sendMessage(msg.chat.id, `You can send me any message and I will repeat it back to you.`);
bot.sendMessage(msg.chat.id, `You can also send me commands like /start, /help.`);
});
// 发送用户头像
bot.onText(/\/sendpic/, (msg) => {
bot.getUserProfilePhotos(msg.chat.id).then(photos => {
const photo = photos.photos[0][0];
bot.sendPhoto(msg.chat.id, photo.file_id, {
caption: "This is a picture of You!"
});
});
// bot.sendPhoto(msg.chat.id, "https://blog.home999.cc/images/avatar.jpg");
});
bot.onText(/\/register/, (msg) => {
bot.sendMessage(msg.chat.id, `Chat id: ${msg.chat.id}\n请把该id告诉管理员用于注册。`);
});
bot.onText(/\/sub/, async (msg) => {
const database = await (await client.get("SUB/database.yaml")).content.toString();
const data = YAML.parse(database);
const users = data.user;
for (let user in users) {
if (users[user].chatID == msg.chat.id) {
bot.sendMessage(msg.chat.id, `您已经注册过了,请勿重复注册。`);
bot.sendMessage(msg.chat.id, `你好,${user}`);
const url = `https://fc.home999.cc/sub?user=${user}`;
bot.sendMessage(msg.chat.id, `您的订阅链接为:${url}`);
return;
}
}
bot.sendMessage(msg.chat.id, `您已经成功注册,请等待管理员审核`);
});
bot.onText(/\/game/, (msg) => {
const chatID = msg.chat.id;
const guess = parseInt(msg.text.replace("/game", ""));
if (game[chatID] == undefined) {
game[chatID] = {
num: Math.floor(Math.random() * 100),
limit: 10,
}
bot.sendMessage(chatID, `我们来玩猜数游戏吧!`);
bot.sendMessage(chatID, `猜一个数字你有10次机会。范围:[0, 100)`);
bot.sendMessage(chatID, `请输入你的猜测:(例:/game 50)`);
return;
}
let {num, limit} = game[chatID];
if (limit <= 0) {
bot.sendMessage(chatID, `游戏结束!未猜出正确答案,正确答案为:${num}`);
game[chatID] = undefined;
return;
}
game[chatID].limit--;
if (guess == num) {
bot.sendMessage(chatID, `恭喜你猜对了!`);
game[chatID] = undefined;
} else if (guess > num) {
bot.sendMessage(chatID, `你猜的数字太大了!`);
} else {
bot.sendMessage(chatID, `你猜的数字太小了!`);
}
});
bot.onText(/\/help/, (msg) => {
const helpMsg = [
{command: 'start', description: '欢迎界面'},
{command: 'game', description: '猜数游戏'},
{command: 'sub', description: '订阅链接'},
{command: 'register', description: '注册'},
{command: 'sendpic', description: '发送你的头像'},
{command: 'setu', description: '随机色图,可加编号'},
{command: 'goindex', description: '查询GoIndex上的文件'},
{command: 'help', description: '帮助'},
];
const helpMsgText = helpMsg.map(item => {
return `/${item.command} - ${item.description}`;
}).join("\n");
bot.sendMessage(msg.chat.id, helpMsgText, {parse_mode: "HTML"});
bot.setMyCommands(helpMsg);
});
bot.onText(/\/setu/, (msg) => {
const index = parseInt(msg.text.replace("/setu", ""));
bot.sendMessage(msg.chat.id, `色图模式`);
axios.get('https://asiantolick.com/ajax/buscar_posts.php', {params: {index}})
.then(res => {
const $ = whacko.load(res.data);
$('.miniatura').each((i, e) => {
const href = $(e).attr('href');
setTimeout(() => {
bot.sendMessage(msg.chat.id, href, {
reply_markup: {
inline_keyboard: [
[{text: '带我去看图', url: href}],
]
}
});
}, i * 250);
});
});
});
bot.onText(/\/goindex/, (msg) => {
const q = msg.text.replace("/goindex ", "")
bot.sendMessage(msg.chat.id, `正在搜寻“${q}”...`);
goindex.query(q).then(res => {
//筛选符合条件的文件
videos = res.filter(e => e.mimeType === "video/mp4").filter(e => e.size < 50 * 1024 * 1024);
images = res.filter(e => e.mimeType === "image/jpeg");
audios = res.filter(e => e.mimeType === "audio/mp3").filter(e => e.size < 50 * 1024 * 1024);
folders = res.filter(e => e.mimeType === "application/vnd.google-apps.folder");
bot.sendMessage(msg.chat.id, `共有${images.length}个图片结果,${videos.length}个视频,${audios.length}个音乐,${folders.length}个目录,搜索结果:`);
bot.sendChatAction(msg.chat.id, "upload_photo");
images = goindex.group(images, 10);
images.forEach((e, i) => {
setTimeout(() => {
bot.sendMediaGroup(msg.chat.id, e.map(e => {
return {
type: "photo",
media: e.thumbnailLink.replace('=s220', '=s0'),
caption: e.name,
}
}));
}, i * 2000);
});
bot.sendChatAction(msg.chat.id, 'upload_video');
videos.forEach((e, i) => {
setTimeout(() => {
goindex.id2path(e.id).then(path => {
console.log(path);
bot.sendVideo(msg.chat.id, encodeURI(path), {
caption: `${e.name}`,
reply_markup: {
inline_keyboard: [
[{text: '带我去看片', url: encodeURI(path)}],
]
}
});
});
}, i * 2000);
});
bot.sendChatAction(msg.chat.id, 'upload_voice');
audios.forEach((e, i) => {
setTimeout(() => {
goindex.id2path(e.id).then(path => {
console.log(path);
bot.sendAudio(msg.chat.id, path, {caption: `${e.name}`});
});
}, i * 2000);
});
})
});
bot.onText(/\/senddice/, (msg) => {
bot.sendDice(msg.chat.id, {emoji: "🎲"});
});
bot.on('polling_error', (error) => {
console.log(error.code); // => 'EFATAL'
})
return bot;
}

83
tgbot/bot/goindex.js Normal file
View File

@@ -0,0 +1,83 @@
const axios = require("axios")
const BASE_URL = 'https://gd.lyz05.workers.dev'
module.exports = {
query,
id2path,
group,
}
function group(array, subGroupLength) {
var index = 0;
var newArray = [];
while(index < array.length) {
newArray.push(array.slice(index, index += subGroupLength));
}
return newArray;
}
async function id2path(id) {
url = BASE_URL+'/0:id2path'
const ret = await axios.post(url, { id: id })
return BASE_URL+'/0:'+ret.data;
}
async function query(q) {
url = BASE_URL+'/0:search'
files = [];
let page_token = null;
while (true) {
data = {
'q': q,
'page_index': 1,
'page_token': page_token,
}
const ret = await axios.post(url, data)
files = files.concat(ret.data.data.files);
// console.log(ret.data.data.files)
page_token = ret.data.nextPageToken
if (page_token === null) {
break;
}
}
// console.log('files:',files);
return files;
}
async function queryData(path = '') {
url = BASE_URL+'/0:/Inbox/seer/%E5%86%99%E7%9C%9F/Miho%20Kaneko%20Complete%20Photo%20Collection/' + path
data = {
'q': '',
'page_index': 0,
'page_token': null,
'password': null,
}
const response = await axios.post(url, data)
return response.data
}
async function dfs(path) {
let l = [];
const res = await queryData(path);
for (const item of res.data.files) {
if (item.mimeType === 'application/vnd.google-apps.folder') {
l = l.concat(await dfs(path + item.name + '/'));
} else {
l.push(item.name)
}
}
return l;
}
async function main(num) {
// const res = await dfs('');
// console.log(res);
const files = await query();
link = files[num].thumbnailLink;
console.log(link)
}
// main(12);
// console.log(response.data.data.files)

46
tgbot/bot/hkaliyun.js Normal file
View File

@@ -0,0 +1,46 @@
const TelegramBot = require('node-telegram-bot-api');
module.exports = (TOKEN) => {
const bot = new TelegramBot(TOKEN, {polling: true});
// Just to ping!
bot.on('message', msg => {
if (msg.text) {
bot.sendMessage(msg.chat.id, msg.text);
} else {
bot.sendMessage(msg.chat.id, 'I can only understand text messages!');
}
});
bot.on('video', msg => {
bot.sendMessage(msg.chat.id, 'I reveive video message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.video));
});
bot.on('photo', msg => {
bot.sendMessage(msg.chat.id, 'I reveive photo message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.photo));
});
bot.on('audio', msg => {
bot.sendMessage(msg.chat.id, 'I reveive audio message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.audio));
});
bot.on('document', msg => {
bot.sendMessage(msg.chat.id, 'I reveive document message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.document));
});
bot.on('sticker', msg => {
bot.sendMessage(msg.chat.id, 'I reveive sticker message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.sticker));
});
bot.on('location', msg => {
bot.sendMessage(msg.chat.id, 'I reveive location message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.location));
});
bot.on('contact', msg => {
bot.sendMessage(msg.chat.id, 'I reveive contact message!');
bot.sendMessage(msg.chat.id, JSON.stringify(msg.contact));
});
bot.on('polling_error', (error) => {
console.log(error.code); // => 'EFATAL'
})
return bot;
}