优化脚本

This commit is contained in:
weiqun
2025-02-13 16:25:44 +08:00
parent d008f0b2f6
commit e0eb4e7f6b
4 changed files with 368 additions and 196 deletions

View File

@@ -14,6 +14,7 @@ from Crypto.Cipher import DES3
from Crypto.Util.Padding import pad, unpad
from aiohttp import ClientSession, TCPConnector
import httpx
import logging
diffValue = 2
filename='Cache.js'
@@ -77,35 +78,50 @@ custom_client = httpx.Client(
)
)
# 添加日志记录
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
def initCookie(getUrl='https://wapact.189.cn:9001/gateway/standQuery/detailNew/exchange'):
try:
global js_code_ym, fileContent
cookie = ''
response = custom_client.post(getUrl)
response.raise_for_status()
# 解析响应内容
content = response.text.split(' content="')[2].split('" r=')[0]
code1 = response.text.split('$_ts=window')[1].split('</script><script type="text/javascript"')[0]
code1Content = '$_ts=window' + code1
Url = response.text.split('$_ts.lcd();</script><script type="text/javascript" charset="utf-8" src="')[1].split('" r=')[0]
urls = getUrl.split('/')
rsurl = urls[0] + '//' + urls[2] + Url
filename = 'Cache.js'
if fileContent == '':
if not os.path.exists(filename):
fileRes = custom_client.get(rsurl)
fileContent = fileRes.text
# 处理文件缓存
if not fileContent:
fileRes = custom_client.get(Url)
if fileRes.status_code == 200:
fileContent = fileRes.text
with open(filename, 'w', encoding='utf-8') as file:
file.write(fileRes.text)
else:
print(f"Failed to download {rsurl}. Status code: {fileRes.status_code}")
if response.headers['Set-Cookie']:
cookie = response.headers['Set-Cookie'].split(';')[0].split('=')[1]
logger.error(f"Failed to download {Url}. Status code: {fileRes.status_code}")
return None
# 处理cookies
cookie = response.headers.get('Set-Cookie', '').split(';')[0].split('=')[1]
runJs = js_code_ym.replace('content_code', content).replace("'ts_code'", code1Content + fileContent)
execjsRun = RefererCookie(runJs)
return {
'cookie': cookie,
'execjsRun': execjsRun
}
except Exception as e:
logger.error(f"初始化cookies失败: {str(e)}")
return None
def RefererCookie(runJs):
try:
execjsRun = execjs.compile(runJs)

View File

