魔改酒神的双向TG消息转发机器人,帮你在互联网上进一步保护自己
原来用的SXbot 现在SXbot强制增加了广告,所以有了这个版本
1.现在只有当检测到骗子时才会展示骗子提示信息 如果没有检测则不提示
2.现在当你回复一条消息之后 后面不需要再点击回复 可以直接发送消息,默认是上一个回复消息的聊天目标
3.当有新聊天目标进入的时候会有一个按钮 点击即可切换聊天目标 不点击则保持原来的聊天目标
4.支持发送photo video等文件格式
5.本人只魔改了代码部分,部署等其他请自行参考酒神原版
6./start依旧展示欢迎语,并增加快捷指令 当输入/时 展示已有的/指令(欢迎语请自行到代码125行修改)
7.代码
const TOKEN = ENV_BOT_TOKEN // Get it from @BotFather
const WEBHOOK = '/endpoint'
const SECRET = ENV_BOT_SECRET // A-Z, a-z, 0-9, _ and -
const ADMIN_UID = ENV_ADMIN_UID // your user id, get it from https://t.me/username_to_id_bot
const NOTIFY_INTERVAL = 3600 * 1000;
const fraudDb = 'https://raw.githubusercontent.com/LloydAsp/nfd/main/data/fraud.db';
const notificationUrl = ''
const chatSessions = {}; // 存储所有聊天会话的状态
const enable_notification = true
let currentChatTarget = null; // 当前聊天目标ID
let chatTargetUpdated = false; // 标志是否更新了聊天目标
/**
* Return url to telegram api, optionally with parameters added
*/
function apiUrl(methodName, params = null) {
let query = ''
if (params) {
query = '?' + new URLSearchParams(params).toString()
}
return `https://api.telegram.org/bot${TOKEN}/${methodName}${query}`
}
function requestTelegram(methodName, body, params = null){
return fetch(apiUrl(methodName, params), body)
.then(r => r.json())
}
function makeReqBody(body){
return {
method:'POST',
headers:{
'content-type':'application/json'
},
body:JSON.stringify(body)
}
}
function sendMessage(msg = {}){
return requestTelegram('sendMessage', makeReqBody(msg))
}
function copyMessage(msg = {}){
return requestTelegram('copyMessage', makeReqBody(msg))
}
function forwardMessage(msg){
return requestTelegram('forwardMessage', makeReqBody(msg))
}
function generateKeyboard(options) {
return {
reply_markup: {
inline_keyboard: options.map(option => [{
text: option.text,
callback_data: option.data
}])
}
};
}
async function setBotCommands() {
const commands = [
{ command: 'start', description: '启动机器人会话' },
{ command: 'help', description: '显示帮助信息' },
{ command: 'block', description: '屏蔽用户' },
{ command: 'unblock', description: '解除屏蔽用户' },
{ command: 'checkblock', description: '检查用户是否被屏蔽' }
// 在此添加更多命令
];
return requestTelegram('setMyCommands', makeReqBody({ commands }));
}
addEventListener('fetch', event => {
const url = new URL(event.request.url)
if (url.pathname === WEBHOOK) {
event.respondWith(handleWebhook(event))
} else if (url.pathname === '/registerWebhook') {
event.respondWith(registerWebhook(event, url, WEBHOOK, SECRET))
} else if (url.pathname === '/unRegisterWebhook') {
event.respondWith(unRegisterWebhook(event))
} else if (url.pathname === '/setCommands') {
event.respondWith(setBotCommands())
} else {
event.respondWith(new Response('No handler for this request'))
}
})
async function handleWebhook(event) {
if (event.request.headers.get('X-Telegram-Bot-Api-Secret-Token') !== SECRET) {
return new Response('Unauthorized', { status: 403 })
}
const update = await event.request.json()
event.waitUntil(onUpdate(update))
return new Response('Ok')
}
async function onUpdate(update) {
if (update.message) {
await onMessage(update.message);
} else if (update.callback_query) {
await onCallbackQuery(update.callback_query);
}
}
async function getUserInfo(chatId) {
const response = await requestTelegram('getChat', makeReqBody({ chat_id: chatId }));
if (response.ok) {
return response.result;
} else {
console.error(`Failed to get user info for chat ID ${chatId}:`, response);
return null;
}
}
async function onMessage(message) {
if(message.text === '/start'){
let startMsg = "\n欢迎使用GunZi的聊天机器人🎉🎉🎉\n\n你现在发送的消息GunZi能够收到❗❗\n\n他会尽快回复你❗❗\n\n"
await setBotCommands()
return sendMessage({
chat_id:message.chat.id,
text:startMsg,
})
} else if (message.text === '/help'){
let helpMsg = "可用指令列表:\n" +
"/start - 启动机器人会话\n" +
"/help - 显示此帮助信息\n" +
"/block - 屏蔽用户 (仅管理员)\n" +
"/unblock - 解除屏蔽用户 (仅管理员)\n" +
"/checkblock - 检查用户是否被屏蔽 (仅管理员)\n" +
"更多指令将在后续更新中添加。";
return sendMessage({
chat_id: message.chat.id,
text: helpMsg,
});
}
// 以下是管理员专用命令
if(message.text === '/block' && message.reply_to_message){
return handleBlock(message);
}
if(message.text === '/unblock' && message.reply_to_message){
return handleUnBlock(message);
}
if(message.text === '/checkblock' && message.reply_to_message){
return checkBlock(message);
}
if(message.chat.id.toString() === ADMIN_UID){
if(message.reply_to_message){
let guestChatId = await nfd.get('msg-map-' + message.reply_to_message.message_id, { type: "json" })
console.log("guestChatId:", guestChatId); // 日志输出
if(guestChatId){
currentChatTarget = guestChatId; // 更新当前聊天目标
if (message.text) {
// 发送管理员输入的文本消息内容
await sendMessage({
chat_id: guestChatId,
text: message.text,
});
} else if (message.photo || message.video || message.document || message.audio) {
console.log("Copying media message:", message.message_id); // 日志输出
// 如果消息包含媒体文件,使用 copyMessage 方法复制媒体文件
await copyMessage({
chat_id: guestChatId,
from_chat_id: message.chat.id,
message_id: message.message_id,
});
}
}
} else {
if (!currentChatTarget) {
return sendMessage({
chat_id: ADMIN_UID,
text: "没有设置当前聊天目标,请先通过回复某条消息来设置聊天目标。"
});
}
if (message.text) {
// 直接发送文本消息到当前聊天目标
await sendMessage({
chat_id: currentChatTarget,
text: message.text,
});
} else if (message.photo) {
await sendPhoto({
chat_id: currentChatTarget,
photo: message.photo[0].file_id,
caption: message.caption || ''
});
} else if (message.video) {
await sendVideo({
chat_id: currentChatTarget,
video: message.video.file_id,
caption: message.caption || ''
});
} else if (message.document) {
await sendDocument({
chat_id: currentChatTarget,
document: message.document.file_id,
caption: message.caption || ''
});
} else if (message.audio) {
await sendAudio({
chat_id: currentChatTarget,
audio: message.audio.file_id,
caption: message.caption || ''
});
}
}
return; // 确保管理员自己不会收到消息
}
return handleGuestMessage(message)
}
async function sendDirectMessage(text) {
if (currentChatTarget) {
return sendMessage({
chat_id: currentChatTarget,
text: text
});
} else {
return sendMessage({
chat_id: ADMIN_UID,
text: "没有设置当前聊天目标,请先通过回复某条消息来设置聊天目标。"
});
}
}
async function handleGuestMessage(message){
let chatId = message.chat.id.toString();
let isblocked = await nfd.get('isblocked-' + chatId, { type: "json" })
if(isblocked){
return sendMessage({
chat_id: chatId,
text:'您已被屏蔽'
})
}
let forwardReq = await forwardMessage({
chat_id:ADMIN_UID,
from_chat_id:message.chat.id,
message_id:message.message_id
});
if(forwardReq.ok){
await nfd.put('msg-map-' + forwardReq.result.message_id, chatId)
// 只有当新的聊天目标与当前聊天目标不同时,才发送提示按钮
if (currentChatTarget !== chatId) {
chatTargetUpdated = false; // 重置标志,因为有新的聊天目标
if (!chatTargetUpdated) { // 检查标志
const userInfo = await getUserInfo(chatId);
const nickname = userInfo ? `${userInfo.first_name} ${userInfo.last_name || ''}`.trim() : `UID:${chatId}`;
await sendMessage({
chat_id: ADMIN_UID,
text: `新的聊天目标: ${nickname}`,
...generateKeyboard([{ text: `选择${nickname}`, data: `select_${chatId}` }])
});
chatTargetUpdated = true; // 设置标志
}
} else {
chatTargetUpdated = true; // 如果当前聊天目标与消息发送者相同,更新标志
}
}
return handleNotify(message)
}
async function sendPhoto(msg) {
return requestTelegram('sendPhoto', makeReqBody(msg));
}
async function sendVideo(msg) {
return requestTelegram('sendVideo', makeReqBody(msg));
}
async function sendDocument(msg) {
return requestTelegram('sendDocument', makeReqBody(msg));
}
async function sendAudio(msg) {
return requestTelegram('sendAudio', makeReqBody(msg));
}
async function onCallbackQuery(callbackQuery) {
const data = callbackQuery.data;
const message = callbackQuery.message;
if (data.startsWith('select_')) {
const selectedChatId = data.split('_')[1];
if (currentChatTarget !== selectedChatId) {
currentChatTarget = selectedChatId;
chatTargetUpdated = true; // 设置标志
const userInfo = await getUserInfo(selectedChatId);
const nickname = userInfo ? `${userInfo.first_name} ${userInfo.last_name || ''}`.trim() : `UID:${selectedChatId}`;
await sendMessage({
chat_id: ADMIN_UID,
text: `已切换到聊天目标: ${nickname}`
});
}
}
}
async function handleNotify(message){
// 先判断是否是诈骗人员,如果是,则直接提醒
// 如果不是,则根据时间间隔提醒:用户id,交易注意点等
let chatId = message.chat.id;
if(await isFraud(chatId)){
return sendMessage({
chat_id: ADMIN_UID,
text:`检测到骗子,UID${chatId}`
})
}
if(enable_notification){
let lastMsgTime = await nfd.get('lastmsg-' + chatId, { type: "json" })
if(!lastMsgTime || Date.now() - lastMsgTime > NOTIFY_INTERVAL){
await nfd.put('lastmsg-' + chatId, Date.now())
return sendMessage({
chat_id: ADMIN_UID,
text:await fetch(notificationUrl).then(r => r.text())
})
}
}
}
async function handleBlock(message){
let guestChatId = await nfd.get('msg-map-' + message.reply_to_message.message_id,
{ type: "json" })
if(guestChatId === ADMIN_UID){
return sendMessage({
chat_id: ADMIN_UID,
text:'不能屏蔽自己'
})
}
const userInfo = await getUserInfo(guestChatId);
const nickname = userInfo ? `${userInfo.first_name} ${userInfo.last_name || ''}`.trim() : `UID:${guestChatId}`;
await nfd.put('isblocked-' + guestChatId, true)
return sendMessage({
chat_id: ADMIN_UID,
text: `用户 ${nickname} 已被屏蔽`,
})
}
async function handleUnBlock(message){
let guestChatId = await nfd.get('msg-map-' + message.reply_to_message.message_id,
{ type: "json" })
const userInfo = await getUserInfo(guestChatId);
const nickname = userInfo ? `${userInfo.first_name} ${userInfo.last_name || ''}`.trim() : `UID:${guestChatId}`;
await nfd.put('isblocked-' + guestChatId, false)
return sendMessage({
chat_id: ADMIN_UID,
text: `用户 ${nickname} 已解除屏蔽`,
})
}
async function checkBlock(message){
let guestChatId = await nfd.get('msg-map-' + message.reply_to_message.message_id,
{ type: "json" })
let blocked = await nfd.get('isblocked-' + guestChatId, { type: "json" })
const userInfo = await getUserInfo(guestChatId);
const nickname = userInfo ? `${userInfo.first_name} ${userInfo.last_name || ''}`.trim() : `UID:${guestChatId}`;
return sendMessage({
chat_id: ADMIN_UID,
text: `用户 ${nickname}` + (blocked ? ' 已被屏蔽' : ' 未被屏蔽')
})
}
/**
* Send plain text message
* https://core.telegram.org/bots/api#sendmessage
*/
async function sendPlainText (chatId, text) {
return sendMessage({
chat_id: chatId,
text
})
}
/**
* Set webhook to this worker's url
* https://core.telegram.org/bots/api#setwebhook
*/
async function registerWebhook (event, requestUrl, suffix, secret) {
// https://core.telegram.org/bots/api#setwebhook
const webhookUrl = `${requestUrl.protocol}//${requestUrl.hostname}${suffix}`
const r = await (await fetch(apiUrl('setWebhook', { url: webhookUrl, secret_token: secret }))).json()
return new Response('ok' in r && r.ok ? 'Ok' : JSON.stringify(r, null, 2))
}
/**
* Remove webhook
* https://core.telegram.org/bots/api#setwebhook
*/
async function unRegisterWebhook (event) {
const r = await (await fetch(apiUrl('setWebhook', { url: '' }))).json()
return new Response('ok' in r && r.ok ? 'Ok' : JSON.stringify(r, null, 2))
}
async function isFraud(id){
id = id.toString()
let db = await fetch(fraudDb).then(r => r.text())
let arr = db.split('\n').filter(v => v)
console.log(JSON.stringify(arr))
let flag = arr.filter(v => v === id).length !== 0
console.log(flag)
return flag
}
ps:没有自行部署过,只在cloudflare部署测试,自行部署的请自己研究,理论上应该差别不大
请注意:/block和/unblock以及查看是否屏蔽 都必须回复目标消息,这里可以魔改,但是为了避免误封,就没有做出修改
如有bug欢迎私信我反馈。。。午饭吃了吗大家。。。
6月19日更新代码---
6月24日更新代码---
原文链接:【魔改】魔改了酒神的双向机器人 (nodeseek.com)
阅读剩余
版权声明:
作者:John
链接:https://vps.la/2024/06/24/%e9%ad%94%e6%94%b9%e9%85%92%e7%a5%9e%e7%9a%84%e5%8f%8c%e5%90%91tg%e6%b6%88%e6%81%af%e8%bd%ac%e5%8f%91%e6%9c%ba%e5%99%a8%e4%ba%ba%ef%bc%8c%e5%b8%ae%e4%bd%a0%e5%9c%a8%e4%ba%92%e8%81%94%e7%bd%91%e4%b8%8a/
文章版权归作者所有,未经允许请勿转载。
THE END