Skip to content

Commit

Permalink
Merge pull request #9 from 14790897/feat_end_pic
Browse files Browse the repository at this point in the history
- 新增获取学习完成截图功能
- 消息推送包含学习完成截图
- 支持设置是否自动保存学习完成截图
- 自动学习时间修正为东八区11点30分
  • Loading branch information
vvbbnn00 authored Jan 11, 2024
2 parents fd762e5 + 5bfc429 commit 86f39d4
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/autoLearn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Learn

on:
schedule:
- cron: '30 11 * * 2' # 每周二11时30分开始学习
- cron: '30 3 * * 2' # 每周二11时30分开始学习
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#providing-inputs
workflow_dispatch:
inputs:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,5 @@ venv.bak/
.mypy_cache/
logs/
/logs/

/qndxximg
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
# 更快的快速上手

该章节适用于**已经关注了`青春上海`微信公众号****已在公众号中留有学习记录****没有更改姓名、学号等需求**的用户。
通过本章节的配置,可以让您直接使用`GitHub`中的`Actions`功能自动学习,关于这一部分内容详见 **[GitHub Actions](#推荐-github-actions)**
通过本章节的配置,可以让您直接使用`GitHub`中的`Actions`功能自动学习,关于这一部分内容详见
**[GitHub Actions](#推荐-github-actions)**

1、访问[https://vvbbnn00.github.io/qndxxAutoStudy/](https://vvbbnn00.github.io/qndxxAutoStudy/)
微信扫码,记录下获取到的`Token`

2、Fork该项目,接着,在项目的`Settings`-`Secrets and variables`-`Actions`-`Repository secrets`处新建一个`Secret`(点击New repository secret),
2、Fork该项目,接着,在项目的`Settings`-`Secrets and variables`-`Actions`-`Repository secrets`处新建一个`Secret`(点击New
repository secret),
名称为`KEY`,内容是获取到的`Token`

3、若您是初次配置,请至`Actions`,点击`I understand my workflows, go ahead and enable
Expand Down Expand Up @@ -83,6 +85,7 @@ python script.py [获取的Token]
| -wx, --wechatWebhook | 企业微信Webhook地址 | 可选,输入此选项后,在学习结束时,会自动向绑定的企业微信机器人发送消息通知。 |
| -dd, --dingdingWebhook | 钉钉Webhook地址 | 可选,输入此选项后,在学习结束时,会自动向绑定的钉钉机器人发送消息通知。 |
| -p, --proxy | 是否启用代理 | 启用该选项后,会自动获取可用代理,并通过代理发送请求 |
| -s, --savePic | 是否保存学习完成截图 | 启用该选项后,会在学习完成后保存学习完成截图,截图保存在`./qndxximg/`目录下,文件名为`endimg_{时间戳}.jpg`,若不启用该选项,则不会保存截图。 |

### 例子

Expand Down Expand Up @@ -136,11 +139,11 @@ Flask应用的端口可以随意更改,但开放Host必须能够从局域网
要使用Github Actions,您首先需要`fork`该项目,接着,在项目的`Settings`-`Actions secrets and
variables`-`Actions`-`Secrets`处新建两个Secret,名称和相应内容如下表

| 键 (Key) | 值 (Value) |
|----------------|------------------------------|
| KEY | 您获取到的Token,如果还未获取,请参考说明的前半部分 |
| WECHAT_WEBHOOK | [可选的] 您的企业微信机器人Webhook地址 |
| DINGDING_WEBHOOK | [可选的] 您的钉钉机器人Webhook地址 |
| 键 (Key) | 值 (Value) |
|------------------|------------------------------|
| KEY | 您获取到的Token,如果还未获取,请参考说明的前半部分 |
| WECHAT_WEBHOOK | [可选的] 您的企业微信机器人Webhook地址 |
| DINGDING_WEBHOOK | [可选的] 您的钉钉机器人Webhook地址 |

接着,若您是初次配置,请至`Actions`,点击`I understand my workflows, go ahead and enable
them`启用`Actions`,在左侧面板找到`Learn`,点击`Enable`启用该任务。
Expand Down
2 changes: 1 addition & 1 deletion config/api_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@
"&headimg={avatar}" \
"&callback=https%3A%2F%2Fqcsh.h5yunban.com%2Fyouth-learning%2F&scope=snsapi_userinfo"
# IP代理池地址
PROXY_POOL_URL = "https://getproxy.bzpl.tech/get/"
PROXY_POOL_URL = "https://getproxy.bzpl.tech/get/"
19 changes: 15 additions & 4 deletions script.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ def doStudy():
card_no = args.name
subOrg = args.subOrg
last_study_info = qcshService.getLastStudyInfo()

if args.savePic:
logging.info("正在尝试抓取完成截图")
pic_success, pic_path = qcshService.downloadEndPic()
if pic_success:
logging.info("抓取截图成功,已经保存到当前文件夹下的 %s", pic_path)
else:
logging.error("抓取截图失败,获取的url为 %s", pic_path)

if not args.onAction:
logging.info("最后一次学习的信息如下")
logging.info(json.dumps(last_study_info, ensure_ascii=False, indent=4))
Expand All @@ -80,7 +89,7 @@ def doStudy():
logging.info(f'学习{"成功" if success else "失败"}')
else:
logging.info(f'学习{"成功" if success else "失败"},返回信息:{ret}')
return success, ret
return success, ret, qcshService.getLatestEndPicURL()


if __name__ == '__main__':
Expand All @@ -106,12 +115,14 @@ def doStudy():
help='可选,输入此选项后,在学习结束时,会自动向绑定的钉钉机器人发送消息通知。')
parser.add_argument('-p', '--proxy', action='store_true', default=False,
help='自动从代理池中获取代理,若不指定此选项,则不使用代理')
parser.add_argument('-s', '--savePic', action='store_true', default=False,
help='自动保存学习完成截图,若不指定此选项,则不保存')
parser.add_argument('-v', '--version', help='输出当前版本号,然后退出程序', action='version',
version=f'青年大学习自动学习脚本 版本{VERSION}')
args = parser.parse_args(sys.argv[1:])

success, message = doStudy()
success, message, endPicUrl = doStudy()
if args.wechatWebhook:
wechatMessagePush(args.wechatWebhook, success, message)
wechatMessagePush(args.wechatWebhook, success, message, endPicUrl)
if args.dingdingWebhook:
dingdingMessagePush(args.dingdingWebhook, success, message)
dingdingMessagePush(args.dingdingWebhook, success, message, endPicUrl)
13 changes: 8 additions & 5 deletions services/messagePush.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
import requests


def wechatMessagePush(webhookUrl: str, success: bool, message: str):
def wechatMessagePush(webhookUrl: str, success: bool, message: str, endPicUrl: str):
"""
推送企业微信消息卡片
:param webhookUrl: 企业微信Webhook地址
:param success: 是否成功
:param message: 返回消息
:param endPicUrl: 完成截图地址
:return:
"""
messageTemplate = {
Expand All @@ -31,7 +32,7 @@ def wechatMessagePush(webhookUrl: str, success: bool, message: str):
},
"main_title": {
"title": "任务完成",
"desc": "定时任务已完成,以下是任务报告"
"desc": "定时任务已完成,以下是任务报告(点击查看截图)"
},
"emphasis_content": {
"title": "学习成功" if success else "学习失败",
Expand All @@ -46,7 +47,7 @@ def wechatMessagePush(webhookUrl: str, success: bool, message: str):
"jump_list": [],
"card_action": {
"type": 1,
"url": "http://news.cyol.com/gb/channels/vrGlAKDl/index.html",
"url": endPicUrl or "https://www.dayimen.net/Public/image/party_2.jpeg"
}
}
}
Expand All @@ -57,13 +58,14 @@ def wechatMessagePush(webhookUrl: str, success: bool, message: str):
logging.info("wechatMessagePush 请求失败")


def dingdingMessagePush(webhookUrl: str, success: bool, message: str):
def dingdingMessagePush(webhookUrl: str, success: bool, message: str, endPicUrl: str):
"""
推送钉钉消息卡片
:param webhookUrl: 钉钉Webhook地址
:param success: 是否成功
:param message: 返回消息
:param endPicUrl: 完成截图地址
:return:
"""
messageTemplate = {
Expand All @@ -73,7 +75,8 @@ def dingdingMessagePush(webhookUrl: str, success: bool, message: str):
"text": "#### [青年大学习](http://news.cyol.com/gb/channels/vrGlAKDl/index.html)任务完成\n" +
"![](https://www.dayimen.net/Public/image/party_2.jpeg)\n\n" +
"> " + ("学习成功" if success else "学习失败") + "\n\n" +
"> " + message + "\n"
"> " + message + "\n" +
"> [点击查看截图](" + endPicUrl + ")"
},
}
try:
Expand Down
50 changes: 50 additions & 0 deletions services/qcsh.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@
"""
import json
import logging
import os
import re
import time

import requests

from config.api_config import *
from config.patterns import PATTERN_accessToken
from urllib.parse import urljoin


def getChildrenNode(pid):
"""
获取子节点
"""
ret = requests.get(QCSH_AREA_LIST_URL.format(pid=pid), headers={
'Users-Agent': USER_AGENT
}, proxies=PROXY)
Expand All @@ -34,6 +40,10 @@ def __init__(self, access_token, proxy=None):
PROXY = proxy

def login(self, login_data):
"""
通过LoginData登录青年大学习
:param login_data: 登录信息
"""
open_id = login_data.get("openid")
nickname = login_data.get("nickname")
avatar = login_data.get("headimg")
Expand All @@ -48,13 +58,50 @@ def login(self, login_data):
return self.accessToken

def getLatestInfo(self):
"""
获取最新的学习ID
"""
ret = requests.get(QCSH_STUDY_INFO_URL.format(access_token=self.accessToken), headers={
'Users-Agent': USER_AGENT
}, proxies=PROXY)
ret_json = ret.json()
return ret_json.get("result")[0].get("id")

def getLatestEndPicURL(self):
"""
获取最新的学习完成截图URL
"""
ret = requests.get(QCSH_STUDY_INFO_URL.format(access_token=self.accessToken), headers={
'Users-Agent': USER_AGENT
}, proxies=PROXY)
ret_json = ret.json()
url = ret_json.get("result")[0].get("uri")
if url is None:
return None
return urljoin(url, "images/end.jpg")

def downloadEndPic(self):
"""
下载学习完成截图
"""
pic_url = self.getLatestEndPicURL()
if pic_url is None:
return False, '未找到截图URL'
timestamp = int(time.time() * 1000)
local_path = f"qndxximg/endimg_{timestamp}.jpg"
response = requests.get(pic_url)
if response.status_code == 200:
os.makedirs(os.path.dirname(local_path), exist_ok=True)
with open(local_path, "wb") as f:
f.write(response.content)
return True, local_path
else:
return False, pic_url

def updateStudyRecord(self, pid, student_number, subOrg=None):
"""
更新学习记录
"""
ret = requests.post(QCSH_STUDY_URL.format(access_token=self.accessToken), headers={
'Users-Agent': USER_AGENT
}, json={
Expand All @@ -69,6 +116,9 @@ def updateStudyRecord(self, pid, student_number, subOrg=None):
return False, json.dumps(ret_json, ensure_ascii=False)

def getLastStudyInfo(self):
"""
获取最后一次学习记录
"""
ret = requests.get(QCSH_STUDY_LAST_INFO_URL.format(access_token=self.accessToken), headers={
'Users-Agent': USER_AGENT
}, proxies=PROXY)
Expand Down

0 comments on commit 86f39d4

Please sign in to comment.