@@ -2,14 +2,14 @@
新电信抢话费
群里发的,未测试好,自测
修改内容如下
修改内容如下"
1.删除内置的一个手机账号
2.修改环境变量名保持和拉菲电信金豆本环境变量一致
3.恢复瑞数通杀.js调用地址确实也不知道是啥。398、399行注释
环境变量chinaTelecomAccount值为账号#密码
cron: 57 9,13,23 * * *
cron: 56 59 09,13 * * *
const $ = new Env("新电信抢话费");
"""
@@ -40,11 +40,27 @@ from Crypto.Util.Padding import pad, unpad
from aiohttp import ClientSession, TCPConnector
from concurrent.futures import ThreadPoolExecutor
import subprocess
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('chinatelecom.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
run_num=os.environ.get('reqNUM') or "2"
# 添加配置类
class Config:
MAX_RETRIES = 3
RATE_LIMIT = 10 # 每秒请求数限制
RATE_LIMIT = 10
REQUEST_TIMEOUT = 30
BASE_URL = "https://wapact.189.cn:9001"
USER_AGENT = "Mozilla/5.0 (Linux; Android 13; 22081212C Build/TKQ1.220829.002) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.97 Mobile Safari/537.36"
class RateLimiter:
def __init__(self, rate_limit):
@@ -427,27 +443,89 @@ async def qgNight(phone, ticket, timeDiff,isTrue):
async def qgDay(phone, ticket, timeDiff, isTrue):
async with AsyncSessionManager() as s:
pass
# 修改 RequestUtil 类
class RequestUtil:
def __init__(self):
# 在创建 ClientSession 时通过 headers 参数设置请求头
self.session = aiohttp.ClientSession(headers={"User-Agent": Config.USER_AGENT})
self.rate_limiter = RateLimiter(Config.RATE_LIMIT)
async def safe_request(self, method, url, **kwargs):
for attempt in range(Config.MAX_RETRIES):
try:
await self.rate_limiter.acquire()
async with self.session.request(method, url, timeout=Config.REQUEST_TIMEOUT, **kwargs) as response:
response.raise_for_status()
return await response.json()
except Exception as e:
if attempt == Config.MAX_RETRIES - 1:
raise
await asyncio.sleep(2 ** attempt)
async def close(self):
if self.session and not self.session.closed:
await self.session.close()
# 修改 main 函数,增加日志记录
async def main(timeDiff, isTRUE, hour):
tasks = []
config = Config()
request_util = RequestUtil()
try:
PHONES = os.environ.get('chinaTelecomAccount')
if not PHONES:
logger.error("未找到环境变量 chinaTelecomAccount")
raise ValueError("未找到环境变量 chinaTelecomAccount")
phone_list = PHONES.split('\n')
tasks = []
logger.info(f"开始处理 {len(phone_list)} 个账号")
for phoneV in phone_list:
try:
value = phoneV.split('#')
if len(value) != 2:
logger.warning(f"账号格式错误: {phoneV}")
continue
phone, password = value[0], value[1]
printn(f'{get_first_three(phone)}开始登录')
logger.info(f'{get_first_three(phone)} 开始登录')
ticket = userLoginNormal(phone, password)
if ticket:
# hour=datetime.datetime.now().hour
# hour=23
if not ticket:
logger.error(f'{get_first_three(phone)} 登录失败')
continue
logger.info(f'{get_first_three(phone)} 登录成功')
if hour > 15:
logger.info(f'{get_first_three(phone)} 加入夜间任务队列')
tasks.append(qgNight(phone, ticket, timeDiff, isTRUE))
# await asyncio.sleep(0.1)
else:#十点//十四点场次
tasks.append(qgDay(phone, ticket, timeDiff, isTRUE))
# await asyncio.sleep(0.1)
else:
printn(f'{phone} 登录失败')
await asyncio.gather(*tasks)
logger.info(f'{get_first_three(phone)} 加入日间任务队列')
tasks.append(qgDay(phone, ticket, timeDiff, isTRUE))
except Exception as e:
logger.error(f'{get_first_three(phone)} 处理失败: {str(e)}')
continue
logger.info(f"开始执行 {len(tasks)} 个任务")
results = await asyncio.gather(*tasks, return_exceptions=True)
# 记录任务执行结果
for i, result in enumerate(results, start=1): # 从1开始计数
if isinstance(result, Exception):
logger.error(f"任务 {i} 执行失败: {str(result)}")
else:
logger.info(f"任务 {i} 执行成功")
except Exception as e:
logger.error(f'主程序运行失败: {str(e)}', exc_info=True)
finally:
logger.info("正在关闭请求会话")
await request_util.close()
logger.info("程序执行完毕")
if __name__ == "__main__":
h = datetime.datetime.now().hour

View File

@@ -8,17 +8,43 @@ export Ikuuu_HOST="ikuuu.one"
cron: 33 08 * * *
const $ = new Env("ikuuu 机场签到");
*/
const { sendNotify } = require("./sendNotify"); // 引入 sendNotify.js 模块
const { sendNotify } = require("./sendNotify");
const fs = require('fs');
const path = require('path');
const host = process.env.Ikuuu_HOST || "ikuuu.one";
// 配置类
class Config {
static get HOST() {
return process.env.Ikuuu_HOST || "ikuuu.one";
}
const protocolPrefix = "https://";
const logInUrl = `${protocolPrefix}${host}/auth/login`;
const checkInUrl = `${protocolPrefix}${host}/user/checkin`;
static get PROTOCOL_PREFIX() {
return "https://";
}
function parseCookie(rawCookie) {
static get LOGIN_URL() {
return `${Config.PROTOCOL_PREFIX}${Config.HOST}/auth/login`;
}
static get CHECKIN_URL() {
return `${Config.PROTOCOL_PREFIX}${Config.HOST}/user/checkin`;
}
}
// 日志配置
const logStream = fs.createWriteStream(path.join(__dirname, 'ikuuu.log'), { flags: 'a' });
function log(level, message) {
const timestamp = new Date().toISOString();
const logMessage = `[${timestamp}] [${level}] ${message}\n`;
logStream.write(logMessage);
console.log(logMessage);
}
// Cookie 工具类
class CookieUtil {
static parseCookie(rawCookie) {
let cookieSets = rawCookie.split("path=/,");
const cookies = {};
cookieSets.forEach((cookie) => {
@@ -26,7 +52,6 @@ function parseCookie(rawCookie) {
if (match) {
const fieldName = match[1].trim();
let fieldValue = match[2].trim();
fieldValue = decodeURIComponent(fieldValue);
if (!cookies[fieldName]) {
@@ -38,51 +63,68 @@ function parseCookie(rawCookie) {
return cookies;
}
function generateCookieStr(cookieObject) {
static generateCookieStr(cookieObject) {
return Object.entries(cookieObject)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join("; ");
}
}
async function logIn(email, passwd) {
console.log(`Logging in with email: ${email}...`);
// Ikuuu 客户端类
class IkuuuClient {
constructor(email, password) {
this.email = email;
this.password = password;
}
async login() {
log('INFO', `Logging in with email: ${this.email}...`);
let formData = new FormData();
formData.append("host", host);
formData.append("email", email);
formData.append("passwd", passwd);
formData.append("host", Config.HOST);
formData.append("email", this.email);
formData.append("passwd", this.password);
formData.append("code", "");
formData.append("remember_me", "off");
let response = await fetch(logInUrl, {
try {
let response = await fetch(Config.LOGIN_URL, {
method: "POST",
body: formData,
});
let rawCookie = response.headers.get("set-cookie");
let responseJson = await response.json();
if (responseJson) {
console.log(responseJson.msg);
log('INFO', responseJson.msg);
}
return parseCookie(rawCookie);
return CookieUtil.parseCookie(rawCookie);
} catch (error) {
log('ERROR', `Login failed for ${this.email}: ${error.message}`);
throw error;
}
}
function checkIn(cookie) {
return fetch(checkInUrl, {
async checkIn(cookie) {
try {
let response = await fetch(Config.CHECKIN_URL, {
method: "POST",
headers: {
Cookie: generateCookieStr(cookie),
Cookie: CookieUtil.generateCookieStr(cookie),
},
})
.then((res) => res.json())
.then((resJson) => {
if (resJson) {
console.log(resJson.msg);
}
});
let responseJson = await response.json();
if (responseJson) {
log('INFO', responseJson.msg);
}
} catch (error) {
log('ERROR', `Check-in failed for ${this.email}: ${error.message}`);
throw error;
}
}
}
// 延迟函数,单位为毫秒
@@ -95,7 +137,7 @@ async function main() {
let passwords = process.env.Ikuuu_PASSWD;
if (!emails || !passwords) {
console.log("ENV ERROR: Please set both Ikuuu_EMAIL and Ikuuu_PASSWD.");
log('ERROR', "ENV ERROR: Please set both Ikuuu_EMAIL and Ikuuu_PASSWD.");
process.exit(1);
}
@@ -103,32 +145,40 @@ async function main() {
let passwdList = passwords.split(";");
if (emailList.length !== passwdList.length) {
console.log("Error: The number of emails does not match the number of passwords.");
log('ERROR', "Error: The number of emails does not match the number of passwords.");
process.exit(1);
}
// 创建一个通知数组,避免多次发送相同的消息
let notifications = [];
// 遍历每个账号执行登录并签到
for (let i = 0; i < emailList.length; i++) {
let email = emailList[i];
let passwd = passwdList[i];
let cookie = await logIn(email, passwd);
await checkIn(cookie);
let client = new IkuuuClient(email, passwd);
// 每个账号的操作只添加一条通知
try {
let cookie = await client.login();
await client.checkIn(cookie);
notifications.push(`账号 ${email} 登录成功,签到完成`);
} catch (error) {
notifications.push(`账号 ${email} 操作失败: ${error.message}`);
}
// 每次登录后延迟 2 秒
await delay(2000); // 延迟 2 秒
}
// 合并所有通知为一条消息,避免多次发送
const notificationMessage = notifications.join("\n");
// 过滤掉 undefined 值
const notificationMessage = notifications
.filter(msg => msg !== undefined)
.join("\n");
// 调试:打印通知数组
console.log("通知数组内容:", notifications);
// 发送合并后的消息通知
sendNotify(`多个账号操作完成:\n${notificationMessage}`);
}
main();
main().catch(error => {
log('ERROR', `Main function failed: ${error.message}`);
process.exit(1);
});

View File

@@ -7,6 +7,7 @@ import os
import time
from requests import session
from hashlib import md5
from concurrent.futures import ThreadPoolExecutor, as_completed
try:
from sendNotify import send
@@ -14,6 +15,11 @@ except ImportError:
print("加载通知服务失败")
class Tieba():
# 将配置项提取为类变量
MAX_RETRY = 10 # 最大重试次数
REQUEST_TIMEOUT = 30 # 请求超时时间
SLEEP_TIME = 10 # 退出前等待时间
Tieba_BDUSS = os.getenv("Tieba_BDUSS")
def __init__(self, STOKEN):
@@ -40,13 +46,17 @@ class Tieba():
self.session.cookies.update({'BDUSS': self.BDUSS, 'STOKEN': self.STOKEN})
def fetch_tbs(self):
try:
r = self.session.get('http://tieba.baidu.com/dc/common/tbs').json()
if r['is_login'] == 1:
self.tbs = r['tbs']
else:
raise Exception('获取tbs错误以下为返回数据' + str(r))
except Exception as e:
raise Exception(f'获取tbs时发生异常{str(e)}')
def fetch_likes(self):
try:
self.rest = set()
self.already = set()
r = self.session.get('https://tieba.baidu.com/mo/q/newmoindex?').json()
@@ -58,14 +68,17 @@ class Tieba():
self.rest.add(forum['forum_name'])
else:
raise Exception('获取关注贴吧错误!以下为返回数据:' + str(r))
except Exception as e:
raise Exception(f'获取关注贴吧时发生异常:{str(e)}')
def sign(self, forum_name):
try:
data = {
'kw': forum_name,
'tbs': self.tbs,
'sign': md5(f'kw={forum_name}tbs={self.tbs}tiebaclient!!!'.encode('utf8')).hexdigest()
}
r = self.session.post('http://c.tieba.baidu.com/c/c/forum/sign', data).json()
r = self.session.post('http://c.tieba.baidu.com/c/c/forum/sign', data, timeout=self.REQUEST_TIMEOUT).json()
if r['error_code'] == '160002':
print(f'"{forum_name}"已签到')
self.sign_list.append(forum_name)
@@ -79,17 +92,28 @@ class Tieba():
print(f'"{forum_name}"签到失败!以下为返回数据:{str(r)}')
self.fail_list.append(forum_name)
return False
except Exception as e:
print(f'"{forum_name}"签到时发生异常:{str(e)}')
self.fail_list.append(forum_name)
return False
def loop(self, n):
print(f'* 开始第{n}轮签到 *')
rest = set()
self.fetch_tbs()
for forum_name in self.rest:
flag = self.sign(forum_name)
if not flag:
# 使用线程池并发签到
with ThreadPoolExecutor(max_workers=5) as executor:
futures = {executor.submit(self.sign, forum_name): forum_name for forum_name in self.rest}
for future in as_completed(futures):
forum_name = futures[future]
try:
if not future.result():
rest.add(forum_name)
except Exception as e:
print(f'"{forum_name}"签到异常:{str(e)}')
rest.add(forum_name)
self.rest = rest
if n >= 10: # 最大重试次数
if n >= self.MAX_RETRY: # 使用类变量
self.rest = set()
def main(self, max):
@@ -114,6 +138,7 @@ class Tieba():
self.send_notification_message()
def send_notification_message(self):
try:
msg = "贴吧签到结果:\n"
if self.success_list:
@@ -124,8 +149,9 @@ class Tieba():
if self.sign_list:
msg += "- **已经签到的贴吧**\n"
msg += " " + "\n ".join(self.sign_list) + "\n"
msg += " " + ", ".join(self.sign_list) # 去掉末尾的换行符
# 直接拼接统计信息,去掉前面的空行
msg += f"\n共关注了{len(self.already) + len(self.success_list)}个贴吧,"
msg += f"本次成功签到了{len(self.success_list)}个,"
msg += f"失败了{len(self.fail_list)}个,"
@@ -134,8 +160,10 @@ class Tieba():
# 发送通知
send('Tieba_Sign', msg)
# Add a 10-second delay before exiting
time.sleep(10)
# 使用类变量
time.sleep(self.SLEEP_TIME)
except Exception as e:
print(f'发送通知时发生异常:{str(e)}')
if __name__ == "__main__":
BDUSS_values = os.getenv("Tieba_BDUSS")