From a245b37f648cb26e377cf2a2f1112f2cad36a2c2 Mon Sep 17 00:00:00 2001 From: yixiu Date: Wed, 13 Nov 2024 15:06:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/69yuncheckin2.yaml | 13 +- 69yun2.py | 278 +++++++++++++++++++++++++++ 2 files changed, 281 insertions(+), 10 deletions(-) create mode 100644 69yun2.py diff --git a/.github/workflows/69yuncheckin2.yaml b/.github/workflows/69yuncheckin2.yaml index e677303..6554c84 100644 --- a/.github/workflows/69yuncheckin2.yaml +++ b/.github/workflows/69yuncheckin2.yaml @@ -22,24 +22,17 @@ jobs: # 不需要手动列出每个USER和PASS,脚本会自动识别它们 steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v2 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v2 with: python-version: '3.9' - - name: Make script executable - run: chmod +x ./generate_config.sh # 赋予执行权限 - - - name: Generate config.json - run: | - echo "Generating config.json based on environment variables..." - ./generate_config.sh - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt # 假设你的项目有 requirements.txt - name: Run Python script - run: python 69yun.py # 执行你的 Python 脚本 + run: python 69yun2.py # 执行你的 Python 脚本 diff --git a/69yun2.py b/69yun2.py new file mode 100644 index 0000000..14c54c1 --- /dev/null +++ b/69yun2.py @@ -0,0 +1,278 @@ +import os +import json +import requests +import time +from bs4 import BeautifulSoup +import re +from datetime import datetime, timedelta + +# 配置文件路径 +config_file_path = "config.json" +签到结果 = "" + +# 获取html中的用户信息 +def fetch_and_extract_info(domain,headers): + url = f"{domain}/user" + + # 发起 GET 请求 + response = requests.get(url, headers=headers) + + if response.status_code != 200: + print("用户信息获取失败,页面打开异常.") + return None + + # 解析网页内容 + soup = BeautifulSoup(response.text, 'html.parser') + + # 找到所有 script 标签 + script_tags = soup.find_all('script') + + # 提取 ChatraIntegration 的 script 内容 + chatra_script = None + for script in script_tags: + if 'window.ChatraIntegration' in str(script): + chatra_script = script.string + break + + if not chatra_script: + print("未识别到用户信息") + return None + + # 使用正则表达式提取需要的信息 + # 提取用户名、邮箱、到期时间和剩余流量 + user_info = {} + # user_info['用户名'] = re.search(r"name: '(.*?)'", chatra_script).group(1) if re.search(r"name: '(.*?)'", chatra_script) else None + # user_info['邮箱'] = re.search(r"email: '(.*?)'", chatra_script).group(1) if re.search(r"email: '(.*?)'", chatra_script) else None + user_info['到期时间'] = re.search(r"'Class_Expire': '(.*?)'", chatra_script).group(1) if re.search(r"'Class_Expire': '(.*?)'", chatra_script) else None + user_info['剩余流量'] = re.search(r"'Unused_Traffic': '(.*?)'", chatra_script).group(1) if re.search(r"'Unused_Traffic': '(.*?)'", chatra_script) else None + + # 输出用户信息 + 用户信息 = f"到期时间: {user_info['到期时间']}\n剩余流量: {user_info['剩余流量']}\n" + # print(f"到期时间: {user_info['到期时间']}") + # print(f"剩余流量: {user_info['剩余流量']}") + + # 提取 Clash 订阅链接 + clash_link = None + for script in script_tags: + if 'index.oneclickImport' in str(script) and 'clash' in str(script): + link = re.search(r"'https://checkhere.top/link/(.*?)\?sub=1'", str(script)) + if link: + 用户信息 += f"Clash 订阅链接: https://checkhere.top/link/{link.group(1)}?clash=1\nv2ray 订阅链接: https://checkhere.top/link/{link.group(1)}?sub=3\n\n" + # print(f"Clash 订阅链接: https://checkhere.top/link/{link.group(1)}?clash=1") + # print(f"v2ray 订阅链接: https://checkhere.top/link/{link.group(1)}?sub=3") + break + return 用户信息 + +def generate_config(): + # 获取环境变量 + domain = os.getenv('DOMAIN', 'https://69yun69.com') # 默认值,如果未设置环境变量 + bot_token = os.getenv('BOT_TOKEN') + chat_id = os.getenv('CHAT_ID') + + if not bot_token or not chat_id: + raise ValueError("BOT_TOKEN 和 CHAT_ID 是必需的环境变量。") + + # 获取用户和密码的环境变量 + accounts = [] + index = 1 + + while True: + user = os.getenv(f'USER{index}') + password = os.getenv(f'PASS{index}') + + if not user or not password: + break # 如果没有找到更多的用户信息,则退出循环 + + accounts.append({ + 'user': user, + 'pass': password + }) + index += 1 + + # 构造配置数据 + config = { + 'domain': domain, + 'BotToken': bot_token, + 'ChatID': chat_id, + 'accounts': accounts + } + print(config) + return config + + +# 发送消息到 Telegram Bot 的函数,支持按钮 +def send_message(msg="", BotToken="", ChatID=""): + # 获取当前 UTC 时间,并转换为北京时间(+8小时) + now = datetime.utcnow() + beijing_time = now + timedelta(hours=8) + formatted_time = beijing_time.strftime("%Y-%m-%d %H:%M:%S") + + # 打印调试信息 + # print(msg) + + # 如果 Telegram Bot Token 和 Chat ID 都配置了,则发送消息 + if BotToken != '' and ChatID != '': + # 构建消息内容 + message_text = f"执行时间: {formatted_time}\n{msg}" + + # 构造按钮的键盘布局 + keyboard = { + "inline_keyboard": [ + [ + { + "text": "一休交流群", + "url": "https://t.me/yxjsjl" + } + ] + ] + } + + # 发送消息时附带内联按钮 + url = f"https://api.telegram.org/bot{BotToken}/sendMessage" + payload = { + "chat_id": ChatID, + "text": message_text, + "parse_mode": "HTML", + "reply_markup": json.dumps(keyboard) + } + + try: + # 发送 POST 请求 + response = requests.post(url, data=payload) + return response + except Exception as e: + print(f"发送电报消息时发生错误: {str(e)}") + return None + +# 登录并签到的主要函数 +def checkin(account, domain, BotToken, ChatID): + user = account['user'] + pass_ = account['pass'] + + 签到结果 = f"地址: {domain[:9]}****{domain[-5:]}\n账号: {user[:1]}****{user[-5:]}\n密码: {pass_[:1]}****{pass_[-1]}\n\n" + + try: + # 检查必要的配置参数是否存在 + if not domain or not user or not pass_: + raise ValueError('必需的配置参数缺失') + + # 登录请求的 URL + login_url = f"{domain}/auth/login" + + # 登录请求的 Payload(请求体) + login_data = { + 'email': user, + 'passwd': pass_, + 'remember_me': 'on', + 'code': "", + } + + # 设置请求头 + login_headers = { + 'Content-Type': 'application/json', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36', + 'Accept': 'application/json, text/plain, */*', + 'Origin': domain, + 'Referer': f"{domain}/auth/login", + } + + # 发送登录请求 + login_response = requests.post(login_url, json=login_data, headers=login_headers) + + print(f'{user}账号登录状态:', login_response.status_code) + + # 如果响应状态不是200,表示登录失败 + if login_response.status_code != 200: + raise ValueError(f"登录请求失败: {login_response.text}") + + # 解析登录响应的 JSON 数据 + login_json = login_response.json() + # print(f'{user}账号登录后返回的用户信息:', login_json) + + # 检查登录是否成功 + if login_json.get("ret") != 1: + raise ValueError(f"登录失败: {login_json.get('msg', '未知错误')}") + + # 获取登录成功后的 Cookie + cookies = login_response.cookies + if not cookies: + raise ValueError('登录成功但未收到Cookie') + + # print('Received cookies:', cookies) + + # 等待确保登录状态生效 + time.sleep(1) + + # 签到请求的 URL + checkin_url = f"{domain}/user/checkin" + + # 签到请求的 Headers + checkin_headers = { + 'Cookie': '; '.join([f"{key}={value}" for key, value in cookies.items()]), + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36', + 'Accept': 'application/json, text/plain, */*', + 'Content-Type': 'application/json', + 'Origin': domain, + 'Referer': f"{domain}/user/panel", + 'X-Requested-With': 'XMLHttpRequest' + } + + # 发送签到请求 + checkin_response = requests.post(checkin_url, headers=checkin_headers) + + print(f'{user}账号签到状态:', checkin_response.status_code) + + # 获取签到请求的响应内容 + response_text = checkin_response.text + # print(f'{user}账号签到响应内容:', response_text) + + + try: + # 尝试解析签到的 JSON 响应 + checkin_result = checkin_response.json() + # print(f'{user}账号签到后的json信息:', checkin_result) + 账号信息 = f"地址: {domain}\n账号: {user}\n密码: {pass_}\n" + + 用户信息 = fetch_and_extract_info(domain,checkin_headers) + + # 账号信息的展示,注意密码用 标签隐藏 + # 根据返回的结果更新签到信息 + if checkin_result.get('ret') == 1 or checkin_result.get('ret') == 0: + 签到结果 = f"🎉 签到结果 🎉\n {checkin_result.get('msg', '签到成功' if checkin_result['ret'] == 1 else '签到失败')}" + else: + 签到结果 = f"🎉 签到结果 🎉\n {checkin_result.get('msg', '签到结果未知')}" + except Exception as e: + # 如果出现解析错误,检查是否由于登录失效 + if "登录" in response_text: + raise ValueError('登录状态无效,请检查Cookie处理') + raise ValueError(f"解析签到响应失败: {str(e)}\n\n原始响应: {response_text}") + + # 发送签到结果到 Telegram + send_message(账号信息 + 用户信息 + 签到结果, BotToken, ChatID) + return 签到结果 + + except Exception as error: + # 捕获异常,打印错误并发送错误信息到 Telegram + print(f'{user}账号签到异常:', error) + 签到结果 = f"签到过程发生错误: {error}" + send_message(签到结果, BotToken, ChatID) + return 签到结果 + +# 主程序执行逻辑 +if __name__ == "__main__": + # 检查环境变量 config 是否存在,如果存在则更新 config.json + # write_config_from_env() + + # 读取配置 + config = generate_config() + + # 读取全局配置 + domain = config['domain'] + BotToken = config['BotToken'] + ChatID = config['ChatID'] + + # 循环执行每个账号的签到任务 + for account in config.get("accounts", []): + print("----------------------------------签到信息----------------------------------") + print(checkin(account, domain, BotToken, ChatID)) + print("---------------------------------------------------------------------------")