diff --git a/Points_Based/Enshan_sign.py b/Points_Based/Enshan_sign.py
new file mode 100644
index 0000000..592c296
--- /dev/null
+++ b/Points_Based/Enshan_sign.py
@@ -0,0 +1,366 @@
+# cron "0 9 2 * * *
+# const $ = new Env('恩山签到')
+# -*- coding: utf-8 -*-
+import os
+import re
+import time
+import random
+import requests
+from DrissionPage import ChromiumPage, ChromiumOptions
+
+USER_AGENT = "Mozilla/5.0 (Linux; Android 13; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36"
+CACHE_FILE = "enshan_users.txt" # Cookie 缓存文件
+
+def random_wait():
+ delay = random.randint(0, 900)
+ print(f"🎲 随机延迟启动: 将在 {delay} 秒后开始执行任务...")
+ time.sleep(delay)
+ print("⏰ 倒计时结束,任务开始!")
+
+def force_kill_chrome():
+ print("🧹 正在清理残留的浏览器进程...")
+ try:
+ os.system("pkill -f chromium")
+ os.system("pkill -f chrome")
+ time.sleep(2)
+ except:
+ pass
+
+def push_pushplus(token, content):
+ if not token:
+ return
+ url = "https://www.pushplus.plus/send"
+ data = {"token": token, "title": "恩山签到结果", "content": content}
+ try:
+ requests.post(url, json=data)
+ print("📨 PushPlus 通知已发送")
+ except Exception as e:
+ print(f"❌ 推送失败: {e}")
+
+def get_cookies_safe(page):
+ try:
+ ret = page.run_cdp('Network.getCookies')
+ cookies_list = ret.get('cookies', [])
+ return "; ".join([f"{item['name']}={item['value']}" for item in cookies_list])
+ except Exception as e:
+ print(f"❌ 获取 Cookie 异常: {e}")
+ return ""
+
+def extract_regex(pattern, text, default="0"):
+ try:
+ match = re.search(pattern, text)
+ return match.group(1).strip() if match else default
+ except:
+ return default
+
+def load_cache():
+ """从本地缓存文件读取 {uid: cookie} 字典"""
+ cache = {}
+ if not os.path.exists(CACHE_FILE):
+ return cache
+ with open(CACHE_FILE, 'r', encoding='utf-8') as f:
+ for line in f:
+ line = line.strip()
+ if not line or line.startswith('#'):
+ continue
+ if '#' in line:
+ parts = line.split('#', 1)
+ uid = parts[0].strip()
+ cookie = parts[1].strip()
+ if uid and cookie:
+ cache[uid] = cookie
+ return cache
+
+def save_cache(cache):
+ """将 {uid: cookie} 字典写入缓存文件"""
+ with open(CACHE_FILE, 'w', encoding='utf-8') as f:
+ for uid, cookie in cache.items():
+ f.write(f"{uid}#{cookie}\n")
+ print(f"💾 Cookie 缓存已更新至 {CACHE_FILE}")
+
+def parse_env_users():
+ """从环境变量 ENS_CK 解析用户列表,返回 {uid: cookie} 字典"""
+ ens_ck = os.environ.get('ENS_CK')
+ if not ens_ck:
+ return {}
+ users = {}
+ for line in ens_ck.strip().splitlines():
+ line = line.strip()
+ if not line or line.startswith('#'):
+ continue
+ if '#' in line:
+ parts = line.split('#', 1)
+ uid = parts[0].strip()
+ cookie = parts[1].strip()
+ if uid and cookie:
+ users[uid] = cookie
+ return users
+
+def sign_for_user(uid, cookie, push_token):
+ """执行单用户签到,返回 (成功否, 消息, 新cookie)"""
+ print(f"\n========== 开始处理用户 UID: {uid} ==========")
+ co = ChromiumOptions()
+ co.set_argument('--no-sandbox')
+ co.set_argument('--disable-gpu')
+ co.set_argument('--disable-dev-shm-usage')
+ co.set_argument('--headless=new')
+ co.set_argument('--window-size=375,812')
+ if os.path.exists("/usr/bin/chromium-browser"):
+ co.set_paths(browser_path="/usr/bin/chromium-browser")
+ elif os.path.exists("/usr/bin/chromium"):
+ co.set_paths(browser_path="/usr/bin/chromium")
+ co.set_user_agent(user_agent=USER_AGENT)
+
+ page = None
+ for attempt in range(2):
+ try:
+ force_kill_chrome()
+ page = ChromiumPage(co)
+ break
+ except Exception as e:
+ print(f"⚠️ 浏览器启动失败 (第 {attempt+1} 次尝试): {e}")
+ time.sleep(3)
+ if not page:
+ error_msg = "浏览器连续启动失败"
+ print(f"❌ {error_msg}")
+ push_pushplus(push_token, f"用户 {uid} 签到失败:{error_msg}")
+ return False, error_msg, cookie
+
+ try:
+ print("1. 访问主页确立作用域...")
+ page.get('https://www.right.com.cn/forum/forum.php?mobile=2')
+ try:
+ page.set.cookies(cookie)
+ except:
+ pass
+ print("2. 刷新页面并过盾...")
+ page.refresh()
+ time.sleep(5)
+ title = page.title
+ if "安全" in title or "验证" in title:
+ print("🛡️ 检测到防火墙拦截,正在等待自动跳转...")
+ time.sleep(15)
+
+ print("3. 正在获取签到信息...")
+ check_url = "https://www.right.com.cn/forum/erling_qd-sign_in_m.html"
+ page.get(check_url)
+ time.sleep(3)
+ is_signed = False
+ html = page.html
+
+ formhash = extract_regex(r"var FORMHASH = '([0-9a-zA-Z]+)'", html, "")
+ if not formhash:
+ formhash = extract_regex(r'name="formhash" value="([0-9a-zA-Z]+)"', html, "")
+ if not formhash:
+ formhash = extract_regex(r'formhash=([0-9a-zA-Z]+)', html, "")
+
+ if not formhash:
+ try:
+ body_text = page.ele('tag:body').text
+ if "登录" in body_text or "Login" in body_text:
+ error_msg = "Cookie 已失效,变为游客状态"
+ print(f"❌ {error_msg}")
+ push_pushplus(push_token, f"用户 {uid} 签到失败:{error_msg},请更新环境变量 ENS_CK 中的 Cookie。")
+ return False, error_msg, cookie
+ except:
+ pass
+
+ try:
+ body_text = page.ele('tag:body').text
+ if "连续签到" in body_text and "立即签到" not in body_text:
+ is_signed = True
+ print("ℹ️ 状态: 今天已经签到过了。")
+ except:
+ pass
+
+ if not formhash and not is_signed:
+ error_msg = "无法提取 formhash (可能页面结构改变)"
+ print(f"❌ {error_msg}")
+ push_pushplus(push_token, f"用户 {uid} 签到失败:{error_msg}")
+ return False, error_msg, cookie
+
+ if formhash:
+ print(f"🔑 获取 Formhash 成功: {formhash}")
+
+ sign_success = False
+ sign_msg = "已签到"
+
+ if not is_signed:
+ sign_api = "https://www.right.com.cn/forum/plugin.php?id=erling_qd:action&action=sign"
+ print("🚀 正在发送签到请求...")
+ js_code = f"""
+ return fetch("{sign_api}", {{
+ method: "POST",
+ headers: {{
+ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
+ "X-Requested-With": "XMLHttpRequest"
+ }},
+ body: "formhash={formhash}"
+ }}).then(response => response.json());
+ """
+ try:
+ result = page.run_js(js_code)
+ print(f"📥 签到接口返回: {result}")
+ if result and (result.get('success') or "已经签到" in str(result)):
+ sign_success = True
+ sign_msg = result.get('message', '签到成功')
+ else:
+ sign_msg = result.get('message', '未知错误') if result else "接口无响应"
+ except Exception as js_err:
+ print(f"❌ JS 执行异常: {js_err}")
+ sign_success = False
+ sign_msg = "JS执行失败或WAF拦截"
+ else:
+ sign_success = True
+
+ if sign_success:
+ print("4. 正在获取最终积分数据...")
+ page.get(check_url)
+ time.sleep(2)
+ sign_html = page.html
+ today_points = extract_regex(r'erqd-current-point[^>]*>(\d+)', sign_html, "未知")
+ if today_points == "未知":
+ today_points = extract_regex(r'今日积分.*?(\d+)', sign_html, "未知")
+ continuous_days = extract_regex(r'erqd-continuous-days[^>]*>(\d+)', sign_html, "未知")
+ if continuous_days == "未知":
+ continuous_days = extract_regex(r'连续签到.*?(\d+)', sign_html, "未知")
+ total_days = extract_regex(r'erqd-total-days[^>]*>(\d+)', sign_html, "未知")
+ if total_days == "未知":
+ total_days = extract_regex(r'总签到天数.*?(\d+)', sign_html, "未知")
+
+ print("🔄 正在刷新积分缓存...")
+ credit_log_url = "https://www.right.com.cn/forum/home.php?mod=spacecp&ac=credit&op=log&mobile=2"
+ page.get(credit_log_url)
+ time.sleep(2)
+
+ profile_url = f"https://www.right.com.cn/forum/home.php?mod=space&uid={uid}&do=profile&mycenter=1&mobile=2"
+ print(f"📥 正在抓取个人资料页 (UID: {uid})...")
+ page.get(profile_url)
+
+ total_points = "未知"
+ contribution = "未知"
+ enshan_coin = "未知"
+
+ try:
+ time.sleep(5)
+ all_lis = page.eles('tag:li')
+ for li in all_lis:
+ clean_text = li.text.replace(" ", "").replace("\n", "").replace("\r", "")
+ if not clean_text:
+ continue
+ if ("积分" in clean_text and "今日" not in clean_text) or "Points" in clean_text:
+ match_cn = re.search(r'(\d+)积分', clean_text)
+ match_en = re.search(r'(\d+)Points', clean_text)
+ if match_cn:
+ total_points = match_cn.group(1)
+ elif match_en:
+ total_points = match_en.group(1)
+ if "贡献" in clean_text or "Contributions" in clean_text:
+ match_cn = re.search(r'(\d+)分贡献', clean_text)
+ match_en = re.search(r'(\d+)pointsContributions', clean_text)
+ if match_cn:
+ contribution = match_cn.group(1)
+ elif match_en:
+ contribution = match_en.group(1)
+ if "恩山币" in clean_text or "EnshanCoin" in clean_text:
+ match_cn = re.search(r'(\d+)币恩山币', clean_text)
+ match_en = re.search(r'(\d+)coinsEnshanCoin', clean_text)
+ if match_cn:
+ enshan_coin = match_cn.group(1)
+ elif match_en:
+ enshan_coin = match_en.group(1)
+ print(f"📊 抓取结果: 积分={total_points}, 贡献={contribution}, 币={enshan_coin}")
+ except Exception as e:
+ print(f"❌ 数据解析异常: {e}")
+
+ new_cookie = get_cookies_safe(page)
+ if not new_cookie:
+ new_cookie = cookie
+
+ notify_content = (
+ f"✅ 用户 {uid} 签到成功!🎊
"
+ f"📊 积分统计如下:
"
+ f"===========
"
+ f"今日积分:{today_points}
"
+ f"连续签到:{continuous_days} 天
"
+ f"总签到天数:{total_days} 天
"
+ f"总积分:{total_points}
"
+ f"贡献分:{contribution} 分
"
+ f"恩山币:{enshan_coin} 币"
+ )
+
+ print("=== 推送内容预览 ===")
+ print(notify_content.replace("
", "\n"))
+ push_pushplus(push_token, notify_content)
+
+ return True, "签到成功", new_cookie
+ else:
+ error_msg = f"签到失败:{sign_msg}"
+ print(f"❌ {error_msg}")
+ push_pushplus(push_token, f"用户 {uid} 签到失败:{sign_msg}")
+ return False, error_msg, cookie
+
+ except Exception as e:
+ import traceback
+ traceback.print_exc()
+ error_msg = f"运行异常: {str(e)}"
+ push_pushplus(push_token, f"用户 {uid} 签到异常:{error_msg}")
+ return False, error_msg, cookie
+ finally:
+ try:
+ if page:
+ page.quit()
+ except:
+ pass
+ force_kill_chrome()
+
+def main():
+ random_wait()
+
+ # 1. 从环境变量读取账号列表(权威来源)
+ env_users = parse_env_users()
+ if not env_users:
+ print("❌ 环境变量 ENS_CK 未设置或为空,无法继续。")
+ return
+
+ # 2. 加载本地 Cookie 缓存
+ cache = load_cache()
+
+ # 3. 合并:优先使用缓存,若缓存不存在或环境变量中的 Cookie 与缓存不同,则使用环境变量(视为手动更新)
+ # 我们以 env_users 为基准,遍历每个 UID,决定使用的 Cookie
+ final_users = {} # {uid: cookie_to_use}
+ for uid, env_cookie in env_users.items():
+ if uid in cache:
+ cached_cookie = cache[uid]
+ # 如果环境变量中的 cookie 与缓存不同,则使用环境变量(用户可能手动更新)
+ if env_cookie != cached_cookie:
+ print(f"ℹ️ 用户 {uid} 的环境变量 Cookie 与缓存不同,将使用环境变量(视为手动更新)。")
+ final_users[uid] = env_cookie
+ else:
+ final_users[uid] = cached_cookie
+ else:
+ final_users[uid] = env_cookie # 新用户,首次使用环境变量
+
+ print(f"📋 共加载 {len(final_users)} 个用户,开始逐个签到...")
+
+ push_token = os.environ.get('PUSHPLUS_TOKEN', '')
+ new_cache = {} # 用于存储处理后的最新 Cookie
+
+ for idx, (uid, cookie) in enumerate(final_users.items(), 1):
+ print(f"\n>>> 正在处理第 {idx}/{len(final_users)} 个用户 (UID: {uid})")
+ ok, msg, new_cookie = sign_for_user(uid, cookie, push_token)
+ # 无论签到是否成功,只要有新 cookie(可能是旧 cookie 或更新后的),都保存
+ # 如果签到成功,new_cookie 是新的;如果失败,new_cookie 是原 cookie(或原样)
+ new_cache[uid] = new_cookie
+ if idx < len(final_users):
+ time.sleep(5)
+
+ # 4. 将更新后的所有 Cookie 写回缓存文件
+ save_cache(new_cache)
+
+ # 汇总信息
+ success_count = sum(1 for u in final_users if u in new_cache and new_cache[u] != '')
+ print(f"\n📊 完成,共 {len(final_users)} 个用户,成功 {success_count} 个。")
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file