From 9910b93eea93d5ac44f9f8de91820188a6784ee4 Mon Sep 17 00:00:00 2001 From: superbei666 <3260115423@qq.com> Date: Wed, 9 Jun 2021 18:47:34 +0800 Subject: [PATCH] =?UTF-8?q?add=20ql=20bot=20=E6=89=80=E9=9C=80=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- repo/dockerbot/jbot/__init__.py | 56 +++++ repo/dockerbot/jbot/__main__.py | 38 ++++ repo/dockerbot/jbot/bot/bean.py | 84 ++++++++ repo/dockerbot/jbot/bot/beandata.py | 114 +++++++++++ repo/dockerbot/jbot/bot/chart.py | 134 ++++++++++++ repo/dockerbot/jbot/bot/cmd.py | 26 +++ repo/dockerbot/jbot/bot/editfile.py | 137 +++++++++++++ repo/dockerbot/jbot/bot/getcookie.py | 176 ++++++++++++++++ repo/dockerbot/jbot/bot/getfile.py | 62 ++++++ repo/dockerbot/jbot/bot/help.py | 35 ++++ repo/dockerbot/jbot/bot/node.py | 19 ++ repo/dockerbot/jbot/bot/quickchart.py | 110 ++++++++++ repo/dockerbot/jbot/bot/sendfile.py | 43 ++++ repo/dockerbot/jbot/bot/setshort.py | 15 ++ repo/dockerbot/jbot/bot/short.py | 57 ++++++ repo/dockerbot/jbot/bot/snode.py | 18 ++ repo/dockerbot/jbot/bot/start.py | 21 ++ repo/dockerbot/jbot/bot/update.py | 10 + repo/dockerbot/jbot/bot/utils.py | 258 ++++++++++++++++++++++++ repo/dockerbot/jbot/diy/example.py | 10 + repo/dockerbot/jbot/ecosystem.config.js | 22 ++ repo/dockerbot/jbot/font/jet.ttf | Bin 0 -> 173264 bytes repo/dockerbot/jbot/requirements.txt | 7 + repo/dockerbot/jbot/utils.py | 22 ++ 24 files changed, 1474 insertions(+) create mode 100644 repo/dockerbot/jbot/__init__.py create mode 100644 repo/dockerbot/jbot/__main__.py create mode 100644 repo/dockerbot/jbot/bot/bean.py create mode 100644 repo/dockerbot/jbot/bot/beandata.py create mode 100644 repo/dockerbot/jbot/bot/chart.py create mode 100644 repo/dockerbot/jbot/bot/cmd.py create mode 100644 repo/dockerbot/jbot/bot/editfile.py create mode 100644 repo/dockerbot/jbot/bot/getcookie.py create mode 100644 repo/dockerbot/jbot/bot/getfile.py create mode 100644 repo/dockerbot/jbot/bot/help.py create mode 100644 repo/dockerbot/jbot/bot/node.py create mode 100644 repo/dockerbot/jbot/bot/quickchart.py create mode 100644 repo/dockerbot/jbot/bot/sendfile.py create mode 100644 repo/dockerbot/jbot/bot/setshort.py create mode 100644 repo/dockerbot/jbot/bot/short.py create mode 100644 repo/dockerbot/jbot/bot/snode.py create mode 100644 repo/dockerbot/jbot/bot/start.py create mode 100644 repo/dockerbot/jbot/bot/update.py create mode 100644 repo/dockerbot/jbot/bot/utils.py create mode 100644 repo/dockerbot/jbot/diy/example.py create mode 100644 repo/dockerbot/jbot/ecosystem.config.js create mode 100644 repo/dockerbot/jbot/font/jet.ttf create mode 100644 repo/dockerbot/jbot/requirements.txt create mode 100644 repo/dockerbot/jbot/utils.py diff --git a/repo/dockerbot/jbot/__init__.py b/repo/dockerbot/jbot/__init__.py new file mode 100644 index 00000000..236784e0 --- /dev/null +++ b/repo/dockerbot/jbot/__init__.py @@ -0,0 +1,56 @@ +from telethon import TelegramClient +import json +import os +import logging + +_JdDir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) +_ConfigDir = _JdDir + '/config' +_ScriptsDir = _JdDir + '/scripts' +_OwnDir = _JdDir + '/own' +_JdbotDir = _JdDir + '/jbot' +_DiyScripts = _JdDir + '/diyscripts' +_LogDir = _JdDir + '/log' +_shortcut = _ConfigDir + '/shortcut.list' +_botlog = _LogDir + '/bot/run.log' +_botjson = _ConfigDir + '/bot.json' +img_file = _ConfigDir + 'qr.jpg' +if not os.path.exists(_LogDir + '/bot'): + os.mkdir(_LogDir + '/bot') +logging.basicConfig( + format='%(asctime)s-%(name)s-%(levelname)s=> [%(funcName)s] %(message)s ', level=logging.INFO, filename=_botlog, + filemode='w') +logger = logging.getLogger(__name__) + +with open(_botjson, 'r', encoding='utf-8') as f: + bot = json.load(f) +chat_id = int(bot['user_id']) +# 机器人 TOKEN +TOKEN = bot['bot_token'] +# HOSTAPI = bot['apihost'] +# 发消息的TG代理 +# my.telegram.org申请到的api_id,api_hash +api_id = bot['api_id'] +api_hash = bot['api_hash'] +proxystart = bot['proxy'] +StartCMD = bot['StartCMD'] +if 'proxy_user' in bot.keys() and bot['proxy_user'] != "代理的username,有则填写,无则不用动": + proxy = { + 'proxy_type': bot['proxy_type'], + 'addr': bot['proxy_add'], + 'port': bot['proxy_port'], + 'username': bot['proxy_user'], + 'password': bot['proxy_password']} +else: + proxy = (bot['proxy_type'], bot['proxy_add'], bot['proxy_port']) +# 开启tg对话 +if proxystart and 'noretry' in bot.keys() and bot['noretry']: + jdbot = TelegramClient('bot', api_id, api_hash, + proxy=proxy).start(bot_token=TOKEN) +elif proxystart: + jdbot = TelegramClient('bot', api_id, api_hash, + proxy=proxy, connection_retries=None).start(bot_token=TOKEN) +elif 'noretry' in bot.keys() and bot['noretry']: + jdbot = TelegramClient('bot', api_id, api_hash).start(bot_token=TOKEN) +else: + jdbot = TelegramClient('bot', api_id, api_hash, + connection_retries=None).start(bot_token=TOKEN) diff --git a/repo/dockerbot/jbot/__main__.py b/repo/dockerbot/jbot/__main__.py new file mode 100644 index 00000000..27ee4c0b --- /dev/null +++ b/repo/dockerbot/jbot/__main__.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# _*_ coding:utf-8 _*_ +# 0.3 版本开始不再区分ql、V3、V4。运行日志:log/bot/run.log +# author: https://github.com/SuMaiKaDe + +from . import jdbot, chat_id, logger,_JdbotDir, _LogDir +from .utils import load_diy +import os +from .bot.update import version,botlog +_botuplog = _LogDir + '/bot/up.log' +botpath = _JdbotDir + "/bot/" +diypath = _JdbotDir + "/diy/" +logger.info('loading bot module...') +load_diy('bot', botpath) +logger.info('loading diy module...') +load_diy('diy', diypath) + +async def hello(): + if os.path.exists(_botuplog): + isnew = False + with open(_botuplog, 'r', encoding='utf-8') as f: + logs = f.readlines() + for log in logs: + if version in log: + isnew = True + return + if not isnew: + with open(_botuplog, 'a', encoding='utf-8') as f: + f.writelines([version, botlog]) + await jdbot.send_message(chat_id, '[机器人上新了](https://github.com/SuMaiKaDe/jddockerbot/tree/master)\n'+botlog+'\n运行日志为log/bot/run.log', link_preview=False) + else: + with open(_botuplog, 'w+', encoding='utf-8') as f: + f.writelines([version, botlog]) + await jdbot.send_message(chat_id, '[机器人上新了](https://github.com/SuMaiKaDe/jddockerbot/tree/master)\n'+botlog+'\n运行日志为log/bot/run.log', link_preview=False) +if __name__ == "__main__": + with jdbot: + jdbot.loop.create_task(hello()) + jdbot.loop.run_forever() diff --git a/repo/dockerbot/jbot/bot/bean.py b/repo/dockerbot/jbot/bot/bean.py new file mode 100644 index 00000000..012d8c8c --- /dev/null +++ b/repo/dockerbot/jbot/bot/bean.py @@ -0,0 +1,84 @@ +from PIL import Image, ImageFont, ImageDraw +from telethon import events +from .. import jdbot, chat_id, _LogDir, _JdbotDir,logger +from prettytable import PrettyTable +import subprocess +from .beandata import get_bean_data +IN = _LogDir + '/bean_income.csv' +OUT = _LogDir + '/bean_outlay.csv' +TOTAL = _LogDir + '/bean_total.csv' +_botimg = _LogDir + '/bean.jpg' +_font = _JdbotDir + '/font/jet.ttf' + + +@jdbot.on(events.NewMessage(chats=chat_id, pattern=r'^/bean')) +async def mybean(event): + try: + await jdbot.send_message(chat_id, '正在查询,请稍后') + if len(event.raw_text.split(' ')) > 1: + text = event.raw_text.replace('/bean ', '') + else: + text = None + if text and text == 'in': + subprocess.check_output( + 'jcsv', shell=True, stderr=subprocess.STDOUT) + creat_bean_counts(IN) + await jdbot.send_message(chat_id, '您的近日收入情况', file=_botimg) + elif text and text == 'out': + subprocess.check_output( + 'jcsv', shell=True, stderr=subprocess.STDOUT) + creat_bean_counts(OUT) + await jdbot.send_message(chat_id, '您的近日支出情况', file=_botimg) + elif text and int(text): + beanin, beanout, beanstotal,date = get_bean_data(int(text)) + if not beanout: + await jdbot.send_message(chat_id, 'something wrong,I\'m sorry\n'+str(beanin)) + else: + creat_bean_count(date,beanin, beanout, beanstotal[1:]) + await jdbot.send_message(chat_id, f'您的账号{text}收支情况', file=_botimg) + else: + subprocess.check_output( + 'jcsv', shell=True, stderr=subprocess.STDOUT) + creat_bean_counts(TOTAL) + await jdbot.send_message(chat_id, '您的总京豆情况', file=_botimg) + except Exception as e: + await jdbot.send_message(chat_id, 'something wrong,I\'m sorry\n'+str(e)) + logger.error('something wrong,I\'m sorry'+str(e)) + +def creat_bean_count(date,beansin,beansout,beanstotal): + tb = PrettyTable() + tb.add_column('DATE',date) + tb.add_column('BEANIN',beansin) + tb.add_column('BEANOUT',beansout) + tb.add_column('TOTAL',beanstotal) + font = ImageFont.truetype(_font, 18) + im = Image.new("RGB", (500, 260), (244, 244, 244)) + dr = ImageDraw.Draw(im) + dr.text((10, 5), str(tb), font=font, fill="#000000") + im.save(_botimg) + +def creat_bean_counts(csv_file): + with open(csv_file, 'r', encoding='utf-8') as f: + data = f.readlines() + tb = PrettyTable() + num = len(data[-1].split(',')) - 1 + title = ['DATE'] + for i in range(0, num): + title.append('COUNT'+str(i+1)) + tb.field_names = title + data = data[-7:] + for line in data: + row = line.split(',') + if len(row) > len(title): + row = row[:len(title)] + elif len(row) < len(title): + i = len(title) - len(row) + for _ in range(0,i): + row.append(0) + tb.add_row(row) + length = 172 + 100 * num + im = Image.new("RGB", (length, 400), (244, 244, 244)) + dr = ImageDraw.Draw(im) + font = ImageFont.truetype(_font, 18) + dr.text((10, 5), str(tb), font=font, fill="#000000") + im.save(_botimg) diff --git a/repo/dockerbot/jbot/bot/beandata.py b/repo/dockerbot/jbot/bot/beandata.py new file mode 100644 index 00000000..f812f71e --- /dev/null +++ b/repo/dockerbot/jbot/bot/beandata.py @@ -0,0 +1,114 @@ +import requests +import datetime +import time +import json +from datetime import timedelta +from datetime import timezone +from .utils import cookies +SHA_TZ = timezone( + timedelta(hours=8), + name='Asia/Shanghai', +) + + +session = requests.session() + + +url = "https://api.m.jd.com/api" + + +def getbody(page): + body = { + "beginDate": datetime.datetime.utcnow().replace(tzinfo=timezone.utc).astimezone(SHA_TZ).strftime("%Y-%m-%d %H:%M:%S"), + "endDate": datetime.datetime.utcnow().replace(tzinfo=timezone.utc).astimezone(SHA_TZ).strftime("%Y-%m-%d %H:%M:%S"), + "pageNo": page, + "pageSize": 20, + } + return body + + +def getparms(page): + body = getbody(page) + parms = { + "functionId": "jposTradeQuery", + "appid": "swat_miniprogram", + "client": "tjj_m", + "sdkName": "orderDetail", + "sdkVersion": "1.0.0", + "clientVersion": "3.1.3", + "timestamp": int(round(time.time() * 1000)), + "body": json.dumps(body) + } + return parms + + +def getbeans(ck): + _7day = True + page = 0 + headers = { + "Host": "api.m.jd.com", + "Connection": "keep-alive", + "charset": "utf-8", + "User-Agent": "Mozilla/5.0 (Linux; Android 10; MI 9 Build/QKQ1.190825.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.62 XWEB/2797 MMWEBSDK/201201 Mobile Safari/537.36 MMWEBID/7986 MicroMessenger/8.0.1840(0x2800003B) Process/appbrand4 WeChat/arm64 Weixin NetType/4G Language/zh_CN ABI/arm64 MiniProgramEnv/android", + "Content-Type": "application/x-www-form-urlencoded;", + "Accept-Encoding": "gzip, compress, deflate, br", + "Cookie": ck, + "Referer": "https://servicewechat.com/wxa5bf5ee667d91626/141/page-frame.html", + } + _7days = [] + for i in range(0, 7): + _7days.append( + (datetime.date.today() - datetime.timedelta(days=i)).strftime("%Y-%m-%d")) + beansin = {key: 0 for key in _7days} + beansout = {key: 0 for key in _7days} + while _7day: + page = page + 1 + resp = session.get(url, params=getparms(page), headers=headers).text + res = json.loads(resp) + if res['resultCode'] == 0: + for i in res['data']['list']: + for date in _7days: + if str(date) in i['createDate'] and i['amount'] > 0: + beansin[str(date)] = beansin[str(date)] + i['amount'] + break + elif str(date) in i['createDate'] and i['amount'] < 0: + beansout[str(date)] = beansout[str(date)] + i['amount'] + break + if i['createDate'].split(' ')[0] not in str(_7days): + _7day = False + else: + return 'error' + str(res), None, None + return beansin, beansout, _7days + + +def getTotal(ck): + headers = { + "Host": "wxapp.m.jd.com", + "Connection": "keep-alive", + "charset": "utf-8", + "User-Agent": "Mozilla/5.0 (Linux; Android 10; MI 9 Build/QKQ1.190825.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.62 XWEB/2797 MMWEBSDK/201201 Mobile Safari/537.36 MMWEBID/7986 MicroMessenger/8.0.1840(0x2800003B) Process/appbrand4 WeChat/arm64 Weixin NetType/4G Language/zh_CN ABI/arm64 MiniProgramEnv/android", + "Content-Type": "application/x-www-form-urlencoded;", + "Accept-Encoding": "gzip, compress, deflate, br", + "Cookie": ck, + } + jurl = "https://wxapp.m.jd.com/kwxhome/myJd/home.json" + resp = session.get(jurl, headers=headers).text + res = json.loads(resp) + return res['user']['jingBean'] + + +def get_bean_data(i): + ck = cookies[i-1] + beansin, beansout, _7days = getbeans(ck) + beantotal = getTotal(ck) + if not beansout: + return str(beansin), None, None,None + else: + beanin, beanout = [], [] + beanstotal = [int(beantotal), ] + for i in beansin: + beantotal = int(beantotal) - int(beansin[i]) - int(beansout[i]) + beanin.append(beansin[i]) + beanout.append(int(str(beansout[i]).replace('-', ''))) + beanstotal.append(beantotal) + return beanin[::-1], beanout[::-1], beanstotal[::-1], _7days[::-1] diff --git a/repo/dockerbot/jbot/bot/chart.py b/repo/dockerbot/jbot/bot/chart.py new file mode 100644 index 00000000..253570aa --- /dev/null +++ b/repo/dockerbot/jbot/bot/chart.py @@ -0,0 +1,134 @@ +from telethon import events +from .. import jdbot, chat_id, _LogDir, logger +from ..bot.quickchart import QuickChart +from .beandata import get_bean_data +_botimg = _LogDir + '/bot/bean.jpeg' + +@jdbot.on(events.NewMessage(chats=chat_id, pattern=r'^/chart')) +async def mybean(event): + try: + await jdbot.send_message(chat_id, '正在查询,请稍后') + if len(event.raw_text.split(' ')) > 1: + text = event.raw_text.replace('/chart ', '') + else: + text = None + if text and int(text): + beanin, beanout, beanstotal, date = get_bean_data(int(text)) + if not beanout: + await jdbot.send_message(chat_id, 'something wrong,I\'m sorry\n'+str(beanin)) + else: + creat_chart(date, '账号'+str(text), + beanin, beanout, beanstotal[1:]) + await jdbot.send_message(chat_id, f'您的账号{text}收支情况', file=_botimg) + else: + await jdbot.send_message(chat_id, '请正确使用命令\n/chart n n为第n个账号') + except Exception as e: + await jdbot.send_message(chat_id, 'something wrong,I\'m sorry\n'+str(e)) + logger.error('something wrong,I\'m sorry'+str(e)) + + +def creat_chart(xdata, title, bardata, bardata2, linedate): + qc = QuickChart() + qc.background_color = '#fff' + qc.width = "1000" + qc.height = "600" + qc.config = { + "type": "bar", + "data": { + "labels": xdata, + "datasets": [ + { + "label": "IN", + "backgroundColor": [ + "rgb(255, 99, 132)", + "rgb(255, 159, 64)", + "rgb(255, 205, 86)", + "rgb(75, 192, 192)", + "rgb(54, 162, 235)", + "rgb(153, 102, 255)", + "rgb(255, 99, 132)" + ], + "yAxisID": "y1", + "data": bardata + }, + { + "label": "OUT", + "backgroundColor": [ + "rgb(255, 99, 132)", + "rgb(255, 159, 64)", + "rgb(255, 205, 86)", + "rgb(75, 192, 192)", + "rgb(54, 162, 235)", + "rgb(153, 102, 255)", + "rgb(255, 99, 132)" + ], + "yAxisID": "y1", + "data": bardata2 + }, + { + "label": "TOTAL", + "type": "line", + "fill": False, + "backgroundColor": "rgb(201, 203, 207)", + "yAxisID": "y2", + "data": linedate + } + ] + }, + "options": { + "plugins": { + "datalabels": { + "anchor": 'end', + "align": -100, + "color": '#666', + "font": { + "size": 20, + } + }, + }, + "legend": { + "labels": { + "fontSize": 20, + "fontStyle": 'bold', + } + }, + "title": { + "display": True, + "text": title + " 收支情况", + "fontSize": 24, + }, + "scales": { + "xAxes": [{ + "ticks": { + "fontSize": 24, + } + }], + "yAxes": [ + { + "id": "y1", + "type": "linear", + "display": False, + "position": "left", + "ticks": { + "max": int(int(max([max(bardata), max(bardata2)])+100)*2) + }, + "scaleLabel": { + "fontSize": 20, + "fontStyle": 'bold', + } + }, + { + "id": "y2", + "type": "linear", + "display": False, + "ticks": { + "min": int(min(linedate)*2-(max(linedate))-100), + "max": int(int(max(linedate))) + }, + "position": "right" + } + ] + } + } + } + qc.to_file(_botimg) diff --git a/repo/dockerbot/jbot/bot/cmd.py b/repo/dockerbot/jbot/bot/cmd.py new file mode 100644 index 00000000..b50048a6 --- /dev/null +++ b/repo/dockerbot/jbot/bot/cmd.py @@ -0,0 +1,26 @@ +from telethon import events +import re +from .. import jdbot, StartCMD, chat_id, logger +from .utils import cmd + + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern='/cmd')) +async def mycmd(event): + '''接收/cmd命令后执行程序''' + if StartCMD: + cmdreg = re.compile(r'^/cmd [\s\S]+') + text = re.findall(cmdreg, event.raw_text) + if len(text) == 0: + msg = '''请正确使用/cmd命令,如 + /cmd jlog # 删除旧日志 + /cmd jup # 更新所有脚本 + /cmd jcode # 导出所有互助码 + /cmd jcsv # 记录豆豆变化情况 + 不建议直接使用cmd命令执行脚本,请使用/node或/snode + ''' + await jdbot.send_message(chat_id, msg) + else: + logger.info(text) + await cmd(text[0].replace('/cmd ', '')) + else: + await jdbot.send_message(chat_id, '未开启CMD命令,如需使用请修改配置文件') diff --git a/repo/dockerbot/jbot/bot/editfile.py b/repo/dockerbot/jbot/bot/editfile.py new file mode 100644 index 00000000..88158c1d --- /dev/null +++ b/repo/dockerbot/jbot/bot/editfile.py @@ -0,0 +1,137 @@ +from telethon import events, Button +import os +import shutil +from asyncio import exceptions +from .. import jdbot, chat_id, _JdDir +from .utils import split_list, logger,press_event + + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern='/edit')) +async def myfileup(event): + '''定义编辑文件操作''' + SENDER = event.sender_id + path = _JdDir + page = 0 + if len(event.raw_text.split(' ')) > 1: + text = event.raw_text.replace('/edit ','') + else: + text =None + if text and os.path.isfile(text): + try: + with open(text,'r',encoding='utf-8') as f: + lines = f.readlines() + filelist = split_list(lines, 15) + path = text + except Exception as e: + await jdbot.send_message(chat_id, 'something wrong,I\'m sorry\n'+str(e)) + elif text and os.path.isdir(text): + path = text + filelist = None + elif text: + await jdbot.send_message(chat_id, 'please marksure it\'s a dir or a file') + filelist = None + else: + filelist = None + async with jdbot.conversation(SENDER, timeout=60) as conv: + msg = await conv.send_message('正在查询,请稍后') + while path: + path, msg, page, filelist = await myedit(conv, SENDER, path, msg, page, filelist) + + +async def myedit(conv, SENDER, path, msg, page, filelist): + mybtn = [Button.inline('上一页', data='up'), Button.inline('下一页', data='next'), Button.inline( + '上级', data='updir'), Button.inline('取消', data='cancel')] + mybtn2 = [[Button.inline('上一页', data='up'), Button.inline( + '下一页', data='next'), Button.inline('取消', data='cancel')], [Button.inline('上十页', data='up10'), Button.inline( + '下十页', data='next10'), Button.inline('编辑', data='edit')]] + try: + if filelist and type(filelist[0][0]) == str: + markup = filelist + newmarkup = markup[page] + msg = await jdbot.edit_message(msg, "".join(newmarkup), buttons=mybtn2) + else: + if filelist: + markup = filelist + newmarkup = markup[page] + if mybtn not in newmarkup: + newmarkup.append(mybtn) + else: + dir = os.listdir(path) + dir.sort() + markup = [Button.inline(file, data=str( + file)) for file in dir] + markup = split_list(markup, 3) + if len(markup) > 30: + markup = split_list(markup, 30) + newmarkup = markup[page] + newmarkup.append(mybtn) + else: + newmarkup = markup + if path == _JdDir: + newmarkup.append([Button.inline('取消', data='cancel')]) + else: + newmarkup.append( + [Button.inline('上级', data='updir'), Button.inline('取消', data='cancel')]) + msg = await jdbot.edit_message(msg, '请做出您的选择:', buttons=newmarkup) + convdata = await conv.wait_event(press_event(SENDER)) + res = bytes.decode(convdata.data) + if res == 'cancel': + msg = await jdbot.edit_message(msg, '对话已取消') + conv.cancel() + return None, None, None, None + elif res == 'next': + page = page + 1 + if page > len(markup) - 1: + page = 0 + return path, msg, page, markup + elif res == 'up': + page = page - 1 + if page < 0: + page = len(markup) - 1 + return path, msg, page, markup + elif res == 'next10': + page = page + 10 + if page > len(markup) - 1: + page = 0 + return path, msg, page, markup + elif res == 'up10': + page = page - 10 + if page < 0: + page = len(markup) - 1 + return path, msg, page, markup + elif res == 'updir': + path = '/'.join(path.split('/')[:-1]) + if path == '': + path = _JdDir + return path, msg, page, None + elif res == 'edit': + await jdbot.send_message(chat_id, '请复制并修改以下内容,修改完成后发回机器人,2分钟内有效') + await jdbot.delete_messages(chat_id, msg) + msg = await conv.send_message("".join(newmarkup)) + resp = await conv.get_response() + markup[page] = resp.raw_text.split('\n') + for a in range(len(markup[page])): + markup[page][a] = markup[page][a]+'\n' + shutil.copy(path, path+'.bak') + with open(path, 'w+', encoding='utf-8') as f: + markup = ["".join(a) for a in markup] + f.writelines(markup) + await jdbot.send_message(chat_id, '文件已修改成功,原文件备份为'+path+'.bak') + conv.cancel() + return None, None, None, None + elif os.path.isfile(path+'/'+res): + msg = await jdbot.edit_message(msg, '文件读取中...请稍候') + with open(path+'/'+res, 'r', encoding='utf-8') as f: + lines = f.readlines() + lines = split_list(lines, 15) + page = 0 + return path+'/'+res, msg, page, lines + else: + return path+'/'+res, msg, page, None + except exceptions.TimeoutError: + msg = await jdbot.edit_message(msg, '选择已超时,本次对话已停止') + return None, None, None, None + except Exception as e: + msg = await jdbot.edit_message(msg, 'something wrong,I\'m sorry\n'+str(e)) + logger.error('something wrong,I\'m sorry\n'+str(e)) + return None, None, None, None diff --git a/repo/dockerbot/jbot/bot/getcookie.py b/repo/dockerbot/jbot/bot/getcookie.py new file mode 100644 index 00000000..4a201da2 --- /dev/null +++ b/repo/dockerbot/jbot/bot/getcookie.py @@ -0,0 +1,176 @@ +from telethon import events, Button +import requests +import re +import time +import qrcode +from asyncio import exceptions +from .. import jdbot, chat_id, img_file +from .utils import press_event + +cookiemsg = '' +# 扫码获取cookie 直接采用LOF大佬代码 +# getSToken请求获取,s_token用于发送post请求是的必须参数 +s_token = "" +# getSToken请求获取,guid,lsid,lstoken用于组装cookies +guid, lsid, lstoken = "", "", "" +# 由上面参数组装生成,getOKLToken函数发送请求需要使用 +cookies = "" +# getOKLToken请求获取,token用户生成二维码使用、okl_token用户检查扫码登录结果使用 +token, okl_token = "", "" +# 最终获取到的可用的cookie +jd_cookie = "" + + +def getSToken(): + time_stamp = int(time.time() * 1000) + get_url = 'https://plogin.m.jd.com/cgi-bin/mm/new_login_entrance?lang=chs&appid=300&returnurl=https://wq.jd.com/passport/LoginRedirect?state=%s&returnurl=https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport' % time_stamp + get_header = { + 'Connection': 'Keep-Alive', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json, text/plain, */*', + 'Accept-Language': 'zh-cn', + 'Referer': 'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wq.jd.com/passport/LoginRedirect?state=%s&returnurl=https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport' % time_stamp, + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + 'Host': 'plogin.m.jd.com' + } + resp = requests.get(url=get_url, headers=get_header) + parseGetRespCookie(resp.headers, resp.json()) + + +def parseGetRespCookie(headers, get_resp): + global s_token + global cookies + s_token = get_resp.get('s_token') + set_cookies = headers.get('set-cookie') + guid = re.findall(r"guid=(.+?);", set_cookies)[0] + lsid = re.findall(r"lsid=(.+?);", set_cookies)[0] + lstoken = re.findall(r"lstoken=(.+?);", set_cookies)[0] + cookies = f"guid={guid}; lang=chs; lsid={lsid}; lstoken={lstoken}; " + + +def getOKLToken(): + post_time_stamp = int(time.time() * 1000) + post_url = 'https://plogin.m.jd.com/cgi-bin/m/tmauthreflogurl?s_token=%s&v=%s&remember=true' % ( + s_token, post_time_stamp) + post_data = { + 'lang': 'chs', + 'appid': 300, + 'returnurl': 'https://wqlogin2.jd.com/passport/LoginRedirect?state=%s&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action' % post_time_stamp, + 'source': 'wq_passport' + } + post_header = { + 'Connection': 'Keep-Alive', + 'Content-Type': 'application/x-www-form-urlencoded; Charset=UTF-8', + 'Accept': 'application/json, text/plain, */*', + 'Cookie': cookies, + 'Referer': 'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=%s&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport' % post_time_stamp, + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + 'Host': 'plogin.m.jd.com', + } + try: + global okl_token + resp = requests.post( + url=post_url, headers=post_header, data=post_data, timeout=20) + parsePostRespCookie(resp.headers, resp.json()) + except Exception as error: + print("Post网络请求错误", error) + + +def parsePostRespCookie(headers, data): + global token + global okl_token + token = data.get('token') + okl_token = re.findall(r"okl_token=(.+?);", headers.get('set-cookie'))[0] + + +def parseJDCookies(headers): + global jd_cookie + set_cookie = headers.get('Set-Cookie') + pt_key = re.findall(r"pt_key=(.+?);", set_cookie)[0] + pt_pin = re.findall(r"pt_pin=(.+?);", set_cookie)[0] + jd_cookie = f'pt_key={pt_key};pt_pin={pt_pin};' + + +def creatqr(text): + '''实例化QRCode生成qr对象''' + qr = qrcode.QRCode( + version=1, + error_correction=qrcode.constants.ERROR_CORRECT_H, + box_size=10, + border=4 + ) + qr.clear() + # 传入数据 + qr.add_data(text) + qr.make(fit=True) + # 生成二维码 + img = qr.make_image() + # 保存二维码 + img.save(img_file) + + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern=r'^/getcookie')) +async def mycookie(event): + '''接收/getcookie后执行程序''' + login = True + msg = await jdbot.send_message(chat_id, '正在获取二维码,请稍后') + global cookiemsg + try: + SENDER = event.sender_id + async with jdbot.conversation(SENDER, timeout=30) as conv: + getSToken() + getOKLToken() + url = 'https://plogin.m.jd.com/cgi-bin/m/tmauth?appid=300&client_type=m&token='+token + creatqr(url) + markup = [Button.inline("已扫码", data='confirm'), + Button.inline("取消", data='cancel')] + await jdbot.delete_messages(chat_id, msg) + cookiemsg = await jdbot.send_message(chat_id, '30s内点击取消将取消本次操作\n如不取消,扫码结果将于30s后显示\n扫码后不想等待点击已扫码', file=img_file, buttons=markup) + convdata = await conv.wait_event(press_event(SENDER)) + res = bytes.decode(convdata.data) + if res == 'cancel': + login = False + await jdbot.delete_messages(chat_id, cookiemsg) + msg = await conv.send_message('对话已取消') + conv.cancel() + else: + raise exceptions.TimeoutError() + except exceptions.TimeoutError: + expired_time = time.time() + 60 * 2 + while login: + check_time_stamp = int(time.time() * 1000) + check_url = 'https://plogin.m.jd.com/cgi-bin/m/tmauthchecktoken?&token=%s&ou_state=0&okl_token=%s' % ( + token, okl_token) + check_data = { + 'lang': 'chs', + 'appid': 300, + 'returnurl': 'https://wqlogin2.jd.com/passport/LoginRedirect?state=%s&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action' % check_time_stamp, + 'source': 'wq_passport' + } + check_header = { + 'Referer': f'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=%s&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport' % check_time_stamp, + 'Cookie': cookies, + 'Connection': 'Keep-Alive', + 'Content-Type': 'application/x-www-form-urlencoded; Charset=UTF-8', + 'Accept': 'application/json, text/plain, */*', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', + } + resp = requests.post( + url=check_url, headers=check_header, data=check_data, timeout=30) + data = resp.json() + if data.get("errcode") == 0: + parseJDCookies(resp.headers) + await jdbot.delete_messages(chat_id, cookiemsg) + await jdbot.send_message(chat_id, '以下为获取到的cookie') + await jdbot.send_message(chat_id, jd_cookie) + return + if data.get("errcode") == 21: + await jdbot.delete_messages(chat_id, cookiemsg) + await jdbot.send_message(chat_id, '发生了某些错误\n'+data.get("errcode")) + return + if time.time() > expired_time: + await jdbot.delete_messages(chat_id, cookiemsg) + await jdbot.send_message(chat_id, '超过3分钟未扫码,二维码已过期') + return + except Exception as e: + await jdbot.send_message(chat_id, 'something wrong,I\'m sorry\n'+str(e)) diff --git a/repo/dockerbot/jbot/bot/getfile.py b/repo/dockerbot/jbot/bot/getfile.py new file mode 100644 index 00000000..b76e549f --- /dev/null +++ b/repo/dockerbot/jbot/bot/getfile.py @@ -0,0 +1,62 @@ +from telethon import events, Button +import subprocess +from asyncio import exceptions +from .. import jdbot, chat_id, _ScriptsDir, _ConfigDir, logger +from .utils import press_event, backfile, _DiyDir, jdcmd, V4 + + +@jdbot.on(events.NewMessage(from_users=chat_id)) +async def myfile(event): + '''定义文件操作''' + try: + v4btn = [[Button.inline('放入config', data=_ConfigDir), Button.inline('放入scripts', data=_ScriptsDir), Button.inline('放入OWN文件夹', data=_DiyDir)], [ + Button.inline('放入scripts并运行', data='node1'), Button.inline('放入OWN并运行', data='node'), Button.inline('取消', data='cancel')]] + btn = [[Button.inline('放入config', data=_ConfigDir), Button.inline('放入scripts', data=_ScriptsDir)], [ + Button.inline('放入scripts并运行', data='node1'), Button.inline('取消', data='cancel')]] + SENDER = event.sender_id + if event.message.file: + markup = [] + filename = event.message.file.name + async with jdbot.conversation(SENDER, timeout=30) as conv: + msg = await conv.send_message('请选择您要放入的文件夹或操作:\n') + if V4: + markup = v4btn + else: + markup = btn + msg = await jdbot.edit_message(msg, '请选择您要放入的文件夹或操作:', buttons=markup) + convdata = await conv.wait_event(press_event(SENDER)) + res = bytes.decode(convdata.data) + if res == 'cancel': + msg = await jdbot.edit_message(msg, '对话已取消') + conv.cancel() + elif res == 'node': + await backfile(_DiyDir+'/'+filename) + await jdbot.download_media(event.message, _DiyDir) + cmdtext = '{} {}/{} now'.format(jdcmd, _DiyDir, filename) + subprocess.Popen( + cmdtext, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + await jdbot.edit_message(msg, '脚本已保存到DIY文件夹,并成功在后台运行,请稍后自行查看日志') + conv.cancel() + elif res == 'node1': + await backfile(_ScriptsDir+'/'+filename) + await jdbot.download_media(event.message, _ScriptsDir) + cmdtext = '{} {}/{} now'.format(jdcmd, + _ScriptsDir, filename) + subprocess.Popen( + cmdtext, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + await jdbot.edit_message(msg, '脚本已保存到scripts文件夹,并成功在后台运行,请稍后自行查看日志') + conv.cancel() + else: + await backfile(res+'/'+filename) + await jdbot.download_media(event.message, res) + await jdbot.edit_message(msg, filename+'已保存到'+res+'文件夹') + if filename == 'crontab.list' and V4: + cmdtext = 'crontab '+res+'/'+filename + subprocess.Popen( + cmdtext, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + await jdbot.edit_message(msg, '定时文件已保存,并更新') + except exceptions.TimeoutError: + msg = await jdbot.send_message(chat_id, '选择已超时,对话已停止') + except Exception as e: + await jdbot.send_message(chat_id, 'something wrong,I\'m sorry\n'+str(e)) + logger.error('something wrong,I\'m sorry\n'+str(e)) diff --git a/repo/dockerbot/jbot/bot/help.py b/repo/dockerbot/jbot/bot/help.py new file mode 100644 index 00000000..8c53b685 --- /dev/null +++ b/repo/dockerbot/jbot/bot/help.py @@ -0,0 +1,35 @@ +from telethon import events +from .. import jdbot, chat_id + + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern='^/help')) +async def myhelp(event): + '''接收/help命令后执行程序''' + if len(event.raw_text) > 6: + text = event.raw_text.replace('/help ', '') + else: + text = 'mhelp' + mhelp = ''' +a-我的自定义快捷按钮 +bean-获取收支 +edit-编辑文件 +start-开始使用本程序 +node-执行js脚本文件,绝对路径。 +cmd-执行cmd命令 +snode-选择脚本后台运行 +log-选择日志 +getfile-获取jd目录下文件 +setshort-设置自定义按钮 +getcookie-扫码获取cookie''' + bean = '/bean 加数字,获取该账户近期收支情况\n/bean in\out获取所有账户近期收或支情况\n/bean 获取账户总豆数量' + cmd = '/cmd用于执行cmd命令,如果命令持续10分钟仍未结束,将强行终止,以保障机器人响应' + edit = '/edit 进入/jd目录选择文件进行编辑,仅限简易编辑\n/edit /jd/config进入config目录选择文件编辑\n/edit /jd/config/config.sh 直接编辑config.sh文件' + getcookie = '/getcookie 扫码获取jdcookie' + node = '/node 用于执行js脚本 用法:\n/node /jd/own/abc/def.js' + getfile = '/getfile 进入/jd目录选择文件进行获取\n/getfile /jd/config进入config目录选择文件获取\n/getfile /jd/config/config.sh 直接获取config.sh文件' + setshort = '/setshort 用于设置快捷方式,格式如下:\n更新-->jup\nAAA-->BBB这种格式使用/a选择\n/bean 1\n/edit /jd/config/config.sh\n以“/”开头的为机器人命令快捷,使用/b选择' + snode = '/snode 选择脚本并运行' + chart = '' + helpme = {'bean': bean, 'cmd': cmd, 'edit': edit, 'getcookie': getcookie, 'node': node, + 'getfile': getfile, 'setshort': setshort, 'snode': snode, 'chart': chart,'mhelp':mhelp} + await jdbot.send_message(chat_id, helpme[text]) diff --git a/repo/dockerbot/jbot/bot/node.py b/repo/dockerbot/jbot/bot/node.py new file mode 100644 index 00000000..af9ab809 --- /dev/null +++ b/repo/dockerbot/jbot/bot/node.py @@ -0,0 +1,19 @@ +from telethon import events +import re +from .. import jdbot, chat_id +from .utils import cmd, jdcmd + + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern='/node')) +async def mynode(event): + '''接收/node命令后执行程序''' + nodereg = re.compile(r'^/node [\S]+') + text = re.findall(nodereg, event.raw_text) + if len(text) == 0: + res = '''请正确使用/node命令,如 + /node /abc/123.js 运行abc/123.js脚本 + /node /own/abc.js 运行own/abc.js脚本 + ''' + await jdbot.send_message(chat_id, res) + else: + await cmd('{} {} now'.format(jdcmd, text[0].replace('/node ', ''))) diff --git a/repo/dockerbot/jbot/bot/quickchart.py b/repo/dockerbot/jbot/bot/quickchart.py new file mode 100644 index 00000000..80a8cef0 --- /dev/null +++ b/repo/dockerbot/jbot/bot/quickchart.py @@ -0,0 +1,110 @@ +"""A python client for quickchart.io, a web service that generates static +charts.""" + +import datetime +import json +import re +try: + from urllib import urlencode +except: + # For Python 3 + from urllib.parse import urlencode + +FUNCTION_DELIMITER_RE = re.compile('\"__BEGINFUNCTION__(.*?)__ENDFUNCTION__\"') + + +class QuickChartFunction: + def __init__(self, script): + self.script = script + + def __repr__(self): + return self.script + + +def serialize(obj): + if isinstance(obj, QuickChartFunction): + return '__BEGINFUNCTION__' + obj.script + '__ENDFUNCTION__' + if isinstance(obj, (datetime.date, datetime.datetime)): + return obj.isoformat() + return obj.__dict__ + + +def dump_json(obj): + ret = json.dumps(obj, default=serialize, separators=(',', ':')) + ret = FUNCTION_DELIMITER_RE.sub( + lambda match: json.loads('"' + match.group(1) + '"'), ret) + return ret + + +class QuickChart: + def __init__(self): + self.config = None + self.width = 500 + self.height = 300 + self.background_color = '#ffffff' + self.device_pixel_ratio = 1.0 + self.format = 'png' + self.key = None + self.scheme = 'https' + self.host = 'quickchart.io' + + def is_valid(self): + return self.config is not None + + def get_url_base(self): + return '%s://%s' % (self.scheme, self.host) + + def get_url(self): + if not self.is_valid(): + raise RuntimeError( + 'You must set the `config` attribute before generating a url') + params = { + 'c': dump_json(self.config) if type(self.config) == dict else self.config, + 'w': self.width, + 'h': self.height, + 'bkg': self.background_color, + 'devicePixelRatio': self.device_pixel_ratio, + 'f': self.format, + } + if self.key: + params['key'] = self.key + return '%s/chart?%s' % (self.get_url_base(), urlencode(params)) + + def _post(self, url): + try: + import requests + except: + raise RuntimeError('Could not find `requests` dependency') + + postdata = { + 'chart': dump_json(self.config) if type(self.config) == dict else self.config, + 'width': self.width, + 'height': self.height, + 'backgroundColor': self.background_color, + 'devicePixelRatio': self.device_pixel_ratio, + 'format': self.format, + } + if self.key: + postdata['key'] = self.key + resp = requests.post(url, json=postdata) + if resp.status_code != 200: + raise RuntimeError( + 'Invalid response code from chart creation endpoint') + return resp + + def get_short_url(self): + resp = self._post('%s/chart/create' % self.get_url_base()) + parsed = json.loads(resp.text) + if not parsed['success']: + raise RuntimeError( + 'Failure response status from chart creation endpoint') + return parsed['url'] + + def get_bytes(self): + resp = self._post('%s/chart' % self.get_url_base()) + return resp.content + + def to_file(self, path): + content = self.get_bytes() + with open(path, 'wb') as f: + f.write(content) diff --git a/repo/dockerbot/jbot/bot/sendfile.py b/repo/dockerbot/jbot/bot/sendfile.py new file mode 100644 index 00000000..e81da875 --- /dev/null +++ b/repo/dockerbot/jbot/bot/sendfile.py @@ -0,0 +1,43 @@ +from telethon import events +from .. import jdbot, chat_id, _LogDir, _JdDir +from .utils import logbtn +import os + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern=r'^/log')) +async def mylog(event): + '''定义日志文件操作''' + SENDER = event.sender_id + path = _LogDir + page = 0 + filelist = None + async with jdbot.conversation(SENDER, timeout=60) as conv: + msg = await conv.send_message('正在查询,请稍后') + while path: + path, msg, page, filelist = await logbtn(conv, SENDER, path, msg, page, filelist) + + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern=r'^/getfile')) +async def mygetfile(event): + '''定义获取文件命令''' + SENDER = event.sender_id + path = _JdDir + page = 0 + if len(event.raw_text.split(' ')) > 1: + text = event.raw_text.replace('/getfile ','') + else: + text =None + if text and os.path.isfile(text): + await jdbot.send_message(chat_id, '请查收文件',file=text) + return + elif text and os.path.isdir(text): + path = text + filelist = None + elif text: + await jdbot.send_message(chat_id, 'please marksure it\'s a dir or a file') + filelist = None + else: + filelist = None + async with jdbot.conversation(SENDER, timeout=60) as conv: + msg = await conv.send_message('正在查询,请稍后') + while path: + path, msg, page, filelist = await logbtn(conv, SENDER, path, msg, page, filelist) diff --git a/repo/dockerbot/jbot/bot/setshort.py b/repo/dockerbot/jbot/bot/setshort.py new file mode 100644 index 00000000..e81c5de2 --- /dev/null +++ b/repo/dockerbot/jbot/bot/setshort.py @@ -0,0 +1,15 @@ +from telethon import events +from .. import jdbot, chat_id, _shortcut + + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern=r'^/setshort$')) +async def setshortcut(event): + SENDER = event.sender_id + async with jdbot.conversation(SENDER, timeout=60) as conv: + await conv.send_message( + '60s内回复有效\n请按格式输入您的快捷命令。例如:\n京豆通知-->jtask jd_bean_change\n更新脚本-->jup\n获取互助码-->jcode\nnode运行XX脚本-->node /XX/XX.js\nbash运行abc/123.sh脚本-->bash /abc/123.sh\n-->前边为要显示的名字,-->后边为要运行的命令\n 如添加运行脚本立即执行命令记得在后边添加now\n如不等待运行结果请添加nohup,如京豆通知-->nohup jtask jd_bean_change now\n如不添加nohup 会等待程序执行完,期间不能交互\n建议运行时间短命令不添加nohup\n部分功能青龙可能不支持,请自行测试,自行设定 ') + shortcut = await conv.get_response() + with open(_shortcut, 'w+', encoding='utf-8') as f: + f.write(shortcut.raw_text) + await conv.send_message('已设置成功可通过"/a"使用') + conv.cancel() diff --git a/repo/dockerbot/jbot/bot/short.py b/repo/dockerbot/jbot/bot/short.py new file mode 100644 index 00000000..73e24e71 --- /dev/null +++ b/repo/dockerbot/jbot/bot/short.py @@ -0,0 +1,57 @@ +from telethon import events, Button +from .utils import split_list, press_event, cmd +import subprocess +from asyncio import exceptions +from .. import jdbot, chat_id, _shortcut, logger + + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern=r'^/a$')) +async def shortcut(event): + markup = [] + SENDER = event.sender_id + msg = await jdbot.send_message(chat_id, '正在查询您的常用命令,请稍后') + with open(_shortcut, 'r', encoding='utf-8') as f: + shortcuts = f.readlines() + try: + async with jdbot.conversation(SENDER, timeout=60) as conv: + markup = [Button.inline(shortcut.split( + '-->')[0], data=str(shortcut.split('-->')[-1])) for shortcut in shortcuts if '-->' in shortcut] + markup = split_list(markup, 3) + markup.append([Button.inline('取消', data='cancel')]) + msg = await jdbot.edit_message(msg, '请做出您的选择:', buttons=markup) + convdata = await conv.wait_event(press_event(SENDER)) + res = bytes.decode(convdata.data) + if res == 'cancel': + msg = await jdbot.edit_message(msg, '对话已取消') + conv.cancel() + elif 'nohup ' in res: + msg = await jdbot.edit_message(msg, '即将执行您的操作'+res) + cmdtext = res.replace('nohup ', '') + subprocess.Popen( + cmdtext, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + msg = await jdbot.edit_message(msg, '已在后台执行您的操作'+res.replace('nohup ', '')) + conv.cancel() + else: + await jdbot.delete_messages(chat_id, msg) + await cmd(res) + conv.cancel() + except exceptions.TimeoutError: + msg = await jdbot.edit_message(msg, '选择已超时,对话已停止') + except Exception as e: + await jdbot.edit_message(msg, 'something wrong,I\'m sorry\n'+str(e)) + logger.error('something wrong,I\'m sorry\n'+str(e)) + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern=r'^/b$')) +async def shortcut(event): + markup = [] + msg = await jdbot.send_message(chat_id, '正在查询您的常用命令,请稍后') + with open(_shortcut, 'r', encoding='utf-8') as f: + shortcuts = f.readlines() + try: + await jdbot.delete_messages(chat_id,msg) + markup = [Button.text(shortcut,single_use=True) for shortcut in shortcuts if '-->' not in shortcut] + markup = split_list(markup, 3) + await jdbot.send_message(chat_id, '请做出您的选择:', buttons=markup) + except Exception as e: + await jdbot.edit_message(msg, 'something wrong,I\'m sorry\n'+str(e)) + logger.error('something wrong,I\'m sorry\n'+str(e)) diff --git a/repo/dockerbot/jbot/bot/snode.py b/repo/dockerbot/jbot/bot/snode.py new file mode 100644 index 00000000..26ead770 --- /dev/null +++ b/repo/dockerbot/jbot/bot/snode.py @@ -0,0 +1,18 @@ +from telethon import events +from .. import jdbot, chat_id, _JdDir +from .utils import cmd, nodebtn + + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern=r'^/snode')) +async def mysnode(event): + '''定义supernode文件命令''' + SENDER = event.sender_id + path = _JdDir + page = 0 + filelist = None + async with jdbot.conversation(SENDER, timeout=60) as conv: + msg = await conv.send_message('正在查询,请稍后') + while path: + path, msg, page, filelist = await nodebtn(conv, SENDER, path, msg, page, filelist) + if filelist and filelist.startswith('CMD-->'): + await cmd(filelist.replace('CMD-->', '')) diff --git a/repo/dockerbot/jbot/bot/start.py b/repo/dockerbot/jbot/bot/start.py new file mode 100644 index 00000000..b7ebc3c6 --- /dev/null +++ b/repo/dockerbot/jbot/bot/start.py @@ -0,0 +1,21 @@ +from telethon import events +from .. import jdbot, chat_id + + +@jdbot.on(events.NewMessage(from_users=chat_id, pattern='/start')) +async def mystart(event): + '''接收/start命令后执行程序''' + msg = '''使用方法如下: + /help 获取命令,可直接发送至botfather + /a 使用你的自定义快捷按钮 + /start 开始使用本程序 + /node 执行js脚本文件,直接输入/node jd_bean_change 如执行其他自己js,需输入绝对路径。即可进行执行。该命令会等待脚本执行完,期间不能使用机器人,建议使用snode命令。 + /cmd 执行cmd命令,例如/cmd python3 /python/bot.py 则将执行python目录下的bot.py 不建议使用机器人使用并发,可能产生不明原因的崩溃 + /snode 命令可以选择脚本执行,只能选择/scripts 和/own目录下的脚本,选择完后直接后台运行,不影响机器人响应其他命令 + /log 选择查看执行日志 + /getfile 获取jd目录下文件 + /setshort 设置自定义按钮,每次设置会覆盖原设置 + /getcookie 扫码获取cookie 增加30s内取消按钮,30s后不能进行其他交互直到2分钟或获取到cookie + /edit 从jd目录下选择文件编辑,需要将编辑好信息全部发给机器人,机器人会根据你发的信息进行替换。建议用来编辑config或crontab.list 其他文件慎用!!! + 此外直接发送文件,会让您选择保存到哪个文件夹,如果选择运行,将保存至own目录下,并立即运行脚本,crontab.list文件会自动更新时间''' + await jdbot.send_message(chat_id, msg) diff --git a/repo/dockerbot/jbot/bot/update.py b/repo/dockerbot/jbot/bot/update.py new file mode 100644 index 00000000..64713022 --- /dev/null +++ b/repo/dockerbot/jbot/bot/update.py @@ -0,0 +1,10 @@ +version = 'version :0.3.5' +botlog = ''' +**2021年5月18日** +本次更新内容如下: +- 修改机器人断网重连 + - 默认断网自动重连 + - 如修改请在bot.json内添加括号内内容【```"noretry":true```】 + - 添加上述内容后,机器人断开连接重连5次,5次不能连接成功将自动结束,如需重新启用需通过终端运行```pm2 start jbot``` +- 修正bean与chart命令 账号不一致问题 +''' \ No newline at end of file diff --git a/repo/dockerbot/jbot/bot/utils.py b/repo/dockerbot/jbot/bot/utils.py new file mode 100644 index 00000000..dc0f2592 --- /dev/null +++ b/repo/dockerbot/jbot/bot/utils.py @@ -0,0 +1,258 @@ +import os +from telethon import events, Button +import re +from .. import jdbot, chat_id, _LogDir, logger, _JdDir, _OwnDir, _ConfigDir +import asyncio +import datetime + +bean_log = _LogDir + '/jd_bean_change/' +_ConfigFile = _ConfigDir+'/config.sh' +V4, QL = False, False +if 'JD_DIR' in os.environ.keys(): + V4 = True + _ConfigFile = _ConfigDir+'/config.sh' + _DiyDir = _OwnDir + jdcmd = 'jtask' +elif 'QL_DIR' in os.environ.keys(): + QL = True + _ConfigFile = _ConfigDir+'/cookie.sh' + _DiyDir = None + jdcmd = 'task' + dirs = os.listdir(_LogDir) + for mydir in dirs: + if 'jd_bean_change' in mydir: + bean_log = _LogDir + '/' + mydir + break +else: + _DiyDir = None + jdcmd = 'node' + +ckreg = re.compile(r'pt_key=\S*;pt_pin=\S*;') +with open(_ConfigFile, 'r', encoding='utf-8') as f: + lines = f.read() +cookies = ckreg.findall(lines) +for ck in cookies: + if ck == 'pt_key=xxxxxxxxxx;pt_pin=xxxx;': + cookies.remove(ck) + break + + +def split_list(datas, n, row: bool = True): + """一维列表转二维列表,根据N不同,生成不同级别的列表""" + length = len(datas) + size = length / n + 1 if length % n else length/n + _datas = [] + if not row: + size, n = n, size + for i in range(int(size)): + start = int(i * n) + end = int((i + 1) * n) + _datas.append(datas[start:end]) + return _datas + + +async def backfile(file): + '''如果文件存在,则备份,并更新''' + if os.path.exists(file): + try: + os.rename(file, file+'.bak') + except WindowsError: + os.remove(file+'.bak') + os.rename(file, file+'.bak') + + +def press_event(user_id): + return events.CallbackQuery(func=lambda e: e.sender_id == user_id) + + +async def cmd(cmdtext): + '''定义执行cmd命令''' + try: + msg = await jdbot.send_message(chat_id, '开始执行命令') + p = await asyncio.create_subprocess_shell( + cmdtext, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + res_bytes, res_err = await p.communicate() + res = res_bytes.decode('utf-8') + if len(res) == 0: + await jdbot.edit_message(msg, '已执行,但返回值为空') + elif len(res) <= 4000: + await jdbot.delete_messages(chat_id, msg) + await jdbot.send_message(chat_id, res) + elif len(res) > 4000: + _log = _LogDir + '/bot/'+cmdtext.split('/')[-1].split( + '.js')[0]+datetime.datetime.now().strftime('%H-%M-%S')+'.log' + with open(_log, 'w+', encoding='utf-8') as f: + f.write(res) + await jdbot.delete_messages(chat_id, msg) + await jdbot.send_message(chat_id, '执行结果较长,请查看日志', file=_log) + os.remove(_log) + except Exception as e: + await jdbot.send_message(chat_id, 'something wrong,I\'m sorry\n'+str(e)) + logger.error('something wrong,I\'m sorry'+str(e)) + + +async def getname(path, dir): + '''获取文件中文名称,如无则返回文件名''' + names = [] + reg = r'new Env\(\'[\S]+?\'\)' + cname = False + for file in dir: + if os.path.isdir(path+'/'+file): + names.append(file) + elif file.endswith('.js') and file != 'jdCookie.js' and file != 'getJDCookie.js' and file != 'JD_extra_cookie.js' and 'ShareCode' not in file: + with open(path+'/'+file, 'r', encoding='utf-8') as f: + resdatas = f.readlines() + for data in resdatas: + if 'new Env' in data: + data = data.replace('\"', '\'') + res = re.findall(reg, data) + if len(res) != 0: + res = res[0].split('\'')[-2] + names.append(res+'--->'+file) + cname = True + break + if not cname: + names.append(file+'--->'+file) + cname = False + else: + continue + return names + + +async def logbtn(conv, SENDER, path, msg, page, filelist): + '''定义log日志按钮''' + mybtn = [Button.inline('上一页', data='up'), Button.inline( + '下一页', data='next'), Button.inline('上级', data='updir'), Button.inline('取消', data='cancel')] + try: + if filelist: + markup = filelist + newmarkup = markup[page] + if mybtn not in newmarkup: + newmarkup.append(mybtn) + else: + dir = os.listdir(path) + dir.sort() + markup = [Button.inline(file, data=str(file)) + for file in dir] + markup = split_list(markup, 3) + if len(markup) > 30: + markup = split_list(markup, 30) + newmarkup = markup[page] + newmarkup.append(mybtn) + else: + newmarkup = markup + if path == _JdDir: + newmarkup.append([Button.inline('取消', data='cancel')]) + else: + newmarkup.append( + [Button.inline('上级', data='updir'), Button.inline('取消', data='cancel')]) + msg = await jdbot.edit_message(msg, '请做出您的选择:', buttons=newmarkup) + convdata = await conv.wait_event(press_event(SENDER)) + res = bytes.decode(convdata.data) + if res == 'cancel': + msg = await jdbot.edit_message(msg, '对话已取消') + conv.cancel() + return None, None, None, None + elif res == 'next': + page = page + 1 + if page > len(markup) - 1: + page = 0 + return path, msg, page, markup + elif res == 'up': + page = page - 1 + if page < 0: + page = len(markup) - 1 + return path, msg, page, markup + elif res == 'updir': + path = '/'.join(path.split('/')[:-1]) + logger.info(path) + if path == '': + path = _JdDir + return path, msg, page, None + elif os.path.isfile(path+'/'+res): + msg = await jdbot.edit_message(msg, '文件发送中,请注意查收') + await conv.send_file(path+'/'+res) + msg = await jdbot.edit_message(msg, res+'发送成功,请查收') + conv.cancel() + return None, None, None, None + else: + return path+'/'+res, msg, page, None + except asyncio.exceptions.TimeoutError: + msg = await jdbot.edit_message(msg, '选择已超时,本次对话已停止') + return None, None, None, None + except Exception as e: + msg = await jdbot.edit_message(msg, 'something wrong,I\'m sorry\n'+str(e)) + logger.error('something wrong,I\'m sorry\n'+str(e)) + return None, None, None, None + + +async def nodebtn(conv, SENDER, path, msg, page, filelist): + '''定义scripts脚本按钮''' + mybtn = [Button.inline('上一页', data='up'), Button.inline( + '下一页', data='next'), Button.inline('上级', data='updir'), Button.inline('取消', data='cancel')] + try: + if filelist: + markup = filelist + newmarkup = markup[page] + if mybtn not in newmarkup: + newmarkup.append(mybtn) + else: + if path == _JdDir and V4: + dir = ['scripts', _OwnDir.split('/')[-1]] + elif path == _JdDir and QL: + dir = ['scripts'] + else: + dir = os.listdir(path) + dir = await getname(path, dir) + dir.sort() + markup = [Button.inline(file.split('--->')[0], data=str(file.split('--->')[-1])) + for file in dir if os.path.isdir(path+'/'+file) or file.endswith('.js')] + markup = split_list(markup, 3) + if len(markup) > 30: + markup = split_list(markup, 30) + newmarkup = markup[page] + newmarkup.append(mybtn) + else: + newmarkup = markup + if path == _JdDir: + newmarkup.append([Button.inline('取消', data='cancel')]) + else: + newmarkup.append( + [Button.inline('上级', data='updir'), Button.inline('取消', data='cancel')]) + msg = await jdbot.edit_message(msg, '请做出您的选择:', buttons=newmarkup) + convdata = await conv.wait_event(press_event(SENDER)) + res = bytes.decode(convdata.data) + if res == 'cancel': + msg = await jdbot.edit_message(msg, '对话已取消') + conv.cancel() + return None, None, None, None + elif res == 'next': + page = page + 1 + if page > len(markup) - 1: + page = 0 + return path, msg, page, markup + elif res == 'up': + page = page - 1 + if page < 0: + page = len(markup) - 1 + return path, msg, page, markup + elif res == 'updir': + path = '/'.join(path.split('/')[:-1]) + if path == '': + path = _JdDir + return path, msg, page, None + elif os.path.isfile(path+'/'+res): + conv.cancel() + logger.info(path+'/'+res+'脚本即将在后台运行') + msg = await jdbot.edit_message(msg, res + '在后台运行成功') + cmdtext = '{} {}/{} now'.format(jdcmd, path, res) + return None, None, None, 'CMD-->'+cmdtext + else: + return path+'/'+res, msg, page, None + except asyncio.exceptions.TimeoutError: + msg = await jdbot.edit_message(msg, '选择已超时,对话已停止') + return None, None, None, None + except Exception as e: + msg = await jdbot.edit_message(msg, 'something wrong,I\'m sorry\n'+str(e)) + logger.error('something wrong,I\'m sorry\n'+str(e)) + return None, None, None, None diff --git a/repo/dockerbot/jbot/diy/example.py b/repo/dockerbot/jbot/diy/example.py new file mode 100644 index 00000000..e9cafc1a --- /dev/null +++ b/repo/dockerbot/jbot/diy/example.py @@ -0,0 +1,10 @@ +#引入库文件,基于telethon +from telethon import events +#从上级目录引入 jdbot,chat_id变量 +from .. import jdbot,chat_id +#格式基本固定,本例子表示从chat_id处接收到包含hello消息后,要做的事情 +@jdbot.on(events.NewMessage(chats=chat_id,pattern=('hello'))) +#定义自己的函数名称 +async def hi(event): + #do something + await jdbot.send_message(chat_id,'hello') \ No newline at end of file diff --git a/repo/dockerbot/jbot/ecosystem.config.js b/repo/dockerbot/jbot/ecosystem.config.js new file mode 100644 index 00000000..4ca9565a --- /dev/null +++ b/repo/dockerbot/jbot/ecosystem.config.js @@ -0,0 +1,22 @@ +module.exports = { + apps: [{ + name: "jbot", + version: "0.3.5", + cwd: "..", + script: "python", + args: "-m jbot", + autorestart: true, + watch: ["jbot"], + ignore_watch: [ + "jbot/__pycache__/*", + "jbot/bot/__pycache__/*", + "jbot/diy/__pycache__/*", + "jbot/*.log", + "jbot/*/*.log", + "jbot/requirements.txt", + "jbot/ecosystem.config.js" + ], + watch_delay: 15000, + interpreter: "" + }] +} \ No newline at end of file diff --git a/repo/dockerbot/jbot/font/jet.ttf b/repo/dockerbot/jbot/font/jet.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0cd1cb66bd193f2b178d0a69a7b0658d76b3a670 GIT binary patch literal 173264 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%0Abi#}=?x9#AzJ05!8Z#!udP+ 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 OwHaMwcmReuwf+ZCw$sx9 literal 0 HcmV?d00001 diff --git a/repo/dockerbot/jbot/requirements.txt b/repo/dockerbot/jbot/requirements.txt new file mode 100644 index 00000000..ba13f3d1 --- /dev/null +++ b/repo/dockerbot/jbot/requirements.txt @@ -0,0 +1,7 @@ +qrcode==6.1 +Telethon==1.21.1 +requests==2.25.1 +Pillow==8.1.2 +python-socks==1.2.4 +async_timeout==3.0.1 +prettytable>=2.1.0 \ No newline at end of file diff --git a/repo/dockerbot/jbot/utils.py b/repo/dockerbot/jbot/utils.py new file mode 100644 index 00000000..ed2d2843 --- /dev/null +++ b/repo/dockerbot/jbot/utils.py @@ -0,0 +1,22 @@ +import sys +import importlib +import os +from . import logger + + +def load_diy(module, path): + files = os.listdir(path) + for file in files: + try: + if file.endswith('.py'): + filename = file.replace('.py', '') + name = "jbot.{}.{}".format(module, filename) + spec = importlib.util.spec_from_file_location(name, path+file) + load = importlib.util.module_from_spec(spec) + spec.loader.exec_module(load) + sys.modules[f"jbot.{module}.{filename}"] = load + logger.info("JBot加载 " + filename+" 完成") + except Exception as e: + logger.info("JBot加载失败"+str(e)) + continue +