Skip to content

Commit 789234c

Browse files
authored
Merge branch 'main' into main
2 parents 044aec8 + 2e7415e commit 789234c

4 files changed

Lines changed: 141 additions & 57 deletions

File tree

.github/workflows/daily-check-in.yml

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,61 @@ name: Daily Check-in
22

33
on:
44
schedule:
5-
- cron: '0 1 * * *' # 每天1点 UTC 时间执行
5+
#- cron: '0 1 * * *' # 每天1点 UTC 时间执行
6+
- cron: '0 */12 * * *' # 每12小时执行一次
7+
68
workflow_dispatch:
79

810
jobs:
911
run_script:
10-
runs-on: ubuntu-latest
12+
runs-on: ubuntu-22.04
1113
steps:
1214
- uses: actions/checkout@v4
15+
1316
- name: Set up Python
1417
uses: actions/setup-python@v5
1518
with:
1619
python-version: '3.9.19'
1720

18-
- name: Install dependencies
21+
- name: Install python dependencies
1922
run: |
2023
python -m pip install --upgrade pip
2124
pip install -r requirements.txt
22-
playwright install firefox
25+
playwright install --with-deps firefox
2326
2427
- name: Execute script
2528
env:
2629
USERNAME: ${{ secrets.USERNAME }}
2730
PASSWORD: ${{ secrets.PASSWORD }}
2831
run: |
2932
python main.py
33+
34+
- name: Send Telegram Notification
35+
env:
36+
TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
37+
TELEGRAM_USERID: ${{ secrets.TELEGRAM_USERID }}
38+
if: ${{ success() && env.TELEGRAM_TOKEN != '' && env.TELEGRAM_USERID != '' }}
39+
run: |
40+
curl -s -X POST "https://api.telegram.org/bot${{ env.TELEGRAM_TOKEN }}/sendMessage" \
41+
-d chat_id=${{ env.TELEGRAM_USERID }} \
42+
-d parse_mode=HTML \
43+
-d text="✅ <b>LINUX DO</b> 每日签到成功完成"
44+
45+
- name: Send Failure Notification
46+
env:
47+
TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
48+
TELEGRAM_USERID: ${{ secrets.TELEGRAM_USERID }}
49+
if: ${{ failure() && env.TELEGRAM_TOKEN != '' && env.TELEGRAM_USERID != '' }}
50+
run: |
51+
curl -s -X POST "https://api.telegram.org/bot${{ env.TELEGRAM_TOKEN }}/sendMessage" \
52+
-d chat_id=${{ env.TELEGRAM_USERID }} \
53+
-d parse_mode=HTML \
54+
-d text="❌ <b>LINUX DO</b> 每日签到失败"
55+
56+
- name: Delete workflow runs
57+
uses: Mattraks/delete-workflow-runs@v2
58+
with:
59+
token: ${{ github.token }}
60+
repository: ${{ github.repository }}
61+
retain_days: 10
62+
keep_minimum_runs: 6

README.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
[English](./README_en.md)
2-
31
# LinuxDo 每日签到(每日打卡)
42

53
## 项目描述
@@ -25,7 +23,7 @@
2523
- 重复上述步骤,这次输入 `PASSWORD` 作为 `Name`,相应的密码作为 `Value`
2624

2725
### GitHub Actions 自动运行
28-
此项目的 GitHub Actions 配置会自动每天零点 UTC 时间运行签到脚本。你无需进行任何操作即可启动此自动化任务。GitHub Actions 的工作流文件位于 `.github/workflows` 目录下,文件名为 `daily-check-in.yml`
26+
此项目的 GitHub Actions 配置会自动每天 UTC 时间1点运行签到脚本。你无需进行任何操作即可启动此自动化任务。GitHub Actions 的工作流文件位于 `.github/workflows` 目录下,文件名为 `daily-check-in.yml`
2927

3028
如果你需要手动触发此工作流,可以通过以下步骤操作:
3129

@@ -35,8 +33,27 @@
3533

3634
## 运行结果
3735

36+
### 网页中查看
3837
`Actions`栏 -> 点击最新的`Daily Check-in` workflow run -> `run_script` -> `Execute script`
3938

