diff --git a/.github/workflows/checkin.yml b/.github/workflows/checkin.yml index db3b345c..570f0690 100644 --- a/.github/workflows/checkin.yml +++ b/.github/workflows/checkin.yml @@ -1,7 +1,7 @@ name: aliyundrive-checkin on: schedule: - - cron: 0 16 * * * + - cron: 0 16 * * * workflow_dispatch: jobs: build: @@ -17,6 +17,7 @@ jobs: env: PUSHPLUS_TOKEN: ${{ secrets.PUSHPLUS_TOKEN }} SERVERCHAN_SENDKEY: ${{ secrets.SCKEY }} + WECOM_TOKENS: ${{ secrets.WECOM_TOKENS }} WECOM_WEBHOOK: ${{ secrets.WECOM_WEBHOOK }} BARK_DEVICEKEY: ${{ secrets.BARK_DEVICEKEY }} FEISHU_DEVICEKEY: ${{ secrets.FEISHU_DEVICEKEY }} diff --git a/README.md b/README.md index b1e64e82..a3af3abf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # aliyundrive-checkin - aliyundrive-checkin是一个定时自动签到的python程序 +- 2023/8/10: 推送支持微信应用图文消息、消息代理,支持获取每日任务[[@thsrite](https://github.com/thsrite)] - 2023/8/02: 采用linux构建,外加飞书推送支持 [[@bequt](https://github.com/bequt)] - 2023/6/12: 增加requests出错重试,使用chatgpt优化代码结构 - 2023/5/17: 增加自动领取签到奖励,显示本月签到次数 @@ -15,12 +16,15 @@ | TOKEN * | 阿里云盘Token 可以添加多个用英文逗号(,)分割 无需空格 | | SCKEY | Server酱 推送密钥 | | PUSHPLUS_TOKEN | pushplus 推送Token | + | WECOM_TOKENS | 企业微信 tokens | | WECOM_WEBHOOK | 企业微信 WEBHOOK | | BARK_DEVICEKEY | IOS应用Bark 推送密钥 | | FEISHU_DEVICEKEY | 飞书 推送密钥 | 以上TOKEN为阿里云盘签到必填项 推送项选择其中一个即可 也可多渠道推送 +WECOM_TOKENS: weCom_corpId, weCom_corpSecret, weCom_agentId, to_user, proxy_url (, to_user, proxy_url可选) + 3. 点击Actions -> 选择aliyundrive-checkin -> 点击Run workflow 运行即可 ### 其它设置 diff --git a/aliyundrive.py b/aliyundrive.py index a38d9755..ddf9b029 100644 --- a/aliyundrive.py +++ b/aliyundrive.py @@ -1,8 +1,10 @@ -import json +import time + import requests from aliyundrive_info import AliyundriveInfo from tenacity import retry, stop_after_attempt, wait_fixed, RetryError + class Aliyundrive: """ 阿里云盘签到(自动领取奖励) @@ -10,42 +12,49 @@ class Aliyundrive: :param token: 阿里云盘token :return AliyundriveInfo: """ + def aliyundrive_check_in(self, token: str) -> AliyundriveInfo: info = AliyundriveInfo( - success=False, - user_name='', - signin_count=-1, - message='', - reward_notice='' + success=False, + user_name='', + signin_count=-1, + message='', + reward_notice='', + task='' ) def handle_error(error_message: str) -> AliyundriveInfo: info.message = error_message return info - + try: flag, user_name, access_token, message = self._get_access_token(token) if not flag: return handle_error(f'get_access_token error: {message}') - + flag, signin_count, message = self._check_in(access_token) if not flag: return handle_error(f'check_in error: {message}') - + flag, message = self._get_reward(access_token, signin_count) if not flag: return handle_error(f'get_reward error: {message}') - + + flag, task = self._get_task(access_token) + if not flag: + return handle_error(f'get_task error: {task}') + info.success = True info.user_name = user_name info.signin_count = signin_count info.reward_notice = message + info.task = task return info except RetryError as e: return handle_error(f'Unexpected error occurred: {str(e)}') - + """ 获取access_token @@ -55,6 +64,7 @@ def handle_error(error_message: str) -> AliyundriveInfo: :return tuple[2]: access_token :return tuple[3]: message """ + @retry(stop=stop_after_attempt(3), wait=wait_fixed(1)) def _get_access_token(self, token: str) -> tuple[bool, str, str, str]: url = 'https://auth.aliyundrive.com/v2/account/token' @@ -70,7 +80,7 @@ def _get_access_token(self, token: str) -> tuple[bool, str, str, str]: name = nick_name if nick_name else user_name access_token = data['access_token'] return True, name, access_token, '成功获取access_token' - + """ 执行签到操作 @@ -79,6 +89,7 @@ def _get_access_token(self, token: str) -> tuple[bool, str, str, str]: :return tuple[1]: 签到次数 :return tuple[2]: message """ + @retry(stop=stop_after_attempt(3), wait=wait_fixed(1)) def _check_in(self, access_token: str) -> tuple[bool, int, str]: url = 'https://member.aliyundrive.com/v1/activity/sign_in_list' @@ -96,7 +107,7 @@ def _check_in(self, access_token: str) -> tuple[bool, int, str]: signin_count = data['result']['signInCount'] return success, signin_count, '签到成功' - + """ 获得奖励 @@ -105,6 +116,7 @@ def _check_in(self, access_token: str) -> tuple[bool, int, str]: :return tuple[0]: 是否成功 :return tuple[1]: message 奖励信息或者出错信息 """ + @retry(stop=stop_after_attempt(3), wait=wait_fixed(1)) def _get_reward(self, access_token: str, sign_day: int) -> tuple[bool, str]: url = 'https://member.aliyundrive.com/v1/activity/sign_in_reward' @@ -117,7 +129,52 @@ def _get_reward(self, access_token: str, sign_day: int) -> tuple[bool, str]: if 'result' not in data: return False, data['message'] - + success = data['success'] notice = data['result']['notice'] return success, notice + + """ + 今日任务 + + :param token: 调用_get_access_token方法返回的access_token + :param sign_day: 领取第几天 + :return tuple[0]: 是否成功 + :return tuple[1]: message 奖励信息或者出错信息 + """ + + @retry(stop=stop_after_attempt(3), wait=wait_fixed(1)) + def _get_task(self, access_token: str) -> tuple[bool, str]: + url = 'https://member.aliyundrive.com/v2/activity/sign_in_list' + payload = {} + params = {'_rx-s': 'mobile'} + headers = {'Authorization': f'Bearer {access_token}'} + + response = requests.post(url, json=payload, params=params, headers=headers, timeout=5) + data = response.json() + + if 'result' not in data: + return False, data['message'] + + success = data['success'] + signInInfos = data['result']['signInInfos'] + year, month, day = time.localtime()[:3] + + task_str = "" + for info in signInInfos: + if int(info['day']) == day: + rewards = info['rewards'] + + for reward in rewards: + name = reward['name'] + remind = reward['remind'] + type = reward['type'] + if type == "dailySignIn": + task_str += f' 类型:签到\n' \ + f' 要求:{remind}\n' \ + f' 奖励:{name}\n' + if type == "dailyTask": + task_str += f' 类型:任务\n' \ + f' 要求:{remind}\n' \ + f' 奖励:{name}\n' + return success, task_str diff --git a/aliyundrive_info.py b/aliyundrive_info.py index add1c9ec..549ad9ad 100644 --- a/aliyundrive_info.py +++ b/aliyundrive_info.py @@ -1,23 +1,27 @@ class AliyundriveInfo: def __init__( - self, - success: bool, - user_name: str, - signin_count: int, - message: str, - reward_notice: str): + self, + success: bool, + user_name: str, + signin_count: int, + message: str, + reward_notice: str, + task: str): self.success = success self.user_name = user_name self.signin_count = signin_count self.message = message self.reward_notice = reward_notice + self.task = task def __str__(self) -> str: message_all = '' if self.success: - message_all = f'用户:{self.user_name}\n'\ - f'签到:本月已签到{self.signin_count}次\n'\ - f'备注:{self.reward_notice}' + message_all = f'用户:{self.user_name}\n' \ + f'签到:本月已签到{self.signin_count}次\n' \ + f'奖励:{self.reward_notice}\n' \ + f'任务:\n' \ + f'{self.task}' else: message_all = f'签到失败\n错误信息:{self.message}' diff --git a/aliyunpan.jpg b/aliyunpan.jpg new file mode 100644 index 00000000..82777e27 Binary files /dev/null and b/aliyunpan.jpg differ diff --git a/main.py b/main.py index 8f33d89a..e992b34f 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,11 @@ +import logging import os import re import argparse from aliyundrive import Aliyundrive from message_send import MessageSend + def main(): parser = argparse.ArgumentParser() parser.add_argument('--token_string', type=str, required=True) @@ -12,6 +14,7 @@ def main(): token_string = args.token_string pushplus_token = os.environ.get('PUSHPLUS_TOKEN') serverChan_sendkey = os.environ.get('SERVERCHAN_SENDKEY') + weCom_tokens = os.environ.get('WECOM_TOKENS') weCom_webhook = os.environ.get('WECOM_WEBHOOK') bark_deviceKey = os.environ.get('BARK_DEVICEKEY') feishu_deviceKey = os.environ.get('FEISHU_DEVICEKEY') @@ -19,6 +22,7 @@ def main(): message_tokens = { 'pushplus_token': pushplus_token, 'serverChan_token': serverChan_sendkey, + 'weCom_tokens': weCom_tokens, 'weCom_webhook': weCom_webhook, 'bark_deviceKey': bark_deviceKey, 'feishu_deviceKey': feishu_deviceKey, @@ -39,10 +43,13 @@ def main(): message_all = '\n'.join(message_all) message_all = re.sub('\n+', '\n', message_all).rstrip('\n') + logging.info(message_all) + message_send = MessageSend() message_send.send_all(message_tokens, title, message_all) print('finish') + if __name__ == '__main__': main() diff --git a/message_send.py b/message_send.py index 2fe223fc..a004e859 100644 --- a/message_send.py +++ b/message_send.py @@ -1,6 +1,7 @@ import requests import json + class MessageSend: def __init__(self): self.sender = {} @@ -70,10 +71,20 @@ def serverChan(self, sendkey, title, content): return 0 def weCom(self, tokens, title, content): - assert len(tokens) == 3 and tokens.count(None) == 0 and tokens.count("") == 0 - weCom_corpId, weCom_corpSecret, weCom_agentId = tokens + proxy_url = None + to_user = None + tokens = tokens.split(",") + if len(tokens) == 3: + weCom_corpId, weCom_corpSecret, weCom_agentId = tokens + elif len(tokens) == 4: + weCom_corpId, weCom_corpSecret, weCom_agentId, to_user = tokens + elif len(tokens) == 5: + weCom_corpId, weCom_corpSecret, weCom_agentId, to_user, proxy_url = tokens + else: + return -1 - get_token_url = f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={weCom_corpId}&corpsecret={weCom_corpSecret}" + qy_url = proxy_url or "https://qyapi.weixin.qq.com" + get_token_url = f"{qy_url}/cgi-bin/gettoken?corpid={weCom_corpId}&corpsecret={weCom_corpSecret}" resp = requests.get(get_token_url) resp_json = resp.json() if resp_json["errcode"] != 0: @@ -81,13 +92,20 @@ def weCom(self, tokens, title, content): access_token = resp_json.get('access_token') if access_token is None or len(access_token) == 0: return -1 - send_msg_url = f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={access_token}' + send_msg_url = f'{qy_url}/cgi-bin/message/send?access_token={access_token}' data = { - "touser": "@all", + "touser": to_user or "@all", "agentid": weCom_agentId, - "msgtype": "markdown", - "markdown": { - "content": content + "msgtype": "news", + "news": { + "articles": [ + { + "title": title, + "description": content, + "picurl": "https://raw.githubusercontent.com/thsrite/aliyundrive-checkin/main/aliyunpan.jpg", + "url": '' + } + ] }, "duplicate_check_interval": 600 } @@ -160,12 +178,12 @@ def feishu(self, device_key, title, content): "zh_cn": { "title": title, "content": [ - [ - { - "tag": "text", - "text": content, - } - ] + [ + { + "tag": "text", + "text": content, + } + ] ] } }