From 80fc81bac0442c6066b86d189f7d7e514e1abffc Mon Sep 17 00:00:00 2001 From: O1Si <45961392+O1Si@users.noreply.github.com> Date: Fri, 24 Dec 2021 21:53:40 +0800 Subject: [PATCH] feat: multi account support (#46) * feat: multi account * imp: update .gitignore * imp: update requirements.txt * imp: update README.md * imp: update README.md * imp: add newline at end of .gitignore * imp: update log string * imp: refactor L525 of miuitask.py * imp: refactor check_config function * imp: optimized check_config method * imp: update config.yaml * imp: optimized check_config method * imp: move changelog to release * imp: update README.md --- .gitignore | 2 +- README.md | 127 ++++++++++------------------------------------- config.env | 25 ---------- config.yaml | 25 ++++++++++ miuitask.py | 71 ++++++++++++++------------ requirements.txt | 5 +- utils/utils.py | 113 +++++++++++++++++++++++++---------------- 7 files changed, 165 insertions(+), 203 deletions(-) delete mode 100644 config.env create mode 100644 config.yaml diff --git a/.gitignore b/.gitignore index bc48267..bee8a64 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -config.env \ No newline at end of file +__pycache__ diff --git a/README.md b/README.md index edb7517..d8a2db0 100644 --- a/README.md +++ b/README.md @@ -9,84 +9,52 @@ 由 `東雲研究所` 的某位大佬编写 由大佬授权 `0-8-4` 使用 `MIT` 开源 `0-8-4` 和 `TardisLX` 会进行基础维护 - 我们认为小米社区无权在无任何回报的情况下强制要求内测用户完成KPI任务,因此诞生了这个脚本 + 我们认为小米社区无权在无任何回报的情况下强制要求内测用户完成 KPI 任务,因此诞生了这个脚本 ## **重要声明**: - 虽然理论上本脚本不会影响小米社区账户安全,但您需要自行承担使用本脚本的后果 - **我们不鼓励,不支持一切商业使用** - - 鉴于项目的特殊性,我们可能在任何时间**停止更新**或**删除项目** + - 鉴于项目的特殊性,我们可能在任何时间 **停止更新** 或 **删除项目** + + +### **使用说明**: +关于项目的详细使用方法请阅览 **[WiKi](https://github.com/0-8-4/miui-auto-tasks/wiki)** ### **项目依赖**: - 1. Python3 - 需要前往 Python 官网自行下载自己系统对应的版本,或使用自己系统对应的包管理安装,这里推荐至少Python 3.6以上 + 1. 需要前往 Python 官网自行下载自己系统对应的 Python 版本,或使用自己系统对应的包管理安装,推荐至少 Python 3.6 以上 ``` https://www.python.org/downloads/ ``` - 2. Python3 安装完成之后,请在 **项目目录** 执行以下命令安装所需模块 + 2. Python 3 安装完成之后,请在 **项目目录** 执行以下命令安装所需模块 ```bash pip install -r requirements.txt ``` - 注:你可能需要使用管理员权限运行命令行 + 注意:你可能需要使用管理员权限运行命令行 ### **项目介绍**: -- [x] 支持 腾讯云函数(详见 [Wiki](https://github.com/0-8-4/miui-auto-tasks/wiki/Run-on-SCF)) -- [x] 支持 Docker 部署(详见 [Wiki](https://github.com/0-8-4/miui-auto-tasks/wiki/Run-on-Docker)) -- [x] 可自动登录小米账号刷新社区 Cookie 实现自动化 -- [x] 可选择启用小米社区拔萝卜签到 -- [x] 可自动完成以下小米社区KPI任务且不留下可见痕迹 - - [x] 可完成 “在内测圈分享这个版本的体验” KPI任务 - - [x] 可完成 “参与当前版本满意度投票” KPI任务 - - [x] 可完成 “内测圈内互动(答疑、点赞、投票)” KPI任务 +- [x] 支持 多账号 配置 +- [x] 支持 Docker 部署 +- [x] 支持 腾讯云函数 部署 +- [x] 自动登录小米账号刷新社区 Cookie 实现自动化 +- [x] 选择性启用小米社区拔萝卜签到 +- [x] 自动完成以下小米社区 KPI任务 且不留下可见痕迹 + - “在内测圈分享这个版本的体验” KPI任务 + - “参与当前版本满意度投票” KPI任务 + - “内测圈内互动(答疑、点赞、投票)” KPI任务 - [x] 可自动完成以下小米社区活跃分任务且不留下可见痕迹 - - [x] 可完成 “加入1个圈子” 活跃分任务 - - [x] 可完成 “关注1位用户” 活跃分任务 - - [x] 可完成 “点赞1篇帖子” 活跃分任务 + - “加入1个圈子” 活跃分任务 + - “关注1位用户” 活跃分任务 + - “点赞1篇帖子” 活跃分任务 - [x] 增强模式下可完成以下社区任务且不留下可见痕迹 - - [x] 可完成 “在内测圈提交带日志的bug反馈” KPI任务 - - [x] 可完成 “发布1条评论” 活跃分任务 - - [x] 可完成 “发布1篇帖子” 活跃分任务 - - -### **使用说明**: -- 使用你偏好的编辑器打开配置文件 `config.env` -- 在配置文件 第2行 中填写你的 小米 ID - - 请注意 小米 ID 不是手机号或邮箱 - - 示例: `MI_ID='123456'` -- 在配置文件 第4行 中填写小米账号密码 或 MD5 加密后的密文 - - 示例: `MI_PASSWORD='654321'` - - 示例: `MI_PASSWORD='C33367701511B4F6020EC61DED352059'` - - 允许使用 MD5 登录,便于代理他人操作 -- 在配置文件 第6行 中填写你常用浏览器的UA,可在诸如 `https://ie.icoa.cn` 等类似的网站查看 - - 示例:` USER_AGENT='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.73'` - - 请务必先使用这个浏览器登录 `https://account.xiaomi.com` -- 在配置文件 第11行 中填写你要完成的内测任务类型 - - 开发版内测 `5428803` 开发版公测 `5433318` 稳定版内测 `5462204` - - 示例: `BOARD_ID='5428803'` -- 在配置文件 第16行 中配置是否开启 社区签到 - - 根据小米社区规则,非正常渠道签到可能会导致账户封禁 - - 本脚本虽是模拟您的操作向社区发送请求,但仍不能保证绝对安全 - - 如果您愿意自行承担一切风险,请将 `N` 改为 `Y` - - 示例: `SIGN_IN='Y'` -- 在配置文件 第19行 中配置是否开启 日志保存 - - 启用后将按照日期保存到 logs 目录中 - - 如果想保存日志到文件,请将 `N` 改为 `Y` - - 示例: `LOG_SAVE='Y'` -- 在配置文件 第25行 中配置是否开启 增强模式 - - 根据小米社区规则,非正常渠道发帖可能会导致账户封禁 - - 本脚本虽是模拟您的操作向社区发送请求,但仍不能保证绝对安全 - - 如果您愿意自行承担一切风险,请将 `N` 改为 `Y` - - 示例: `ENHANCED_MODE='Y'` -- 确保网络正常且无代理服务器后,可以尝试在脚本目录下使用 `python3 miuitask.py` 命令运行脚本了 - - GNU/Linux 和 MacOS 环境下首次运行前可能需要手动执行以下命令 - ```bash - $ chmod +x miuitask.py - ``` + - “在内测圈提交带日志的 bug 反馈” KPI任务 + - “发布1条评论” 活跃分任务 + - “发布1篇帖子” 活跃分任务 #### **其他**: @@ -95,53 +63,12 @@ * 建议配合 Python3 及 Crontab 使用 * **欢迎提供有关的思路,提交BUG以及更多完成社区其他任务方式,我们会认真对待~** + #### **贡献**: -如果你在使用过程中发现任何问题,可以 [提交 issue](https://github.com/0-8-4/miui-auto-tasks/issues/new) 或自行 Fork 修改后提交 Pull request。 +如果你在使用过程中发现任何问题,可以 [提交 issue](https://github.com/0-8-4/miui-auto-tasks/issues/new) 或自行 Fork 修改后提交 Pull request -如果你要提交 Pull request,请确保你的代码风格和项目已有的代码保持一致,遵循 [PEP 8](https://www.python.org/dev/peps/pep-0008) ,变量命名清晰,有适当的注释。 - -#### **更新说明**: - - v1.3.3 - - 新增 Docker 支持(使用方法见 [Wiki](https://github.com/0-8-4/miui-auto-tasks/wiki/Run-on-Docker)) - - 新增 腾讯云函数 支持(使用方法见 [Wiki](https://github.com/0-8-4/miui-auto-tasks/wiki/Run-on-SCF)) - - 新增 回帖签名算法 - - 修改 使用面向对象编程重构代码 - - 修改 发帖相关任务移至增强模式 - - 修复 回帖失败的问题 - - v1.3.2 - bugfix - - 修复 在部分Python环境中,读取不到配置文件 - - 修复 安卓的部分编辑器中 找不到隐藏文件的问题 - - v1.3.2 : - - 增加 获取最新的内测分 - - v1.3.1 : - - 增加 增加写入 Log 到文件 - - v1.3 : - - 增加 独立配置文件 - - 增加 密码登陆方式 - - v1.2.3 : - - 符合 [PEP 8](https://www.python.org/dev/peps/pep-0008) 代码风格 - - v1.2.2 : -- 增加 输出系统信息到控制台 - - v1.2.1 : -- 默认关闭 “社区拔萝卜签到” 功能 - - 根据小米社区规则,非正常渠道签到**一经发现可能会导致账户封禁** - - 如您愿意承担一切可能的后果,请根据 [使用说明](#使用说明) 开启功能 - - v1.2.0 : -- 增加 “社区拔萝卜签到” 功能 - - v1.1.0 : -- 增加领取延迟保证成功率 -- 增加完成 “发布1篇帖子” 活跃分任务功能 +如果你要提交 Pull request,请确保你的代码风格和项目已有的代码保持一致,遵循 [PEP 8](https://www.python.org/dev/peps/pep-0008) ,变量命名清晰,有适当的注释 # **License** diff --git a/config.env b/config.env deleted file mode 100644 index 5d7b08f..0000000 --- a/config.env +++ /dev/null @@ -1,25 +0,0 @@ -# 小米账户 ID -MI_ID='' -# 小米账户 密码 / MD5 -MI_PASSWORD='' -# 登录所用的 User-Agent -USER_AGENT='' -# 开发版内测 5428803 -# 开发版公测 5433318 -# 稳定版内测 5462204 -# 目前测试三个中完成任意一个即可全部完成 -BOARD_ID='' -# 小米社区签到 -# 警告:根据小米社区规则,非正常渠道签到可能会导致账户封禁 -# 本脚本虽是模拟您的操作向社区发送请求,但仍不能保证绝对安全 -# 如果您愿意自行承担一切风险,请将 N 改为 Y -SIGN_IN='N' -# 保存程序日志到文件 -# 如果想保存日志到文件,请将 N 改为 Y -LOG_SAVE='N' -# 增强模式可通过发帖获取更多内测分 -# 如果只需要保留内测资格,请不要开启本模式 -# 警告:根据小米社区规则,非正常渠道发帖可能会导致账户封禁 -# 本模式风险较大,因此存在一定的封号风险 -# 如果您愿意自行承担一切风险,请将 N 改为 Y -ENHANCED_MODE='N' diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..06cd03b --- /dev/null +++ b/config.yaml @@ -0,0 +1,25 @@ +accounts: + - uid: 100000 + # 小米账户ID 非小米账户用户名 + password: abc123 + # 小米账户密码或其MD5哈希 + user-agent: 'Mozilla/5.0 (Android 11; Mobile; rv:95.0) Gecko/95.0 Firefox/95.0' + # 登录小米社区时所用浏览器的 User-Agent + # 可在此工具查看:https://tool.chinaz.com/useragent + board-id: 5462204 + # 测试任务类型 + # 开发版内测 5428803 开发版公测 5433318 稳定版内测 5462204 + check-in: false + # 小米社区签到,存在封号风险 + enhance-mode: false + # 增强模式,存在封号风险 + # 一般情况下,本脚本只会执行3次发帖和回帖以及五次点赞的基本操作 +# 若有多个小米账户,按照以下模板进行修改,使用时删除前端 #注释 +# - uid: 100001 +# password: abc123 +# user-agent: 'Mozilla/5.0 (Android 11; Mobile; rv:95.0) Gecko/95.0 Firefox/95.0' +# board-id: 5462204 +# check-in: false +# enhance-mode: false +logging: false +# 归档日志到本地文件 diff --git a/miuitask.py b/miuitask.py index 4f64578..3b23fb6 100644 --- a/miuitask.py +++ b/miuitask.py @@ -6,19 +6,18 @@ import hashlib from urllib import request from http import cookiejar -from utils.utils import system_info, get_config, w_log, s_log, conf_check + +from utils.utils import system_info, get_config, w_log, s_log, check_config, format_config class MIUITask: - def __init__(self, mi_id, p_md5, l_ua, board_id, dev_id=None): - self.mi_id = mi_id - self.p_md5 = p_md5 - self.l_ua = l_ua + def __init__(self, uid, password, user_agent, board_id, device_id): + self.uid = uid + self.password = password + self.user_agent = user_agent self.board_id = board_id - - if not dev_id: - self.dev_id = dev_id + self.device_id = device_id # 留空 self.cookie = '' @@ -335,7 +334,7 @@ class MIUITask: w_log(e) # 社区拔萝卜签到 - def vip_sign_in(self): + def vip_check_in(self): headers = { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', 'cookie': str(self.cookie) @@ -374,10 +373,10 @@ class MIUITask: '%25252Fmio%25252Fmio%25252FinternalTest%25253Fref%25253Dhomepage&_sign=L%2BdSQY6sjSQ%2FCRjJs4p' '%2BU1vNYLY%3D&serviceParam=%7B%22checkSafePhone%22%3Afalse%2C%22checkSafeAddress%22%3Afalse%2C' '%22lsrp_score%22%3A0.0%7D&showActiveX=false&theme=&needTheme=false&bizDeviceType=', - 'User-Agent': str(self.l_ua), + 'User-Agent': str(self.user_agent), 'Origin': 'https://account.xiaomi.com', 'X-Requested-With': 'XMLHttpRequest', - 'Cookie': 'deviceId=' + str(self.dev_id) + '; pass_ua=web; uLocale=zh_CN' + 'Cookie': 'deviceId=' + str(self.device_id) + '; pass_ua=web; uLocale=zh_CN' } data = { 'bizDeviceType': '', @@ -394,9 +393,9 @@ class MIUITask: '%2525252Fmio%2525252Fmio%2525252FinternalTest%2525253Fref%2525253Dhomepage%26sid%3Dmiui_vip', 'sid': 'miui_vip', '_sign': 'L+dSQY6sjSQ/CRjJs4p+U1vNYLY=', - 'user': str(self.mi_id), + 'user': str(self.uid), 'cc': '+86', - 'hash': str(self.p_md5), + 'hash': str(self.password), '_json': 'true' } try: @@ -425,7 +424,7 @@ class MIUITask: def get_score(self) -> int: """ - 这个方法待返回值的原因是,可以调用这个方法获取返回值,可根据这个方法定制自己的“消息提示功能”。 + 这个方法带返回值的原因是,可以调用这个方法获取返回值,可根据这个方法定制自己的“消息提示功能”。 如:Qmsg发送到QQ 或者 发送邮件提醒 :return: 当前的内测分值 """ @@ -453,14 +452,14 @@ def process_exception(e: Exception): w_log('系统设置了代理,出现异常') -def start(miui_task: MIUITask, sign_in: bool, enhanced_mode: bool): +def start(miui_task: MIUITask, check_in: bool, enhanced_mode: bool): if miui_task.mi_login(): w_log("本脚本支持社区签到,因该功能存在风险默认禁用") w_log("如您愿意承担一切可能的后果,可编辑配置文件手动打开该功能") - if sign_in: + if check_in: w_log("风险功能提示:正在进行社区签到") - miui_task.vip_sign_in() + miui_task.vip_check_in() w_log("正在完成满意度调查任务") miui_task.get_survey_id() w_log("正在完成点赞任务") @@ -505,27 +504,35 @@ def start(miui_task: MIUITask, sign_in: bool, enhanced_mode: bool): def main(): - w_log("MIUITask_v1.3.3") - w_log('----------系统信息-开始-------------') + w_log("MIUI-AUTO-TASK v1.4") + w_log('---------- 系统信息 -------------') system_info() - w_log('----------系统信息-结束-------------') + w_log('---------- 项目信息 -------------') w_log("项目地址:https://github.com/0-8-4/miui-auto-tasks") - w_log("欢迎star,感谢東雲研究所中的大佬") - w_log('----------检测配置文件-------------') - + w_log("欢迎 star,感谢東雲研究所中的大佬") + w_log('---------- 配置检测 -------------') + config = get_config() - if not conf_check(config): - w_log('配置文件没有正确配置,请检查') - mi_id = config.get('MI_ID') - p_md5 = config.get('MI_PASSWORD').upper() - l_ua = config.get('USER_AGENT') - board_id = config.get('BOARD_ID') + if not check_config(config): + w_log('配置文件没有正确配置') + exit(1) + else: + config = format_config(config) - miui = MIUITask(mi_id, p_md5, l_ua, board_id) - start(miui, config.get('SIGN_IN'), config.get('ENHANCED_MODE')) + for i in config.get('accounts'): + w_log('---------- EXECUTING -------------') + start( + MIUITask(i.get('uid'), i.get('password'), i.get('user-agent'), i.get('board-id'), device_id=i.get('device-id')), + i.get('check-in'), + i.get('enhance-mode') + ) - s_log() + s_log(config.get('logging')) + + +def main_handler(event, context): + main() if __name__ == "__main__": diff --git a/requirements.txt b/requirements.txt index f0b6301..db0c977 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ -requests~=2.25.1 -python-dotenv \ No newline at end of file +requests>=2.25.1 +python-dotenv>=0.19.2 +PyYAML>=6.0 \ No newline at end of file diff --git a/utils/utils.py b/utils/utils.py index 55d7b62..56a6919 100644 --- a/utils/utils.py +++ b/utils/utils.py @@ -1,11 +1,9 @@ import os import time import platform +import dotenv, yaml from hashlib import md5 - -import dotenv -from dotenv import dotenv_values from urllib.request import getproxies @@ -21,37 +19,55 @@ def show_info(tip, info): def system_info(): - w_log(show_info("系统及版本信息", platform.platform())) - w_log(show_info('系统版本号', platform.version())) - w_log(show_info('系统名称', platform.system())) - w_log(show_info('系统位数', platform.architecture())) - w_log(show_info('计算机类型', platform.machine())) - w_log(show_info('处理器类型', platform.processor())) - w_log(show_info('Python版本', str(platform.python_version()) + ' ' + str(platform.python_build()))) + w_log(show_info('操作系统平台', platform.platform())) + w_log(show_info('操作系统版本', platform.version())) + w_log(show_info('操作系统名称', platform.system())) + w_log(show_info('操作系统位元', platform.architecture())) + w_log(show_info('操作系统类型', platform.machine())) + w_log(show_info('处理器信息', platform.processor())) + w_log(show_info('Python 版本', str(platform.python_version()) + ' ' + str(platform.python_build()))) if getproxies(): w_log(show_info('系统代理', getproxies())) def get_config() -> dict: - config_path = dotenv.find_dotenv(filename='config.env') - w_log('正在使用 ' + config_path + ' 作为配置文件') - config = dotenv.dotenv_values(config_path) - if not config: - w_log('配置文件未配置,请编辑项目目录的.env文件。如文件不存在请自行创建') + config = {'account': []} + config_path_legacy = dotenv.find_dotenv(filename='config.env') + config_path_yaml = dotenv.find_dotenv(filename='config.yaml') + + if config_path_legacy: + w_log('正在使用 ' + config_path_legacy + ' 作为配置文件') + legacy_config = dotenv.dotenv_values(config_path_legacy) + config['account'].append({'uid': legacy_config.get('MI_ID')}) + config['account'][0]['password'] = legacy_config.get('MI_PASSWORD') + config['account'][0]['user-agent'] = legacy_config.get('USER_AGENT') + config['account'][0]['board-id'] = legacy_config.get('BOARD_ID') + if legacy_config.get('SIGN_IN') and legacy_config.get('SIGN_IN').upper() in ('Y', 'YES'): + config['account'][0]['check-in'] = True + else: + config['account'][0]['check-in'] = False + if legacy_config.get('ENHANCED_MODE') and legacy_config.get('ENHANCED_MODE').upper() in ('Y', 'YES'): + config['account'][0]['enhance-mode'] = True + else: + config['account'][0]['enhance-mode'] = False + if legacy_config.get('LOG_SAVE') and legacy_config.get('LOG_SAVE').upper() in ('Y', 'YES'): + config['logging'] = True + else: + config['logging'] = False + return config + elif config_path_yaml: + w_log('正在使用 ' + config_path_yaml + ' 作为配置文件') + with open(config_path_yaml, "rb") as stream: + try: + config = yaml.safe_load(stream) + except yaml.YAMLError as e: + w_log('配置文件载入错误') + w_log(e) + return config + else: + w_log('配置文件不存在') exit(1) - passwd = config.get('MI_PASSWORD') - if len(passwd) != 32: - config['MI_PASSWORD'] = md5_crypto(passwd) - if config.get('SIGN_IN').upper() in ('Y', 'YES'): - config['SIGN_IN'] = True - else: - config['SIGN_IN'] = False - if config.get('ENHANCED_MODE').upper() in ('Y', 'YES'): - config['ENHANCED_MODE'] = True - else: - config['ENHANCED_MODE'] = False - return config - + def w_log(text): global logs @@ -60,9 +76,8 @@ def w_log(text): print(now_localtime + ' | ' + str(text)) -def s_log(): - logs_save= get_config().get('LOG_SAVE') - if logs_save == 'Y': +def s_log(flag): + if flag == True: global logs folder = os.path.exists('./logs') if not folder: @@ -73,18 +88,30 @@ def s_log(): f.write(logs) -def conf_check(config: dict): - if not config.get('MI_ID'): - w_log('小米账户 ID 未配置') +def check_config(config: dict) -> bool: + if config.get('accounts'): + for i in config.get('accounts'): + if not i.get('uid') or not i.get('password') or not i.get('user-agent') or not i.get('board-id'): + return False + if not isinstance(i.get('check-in'), bool) or not isinstance(i.get('enhance-mode'), bool): + return False + else: return False - if not config.get('MI_PASSWORD'): - w_log('小米账户 密码 / MD5 未配置') + if not isinstance(config.get('logging'), bool): return False - if not config.get('USER_AGENT'): - w_log('User-Agent 未配置') - return False - if not config.get('BOARD_ID'): - w_log('测试类型 ID 未配置') - return False - w_log('config.env 已配置') return True + + +def format_config(config: dict) -> dict: + for i in config.get('accounts'): + i['uid'] = str(i.get('uid')) + i['user-agent'] = str(i.get('user-agent')) + i['board-id'] = str(i.get('board-id')) + i['password'] = str(i.get('password')).upper() + if len(i.get('password')) != 32: + i['password'] = md5_crypto(i.get('password')).upper() + if i.get('device-id'): + i['device-id'] = str(i.get('device-id')) + else: + i['device-id'] = None + return config