4039
可看到`Connect Info`
4140
(新号可能这里为空,多挂几天就有了)
4241
![image](https://github.com/user-attachments/assets/853549a5-b11d-4d5a-9284-7ad2f8ea698b)
42+
43+
### Telegram 通知
44+
45+
可选功能:配置 Telegram 通知,实时获取签到结果。
46+
47+
需要在 GitHub Secrets 中配置:
48+
- `TELEGRAM_TOKEN`:Telegram Bot Token
49+
- `TELEGRAM_USERID`:Telegram 用户 ID
50+
51+
获取方法:
52+
1. Bot Token:与 [@BotFather](https://t.me/BotFather) 对话创建机器人获取
53+
2. 用户 ID:与 [@userinfobot](https://t.me/userinfobot) 对话获取
54+
55+
未配置时将自动跳过通知功能,不影响签到。
56+
57+
## 自动更新
58+
59+
默认状态下自动更新是关闭的,[点击此处](https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web/blob/main/README_CN.md#%E6%89%93%E5%BC%80%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0)查看打开自动更新步骤。

README_en.md

Lines changed: 0 additions & 33 deletions
This file was deleted.

main.py

Lines changed: 84 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,36 @@
11
import os
22
import random
33
import time
4+
import functools
5+
import sys
46

57
from loguru import logger
68
from playwright.sync_api import sync_playwright
79
from tabulate import tabulate
810

11+
12+
def retry_decorator(retries=3):
13+
def decorator(func):
14+
@functools.wraps(func)
15+
def wrapper(*args, **kwargs):
16+
for attempt in range(retries):
17+
try:
18+
return func(*args, **kwargs)
19+
except Exception as e:
20+
if attempt == retries - 1: # 最后一次尝试
21+
logger.error(f"函数 {func.__name__} 最终执行失败: {str(e)}")
22+
logger.warning(f"函数 {func.__name__}{attempt + 1}/{retries} 次尝试失败: {str(e)}")
23+
time.sleep(1)
24+
return None
25+
26+
return wrapper
27+
28+
return decorator
29+
30+
31+
os.environ.pop("DISPLAY", None)
32+
os.environ.pop("DYLD_LIBRARY_PATH", None)
33+
934
USERNAME = os.environ.get("USERNAME")
1035
PASSWORD = os.environ.get("PASSWORD")
1136

@@ -21,7 +46,7 @@ def __init__(self) -> None:
2146
self.page.goto(HOME_URL)
2247

2348
def login(self):
24-
logger.info("Login")
49+
logger.info("开始登录")
2550
self.page.click(".login-button .d-button-label")
2651
time.sleep(2)
2752
self.page.fill("#login-account-name", USERNAME)
@@ -32,36 +57,78 @@ def login(self):
3257
time.sleep(10)
3358
user_ele = self.page.query_selector("#current-user")
3459
if not user_ele:
35-
logger.error("Login failed")
60+
logger.error("登录失败")
3661
return False
3762
else:
38-
logger.info("Login success")
63+
logger.info("登录成功")
3964
return True
4065

4166
def click_topic(self):
42-
for topic in self.page.query_selector_all("#list-area .title"):
43-
logger.info("Click topic: " + topic.get_attribute("href"))
44-
page = self.context.new_page()
45-
page.goto(HOME_URL + topic.get_attribute("href"))
46-
time.sleep(3)
47-
if random.random() < 0.02: # 100 * 0.02 * 30 = 60
48-
self.click_like(page)
49-
time.sleep(3)
50-
page.close()
67+
topic_list = self.page.query_selector_all("#list-area .title")
68+
logger.info(f"发现 {len(topic_list)} 个主题帖")
69+
for topic in topic_list:
70+
self.click_one_topic(topic.get_attribute("href"))
71+
72+
@retry_decorator()
73+
def click_one_topic(self, topic_url):
74+
page = self.context.new_page()
75+
page.goto(HOME_URL + topic_url)
76+
if random.random() < 0.3: # 0.3 * 30 = 9
77+
self.click_like(page)
78+
self.browse_post(page)
79+
page.close()
80+
81+
def browse_post(self, page):
82+
prev_url = None
83+
# 开始自动滚动,最多滚动10次
84+
for _ in range(10):
85+
# 随机滚动一段距离
86+
scroll_distance = random.randint(550, 650) # 随机滚动 550-650 像素
87+
logger.info(f"向下滚动 {scroll_distance} 像素...")
88+
page.evaluate(f"window.scrollBy(0, {scroll_distance})")
89+
logger.info(f"已加载页面: {page.url}")
90+
91+
if random.random() < 0.03: # 33 * 4 = 132
92+
logger.success("随机退出浏览")
93+
break
94+
95+
# 检查是否到达页面底部
96+
at_bottom = page.evaluate("window.scrollY + window.innerHeight >= document.body.scrollHeight")
97+
current_url = page.url
98+
if current_url != prev_url:
99+
prev_url = current_url
100+
elif at_bottom and prev_url == current_url:
101+
logger.success("已到达页面底部,退出浏览")
102+
break
103+
104+
# 动态随机等待
105+
wait_time = random.uniform(2, 4) # 随机等待 2-4 秒
106+
logger.info(f"等待 {wait_time:.2f} 秒...")
107+
time.sleep(wait_time)
51108

52109
def run(self):
53110
if not self.login():
54-
return
111+
logger.error("登录失败,程序终止")
112+
sys.exit(1) # 使用非零退出码终止整个程序
55113
self.click_topic()
56114
self.print_connect_info()
57115

58116
def click_like(self, page):
59-
logger.info("Click like")
60-
page.locator(".discourse-reactions-reaction-button").first.click()
61-
logger.info("Like success")
117+
try:
118+
# 专门查找未点赞的按钮
119+
like_button = page.locator('.discourse-reactions-reaction-button[title="点赞此帖子"]').first
120+
if like_button:
121+
logger.info("找到未点赞的帖子,准备点赞")
122+
like_button.click()
123+
logger.info("点赞成功")
124+
time.sleep(random.uniform(1, 2))
125+
else:
126+
logger.info("帖子可能已经点过赞了")
127+
except Exception as e:
128+
logger.error(f"点赞失败: {str(e)}")
62129

63130
def print_connect_info(self):
64-
logger.info("Print connect info")
131+
logger.info("获取连接信息")
65132
page = self.context.new_page()
66133
page.goto("https://connect.linux.do/")
67134
rows = page.query_selector_all("table tr")

0 commit comments

Comments
 (0)