646 lines
24 KiB
Python
646 lines
24 KiB
Python
# [author: authook]
|
||
# [title: jd_账密登陆]
|
||
# [create_at: 2023-09-19 15:29:17]
|
||
# [version: 2.3]
|
||
# [pin: true]
|
||
# [price: 0]
|
||
# [rule: ^账密登录$]
|
||
# [rule: ^账密登陆$]
|
||
# [rule: ^账密刷新$]
|
||
# [rule: ^账密强制刷新$]
|
||
# [rule: ^账密管理$]
|
||
# [priority: 6666666]优先级
|
||
# [admin: false]
|
||
# [service: authook]
|
||
# [icon: https://bbs.autman.cn/assets/files/2024-05-16/1715842374-826456-2584e965be6ed12773865dbb8e29a449.png]
|
||
# [description: jd_账密登陆插件 兼容兔子,pro等框架</br>指令:账密登录,账密登录,账密管理 </br> 配置:在插件配参中配置,</br>权限:需开启qls,jdNotify权限</br>注意⚠️账密刷新请勿手动发送,否则会将ck绑定至管理员账号上!!!(插件已自动内置定时刷新账密)]
|
||
|
||
# [param: {"required":true,"key":"jd.rabbit_host","placeholder":"http://192.168.1.1:81","name":"【rabbit】登陆地址:","desc":"登陆地址,例:http://192.168.3.22"}]
|
||
# [param: {"required":true,"key":"jd.pro_host","placeholder":"http://192.168.1.1:81","name":"【pro】登陆地址:","desc":"pro登陆地址"}]
|
||
# [param: {"required":true,"key":"jd.login_ql_name","placeholder":"ql容器名称","name":"【ql】容器名称","desc":"ql容器名称"}]
|
||
# [param: {"required":true,"key":"jd.login_type","placeholder":"登陆框架","name":"登陆框架","desc":"pro框架请输入pro rabbit兔子框架请输入rabbit"}]
|
||
|
||
# =======================
|
||
# 项目:jd_账密登陆.py
|
||
# 构建时间:2025-02-10 20:52:29
|
||
import datetime
|
||
from email import message
|
||
import json
|
||
import logging
|
||
import math
|
||
import os
|
||
import random
|
||
import re
|
||
import time
|
||
import traceback
|
||
import inspect
|
||
from base64 import b64encode
|
||
from urllib.parse import quote, urlparse
|
||
|
||
import colorlog
|
||
import middleware
|
||
import requests
|
||
from Crypto.Cipher import AES
|
||
from Crypto.Util.Padding import pad
|
||
|
||
|
||
class TOOL:
|
||
def __init__(self):
|
||
self.plugin_pre = "rabbit_zm"
|
||
self.remark = ""
|
||
self.platform_arr = self.platformArr()
|
||
# 将日期和时间格式化为字符串
|
||
self.cut_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||
self.logger = logging.getLogger()
|
||
self.color_formatter = colorlog.ColoredFormatter(
|
||
'%(log_color)s%(levelname)s: %(message)s',
|
||
log_colors={
|
||
'DEBUG': 'cyan',
|
||
'INFO': 'green',
|
||
'WARNING': 'yellow',
|
||
'ERROR': 'red',
|
||
'CRITICAL': 'red,bg_white',
|
||
}
|
||
)
|
||
self.logger = self._configure_logger()
|
||
|
||
def _configure_logger(self):
|
||
"""配置并返回一个带颜色的 logger 对象"""
|
||
logger = logging.getLogger(self.plugin_pre)
|
||
logger.setLevel(logging.DEBUG) # 设置日志默认最低级别
|
||
|
||
# 检查是否已添加过控制台处理器,避免重复添加
|
||
if not any(isinstance(handler, logging.StreamHandler) for handler in logger.handlers):
|
||
console_handler = logging.StreamHandler()
|
||
console_handler.setLevel(logging.DEBUG) # 控制台日志最低级别
|
||
console_handler.setFormatter(self.color_formatter)
|
||
logger.addHandler(console_handler)
|
||
|
||
return logger
|
||
|
||
def log(self, level, message):
|
||
"""通用日志方法"""
|
||
if level == logging.INFO:
|
||
self.logger.info(message)
|
||
elif level == logging.ERROR:
|
||
self.logger.error(message)
|
||
elif level == logging.WARNING:
|
||
self.logger.warning(message)
|
||
elif level == logging.DEBUG:
|
||
self.logger.debug(message)
|
||
elif level == logging.CRITICAL:
|
||
self.logger.critical(message)
|
||
|
||
def log_info(self, message):
|
||
self.log(logging.INFO, message)
|
||
|
||
def log_err(self, message):
|
||
self.log(logging.ERROR, message)
|
||
|
||
def log_warn(self, message):
|
||
self.log(logging.WARNING, message)
|
||
|
||
def platformArr(self):
|
||
plat_arr = []
|
||
for p in ["qq", "wx", "wb", "qb", "bt", "tg"]:
|
||
t = {"platform": f"{p}", "imType": p}
|
||
plat_arr.append(t)
|
||
return plat_arr
|
||
|
||
def pushMsg(self, userId, chatId, imType, title, content):
|
||
# 获取当前日期和时间
|
||
now = datetime.datetime.now()
|
||
# 将日期和时间格式化为字符串
|
||
formatted_datetime = now.strftime('%Y-%m-%d %H:%M:%S')
|
||
self.remark = ""
|
||
return middleware.push(imType, chatId, userId, title, f"{formatted_datetime}\n{content}")
|
||
|
||
def pushGroup(self, imtype, groupCode, content):
|
||
self.pushMsg(0, groupCode, imtype, "", content)
|
||
|
||
def autman_host(self):
|
||
file_path = inspect.getframeinfo(inspect.currentframe()).filename
|
||
dir_path = os.path.dirname(os.path.abspath(file_path))
|
||
setConfPath = dir_path.split("develop/scripts")[0] + "/middleware.py"
|
||
try:
|
||
os.setuid(0) # 强制转为root 前提是autman账户以root用户启用
|
||
with open(setConfPath, "r", encoding="utf-8") as f:
|
||
data = f.read()
|
||
lines = data.splitlines()
|
||
for line in lines:
|
||
if "url =" in line:
|
||
res = line.split('"')
|
||
url = res[1][0:-5]
|
||
self.log_info(url)
|
||
return url
|
||
except Exception as e:
|
||
self.log_info(f"❌autman_host error {e}")
|
||
|
||
def replyMsg(self, content):
|
||
return sender.reply(content)
|
||
|
||
def pushMaster(self, content):
|
||
arr = ["qq", "wx", "tg", "qb", 'wb']
|
||
for p in arr:
|
||
masters = sender.bucketGet(p, "masters")
|
||
if masters:
|
||
masters_arr = masters.split(",") if "," in masters else masters.split("&")
|
||
for m in masters_arr:
|
||
middleware.push(p, "", m, "", content)
|
||
|
||
def qls(self):
|
||
qls = []
|
||
ql_id_arr = sender.bucketAllKeys("qls")
|
||
if not ql_id_arr:
|
||
return []
|
||
for ql_id in ql_id_arr:
|
||
value = sender.bucketGet("qls", ql_id)
|
||
if value:
|
||
qls.append(json.loads(value))
|
||
return qls
|
||
|
||
def autman_host(self):
|
||
file_path = inspect.getframeinfo(inspect.currentframe()).filename
|
||
dir_path = os.path.dirname(os.path.abspath(file_path))
|
||
setConfPath = dir_path.split("develop/scripts")[0] + "/middleware.py"
|
||
try:
|
||
os.setuid(0) # 强制转为root 前提是autman账户以root用户启用
|
||
with open(setConfPath, "r", encoding="utf-8") as f:
|
||
data = f.read()
|
||
lines = data.splitlines()
|
||
for line in lines:
|
||
if "url =" in line:
|
||
res = line.split('"')
|
||
url = res[1][0:-5]
|
||
self.log_info(url)
|
||
return url
|
||
except Exception as e:
|
||
self.log_info(f"❌autman_host error {e}")
|
||
|
||
|
||
class QL:
|
||
def __init__(self, ql):
|
||
self.host = ql["host"]
|
||
self.client_id = ql["client_id"]
|
||
self.client_secret = ql["client_secret"]
|
||
self.token = self.get_token()
|
||
self.name = ql['name']
|
||
self.content = ""
|
||
self.version = self.system()
|
||
|
||
def gettimestamp(self):
|
||
return str(int(time.time() * 1000))
|
||
|
||
def get_token(self):
|
||
url = f"{self.host}/open/auth/token?client_id={self.client_id}&client_secret={self.client_secret}"
|
||
print(url)
|
||
headers = {
|
||
'Content-Type': 'application/json',
|
||
'Accept': '*/*',
|
||
'Cache-Control': 'no-cache',
|
||
'Host': "",
|
||
'Connection': 'keep-alive'
|
||
}
|
||
host = urlparse(url).netloc
|
||
if ":" in host:
|
||
host = host.split(":")[0]
|
||
headers['Host'] = host
|
||
try:
|
||
response = requests.get(url, timeout=10, headers=headers)
|
||
res = response.json()
|
||
if response.status_code == 200 and res["code"] == 200:
|
||
return res["data"]["token"]
|
||
else:
|
||
return None
|
||
except Exception as e:
|
||
return None
|
||
|
||
def Api(self, api, apd, method, payload):
|
||
url = f"{self.host}/open/{api}/{apd}"
|
||
headers = {
|
||
"Content-Type": "application/json;charset=UTF-8",
|
||
"Authorization": f"Bearer {self.token}",
|
||
}
|
||
try:
|
||
response = requests.request(method, url, headers=headers, data=payload, timeout=5)
|
||
return response.json()
|
||
except Exception as e:
|
||
return None
|
||
|
||
# 环境变量
|
||
def envGet(self, keyword):
|
||
return self.Api('envs', f"?searchValue={keyword}&t={self.gettimestamp()}", 'GET', {})
|
||
|
||
def envSet(self, env):
|
||
return self.Api('envs', f"?t={self.gettimestamp()}", 'POST', env)
|
||
|
||
def envUpdate(self, env):
|
||
return self.Api('envs', f"?t={self.gettimestamp()}", 'PUT', env)
|
||
|
||
def envEnable(self, ids):
|
||
return self.Api('envs', f"/enable?t={self.gettimestamp()}", 'PUT', json.dumps(ids))
|
||
|
||
def envDisable(self, ids):
|
||
return self.Api('envs', f"/disable?t={self.gettimestamp()}", 'PUT', json.dumps(ids))
|
||
|
||
def envDel(self, ids):
|
||
return self.Api('envs', f"?t={self.gettimestamp()}", 'delete', json.dumps(ids))
|
||
|
||
def envMove(self, id, data):
|
||
return self.Api('envs', f"/{id}/move?t={self.gettimestamp()}", 'PUT', json.dumps(data))
|
||
|
||
# 定时任务
|
||
def cronGet(self, keyword):
|
||
return self.Api('crons', f"?searchValue={keyword}&t={self.gettimestamp()}", 'GET', None)
|
||
|
||
def cronRun(self, ids):
|
||
return self.Api('crons', f"run?t={self.gettimestamp()}", 'PUT', ids)
|
||
|
||
def cronStop(self, ids):
|
||
return self.Api('crons', f"stop?t={self.gettimestamp()}", 'PUT', ids)
|
||
|
||
def cronEnable(self, ids):
|
||
return self.Api('crons', f"enable?t={self.gettimestamp()}", 'PUT', ids)
|
||
|
||
def cronDisable(self, ids):
|
||
return self.Api('crons', f"disable?t={self.gettimestamp()}", 'PUT', ids)
|
||
|
||
def cronDetail(self, cronId):
|
||
return self.Api('crons', f"{cronId}?t={self.gettimestamp()}", 'GET', None)
|
||
|
||
def cronLogs(self, cronId):
|
||
return self.Api('crons', f"{cronId}/log?t={self.gettimestamp()}", 'GET', None)
|
||
|
||
def cronLog(self, cronId):
|
||
return self.Api('crons', f"{cronId}/log?t={self.gettimestamp()}", 'GET', None)
|
||
|
||
# 配置文件
|
||
def configsGet(self, name):
|
||
if self.version < "2.17":
|
||
return self.Api('configs', f"{name}?t={self.gettimestamp()}", 'GET', None)
|
||
else:
|
||
return self.Api('configs/detail', f"?path={name}&t={self.gettimestamp()}", 'GET', None)
|
||
|
||
def configsSet(self, data):
|
||
return self.Api('configs', f"save?t={self.gettimestamp()}", 'POST', data)
|
||
|
||
# 订阅任务
|
||
def subsGet(self, keyword):
|
||
return self.Api('subscriptions', f"?searchValue={keyword}&t={self.gettimestamp()}", 'GET', None)
|
||
|
||
def subsSet(self, data):
|
||
return self.Api('subscriptions', f"save?t={self.gettimestamp()}", 'PUT', data)
|
||
|
||
def subsRun(self, ids):
|
||
return self.Api('subscriptions', f"run?t={self.gettimestamp()}", 'PUT', ids)
|
||
|
||
def subsEnable(self, ids):
|
||
return self.Api('subscriptions', f"enable?t={self.gettimestamp()}", 'PUT', ids)
|
||
|
||
def subsDisable(self, ids):
|
||
return self.Api('subscriptions', f"disable?t={self.gettimestamp()}", 'PUT', ids)
|
||
|
||
def subsLog(self, subId):
|
||
return self.Api('subscriptions', f"{subId}/log?t={self.gettimestamp()}", 'GET', None)
|
||
|
||
def system(self):
|
||
url = f"{self.host}/open/system?t={self.gettimestamp()}"
|
||
headers = {
|
||
"Content-Type": "application/json;charset=UTF-8",
|
||
}
|
||
try:
|
||
res = requests.get(url)
|
||
if res.status_code == 200:
|
||
rj = res.json()
|
||
return rj['data']['version']
|
||
except Exception as e:
|
||
return 2.16
|
||
|
||
|
||
class ZM_RABBIT():
|
||
def __init__(self):
|
||
self.pins = self.get_pins()
|
||
self.conf = self.get_conf()
|
||
self.init()
|
||
self.s = requests.session()
|
||
pass
|
||
|
||
def hide_phone(self, text):
|
||
if not text:
|
||
return text
|
||
if len(text) != 11:
|
||
return text
|
||
return re.sub(r'(\d{3})\d{4}(\d{4})', r'\1****\2', text)
|
||
|
||
def check_ck_status(self, ck):
|
||
headers = {
|
||
"Cookie": ck,
|
||
"referer": "https://h5.m.jd.com/",
|
||
"User-Agent": "jdapp;iPhone;10.1.2;15.0;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
|
||
}
|
||
|
||
response = requests.get('https://plogin.m.jd.com/cgi-bin/ml/islogin', headers=headers)
|
||
data = response.json()
|
||
return data['islogin'] == "1" if 'islogin' in data else False
|
||
|
||
def en_pwd(self, pwd):
|
||
key = b"wn:_/imCQF;rBNS{V=|kML[(+$%Tjgy)"
|
||
iv = b"zA#f.x>jN!h-0[{$"
|
||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||
encrypted = cipher.encrypt(pad(pwd.encode(), AES.block_size))
|
||
return b64encode(encrypted).decode()
|
||
|
||
def get_conf(self):
|
||
self.conf = {
|
||
"paid": "n",
|
||
"fee": 0,
|
||
"qr_code": "",
|
||
"host": "",
|
||
"ql_name": None
|
||
}
|
||
if middleware.bucketGet("otto", "rabbit_pro_paid"):
|
||
self.conf["paid"] = middleware.bucketGet("otto", "rabbit_pro_paid")
|
||
if middleware.bucketGet("otto", "rabbit_pro_fee"):
|
||
self.conf['fee'] = middleware.bucketGet("otto", "rabbit_pro_fee")
|
||
if middleware.bucketGet("otto", "rabbit_pro_qr_code"):
|
||
self.conf['qr_code'] = middleware.bucketGet("otto", "rabbit_pro_qr_code")
|
||
if not middleware.bucketGet("otto", "rabbit_pro_host"):
|
||
tool.pushMaster("未配置rabbit登录地址,请先去【配参】配置")
|
||
exit()
|
||
self.conf['host'] = middleware.bucketGet("otto", "rabbit_pro_host")
|
||
if not middleware.bucketGet("otto", "rabbit_ql_name"):
|
||
tool.pushMaster("未配置rabbit登陆容器名称,请先去【配参】配置")
|
||
exit()
|
||
self.conf['ql_name'] = middleware.bucketGet("otto", "rabbit_ql_name")
|
||
return self.conf
|
||
|
||
def init(self):
|
||
res = requests.get(self.conf['host'] + "/api/Config")
|
||
tool.log_info(res.text)
|
||
if res.status_code == 200:
|
||
rj = res.json()
|
||
if rj['success']:
|
||
self.conf['container_id'] = rj['data']['list'][0]['container_id']
|
||
self.conf['container_name'] = rj['data']['list'][0]['container_name']
|
||
self.conf['autocount'] = rj['data']['autocount']
|
||
return self.conf
|
||
tool.replyMsg(rj['message'] + ",请完善rabbitPro配置")
|
||
exit()
|
||
|
||
def get_pins(self):
|
||
return sender.bucketKeys("pin" + imType.upper(), userId)
|
||
|
||
def account_list(self):
|
||
acc_list = []
|
||
acc_key = set()
|
||
if self.pins and len(self.pins) > 0:
|
||
for pin in self.pins:
|
||
acc_str = sender.bucketGet("", pin)
|
||
if acc_str:
|
||
acc = {
|
||
"username": acc_str.split("#")[0],
|
||
"pwd": acc_str.split("#")[1],
|
||
"ck": acc_str.split("#")[2],
|
||
}
|
||
if acc_str.split("#")[0] not in acc_key:
|
||
acc_list.append(acc)
|
||
acc_key.add(acc_str.split("#")[0])
|
||
|
||
return acc_list
|
||
|
||
def login_init(self, mobile):
|
||
headers = {
|
||
"Content-Type": "application/json",
|
||
"User_Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1"
|
||
}
|
||
data = {"account": mobile, "container_id": self.conf['container_id']}
|
||
url = self.conf['host'] + "/pwd/init"
|
||
res = self.s.post(url, headers=headers, data=json.dumps(data))
|
||
tool.log_info(f"{mobile}: login_init res {res.text}")
|
||
if res.status_code == 200:
|
||
rj = res.json()
|
||
if not rj['success']:
|
||
tool.replyMsg(f"[{self.hide_phone(mobile)}]登陆初始化失败:{rj['message']}")
|
||
return
|
||
if rj['data']['status'] == 505:
|
||
return True
|
||
else:
|
||
tool.replyMsg(f"f{rj['message']}")
|
||
return False
|
||
|
||
pass
|
||
|
||
def login(self, mobile, pwd):
|
||
headers = {
|
||
"Content-Type": "application/json",
|
||
"User_Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1"
|
||
}
|
||
data = {"account": mobile, "pwd": self.en_pwd(pwd), "container_id": self.conf['container_id']}
|
||
res = self.s.post(f"{self.conf['host']}/pwd/login", headers=headers, data=json.dumps(data))
|
||
tool.log_info(f"{mobile}: login res {res.text}")
|
||
if res.status_code == 200:
|
||
rj = res.json()
|
||
if rj['code'] == 601:
|
||
tool.replyMsg(f"[{self.hide_phone(mobile)}]账号需要点击验证之后,重新登陆\n{rj['RiskUrl']}")
|
||
return False, None
|
||
if rj['code'] == 200:
|
||
tool.replyMsg(f"【登陆账户】:{self.hide_phone(mobile)}\n【JD账户】:{rj['pin']}\n【登陆结果】:{rj['message']}")
|
||
value_json = {
|
||
"mobile": mobile,
|
||
"pwd": pwd
|
||
}
|
||
sender.bucketSet("rabbit_zm_acc", rj['pin'], json.dumps(value_json))
|
||
return True, rj['pin']
|
||
elif rj['code'] == 503:
|
||
tool.replyMsg(f"[{self.hide_phone(mobile)}]{rj['message']}")
|
||
return False, None
|
||
elif rj['code'] == 555:
|
||
# 需要验证
|
||
riskUrl = rj['RiskUrl']
|
||
tool.replyMsg(f"[{self.hide_phone(mobile)}]请手动点击验证链接,然后再次返回登陆:{riskUrl}")
|
||
return False, None
|
||
else:
|
||
tool.replyMsg(f"[{self.hide_phone(mobile)}]登陆异常:{rj['message']}")
|
||
return False, None
|
||
|
||
def after_login(self, pin):
|
||
time.sleep(random.randint(3,5))
|
||
sender.bucketSet('pin' + imType.upper(), pin, userId)
|
||
qls = tool.qls()
|
||
if not qls or len(qls) == 0:
|
||
tool.pushMaster("未配置青龙容器,无法同步更新容器ck")
|
||
exit()
|
||
default_ql = list(filter(lambda item: self.conf['ql_name'] in item['name'],qls))
|
||
if not default_ql:
|
||
tool.pushMaster(f"容器【{self.conf['ql_name']}】,不存在,请重新配置")
|
||
return
|
||
tql = QL(default_ql[0])
|
||
if not tql.token:
|
||
return
|
||
res = tql.envGet("JD_COOKIE")
|
||
if res['code'] != 200 or len(res['data']) == 0:
|
||
return
|
||
if len(res['data']) <= 0:
|
||
return
|
||
cookie = list(filter(lambda item: pin in item['value'], res['data']))
|
||
if not cookie:
|
||
return
|
||
if cookie[0]['status'] == 1:
|
||
return
|
||
if not self.check_ck_status(cookie[0]['value']):
|
||
return
|
||
ck = cookie[0]['value']
|
||
pt_key = re.findall(r"pt_key=(.*?);", ck)[0]
|
||
val = {
|
||
"ID": pin,
|
||
"Pet": False,
|
||
"Fruit": False,
|
||
"DreamFactory": False,
|
||
"Note": "",
|
||
"PtKey": pt_key,
|
||
"AssetCron": "",
|
||
"PushPlus": "",
|
||
"LoginedAt": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
|
||
"ClientID": tql.client_id
|
||
}
|
||
sender.bucketSet('jdNotify', pin, json.dumps(val))
|
||
|
||
for ql in qls:
|
||
if self.conf['ql_name'] in ql['name']:
|
||
continue
|
||
tql = QL(ql)
|
||
if not tql.token:
|
||
continue
|
||
res = tql.envGet("JD_COOKIE")
|
||
if res['code'] != 200 or len(res['data']) == 0:
|
||
continue
|
||
if len(res['data']) <= 0:
|
||
continue
|
||
cookie = list(filter(lambda item: pin in item['value'], res['data']))
|
||
if not cookie:
|
||
continue
|
||
ck = cookie[0]['value']
|
||
id = cookie[0].get('id', cookie[0].get("_id"))
|
||
remarks = cookie[0].get('remarks', pin)
|
||
if ck:
|
||
updateEnv = {
|
||
"name": "JD_COOKIE",
|
||
"value": ck,
|
||
"remarks": remarks,
|
||
"id": id,
|
||
}
|
||
res = tql.envUpdate(json.dumps(updateEnv))
|
||
tool.log_info(f"update res {res}")
|
||
res = tql.envEnable([id])
|
||
tool.log_info(f"envEnable res {res}")
|
||
|
||
def refresh_account(self):
|
||
need = 0
|
||
success = 0
|
||
failed = 0
|
||
failed_user = []
|
||
tool.log_info(f"[rabbit]账密刷新开始......")
|
||
acc_map = sender.bucketAll("rabbit_zm_acc")
|
||
if not acc_map:
|
||
sender.reply("暂无账密数据,已退出")
|
||
# 查询pin对应的ck是否有效
|
||
for pin, accStr in acc_map.items():
|
||
jdStr = sender.bucketGet("jdNotify", pin)
|
||
if not jdStr:
|
||
continue
|
||
jd_json = json.loads(jdStr)
|
||
ck = f"pt_pin={pin}; pt_key={jd_json['PtKey']}"
|
||
if self.check_ck_status(ck):
|
||
tool.log_info(f"账号【{pin}】有效✅,跳过刷新")
|
||
continue
|
||
need += 1
|
||
acc_json = json.loads(accStr)
|
||
refresh_res = self.run_login(acc_json['mobile'], acc_json['pwd'])
|
||
if not refresh_res:
|
||
failed += 1
|
||
failed_user.append(f"{quote(pin)}[{self.hide_phone(acc_json['mobile'])}]")
|
||
else:
|
||
success += 1
|
||
content = f"[rabbit]账密刷新结束"
|
||
if need > 0:
|
||
content += f"\n本次需要刷新:{need}个"
|
||
content += f"\n本次刷新成功:{success}个🎉"
|
||
if failed_user:
|
||
content += f"\n本次刷新失败:{failed}个😭"
|
||
s = "\n".join(failed_user)
|
||
content += f"\n刷新失败用户:{s}"
|
||
else:
|
||
content += f"\n本次所有账户有效,无需刷新🎉"
|
||
tool.pushMaster(content)
|
||
|
||
def account_manage(self):
|
||
acc_map = sender.bucketAll("rabbit_zm_acc")
|
||
if not acc_map:
|
||
tool.replyMsg("暂无账密记录,请先登录")
|
||
exit()
|
||
content = f"账密列表如下:"
|
||
no = 0
|
||
for pin,accStr in acc_map.items():
|
||
acc_json = json.loads(accStr)
|
||
no +=1
|
||
content += f"\n{no}、{quote(pin)}[{self.hide_phone(acc_json['mobile'])}]"
|
||
tool.replyMsg(content)
|
||
|
||
|
||
def run_login(self, mobile, pwd):
|
||
if not self.login_init(mobile):
|
||
return False
|
||
login_res, pin = self.login(mobile, pwd)
|
||
if not login_res:
|
||
return False
|
||
self.after_login(pin)
|
||
return True
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sender = middleware.Sender(middleware.getSenderID())
|
||
plugin_ver = sender.getPluginVersion()
|
||
plugin_name = sender.getPluginName()
|
||
msg = sender.getMessage().strip('"')
|
||
imType = "fake" if sender.getImtype() == "cron" else sender.getImtype()
|
||
chatId = sender.getChatID()
|
||
userId = sender.getUserID()
|
||
isAdmin = sender.isAdmin()
|
||
username = sender.getUserName()
|
||
tool = TOOL()
|
||
#### 定时任务 #####
|
||
cron = middleware.Cron(None)
|
||
crons = list(filter(lambda item: "兔子账密刷新" in item['cmd'],cron.getCrons()))
|
||
if not crons:
|
||
tool.log_info(f"【兔子账密刷新】定时任务不存在,重新添加")
|
||
id = cron.addCron("0 0,3,5 * * *","兔子账密刷新",True,False,"兔子账密刷新","","","")
|
||
tool.log_info(f"add cron id = {id}")
|
||
#### 定时任务 ####
|
||
tz = ZM_RABBIT()
|
||
if "登录" in msg or "登陆" in msg:
|
||
sms_content = "请在60秒内输入手机号(q:退出)"
|
||
tool.replyMsg(sms_content)
|
||
mobile = sender.listen(60000)
|
||
if not mobile or mobile == "q" or mobile == "error":
|
||
tool.replyMsg("已退出!")
|
||
exit()
|
||
pattern = r'^1[3-9]\d{9}$'
|
||
if not re.match(pattern, mobile):
|
||
tool.replyMsg("手机号格式错误,已退出!")
|
||
exit()
|
||
tool.replyMsg("请在60秒内输入登录密码(q:退出)")
|
||
pwd = sender.listen(60000)
|
||
if not pwd or pwd == "q" or pwd == "error":
|
||
tool.replyMsg("已退出!")
|
||
exit()
|
||
if len(pwd) < 8:
|
||
tool.replyMsg("密码格式错误,已退出!")
|
||
exit()
|
||
tz.run_login(mobile, pwd)
|
||
exit()
|
||
if "刷新" in msg:
|
||
tz.refresh_account()
|
||
exit()
|
||
if "管理" in msg:
|
||
tz.account_manage()
|