mirror of
https://github.com/whyour/qinglong.git
synced 2025-07-30 08:26:08 +08:00
add ql bot 所需文件
This commit is contained in:
parent
d14ca52666
commit
9910b93eea
56
repo/dockerbot/jbot/__init__.py
Normal file
56
repo/dockerbot/jbot/__init__.py
Normal file
|
@ -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)
|
38
repo/dockerbot/jbot/__main__.py
Normal file
38
repo/dockerbot/jbot/__main__.py
Normal file
|
@ -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()
|
84
repo/dockerbot/jbot/bot/bean.py
Normal file
84
repo/dockerbot/jbot/bot/bean.py
Normal file
|
@ -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)
|
114
repo/dockerbot/jbot/bot/beandata.py
Normal file
114
repo/dockerbot/jbot/bot/beandata.py
Normal file
|
@ -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]
|
134
repo/dockerbot/jbot/bot/chart.py
Normal file
134
repo/dockerbot/jbot/bot/chart.py
Normal file
|
@ -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)
|
26
repo/dockerbot/jbot/bot/cmd.py
Normal file
26
repo/dockerbot/jbot/bot/cmd.py
Normal file
|
@ -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命令,如需使用请修改配置文件')
|
137
repo/dockerbot/jbot/bot/editfile.py
Normal file
137
repo/dockerbot/jbot/bot/editfile.py
Normal file
|
@ -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
|
176
repo/dockerbot/jbot/bot/getcookie.py
Normal file
176
repo/dockerbot/jbot/bot/getcookie.py
Normal file
|
@ -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))
|
62
repo/dockerbot/jbot/bot/getfile.py
Normal file
62
repo/dockerbot/jbot/bot/getfile.py
Normal file
|
@ -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))
|
35
repo/dockerbot/jbot/bot/help.py
Normal file
35
repo/dockerbot/jbot/bot/help.py
Normal file
|
@ -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])
|
19
repo/dockerbot/jbot/bot/node.py
Normal file
19
repo/dockerbot/jbot/bot/node.py
Normal file
|
@ -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 ', '')))
|
110
repo/dockerbot/jbot/bot/quickchart.py
Normal file
110
repo/dockerbot/jbot/bot/quickchart.py
Normal file
|
@ -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)
|
43
repo/dockerbot/jbot/bot/sendfile.py
Normal file
43
repo/dockerbot/jbot/bot/sendfile.py
Normal file
|
@ -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)
|
15
repo/dockerbot/jbot/bot/setshort.py
Normal file
15
repo/dockerbot/jbot/bot/setshort.py
Normal file
|
@ -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()
|
57
repo/dockerbot/jbot/bot/short.py
Normal file
57
repo/dockerbot/jbot/bot/short.py
Normal file
|
@ -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))
|
18
repo/dockerbot/jbot/bot/snode.py
Normal file
18
repo/dockerbot/jbot/bot/snode.py
Normal file
|
@ -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-->', ''))
|
21
repo/dockerbot/jbot/bot/start.py
Normal file
21
repo/dockerbot/jbot/bot/start.py
Normal file
|
@ -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)
|
10
repo/dockerbot/jbot/bot/update.py
Normal file
10
repo/dockerbot/jbot/bot/update.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
version = 'version :0.3.5'
|
||||||
|
botlog = '''
|
||||||
|
**2021年5月18日**
|
||||||
|
本次更新内容如下:
|
||||||
|
- 修改机器人断网重连
|
||||||
|
- 默认断网自动重连
|
||||||
|
- 如修改请在bot.json内添加括号内内容【```"noretry":true```】
|
||||||
|
- 添加上述内容后,机器人断开连接重连5次,5次不能连接成功将自动结束,如需重新启用需通过终端运行```pm2 start jbot```
|
||||||
|
- 修正bean与chart命令 账号不一致问题
|
||||||
|
'''
|
258
repo/dockerbot/jbot/bot/utils.py
Normal file
258
repo/dockerbot/jbot/bot/utils.py
Normal file
|
@ -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
|
10
repo/dockerbot/jbot/diy/example.py
Normal file
10
repo/dockerbot/jbot/diy/example.py
Normal file
|
@ -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')
|
22
repo/dockerbot/jbot/ecosystem.config.js
Normal file
22
repo/dockerbot/jbot/ecosystem.config.js
Normal file
|
@ -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: ""
|
||||||
|
}]
|
||||||
|
}
|
BIN
repo/dockerbot/jbot/font/jet.ttf
Normal file
BIN
repo/dockerbot/jbot/font/jet.ttf
Normal file
Binary file not shown.
7
repo/dockerbot/jbot/requirements.txt
Normal file
7
repo/dockerbot/jbot/requirements.txt
Normal file
|
@ -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
|
22
repo/dockerbot/jbot/utils.py
Normal file
22
repo/dockerbot/jbot/utils.py
Normal file
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user