diff --git a/README.md b/README.md index bdbaba0..1480415 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,67 @@ -# CommuTrace_Monitor_TaskList -监听共迹算力平台任务列表 +# 监听“算了么”平台任务列表 + +遵循GPL 3.0协议 + +### 对于不便的用户 + +现有一个已部署的demo,使用微信扫码,也可接收消息推送: + +showqrcode + +这个二维码**有效期至2024年2月20日** + +### 使用说明 + +```bash +python index.py +``` + +或下载运行[index.exe](https://github.com/pooneyy/suanleme/releases/latest) + +![image-20230316165557606](https://s2.loli.net/2023/03/16/tscoEFUr5X6SG2i.png) + +##### 首次运行时你需要准备: + +1. 平台账号、密码 [注册帐号](https://suanleme.cn/) + +2. [PushPlus](http://www.pushplus.plus/)的`token`用于消息推送 + + ![image-20230316161929749](https://s2.loli.net/2023/03/16/m28Pc7BJQinXMZh.png) + - (选填)群组编码:用于PushPlus发送一对多消息(群发消息)。详见[一对多消息|pushplus(推送加)](http://www.pushplus.plus/push2.html),留空时发送一对一消息。 + +### 更新日志 + +``` +1.2 (2024.01.24) 更新:现有任务增加任务点时,将会收到提醒 + +1.1 (2024.01.20) 更新:优化了推送消息中表格的显示。 + +1.0 (2024.01.20) 更新:CommuTrace共迹算力平台已升级为“算了么”平台,现已对新平台进行适配。 + +0.2.1 (2023.03.31) 修复:某些情况下“远程主机强迫关闭了一个现有的连接”时,报错退出的问题。 + +0.2 (2023.03.25) 更新: + 1、登录时将Cookies保存到文件,并优先从文件载入Cookies; + 2、新增检查更新。 + 修复: + 1、修复了某些情况下订单解析失败的问题; + 2、修复了Cookies失效后,重新登录失败的问题。 + +0.1.4 (2023.03.22) 修复: + 1、当订单数=0时,重复登录的问题; + 2、调整了输出的消息的格式,并做了精简,避免过多无意义内容。 + +0.1.3 (2023.03.20) 修复:当订单数>1时,只显示首个订单的问题。 + +0.1.2 (2023.03.19) 修复: + 1、当无订单时崩溃的问题; + 2、当订单数>1时,订单创建时间解析错误的问题; + 3、修复其它错误。 + +0.1.1 (2023.03.16) 若干更新: + 1、令当连接出错时自动重试; + 2、令当验证码识别出错时自动重试; + 3、处理其他报错。 + +0.1 (2023.03.16) 初版。 +``` diff --git a/index.py b/index.py new file mode 100644 index 0000000..b6ac654 --- /dev/null +++ b/index.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python3 +# -*- coding: utf8 -*- +''' +Author : Pooneyy +Date : 2023-03-14 20:08:52 +LastEditors : Pooneyy 85266337+pooneyy@users.noreply.github.com +LastEditTime : 2023-03-31 21:48:32 +FilePath : /suanleme/index.py +Description : “算了么”平台 监听任务列表 + +Copyright (c) 2023-2024 by Pooneyy, All Rights Reserved. +''' + +import json +import os +import datetime, pytz, time +import sys +import requests + +VERSION = '1.2' # 2024.01.24 +CONFIG_VERSION = 2 +HOST = "https://api.suanleme.cn/api/v1" + +def timeStamp_To_dateTime(timeStamp):return datetime.datetime.fromtimestamp(int(timeStamp), pytz.timezone('Asia/Shanghai')).strftime('%Y-%m-%d %H:%M:%S') + +def isoDateTime_To_dateTime(iso_date_time):return datetime.datetime.strptime(iso_date_time, "%Y-%m-%dT%H:%M:%S.%f%z").strftime('%Y-%m-%d
%H:%M:%S') + +def saveConfig(config): + with open("config.json", "w", encoding='utf8') as file: + json.dump(config, file, ensure_ascii=False, indent = 4) + +def loadConfig(): + with open("config.json", "r+", encoding='utf8') as file: + config = json.load(file) + return config + +def checkUpdate(): + url = "https://api.github.com/repos/pooneyy/suanleme/releases/latest" + try: + response = requests.get(url) + latest = json.loads(response.text)["tag_name"] + return VERSION != latest + except:return False + +def init(): + print('首次运行初始化') + config = {} + config['config_version'] = CONFIG_VERSION + config['latest_id'] = 0 + config['suanleme_username'] = input('请输入算了么账号:') + config['suanleme_password'] = input('请输入算了么密码:') + config['truecaptcha_userid'] = '' + config['truecaptcha_apikey'] = '' + config['pushplus_token'] = input('请输入pushplus推送加的token:') + config['pushplus_topic'] = input('(选填)输入pushplus推送加的群组编码:') + config['tasks_record'] = {} + saveConfig(config) + print('初始化完成,请重新运行') + +def sendMsg(config, msg): + data = {} + url = "http://www.pushplus.plus/send" + data['token'] = config['pushplus_token'] + data['title'] = '算了么来新单啦!' + data['template'] = 'markdown' + data['topic'] = config['pushplus_topic'] # 群组编码,发送群组消息。 + data['content'] = msg + response = requests.post(url,data=data) + return response.text + +def login(config): + url = f"{HOST}/user/token" + payload={ + 'username': config['suanleme_username'], + 'password': config['suanleme_password'], + } + response = requests.post(url, data=payload) + print(f"{timeStamp_To_dateTime(time.time())}\t登录成功") + refresh_token = response.json()['refresh'] + return refresh_token + +def refresh(refresh_token): + url = f"{HOST}/user/token/refresh" + payload={'refresh': refresh_token} + response = requests.post(url, data=payload) + return response.json()["access"] + +def getTasks(refresh_token): + '''获取全部订单''' + url = f"{HOST}/tasks/?page=1&data_type=all" + headers = {'Authorization': f'Bearer {refresh(refresh_token)}'} + response = requests.get(url, headers=headers) + response.close() + return response.json() + +def analyzing_tasks_info(tasks): + '''分析订单页面 + 这是一个订单信息的数据结构 + ```json +{ + "id": 107, //订单id + "author": 23, //发布者id? + "status": "Running", //状态 Running / Finished / Canceled / Received + "finished_points": 28, //已完成任务点 + "running_points": 2, //进行中任务点 + "name": "cytx", //任务名 + "desc": "cytx", //任务描述 + "peer_income": 1, //单位收益 + "expect_time": "1", //预期单位时长 + "type": "Deployment", //类型 Deployment / Job + "points": 30, //总任务点 + "cpu_required": 0, //硬件要求 CPU核心数 + "memory_required": 0, //硬件要求 内存 单位GB + "disk_required": 0, //硬件要求 磁盘空间要求 单位GB + "time_required": "00:00:00", //连续时长要求 + "created_time": "2024-01-10T11:19:36.165607+08:00", //创建时间() + "modify_time": "2024-01-19T17:48:05.918623+08:00", //修改时间 + "finished_time": "2024-01-18T07:31:00+08:00", //完成时间 + "runtime": 4, + "package": "eca6bf8b-d71d-4143-b259-f7ca9294d9ff", + "joined_user": [ //参加计算成员id? + 1, + 22, + 36, + 46, + 47, + 50 + ], + "affinity": [ + 1, + 2 + ], + "aversion": [] +} + ``` + ''' + taskList = [] + for task in tasks['results']: + taskData = {} + taskData['id'] = task['id'] + taskData['detail'] = task['desc'] + taskData['created_time'] = task['created_time'] + taskData['peer_income'] = task['peer_income'] + taskData['points'] = task['points'] + taskList.append(taskData) + return taskList + +def taskList_To_Msg(taskList): + msg = r'''
''' + for i in taskList: + msg += f'''''' + msg += "
任务ID任务细节创建时间单位收益总量
{i['id']}{i['detail']}{isoDateTime_To_dateTime(i['created_time'])}{i['peer_income']}{i['points']}
" + return msg + +def updated_Tasks_To_Msg(tasksList,config): + msg = f'''|任务ID|任务点更新前|任务点更新后|\n|:----:|:----:|:----:|\n''' + for task in tasksList: + msg += f'''|{task['id']}|{config.get('tasks_record').get(str(task['id']),{}).get('points',0)}|{task['points']}|\n''' + return msg + +def loop(config): + try: + refresh_token = login(config) + while True: + tasksList = analyzing_tasks_info(getTasks(refresh_token)) + if tasksList: + i = [i['id'] for i in tasksList] # 列表,临时存储订单ID用于寻找最大的ID + latest_id = int(max(i)) + msg = '' + if latest_id > config['latest_id']: + config['latest_id'] = latest_id + msg += f"#### 有新订单。当前最新是 {latest_id}\n" + msg += taskList_To_Msg(tasksList) + print(f"{taskList_To_Msg(tasksList)}") + updated_tasks = [] + for task in tasksList: + if task['points'] > config.get('tasks_record').get(str(task['id']),{}).get('points',0):updated_tasks.append(task) + if updated_tasks: + msg += f"#### 有新任务点\n" + msg += updated_Tasks_To_Msg(tasksList,config) + print(f"{updated_Tasks_To_Msg(tasksList,config)}") + for task in tasksList:config['tasks_record'][str(task['id'])] = task + sendMsg(config, msg) + saveConfig(config) + print(f"{timeStamp_To_dateTime(time.time())}\t当前最新{latest_id}...\r",end='') + else: + print(f"{timeStamp_To_dateTime(time.time())}\t当前没有订单...\r",end='') + time.sleep(30) + except KeyboardInterrupt:print("\n结束") + except requests.exceptions.ConnectionError: + try: + print(f"{timeStamp_To_dateTime(time.time())}\t网络连接中断") + time.sleep(30) + loop(config) + except KeyboardInterrupt:print("结束") + except requests.exceptions.ChunkedEncodingError: + print(f"{timeStamp_To_dateTime(time.time())}\t远程主机关闭连接") + time.sleep(3) + loop(config) + +def main(): + if 'linux' in sys.platform: sys.stdout.write(f"\x1b]2;算了么 - 监听任务列表 - 版本 {VERSION}\x07") + elif 'win' in sys.platform: os.system(f"title 算了么 - 监听任务列表 - 版本 {VERSION}") + if checkUpdate():print("请更新到最新版本:https://github.com/pooneyy/suanleme/releases/latest \n") + try:loop(loadConfig()) + except FileNotFoundError: + try:init() + except KeyboardInterrupt:print("\n退出,取消初始化") + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b9d6fbf --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pytz +requests \ No newline at end of file