Continue seeded Qinglong script collection
This commit is contained in:
File diff suppressed because it is too large
Load Diff
181
脚本库/web版/账密/102-雨云/2023-09-20_yu_0548064a.py
Normal file
181
脚本库/web版/账密/102-雨云/2023-09-20_yu_0548064a.py
Normal file
@@ -0,0 +1,181 @@
|
||||
# Source: https://github.com/xfmeng970526/ql/blob/main/yu.py
|
||||
# Raw: https://raw.githubusercontent.com/xfmeng970526/ql/main/yu.py
|
||||
# Repo: xfmeng970526/ql
|
||||
# Path: yu.py
|
||||
# UploadedAt: 2023-09-20T12:13:28+08:00
|
||||
# SHA256: 0548064af1ce7ef8d6d449edb5bb0555d2911a7ea795da689b70f7b325282fdc
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time: 2023年04月06日14时26分
|
||||
import requests
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
import logging
|
||||
import json
|
||||
cron: 3 9,14 * * *
|
||||
new Env('102-雨云');
|
||||
项目名称:雨云
|
||||
''''脚本使用说明:
|
||||
后缀名改成py
|
||||
|
||||
白嫖的项目:签到白嫖游戏服务器或者稳定的虚拟主机,攒着提现也可以(2018年以来一直稳定运行的,自己可以查一查资料)
|
||||
|
||||
第一步:上传本脚本到青龙(本脚本是py不是js 别搞错了)
|
||||
第二步:去 https://www.rainyun.cc/?ref=MzUxMzA= 注册一个账号(不提现只抢游戏云和主机的话不用实名)
|
||||
想提现的话6万积分起提现...绑定支付宝提现(稳到,亲测过,也有官方用户群)。
|
||||
第三步:本脚本里第121行122行里设置一下自己注册的账号和密码!!!
|
||||
本脚本里第121行122行里设置一下自己注册的账号和密码!!!
|
||||
本脚本里第121行122行里设置一下自己注册的账号和密码!!!
|
||||
第四步:时间规则:0 0 23 * * ? #每天 23 点执行一次 (可以按自己的需求,每天执行一次)
|
||||
|
||||
积分规则及说明:本脚本是每天实现自动签到(每天300个积分),入门级游戏云或者虚拟主机2000积分一周。
|
||||
这样下来一直用积分续费,想提现的话6万积分起提现...绑定支付宝提现(稳到)。
|
||||
|
||||
|
||||
注册地址:
|
||||
https://www.rainyun.cc/?ref=rain
|
||||
|
||||
https://www.rainyun.cc/?ref=rain
|
||||
|
||||
|
||||
提现规则:6万积分起提现(稳到,不过建议用来续费游戏云比较划算)
|
||||
|
||||
新人完成积分任务以后大概会有7000积分(积分商城每天20点刷新,自己抢一下一个主机或者游戏云)。
|
||||
而2000积分就可以领取一个免费的MC服务器或者主机,而且可以用积分进行续费!续费也只需要2000积分!
|
||||
前期积分任务做完加上每日签到,足够免费续费一个月了!后面一直用积分续费。
|
||||
|
||||
|
||||
注册地址:
|
||||
https://www.rainyun.cc/?ref=rain
|
||||
|
||||
'''
|
||||
# 忽略 不验证ssl的提示
|
||||
import warnings
|
||||
warnings.filterwarnings('ignore')
|
||||
|
||||
class RainYun():
|
||||
|
||||
def __init__(self, user: str, pwd: str) -> None:
|
||||
# 认证信息
|
||||
self.user = user.lower()
|
||||
self.pwd = pwd
|
||||
self.json_data = json.dumps({
|
||||
"field": self.user,
|
||||
"password": self.pwd,
|
||||
})
|
||||
# 日志输出
|
||||
self.logger = logging.getLogger(self.user)
|
||||
formatter = logging.Formatter(datefmt='%Y/%m/%d %H:%M:%S',
|
||||
fmt="%(asctime)s 雨云 %(levelname)s: 用户<%(name)s> %(message)s")
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(formatter)
|
||||
self.logger.addHandler(handler)
|
||||
self.logger.setLevel(logging.INFO)
|
||||
# 签到结果初始化
|
||||
self.signin_result = False
|
||||
# 请求设置
|
||||
self.session = requests.Session()
|
||||
self.session.headers.update({
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36",
|
||||
"Origin": "https://api.rainyun.com",
|
||||
"Referer": "https://api.rainyun.com"
|
||||
})
|
||||
self.login_url = "https://api.v2.rainyun.com/user/login"
|
||||
self.signin_url = "https://api.v2.rainyun.com/user/reward/tasks"
|
||||
self.logout_url = "https://api.v2.rainyun.com/user/logout"
|
||||
self.query_url = "https://api.v2.rainyun.com/user/"
|
||||
# 忽略 .cc ssl错误
|
||||
self.session.verify = False
|
||||
|
||||
def login(self) -> None:
|
||||
"""登录"""
|
||||
res = self.session.post(
|
||||
url=self.login_url, headers={"Content-Type": "application/json"}, data=self.json_data)
|
||||
if res.text.find("200") > -1:
|
||||
self.logger.info("登录成功")
|
||||
self.session.headers.update({
|
||||
"X-CSRF-Token": res.cookies.get("X-CSRF-Token", "")
|
||||
})
|
||||
else:
|
||||
self.logger.error(f"登录失败,响应信息:{res.text}")
|
||||
|
||||
def signin(self) -> None:
|
||||
"""签到"""
|
||||
res = self.session.post(url=self.signin_url, headers={"Content-Type": "application/json"}, data=json.dumps({
|
||||
"task_name": "每日签到",
|
||||
"verifyCode": ""
|
||||
}))
|
||||
self.signin_date = datetime.utcnow()
|
||||
if res.text.find("200") > -1:
|
||||
self.logger.info("成功签到并领取积分")
|
||||
self.signin_result = True
|
||||
else:
|
||||
self.logger.error(f"签到失败,响应信息:{res.text}")
|
||||
self.signin_result = False
|
||||
|
||||
def logout(self) -> None:
|
||||
res = self.session.post(url=self.logout_url)
|
||||
if res.text.find("200") > -1:
|
||||
self.logger.info('已退出登录')
|
||||
else:
|
||||
self.logger.warning(f"退出登录时出了些问题,响应信息:{res.text}")
|
||||
|
||||
def query(self) -> None:
|
||||
res = self.session.get(url=self.query_url)
|
||||
self.points = None
|
||||
if res.text.find("200") > -1:
|
||||
data = res.json()["data"]
|
||||
self.points = data.get("Points", None) or data["points"]
|
||||
self.logger.info("积分查询成功为 " + repr(self.points))
|
||||
else:
|
||||
self.logger.error(f"积分信息失败,响应信息:{res.text}")
|
||||
|
||||
def log(self, log_file: str, max_num=5) -> None:
|
||||
"""存储本次签到结果的日志"""
|
||||
# 北京时间
|
||||
time_string = self.signin_date.replace(tzinfo=timezone.utc).astimezone(
|
||||
timezone(timedelta(hours=8))).strftime("%Y/%m/%d %H:%M:%S")
|
||||
file = Path(log_file)
|
||||
record = {
|
||||
"date": time_string,
|
||||
"result": self.signin_result,
|
||||
"points": self.points
|
||||
}
|
||||
previous_records = {}
|
||||
if file.is_file():
|
||||
try:
|
||||
with open(log_file, 'r') as f:
|
||||
previous_records = json.load(f)
|
||||
if not previous_records.get(self.user):
|
||||
previous_records[self.user] = []
|
||||
previous_records[self.user].insert(0, record)
|
||||
previous_records[self.user] = previous_records[self.user][:max_num]
|
||||
except Exception as e:
|
||||
self.logger.error("序列化日志时出错:"+repr(e))
|
||||
else:
|
||||
previous_records[self.user] = [record]
|
||||
with open(log_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(previous_records, f, indent=4)
|
||||
self.logger.info('日志保存成功')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
accounts = [
|
||||
{
|
||||
"user": "账户", # 账户
|
||||
"password": "密码" # 密码
|
||||
}
|
||||
]
|
||||
for acc in accounts:
|
||||
ry = RainYun(acc["user"], acc["password"]) # 实例
|
||||
ry.login() # 登录
|
||||
ry.signin() # 签到
|
||||
ry.query() # 查询积分
|
||||
ry.logout() # 登出
|
||||
# 保存日志则打开注释 推荐文件绝对路径
|
||||
# file = "./rainyun-signin-log.json"
|
||||
# 日志最大记录数量
|
||||
# max_num = 5
|
||||
# ry.log(file, max_num) # 保存日志
|
||||
895
脚本库/web版/账密/12-58同城/2023-09-20_raw_main_58tc_7dff6e95.js
Normal file
895
脚本库/web版/账密/12-58同城/2023-09-20_raw_main_58tc_7dff6e95.js
Normal file
File diff suppressed because one or more lines are too long
569
脚本库/web版/账密/24-吉利汽车_0121/2023-09-20_jlqc_0121_e8e74e4e.js
Normal file
569
脚本库/web版/账密/24-吉利汽车_0121/2023-09-20_jlqc_0121_e8e74e4e.js
Normal file
File diff suppressed because one or more lines are too long
152
脚本库/web版/账密/33台词/2025-04-28_sudojia_33agilestudio_cc8d2ad2.js
Normal file
152
脚本库/web版/账密/33台词/2025-04-28_sudojia_33agilestudio_cc8d2ad2.js
Normal file
@@ -0,0 +1,152 @@
|
||||
// # Source: https://github.com/sudojia/AutoTaskScript/blob/script/src/web/sudojia_33agilestudio.js
|
||||
// # Raw: https://raw.githubusercontent.com/sudojia/AutoTaskScript/script/src/web/sudojia_33agilestudio.js
|
||||
// # Repo: sudojia/AutoTaskScript
|
||||
// # Path: src/web/sudojia_33agilestudio.js
|
||||
// # UploadedAt: 2025-04-28T19:26:13+08:00
|
||||
// # SHA256: cc8d2ad222b3206b91833e9b2724bb7b0a300c5c9a73679ced82953f001dd89b
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/**
|
||||
* 33台词 https://33.agilestudio.cn/invite?userCode=Rx5X7gjH
|
||||
* 一个通过台词找影片素材
|
||||
* 每日签到获得积分
|
||||
*
|
||||
* 积分有什么用?
|
||||
* 官方文档回答:
|
||||
* 1. 积分可以用来截取图片和剪切视频。
|
||||
* 2. 积分可以兑换会员。(限普通积分)
|
||||
*
|
||||
* export AGILE_STUDIO_ACCOUNTS = 'email#password'
|
||||
* 多账号用 & 或换行
|
||||
*
|
||||
* @author Telegram@sudojia
|
||||
* @site https://blog.imzjw.cn
|
||||
* @date 2024/12/3
|
||||
*
|
||||
* const $ = new Env('33台词')
|
||||
* cron: 1 11 * * *
|
||||
*/
|
||||
const initScript = require('../utils/initScript')
|
||||
const {$, notify, sudojia, checkUpdate} = initScript('33台词');
|
||||
const agileList = process.env.AGILE_STUDIO_ACCOUNTS ? process.env.AGILE_STUDIO_ACCOUNTS.split(/[\n&]/) : [];
|
||||
let message = '';
|
||||
// 接口地址
|
||||
const baseUrl = 'https://ssv-api.agilestudio.cn'
|
||||
// 请求头
|
||||
const headers = {
|
||||
'User-Agent': sudojia.getRandomUserAgent('PC'),
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
||||
'Host': 'ssv-api.agilestudio.cn',
|
||||
'Origin': 'https://33.agilestudio.cn',
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
};
|
||||
|
||||
!(async () => {
|
||||
await checkUpdate($.name, agileList);
|
||||
console.log(`\n已随机分配 User-Agent\n\n${headers['user-agent'] || headers['User-Agent']}`);
|
||||
for (let i = 0; i < agileList.length; i++) {
|
||||
const index = i + 1;
|
||||
const [email, password] = agileList[i].split('#');
|
||||
console.log(`\n*****第[${index}]个${$.name}账号*****`);
|
||||
console.log('开始登录~');
|
||||
const loginSuccess = await login(email, password);
|
||||
if (!loginSuccess) {
|
||||
break;
|
||||
}
|
||||
await $.wait(sudojia.getRandomWait(1e3, 2e3));
|
||||
message += `📣====${$.name}账号[${index}]====📣\n`;
|
||||
await main();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2300));
|
||||
}
|
||||
if (message) {
|
||||
await notify.sendNotify(`「${$.name}」`, `${message}`);
|
||||
}
|
||||
})().catch((e) => $.logErr(e)).finally(() => $.done());
|
||||
|
||||
async function main() {
|
||||
await getUserInfo();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2300));
|
||||
await dailyCheck();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2300));
|
||||
await getPoints();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @param email
|
||||
* @param password
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function login(email, password) {
|
||||
try {
|
||||
const ts = (new Date).getTime() - 9999;
|
||||
headers['x-signature'] = generateXSignature(ts);
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/auth/email-login?_platform=web&_versioin=0.2.5&_ts=${ts}`, 'post', headers, {
|
||||
"email": email,
|
||||
"password": password
|
||||
});
|
||||
if (0 !== data.code) {
|
||||
console.error(data.msg);
|
||||
return false;
|
||||
}
|
||||
headers['x-token'] = data.data.token;
|
||||
console.log('登录成功~');
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error(`登录时发生异常:${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function getUserInfo() {
|
||||
try {
|
||||
const ts = (new Date).getTime() - 9999;
|
||||
headers['x-signature'] = generateXSignature(ts);
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/user/my-info?_platform=web&_versioin=0.2.5&_ts=${ts}`, 'get', headers);
|
||||
if (0 !== data.code) {
|
||||
return console.error(data.msg);
|
||||
}
|
||||
console.log(`用户:${data.data.email}`);
|
||||
message += `用户:${data.data.email}\n`;
|
||||
} catch (e) {
|
||||
console.error(`获取用户信息时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function dailyCheck() {
|
||||
try {
|
||||
const ts = (new Date).getTime() - 9999;
|
||||
headers['x-signature'] = generateXSignature(ts);
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/integral/do-daily-check?_platform=web&_versioin=0.2.5&_ts=${ts}`, 'post', headers);
|
||||
if (0 !== data.code) {
|
||||
return console.error(data.msg);
|
||||
}
|
||||
console.log('签到成功!');
|
||||
message += `签到成功!\n`;
|
||||
} catch (e) {
|
||||
console.error(`签到时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function getPoints() {
|
||||
try {
|
||||
const ts = (new Date).getTime() - 9999;
|
||||
headers['x-signature'] = generateXSignature(ts);
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/user/user-info?_platform=web&_versioin=0.2.5&_ts=${ts}`, 'get', headers);
|
||||
if (0 !== data.code) {
|
||||
return console.error(data.msg);
|
||||
}
|
||||
console.log(`当前积分:${data.data.integral}`);
|
||||
message += `当前积分:${data.data.integral}\n\n`;
|
||||
} catch (e) {
|
||||
console.error(`获取积分时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
function generateXSignature(ts) {
|
||||
return sudojia.md5(`_platform=web,_ts=${ts},_versioin=0.2.5,`);
|
||||
}
|
||||
23
脚本库/web版/账密/40-图虫/2023-09-20_tuc_5eaa7925.js
Normal file
23
脚本库/web版/账密/40-图虫/2023-09-20_tuc_5eaa7925.js
Normal file
File diff suppressed because one or more lines are too long
719
脚本库/web版/账密/44-微博年终购物清单/2023-09-20_weibonz_c6894d10.js
Normal file
719
脚本库/web版/账密/44-微博年终购物清单/2023-09-20_weibonz_c6894d10.js
Normal file
@@ -0,0 +1,719 @@
|
||||
// # Source: https://github.com/xfmeng970526/ql/blob/main/weibonz.js
|
||||
// # Raw: https://raw.githubusercontent.com/xfmeng970526/ql/main/weibonz.js
|
||||
// # Repo: xfmeng970526/ql
|
||||
// # Path: weibonz.js
|
||||
// # UploadedAt: 2023-09-20T12:13:28+08:00
|
||||
// # SHA256: c6894d109c74946e5c4bab7a9e3d8892e6103afbc36ace17d55102149f65d17f
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/*
|
||||
地址:https://act.e.weibo.com/web/goodsthings/drawIndex.html?lotteryId=149
|
||||
网页登录抓CK或者APP抓CK
|
||||
变量
|
||||
export weibonzhd=''
|
||||
多号@或换行
|
||||
cron: 3 9,14 * * *
|
||||
new Env('44-微博年终购物清单');
|
||||
项目名称:微博年终购物清单
|
||||
*/
|
||||
const $ = new Env('微博年终购物清单');
|
||||
const axios = require('axios');
|
||||
let request = require("request");
|
||||
request = request.defaults({
|
||||
jar: true
|
||||
});
|
||||
const {
|
||||
log
|
||||
} = console;
|
||||
const Notify = 1; //0为关闭通知,1为打开通知,默认为1
|
||||
const debug = 0; //0为关闭调试,1为打开调试,默认为0
|
||||
|
||||
let weibonzhd = ($.isNode() ? process.env.weibonzhd : $.getdata("weibonzhd")) || ""
|
||||
let weibonzhdArr = [];
|
||||
let data = '';
|
||||
let msg = '';
|
||||
var hours = new Date().getMonth();
|
||||
|
||||
var timestamp = Math.round(new Date().getTime()).toString();
|
||||
!(async () => {
|
||||
if (typeof $request !== "undefined") {
|
||||
await GetRewrite();
|
||||
} else {
|
||||
if (!(await Envs()))
|
||||
return;
|
||||
else {
|
||||
|
||||
log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date(
|
||||
new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 +
|
||||
8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`);
|
||||
|
||||
|
||||
|
||||
log(`\n============ 微信公众号:柠檬玩机交流 ============`)
|
||||
log(`\n=================== 共找到 ${weibonzhdArr.length} 个账号 ===================`)
|
||||
if (debug) {
|
||||
log(`【debug】 这是你的全部账号数组:\n ${weibonzhdArr}`);
|
||||
}
|
||||
for (let index = 0; index < weibonzhdArr.length; index++) {
|
||||
|
||||
let num = index + 1
|
||||
addNotifyStr(`\n==== 开始【第 ${num} 个账号】====\n`, true)
|
||||
|
||||
weibonzhd = weibonzhdArr[index];
|
||||
await hit()
|
||||
|
||||
await $.wait(3000)
|
||||
await addChance(426,'1000')
|
||||
await $.wait(3000)
|
||||
await addChance(430,'1000')
|
||||
await $.wait(3000)
|
||||
await addChance(431,'1000')
|
||||
await $.wait(3000)
|
||||
await addChance(427,'754198')
|
||||
await $.wait(3000)
|
||||
await addChance(427,'754199')
|
||||
await $.wait(3000)
|
||||
await addChance(427,'754203')
|
||||
await hasChance()
|
||||
|
||||
|
||||
}
|
||||
//await SendMsg(msg);
|
||||
}
|
||||
}
|
||||
})()
|
||||
.catch((e) => log(e))
|
||||
.finally(() => $.done())
|
||||
async function hit() {
|
||||
return new Promise((resolve) => {
|
||||
var options = {
|
||||
method: 'POST',
|
||||
url: 'https://act.e.weibo.com/api/ac/hit',
|
||||
headers: {
|
||||
Accept: 'application/json, text/plain, */*',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9',
|
||||
Connection: 'keep-alive',
|
||||
'Content-Length': '15',
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
Cookie: weibonzhd,
|
||||
Host: 'act.e.weibo.com',
|
||||
Origin: 'https://act.e.weibo.com',
|
||||
Referer: 'https://act.e.weibo.com/web/goodsthings/drawIndex.html?lotteryId=149',
|
||||
'sec-ch-ua': 'sec-ch-ua',
|
||||
'sec-ch-ua-mobile': '?1',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Site': 'same-origin',
|
||||
'content-type': 'application/json',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Weibo (iPhone12,8__weibo__11.8.1__iphone__os14.4)',
|
||||
|
||||
},
|
||||
data: {task_id: 425}
|
||||
};
|
||||
if (debug) {
|
||||
log(`\n【debug】=============== 这是 请求 url ===============`);
|
||||
log(JSON.stringify(options));
|
||||
}
|
||||
axios.request(options).then(async function(response) {
|
||||
try {
|
||||
data = response.data;
|
||||
if (debug) {
|
||||
log(`\n\n【debug】===============这是 返回data==============`);
|
||||
log(JSON.stringify(response.data));
|
||||
}
|
||||
if (data.code == 100000) {
|
||||
log(data.msg)
|
||||
} else
|
||||
log(data.msg)
|
||||
|
||||
|
||||
|
||||
} catch (e) {
|
||||
log(`异常:${data},原因:${data.msg}`)
|
||||
}
|
||||
}).catch(function(error) {
|
||||
console.error(error);
|
||||
}).then(res => {
|
||||
//这里处理正确返回
|
||||
resolve();
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
async function addChance(task_id,relation_id) {
|
||||
return new Promise((resolve) => {
|
||||
var options = {
|
||||
method: 'POST',
|
||||
url: 'https://act.e.weibo.com/api/lottery/addChance?lottery_id=149',
|
||||
|
||||
headers: {
|
||||
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
Cookie: weibonzhd,
|
||||
Host: 'act.e.weibo.com',
|
||||
Origin: 'https://act.e.weibo.com',
|
||||
Referer: 'https://act.e.weibo.com/web/goodsthings/drawIndex.html?lotteryId=149',
|
||||
'Sec-Fetch-Site': 'same-origin',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Weibo (iPhone12,8__weibo__11.8.1__iphone__os14.4)',
|
||||
|
||||
},
|
||||
data: {lottery_id: 149, task_id: task_id, relation_id: relation_id}
|
||||
};
|
||||
if (debug) {
|
||||
log(`\n【debug】=============== 这是 请求 url ===============`);
|
||||
log(JSON.stringify(options));
|
||||
}
|
||||
axios.request(options).then(async function(response) {
|
||||
try {
|
||||
data = response.data;
|
||||
if (debug) {
|
||||
log(`\n\n【debug】===============这是 返回data==============`);
|
||||
log(JSON.stringify(response.data));
|
||||
}
|
||||
if (data.code == 100000) {
|
||||
log(data.msg)
|
||||
|
||||
} else
|
||||
log(data.msg)
|
||||
|
||||
|
||||
|
||||
} catch (e) {
|
||||
log(`异常:${data},原因:${data.msg}`)
|
||||
}
|
||||
}).catch(function(error) {
|
||||
console.error(error);
|
||||
}).then(res => {
|
||||
//这里处理正确返回
|
||||
resolve();
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
async function draw() {
|
||||
return new Promise((resolve) => {
|
||||
var options = {
|
||||
method: 'POST',
|
||||
url: 'https://act.e.weibo.com/api/lottery/draw',
|
||||
params: {lottery_id: '149'},
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
Cookie: weibonzhd,
|
||||
Host: 'act.e.weibo.com',
|
||||
Origin: 'https://act.e.weibo.com',
|
||||
Referer: 'https://act.e.weibo.com/web/goodsthings/drawIndex.html?lotteryId=149',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Weibo (iPhone12,8__weibo__11.8.1__iphone__os14.4)',
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
data: {
|
||||
lottery_id: 149,
|
||||
aid: '01A_DItRRK8EHtxj6ITqSsprU6TWEmDbzefAbma0Dz9PKXK-w.',
|
||||
from: '10B8193010'
|
||||
}
|
||||
};
|
||||
if (debug) {
|
||||
log(`\n【debug】=============== 这是 请求 url ===============`);
|
||||
log(JSON.stringify(options));
|
||||
}
|
||||
axios.request(options).then(async function(response) {
|
||||
try {
|
||||
data = response.data;
|
||||
if (debug) {
|
||||
log(`\n\n【debug】===============这是 返回data==============`);
|
||||
log(JSON.stringify(response.data));
|
||||
}
|
||||
if (data.code == 100000) {
|
||||
log(data)
|
||||
|
||||
} else
|
||||
log(data.msg)
|
||||
|
||||
|
||||
|
||||
} catch (e) {
|
||||
log(`异常:${data},原因:${data.msg}`)
|
||||
}
|
||||
}).catch(function(error) {
|
||||
console.error(error);
|
||||
}).then(res => {
|
||||
//这里处理正确返回
|
||||
resolve();
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
async function hasChance() {
|
||||
return new Promise((resolve) => {
|
||||
var options = {
|
||||
method: 'GET',
|
||||
url: 'https://act.e.weibo.com/api/lottery/hasChance',
|
||||
params: {lottery_id: '149'},
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
Cookie: weibonzhd,
|
||||
Host: 'act.e.weibo.com',
|
||||
Origin: 'https://act.e.weibo.com',
|
||||
Referer: 'https://act.e.weibo.com/web/goodsthings/drawIndex.html?lotteryId=149',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Weibo (iPhone12,8__weibo__11.8.1__iphone__os14.4)',
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
if (debug) {
|
||||
log(`\n【debug】=============== 这是 请求 url ===============`);
|
||||
log(JSON.stringify(options));
|
||||
}
|
||||
axios.request(options).then(async function(response) {
|
||||
try {
|
||||
data = response.data;
|
||||
if (debug) {
|
||||
log(`\n\n【debug】===============这是 返回data==============`);
|
||||
log(JSON.stringify(response.data));
|
||||
}
|
||||
if (data.code == 100000) {
|
||||
log(data)
|
||||
left =data.data.left_num
|
||||
for(let i=0;i<left;i++){
|
||||
draw()
|
||||
await $.wait(3000)
|
||||
}
|
||||
|
||||
} else
|
||||
log(data.msg)
|
||||
|
||||
|
||||
|
||||
} catch (e) {
|
||||
log(`异常:${data},原因:${data.msg}`)
|
||||
}
|
||||
}).catch(function(error) {
|
||||
console.error(error);
|
||||
}).then(res => {
|
||||
//这里处理正确返回
|
||||
resolve();
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
async function Envs() {
|
||||
if (weibonzhd) {
|
||||
if (weibonzhd.indexOf("@") != -1) {
|
||||
weibonzhd.split("@").forEach((item) => {
|
||||
|
||||
weibonzhdArr.push(item);
|
||||
});
|
||||
} else if (weibonzhd.indexOf("\n") != -1) {
|
||||
weibonzhd.split("\n").forEach((item) => {
|
||||
weibonzhdArr.push(item);
|
||||
});
|
||||
} else {
|
||||
weibonzhdArr.push(weibonzhd);
|
||||
}
|
||||
} else {
|
||||
log(`\n 【${$.name}】:未填写变量 weibonzhd`)
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
function addNotifyStr(str, is_log = true) {
|
||||
if (is_log) {
|
||||
log(`${str}\n`)
|
||||
}
|
||||
msg += `${str}\n`
|
||||
}
|
||||
|
||||
// ============================================发送消息============================================ \\
|
||||
async function SendMsg(message) {
|
||||
if (!message)
|
||||
return;
|
||||
|
||||
if (Notify > 0) {
|
||||
if ($.isNode()) {
|
||||
var notify = require('./sendNotify');
|
||||
await notify.sendNotify($.name, message);
|
||||
} else {
|
||||
$.msg(message);
|
||||
}
|
||||
} else {
|
||||
log(message);
|
||||
}
|
||||
}
|
||||
function Env(t, e) {
|
||||
"undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0);
|
||||
|
||||
class s {
|
||||
constructor(t) {
|
||||
this.env = t
|
||||
}
|
||||
|
||||
send(t, e = "GET") {
|
||||
t = "string" == typeof t ? {
|
||||
url: t
|
||||
} : t;
|
||||
let s = this.get;
|
||||
return "POST" === e && (s = this.post), new Promise((e, i) => {
|
||||
s.call(this, t, (t, s, r) => {
|
||||
t ? i(t) : e(s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
get(t) {
|
||||
return this.send.call(this.env, t)
|
||||
}
|
||||
|
||||
post(t) {
|
||||
return this.send.call(this.env, t, "POST")
|
||||
}
|
||||
}
|
||||
|
||||
return new class {
|
||||
constructor(t, e) {
|
||||
this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`)
|
||||
}
|
||||
|
||||
isNode() {
|
||||
return "undefined" != typeof module && !!module.exports
|
||||
}
|
||||
|
||||
isQuanX() {
|
||||
return "undefined" != typeof $task
|
||||
}
|
||||
|
||||
isSurge() {
|
||||
return "undefined" != typeof $httpClient && "undefined" == typeof $loon
|
||||
}
|
||||
|
||||
isLoon() {
|
||||
return "undefined" != typeof $loon
|
||||
}
|
||||
|
||||
toObj(t, e = null) {
|
||||
try {
|
||||
return JSON.parse(t)
|
||||
} catch {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
toStr(t, e = null) {
|
||||
try {
|
||||
return JSON.stringify(t)
|
||||
} catch {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
getjson(t, e) {
|
||||
let s = e;
|
||||
const i = this.getdata(t);
|
||||
if (i) try {
|
||||
s = JSON.parse(this.getdata(t))
|
||||
} catch {}
|
||||
return s
|
||||
}
|
||||
|
||||
setjson(t, e) {
|
||||
try {
|
||||
return this.setdata(JSON.stringify(t), e)
|
||||
} catch {
|
||||
return !1
|
||||
}
|
||||
}
|
||||
|
||||
getScript(t) {
|
||||
return new Promise(e => {
|
||||
this.get({
|
||||
url: t
|
||||
}, (t, s, i) => e(i))
|
||||
})
|
||||
}
|
||||
|
||||
runScript(t, e) {
|
||||
return new Promise(s => {
|
||||
let i = this.getdata("@chavy_boxjs_userCfgs.httpapi");
|
||||
i = i ? i.replace(/\n/g, "").trim() : i;
|
||||
let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");
|
||||
r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r;
|
||||
const [o, h] = i.split("@"), n = {
|
||||
url: `http://${h}/v1/scripting/evaluate`,
|
||||
body: {
|
||||
script_text: t,
|
||||
mock_type: "cron",
|
||||
timeout: r
|
||||
},
|
||||
headers: {
|
||||
"X-Key": o,
|
||||
Accept: "*/*"
|
||||
}
|
||||
};
|
||||
this.post(n, (t, e, i) => s(i))
|
||||
}).catch(t => this.logErr(t))
|
||||
}
|
||||
|
||||
loaddata() {
|
||||
if (!this.isNode()) return {}; {
|
||||
this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path");
|
||||
const t = this.path.resolve(this.dataFile),
|
||||
e = this.path.resolve(process.cwd(), this.dataFile),
|
||||
s = this.fs.existsSync(t),
|
||||
i = !s && this.fs.existsSync(e);
|
||||
if (!s && !i) return {}; {
|
||||
const i = s ? t : e;
|
||||
try {
|
||||
return JSON.parse(this.fs.readFileSync(i))
|
||||
} catch (t) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writedata() {
|
||||
if (this.isNode()) {
|
||||
this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path");
|
||||
const t = this.path.resolve(this.dataFile),
|
||||
e = this.path.resolve(process.cwd(), this.dataFile),
|
||||
s = this.fs.existsSync(t),
|
||||
i = !s && this.fs.existsSync(e),
|
||||
r = JSON.stringify(this.data);
|
||||
s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r)
|
||||
}
|
||||
}
|
||||
|
||||
lodash_get(t, e, s) {
|
||||
const i = e.replace(/\[(\d+)\]/g, ".$1").split(".");
|
||||
let r = t;
|
||||
for (const t of i)
|
||||
if (r = Object(r)[t], void 0 === r) return s;
|
||||
return r
|
||||
}
|
||||
|
||||
lodash_set(t, e, s) {
|
||||
return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t)
|
||||
}
|
||||
|
||||
getdata(t) {
|
||||
let e = this.getval(t);
|
||||
if (/^@/.test(t)) {
|
||||
const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : "";
|
||||
if (r) try {
|
||||
const t = JSON.parse(r);
|
||||
e = t ? this.lodash_get(t, i, "") : e
|
||||
} catch (t) {
|
||||
e = ""
|
||||
}
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
setdata(t, e) {
|
||||
let s = !1;
|
||||
if (/^@/.test(e)) {
|
||||
const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i),
|
||||
h = i ? "null" === o ? null : o || "{}" : "{}";
|
||||
try {
|
||||
const e = JSON.parse(h);
|
||||
this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i)
|
||||
} catch (e) {
|
||||
const o = {};
|
||||
this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i)
|
||||
}
|
||||
} else s = this.setval(t, e);
|
||||
return s
|
||||
}
|
||||
|
||||
getval(t) {
|
||||
return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null
|
||||
}
|
||||
|
||||
setval(t, e) {
|
||||
return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null
|
||||
}
|
||||
|
||||
initGotEnv(t) {
|
||||
this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar))
|
||||
}
|
||||
|
||||
get(t, e = (() => {})) {
|
||||
t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, {
|
||||
"X-Surge-Skip-Scripting": !1
|
||||
})), $httpClient.get(t, (t, s, i) => {
|
||||
!t && s && (s.body = i, s.statusCode = s.status), e(t, s, i)
|
||||
})) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, {
|
||||
hints: !1
|
||||
})), $task.fetch(t).then(t => {
|
||||
const {
|
||||
statusCode: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
} = t;
|
||||
e(null, {
|
||||
status: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
}, o)
|
||||
}, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => {
|
||||
try {
|
||||
if (t.headers["set-cookie"]) {
|
||||
const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();
|
||||
s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar
|
||||
}
|
||||
} catch (t) {
|
||||
this.logErr(t)
|
||||
}
|
||||
}).then(t => {
|
||||
const {
|
||||
statusCode: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
} = t;
|
||||
e(null, {
|
||||
status: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
}, o)
|
||||
}, t => {
|
||||
const {
|
||||
message: s,
|
||||
response: i
|
||||
} = t;
|
||||
e(s, i, i && i.body)
|
||||
}))
|
||||
}
|
||||
|
||||
post(t, e = (() => {})) {
|
||||
if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, {
|
||||
"X-Surge-Skip-Scripting": !1
|
||||
})), $httpClient.post(t, (t, s, i) => {
|
||||
!t && s && (s.body = i, s.statusCode = s.status), e(t, s, i)
|
||||
});
|
||||
else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, {
|
||||
hints: !1
|
||||
})), $task.fetch(t).then(t => {
|
||||
const {
|
||||
statusCode: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
} = t;
|
||||
e(null, {
|
||||
status: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
}, o)
|
||||
}, t => e(t));
|
||||
else if (this.isNode()) {
|
||||
this.initGotEnv(t);
|
||||
const {
|
||||
url: s,
|
||||
...i
|
||||
} = t;
|
||||
this.got.post(s, i).then(t => {
|
||||
const {
|
||||
statusCode: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
} = t;
|
||||
e(null, {
|
||||
status: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
}, o)
|
||||
}, t => {
|
||||
const {
|
||||
message: s,
|
||||
response: i
|
||||
} = t;
|
||||
e(s, i, i && i.body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
time(t, e = null) {
|
||||
const s = e ? new Date(e) : new Date;
|
||||
let i = {
|
||||
"M+": s.getMonth() + 1,
|
||||
"d+": s.getDate(),
|
||||
"H+": s.getHours(),
|
||||
"m+": s.getMinutes(),
|
||||
"s+": s.getSeconds(),
|
||||
"q+": Math.floor((s.getMonth() + 3) / 3),
|
||||
S: s.getMilliseconds()
|
||||
};
|
||||
/(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length)));
|
||||
for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length)));
|
||||
return t
|
||||
}
|
||||
|
||||
msg(e = t, s = "", i = "", r) {
|
||||
const o = t => {
|
||||
if (!t) return t;
|
||||
if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? {
|
||||
"open-url": t
|
||||
} : this.isSurge() ? {
|
||||
url: t
|
||||
} : void 0;
|
||||
if ("object" == typeof t) {
|
||||
if (this.isLoon()) {
|
||||
let e = t.openUrl || t.url || t["open-url"],
|
||||
s = t.mediaUrl || t["media-url"];
|
||||
return {
|
||||
openUrl: e,
|
||||
mediaUrl: s
|
||||
}
|
||||
}
|
||||
if (this.isQuanX()) {
|
||||
let e = t["open-url"] || t.url || t.openUrl,
|
||||
s = t["media-url"] || t.mediaUrl;
|
||||
return {
|
||||
"open-url": e,
|
||||
"media-url": s
|
||||
}
|
||||
}
|
||||
if (this.isSurge()) {
|
||||
let e = t.url || t.openUrl || t["open-url"];
|
||||
return {
|
||||
url: e
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) {
|
||||
let t = ["", "==============📣系统通知📣=============="];
|
||||
t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t)
|
||||
}
|
||||
}
|
||||
|
||||
log(...t) {
|
||||
t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator))
|
||||
}
|
||||
|
||||
logErr(t, e) {
|
||||
const s = !this.isSurge() && !this.isQuanX() && !this.isLoon();
|
||||
s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t)
|
||||
}
|
||||
|
||||
wait(t) {
|
||||
return new Promise(e => setTimeout(e, t))
|
||||
}
|
||||
|
||||
done(t = {}) {
|
||||
const e = (new Date).getTime(),
|
||||
s = (e - this.startTime) / 1e3;
|
||||
this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t)
|
||||
}
|
||||
}(t, e)
|
||||
}
|
||||
646
脚本库/web版/账密/45-牙e家/2023-09-20_yayi_9713ec7b.js
Normal file
646
脚本库/web版/账密/45-牙e家/2023-09-20_yayi_9713ec7b.js
Normal file
@@ -0,0 +1,646 @@
|
||||
// # Source: https://github.com/xfmeng970526/ql/blob/main/yayi.js
|
||||
// # Raw: https://raw.githubusercontent.com/xfmeng970526/ql/main/yayi.js
|
||||
// # Repo: xfmeng970526/ql
|
||||
// # Path: yayi.js
|
||||
// # UploadedAt: 2023-09-20T12:13:28+08:00
|
||||
// # SHA256: 9713ec7bd7b07bc955e68a3c41841a399aba3c1d2d339b8eeba9884e586f0e08
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/*
|
||||
APP:牙e家
|
||||
设置密码
|
||||
export yayihd='手机号&密码'
|
||||
多号@或换行隔开
|
||||
10话费
|
||||
cron: 3 9,14 * * *
|
||||
new Env('45-牙e家');
|
||||
项目名称:牙e家
|
||||
*/
|
||||
|
||||
const $ = new Env('45-牙e家');
|
||||
const axios = require('axios');
|
||||
let request = require("request");
|
||||
request = request.defaults({
|
||||
jar: true
|
||||
});
|
||||
const {
|
||||
log
|
||||
} = console;
|
||||
const Notify = 1; //0为关闭通知,1为打开通知,默认为1
|
||||
const debug = 0; //0为关闭调试,1为打开调试,默认为0
|
||||
|
||||
let yayihd = ($.isNode() ? process.env.yayihd : $.getdata("yayihd")) || ""
|
||||
let yayihdArr = [];
|
||||
let data = '';
|
||||
let msg = '';
|
||||
var hours = new Date().getMonth();
|
||||
|
||||
var timestamp = Math.round(new Date().getTime()).toString();
|
||||
!(async () => {
|
||||
if (typeof $request !== "undefined") {
|
||||
await GetRewrite();
|
||||
} else {
|
||||
if (!(await Envs()))
|
||||
return;
|
||||
else {
|
||||
|
||||
log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date(
|
||||
new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 +
|
||||
8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`);
|
||||
|
||||
|
||||
|
||||
log(`\n============ 微信公众号:柠檬玩机交流 ============`)
|
||||
log(`\n=================== 共找到 ${yayihdArr.length} 个账号 ===================`)
|
||||
if (debug) {
|
||||
log(`【debug】 这是你的全部账号数组:\n ${yayihdArr}`);
|
||||
}
|
||||
for (let index = 0; index < yayihdArr.length; index++) {
|
||||
|
||||
let num = index + 1
|
||||
addNotifyStr(`\n==== 开始【第 ${num} 个账号】====\n`, true)
|
||||
|
||||
yayihd = yayihdArr[index];
|
||||
pass = yayihd.split('&')[1]
|
||||
phones = yayihd.split('&')[0]
|
||||
await Userlogin(pass,phones)
|
||||
log(encodeURIComponent(authcode))
|
||||
await req('Signlist/openapp')
|
||||
|
||||
log(data)
|
||||
await req('Signlist/toshare')
|
||||
log(data)
|
||||
await req('Signlist/toshare')
|
||||
log(data)
|
||||
await req('Signlist/toshare')
|
||||
log(data)
|
||||
await req1('Hotrecommendlist/torecommend','4879')
|
||||
log(data)
|
||||
await req1('Hotrecommendlist/torecommend','4878')
|
||||
log(data)
|
||||
await req1('Hotrecommendlist/torecommend','4877')
|
||||
log(data)
|
||||
await req1('Hotrecommendlist/torecommend','4876')
|
||||
log(data)
|
||||
await req1('Hotrecommendlist/torecommend','4875')
|
||||
log(data)
|
||||
}
|
||||
//await SendMsg(msg);
|
||||
}
|
||||
}
|
||||
})()
|
||||
.catch((e) => log(e))
|
||||
.finally(() => $.done())
|
||||
async function Userlogin(password,phone) {
|
||||
return new Promise((resolve) => {
|
||||
var options = {
|
||||
method: 'POST',
|
||||
url: 'http://api.kq88.com/Userlogin',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
|
||||
Host: 'api.kq88.com',
|
||||
|
||||
'User-Agent': 'okhttp/3.8.1'
|
||||
},
|
||||
data: 'password='+password+'&phone='+phone+'&device='
|
||||
};
|
||||
if (debug) {
|
||||
log(`\n【debug】=============== 这是 请求 url ===============`);
|
||||
log(JSON.stringify(options));
|
||||
}
|
||||
axios.request(options).then(async function(response) {
|
||||
try {
|
||||
data = response.data;
|
||||
if (debug) {
|
||||
log(`\n\n【debug】===============这是 返回data==============`);
|
||||
authcode = data.listdata.authcode
|
||||
}
|
||||
if (data.result == 0) {
|
||||
authcode = data.listdata.authcode
|
||||
} else
|
||||
log(data)
|
||||
|
||||
|
||||
|
||||
} catch (e) {
|
||||
log(`异常:${data},原因:${data.message}`)
|
||||
}
|
||||
}).catch(function(error) {
|
||||
console.error(error);
|
||||
}).then(res => {
|
||||
//这里处理正确返回
|
||||
resolve();
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
async function req1(api,id) {
|
||||
return new Promise((resolve) => {
|
||||
var options = {
|
||||
method: 'POST',
|
||||
url: 'https://api.kq88.com/'+api,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
|
||||
Host: 'api.kq88.com',
|
||||
|
||||
'User-Agent': 'okhttp/3.8.1'
|
||||
},
|
||||
data: `code=${encodeURIComponent(authcode)}&ffid=0&commentpics=%5B%5D&sconect=%E5%BE%88%E5%A5%BD%20%E5%AD%A6%E5%88%B0%E4%BA%86%E8%80%81%E5%B8%88%20%E5%8F%97%E6%95%99%E4%BA%86%E3%80%82&id=${id}`
|
||||
};
|
||||
if (debug) {
|
||||
log(`\n【debug】=============== 这是 请求 url ===============`);
|
||||
log(JSON.stringify(options));
|
||||
}
|
||||
axios.request(options).then(async function(response) {
|
||||
try {
|
||||
data = response.data;
|
||||
if (debug) {
|
||||
log(`\n\n【debug】===============这是 返回data==============`);
|
||||
log(data)
|
||||
}
|
||||
if (data.result == 0) {
|
||||
|
||||
} else
|
||||
log(data)
|
||||
|
||||
|
||||
|
||||
} catch (e) {
|
||||
log(`异常:${data},原因:${data.message}`)
|
||||
}
|
||||
}).catch(function(error) {
|
||||
console.error(error);
|
||||
}).then(res => {
|
||||
//这里处理正确返回
|
||||
resolve();
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
async function req(api) {
|
||||
return new Promise((resolve) => {
|
||||
var options = {
|
||||
method: 'POST',
|
||||
url: 'https://api.kq88.com/'+api,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
|
||||
Host: 'api.kq88.com',
|
||||
|
||||
|
||||
'User-Agent': 'okhttp/3.8.1'
|
||||
},
|
||||
data: 'code='+encodeURIComponent(authcode)
|
||||
};
|
||||
if (debug) {
|
||||
log(`\n【debug】=============== 这是 请求 url ===============`);
|
||||
log(JSON.stringify(options));
|
||||
}
|
||||
axios.request(options).then(async function(response) {
|
||||
try {
|
||||
data = response.data;
|
||||
if (debug) {
|
||||
log(`\n\n【debug】===============这是 返回data==============`);
|
||||
log(data)
|
||||
}
|
||||
if (data.result == 0) {
|
||||
|
||||
} else
|
||||
log(data)
|
||||
|
||||
|
||||
|
||||
} catch (e) {
|
||||
log(`异常:${data},原因:${data.message}`)
|
||||
}
|
||||
}).catch(function(error) {
|
||||
console.error(error);
|
||||
}).then(res => {
|
||||
//这里处理正确返回
|
||||
resolve();
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
async function Envs() {
|
||||
if (yayihd) {
|
||||
if (yayihd.indexOf("@") != -1) {
|
||||
yayihd.split("@").forEach((item) => {
|
||||
|
||||
yayihdArr.push(item);
|
||||
});
|
||||
} else if (yayihd.indexOf("\n") != -1) {
|
||||
yayihd.split("\n").forEach((item) => {
|
||||
yayihdArr.push(item);
|
||||
});
|
||||
} else {
|
||||
yayihdArr.push(yayihd);
|
||||
}
|
||||
} else {
|
||||
log(`\n 【${$.name}】:未填写变量 yayihd`)
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
function addNotifyStr(str, is_log = true) {
|
||||
if (is_log) {
|
||||
log(`${str}\n`)
|
||||
}
|
||||
msg += `${str}\n`
|
||||
}
|
||||
|
||||
// ============================================发送消息============================================ \\
|
||||
async function SendMsg(message) {
|
||||
if (!message)
|
||||
return;
|
||||
|
||||
if (Notify > 0) {
|
||||
if ($.isNode()) {
|
||||
var notify = require('./sendNotify');
|
||||
await notify.sendNotify($.name, message);
|
||||
} else {
|
||||
$.msg(message);
|
||||
}
|
||||
} else {
|
||||
log(message);
|
||||
}
|
||||
}
|
||||
function Env(t, e) {
|
||||
"undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0);
|
||||
|
||||
class s {
|
||||
constructor(t) {
|
||||
this.env = t
|
||||
}
|
||||
|
||||
send(t, e = "GET") {
|
||||
t = "string" == typeof t ? {
|
||||
url: t
|
||||
} : t;
|
||||
let s = this.get;
|
||||
return "POST" === e && (s = this.post), new Promise((e, i) => {
|
||||
s.call(this, t, (t, s, r) => {
|
||||
t ? i(t) : e(s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
get(t) {
|
||||
return this.send.call(this.env, t)
|
||||
}
|
||||
|
||||
post(t) {
|
||||
return this.send.call(this.env, t, "POST")
|
||||
}
|
||||
}
|
||||
|
||||
return new class {
|
||||
constructor(t, e) {
|
||||
this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`)
|
||||
}
|
||||
|
||||
isNode() {
|
||||
return "undefined" != typeof module && !!module.exports
|
||||
}
|
||||
|
||||
isQuanX() {
|
||||
return "undefined" != typeof $task
|
||||
}
|
||||
|
||||
isSurge() {
|
||||
return "undefined" != typeof $httpClient && "undefined" == typeof $loon
|
||||
}
|
||||
|
||||
isLoon() {
|
||||
return "undefined" != typeof $loon
|
||||
}
|
||||
|
||||
toObj(t, e = null) {
|
||||
try {
|
||||
return JSON.parse(t)
|
||||
} catch {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
toStr(t, e = null) {
|
||||
try {
|
||||
return JSON.stringify(t)
|
||||
} catch {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
getjson(t, e) {
|
||||
let s = e;
|
||||
const i = this.getdata(t);
|
||||
if (i) try {
|
||||
s = JSON.parse(this.getdata(t))
|
||||
} catch {}
|
||||
return s
|
||||
}
|
||||
|
||||
setjson(t, e) {
|
||||
try {
|
||||
return this.setdata(JSON.stringify(t), e)
|
||||
} catch {
|
||||
return !1
|
||||
}
|
||||
}
|
||||
|
||||
getScript(t) {
|
||||
return new Promise(e => {
|
||||
this.get({
|
||||
url: t
|
||||
}, (t, s, i) => e(i))
|
||||
})
|
||||
}
|
||||
|
||||
runScript(t, e) {
|
||||
return new Promise(s => {
|
||||
let i = this.getdata("@chavy_boxjs_userCfgs.httpapi");
|
||||
i = i ? i.replace(/\n/g, "").trim() : i;
|
||||
let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");
|
||||
r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r;
|
||||
const [o, h] = i.split("@"), n = {
|
||||
url: `http://${h}/v1/scripting/evaluate`,
|
||||
body: {
|
||||
script_text: t,
|
||||
mock_type: "cron",
|
||||
timeout: r
|
||||
},
|
||||
headers: {
|
||||
"X-Key": o,
|
||||
Accept: "*/*"
|
||||
}
|
||||
};
|
||||
this.post(n, (t, e, i) => s(i))
|
||||
}).catch(t => this.logErr(t))
|
||||
}
|
||||
|
||||
loaddata() {
|
||||
if (!this.isNode()) return {}; {
|
||||
this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path");
|
||||
const t = this.path.resolve(this.dataFile),
|
||||
e = this.path.resolve(process.cwd(), this.dataFile),
|
||||
s = this.fs.existsSync(t),
|
||||
i = !s && this.fs.existsSync(e);
|
||||
if (!s && !i) return {}; {
|
||||
const i = s ? t : e;
|
||||
try {
|
||||
return JSON.parse(this.fs.readFileSync(i))
|
||||
} catch (t) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writedata() {
|
||||
if (this.isNode()) {
|
||||
this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path");
|
||||
const t = this.path.resolve(this.dataFile),
|
||||
e = this.path.resolve(process.cwd(), this.dataFile),
|
||||
s = this.fs.existsSync(t),
|
||||
i = !s && this.fs.existsSync(e),
|
||||
r = JSON.stringify(this.data);
|
||||
s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r)
|
||||
}
|
||||
}
|
||||
|
||||
lodash_get(t, e, s) {
|
||||
const i = e.replace(/\[(\d+)\]/g, ".$1").split(".");
|
||||
let r = t;
|
||||
for (const t of i)
|
||||
if (r = Object(r)[t], void 0 === r) return s;
|
||||
return r
|
||||
}
|
||||
|
||||
lodash_set(t, e, s) {
|
||||
return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t)
|
||||
}
|
||||
|
||||
getdata(t) {
|
||||
let e = this.getval(t);
|
||||
if (/^@/.test(t)) {
|
||||
const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : "";
|
||||
if (r) try {
|
||||
const t = JSON.parse(r);
|
||||
e = t ? this.lodash_get(t, i, "") : e
|
||||
} catch (t) {
|
||||
e = ""
|
||||
}
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
setdata(t, e) {
|
||||
let s = !1;
|
||||
if (/^@/.test(e)) {
|
||||
const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i),
|
||||
h = i ? "null" === o ? null : o || "{}" : "{}";
|
||||
try {
|
||||
const e = JSON.parse(h);
|
||||
this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i)
|
||||
} catch (e) {
|
||||
const o = {};
|
||||
this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i)
|
||||
}
|
||||
} else s = this.setval(t, e);
|
||||
return s
|
||||
}
|
||||
|
||||
getval(t) {
|
||||
return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null
|
||||
}
|
||||
|
||||
setval(t, e) {
|
||||
return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null
|
||||
}
|
||||
|
||||
initGotEnv(t) {
|
||||
this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar))
|
||||
}
|
||||
|
||||
get(t, e = (() => {})) {
|
||||
t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, {
|
||||
"X-Surge-Skip-Scripting": !1
|
||||
})), $httpClient.get(t, (t, s, i) => {
|
||||
!t && s && (s.body = i, s.statusCode = s.status), e(t, s, i)
|
||||
})) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, {
|
||||
hints: !1
|
||||
})), $task.fetch(t).then(t => {
|
||||
const {
|
||||
statusCode: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
} = t;
|
||||
e(null, {
|
||||
status: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
}, o)
|
||||
}, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => {
|
||||
try {
|
||||
if (t.headers["set-cookie"]) {
|
||||
const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();
|
||||
s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar
|
||||
}
|
||||
} catch (t) {
|
||||
this.logErr(t)
|
||||
}
|
||||
}).then(t => {
|
||||
const {
|
||||
statusCode: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
} = t;
|
||||
e(null, {
|
||||
status: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
}, o)
|
||||
}, t => {
|
||||
const {
|
||||
message: s,
|
||||
response: i
|
||||
} = t;
|
||||
e(s, i, i && i.body)
|
||||
}))
|
||||
}
|
||||
|
||||
post(t, e = (() => {})) {
|
||||
if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, {
|
||||
"X-Surge-Skip-Scripting": !1
|
||||
})), $httpClient.post(t, (t, s, i) => {
|
||||
!t && s && (s.body = i, s.statusCode = s.status), e(t, s, i)
|
||||
});
|
||||
else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, {
|
||||
hints: !1
|
||||
})), $task.fetch(t).then(t => {
|
||||
const {
|
||||
statusCode: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
} = t;
|
||||
e(null, {
|
||||
status: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
}, o)
|
||||
}, t => e(t));
|
||||
else if (this.isNode()) {
|
||||
this.initGotEnv(t);
|
||||
const {
|
||||
url: s,
|
||||
...i
|
||||
} = t;
|
||||
this.got.post(s, i).then(t => {
|
||||
const {
|
||||
statusCode: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
} = t;
|
||||
e(null, {
|
||||
status: s,
|
||||
statusCode: i,
|
||||
headers: r,
|
||||
body: o
|
||||
}, o)
|
||||
}, t => {
|
||||
const {
|
||||
message: s,
|
||||
response: i
|
||||
} = t;
|
||||
e(s, i, i && i.body)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
time(t, e = null) {
|
||||
const s = e ? new Date(e) : new Date;
|
||||
let i = {
|
||||
"M+": s.getMonth() + 1,
|
||||
"d+": s.getDate(),
|
||||
"H+": s.getHours(),
|
||||
"m+": s.getMinutes(),
|
||||
"s+": s.getSeconds(),
|
||||
"q+": Math.floor((s.getMonth() + 3) / 3),
|
||||
S: s.getMilliseconds()
|
||||
};
|
||||
/(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length)));
|
||||
for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length)));
|
||||
return t
|
||||
}
|
||||
|
||||
msg(e = t, s = "", i = "", r) {
|
||||
const o = t => {
|
||||
if (!t) return t;
|
||||
if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? {
|
||||
"open-url": t
|
||||
} : this.isSurge() ? {
|
||||
url: t
|
||||
} : void 0;
|
||||
if ("object" == typeof t) {
|
||||
if (this.isLoon()) {
|
||||
let e = t.openUrl || t.url || t["open-url"],
|
||||
s = t.mediaUrl || t["media-url"];
|
||||
return {
|
||||
openUrl: e,
|
||||
mediaUrl: s
|
||||
}
|
||||
}
|
||||
if (this.isQuanX()) {
|
||||
let e = t["open-url"] || t.url || t.openUrl,
|
||||
s = t["media-url"] || t.mediaUrl;
|
||||
return {
|
||||
"open-url": e,
|
||||
"media-url": s
|
||||
}
|
||||
}
|
||||
if (this.isSurge()) {
|
||||
let e = t.url || t.openUrl || t["open-url"];
|
||||
return {
|
||||
url: e
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) {
|
||||
let t = ["", "==============📣系统通知📣=============="];
|
||||
t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t)
|
||||
}
|
||||
}
|
||||
|
||||
log(...t) {
|
||||
t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator))
|
||||
}
|
||||
|
||||
logErr(t, e) {
|
||||
const s = !this.isSurge() && !this.isQuanX() && !this.isLoon();
|
||||
s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t)
|
||||
}
|
||||
|
||||
wait(t) {
|
||||
return new Promise(e => setTimeout(e, t))
|
||||
}
|
||||
|
||||
done(t = {}) {
|
||||
const e = (new Date).getTime(),
|
||||
s = (e - this.startTime) / 1e3;
|
||||
this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t)
|
||||
}
|
||||
}(t, e)
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
1027
脚本库/web版/账密/50-雅迪星球/2023-09-20_ydqx_15686835.js
Normal file
1027
脚本库/web版/账密/50-雅迪星球/2023-09-20_ydqx_15686835.js
Normal file
File diff suppressed because it is too large
Load Diff
24
脚本库/web版/账密/58-姐妹帮/2023-09-20_jmb_7328796e.js
Normal file
24
脚本库/web版/账密/58-姐妹帮/2023-09-20_jmb_7328796e.js
Normal file
File diff suppressed because one or more lines are too long
721
脚本库/web版/账密/6-十堰头条/2023-09-20_sytt_f2743bee.js
Normal file
721
脚本库/web版/账密/6-十堰头条/2023-09-20_sytt_f2743bee.js
Normal file
@@ -0,0 +1,721 @@
|
||||
// # Source: https://github.com/xfmeng970526/ql/blob/main/sytt.js
|
||||
// # Raw: https://raw.githubusercontent.com/xfmeng970526/ql/main/sytt.js
|
||||
// # Repo: xfmeng970526/ql
|
||||
// # Path: sytt.js
|
||||
// # UploadedAt: 2023-09-20T12:13:28+08:00
|
||||
// # SHA256: f2743bee7135f0b733a26d8225a842a5cb079131a11dd9145a0f85c0d9e5ff2f
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/*
|
||||
cron 8 7 * * * yml_javascript/sytt.js
|
||||
|
||||
软件名称:十堰头条
|
||||
下载地址:http://appx.10yan.com.cn/appshare/
|
||||
或者自己搜索下载
|
||||
3-17 完成签到、评论、分享、回帖 任务
|
||||
3-21 关闭评论、回帖功能 需要的自行打开,并自行设置回复内容
|
||||
感谢所有测试人员
|
||||
|
||||
自行安装 axios qs 依赖; 自行安装 axios qs 依赖; 自行安装 axios qs 依赖;
|
||||
青龙直接node中安装就行
|
||||
|
||||
注意事项 : 一定要仔细阅读一下内容
|
||||
=============青龙变量格式=============
|
||||
export yml_sytt_data='手机号&密码'
|
||||
多账号使用 @ 分割;
|
||||
|
||||
=============青龙变量实例=============
|
||||
我觉得已经不需要例子了 填上账号密码再不回那就别薅羊毛了吧
|
||||
=============变量解释==========
|
||||
手机号 密码 填入自己的数据就行
|
||||
=============变量获取==========
|
||||
|
||||
cron: 4 5,19 * * *
|
||||
new Env('6-十堰头条');
|
||||
项目名称:十堰头条
|
||||
*/
|
||||
const axios = require("axios");
|
||||
const qs = require("qs");
|
||||
const $ = new Env('十堰头条');
|
||||
const notify = $.isNode() ? require('./sendNotify') : '';
|
||||
let app_yml_sytt_data='';
|
||||
let user = '';
|
||||
let pwd = '';
|
||||
let uid;
|
||||
|
||||
|
||||
!(async () => {
|
||||
if ($.isNode()) {
|
||||
//$.isNode()环境执行部分 青龙执行
|
||||
if (!process.env.yml_sytt_data) {
|
||||
console.log(`\n【${$.name}】:未填写相应变量 yml_sytt_data`);
|
||||
return;
|
||||
}
|
||||
if (process.env.yml_sytt_data && process.env.yml_sytt_data.indexOf('@') > -1) {
|
||||
app_yml_sytt_data = process.env.yml_sytt_data.split('@');
|
||||
}else {
|
||||
app_yml_sytt_data = process.env.yml_sytt_data.split();
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`-------- 共 ${app_yml_sytt_data.length} 个账号 --------`)
|
||||
// console.log(app_yml_sytt_data)
|
||||
console.log(
|
||||
`\n\n====== 脚本执行 - 北京时间(UTC+8):${new Date(
|
||||
new Date().getTime() +
|
||||
new Date().getTimezoneOffset() * 60 * 1000 +
|
||||
8 * 60 * 60 * 1000
|
||||
).toLocaleString()} ======\n`);
|
||||
|
||||
|
||||
await wyy();
|
||||
|
||||
for (i = 0; i < app_yml_sytt_data.length; i++) {
|
||||
$.index = i + 1;
|
||||
console.log(`\n====== 开始【第 ${$.index} 个账号】======`)
|
||||
// console.log(`这里是分割后:${app_yml_sytt_data}`);
|
||||
data = app_yml_sytt_data[i].split('&');
|
||||
// console.log(`====== ${data}`)
|
||||
user = data[0]
|
||||
// console.log(`====user==== ${user}`)
|
||||
pwd = data[1]
|
||||
// console.log(`====pwd==== ${pwd}`)
|
||||
|
||||
//执行任务
|
||||
await syttdl();
|
||||
await $.wait(2 * 1000);
|
||||
await syttqd();
|
||||
await $.wait(2 * 1000);
|
||||
await plid();
|
||||
await $.wait(2 * 1000);
|
||||
await fxwz();
|
||||
await $.wait(2 * 1000);
|
||||
await tzid();
|
||||
await $.wait(2 * 1000);
|
||||
}
|
||||
|
||||
})()
|
||||
.catch((e) => $.logErr(e))
|
||||
.finally(() => $.done())
|
||||
|
||||
|
||||
//每日网抑云
|
||||
function wyy(timeout = 3 * 1000) {
|
||||
return new Promise((resolve) => {
|
||||
let url = {
|
||||
url: `https://keai.icu/apiwyy/api`
|
||||
}
|
||||
$.get(url, async (err, resp, data) => {
|
||||
try {
|
||||
data = JSON.parse(data)
|
||||
$.log(`\n【网抑云时间】: ${data.content} by--${data.music}`);
|
||||
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve()
|
||||
}
|
||||
}, timeout)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 登录
|
||||
function syttdl(timeout = 0) {
|
||||
urldl = `https://app.site.10yan.com.cn/index.php?s=/Api/Loginv3/signInv3&password=${pwd}&username=${user}`
|
||||
// console.log(urldl)
|
||||
return new Promise((resolve) => {
|
||||
let url = {
|
||||
url: urldl,
|
||||
headers: { } ,
|
||||
body: '',
|
||||
}
|
||||
// console.log(url);
|
||||
$.post(url, async (err, resp, data) => {
|
||||
try {
|
||||
// console.log(`输出 登录 data开始===================`);
|
||||
// console.log(data);
|
||||
// console.log(`输出 登录 data结束===================`);
|
||||
result = JSON.parse(data);
|
||||
if (result.code == "200") {
|
||||
console.log(`登录用户: ${user}`)
|
||||
$.log(`\n【🎉🎉🎉 恭喜您鸭 🎉🎉🎉】登录状态: ${result.retinfo} ✅ `)
|
||||
// await $.wait(3 * 1000)
|
||||
}else {
|
||||
$.log(`\n【🎉 恭喜个屁 🎉】登录状态:${result.retinfo} `)
|
||||
}
|
||||
uid = result.data.uid
|
||||
console.log(`这是你的用户id:uid=${uid}`)
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve()
|
||||
}
|
||||
}, timeout)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 签到
|
||||
function syttqd(timeout = 0) {
|
||||
return new Promise((resolve) => {
|
||||
let url = {
|
||||
url: `https://app.site.10yan.com.cn/index.php?s=/Api/Activityv1/sign&uid=${uid}&source=android&ver=6.2.3&build=145`,
|
||||
headers:'',
|
||||
}
|
||||
// console.log(url);
|
||||
$.get(url, async (err, resp, data) => {
|
||||
try {
|
||||
// console.log(`========输出签到 data开始===========`);
|
||||
// console.log(data);
|
||||
// console.log(`========输出签到 data结束=========`);
|
||||
result = JSON.parse(data);
|
||||
if (result.code == 200) {
|
||||
$.log(`\n【🎉🎉🎉 恭喜您鸭 🎉🎉🎉】签到状态:(${result.retinfo}) ,获得 ${result.money} ✅ `)
|
||||
// await $.wait(3 * 1000)
|
||||
} else if (result.code == 400) {
|
||||
$.log(`\n【🎉 恭喜个屁 🎉】签到状态: ${result.retinfo}`)
|
||||
}else {
|
||||
$.log(`\n【🎉 恭喜个屁 🎉】执行签到:失败 ❌ 了呢,原因未知! `)
|
||||
}
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve()
|
||||
}
|
||||
}, timeout)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 评论任务部分
|
||||
// 评论id
|
||||
function plid(timeout = 0) {
|
||||
// 获取文章id
|
||||
return new Promise((resolve) => {
|
||||
let url = {
|
||||
url: `https://app.site.10yan.com.cn/index.php?s=/Api/Newsv4/newslist&page=1&type=reply&source=android`,
|
||||
headers: {},
|
||||
}
|
||||
// console.log(url);
|
||||
$.get(url, async (err, resp, data) => {
|
||||
try {
|
||||
// console.log(`输出 data开始===================`);
|
||||
// console.log(data);
|
||||
// console.log(`输出data结束===================`);
|
||||
result = JSON.parse(data);
|
||||
for (let l = 0; l < 3; l++) {
|
||||
// console.log(`我是l===== ${l}`)
|
||||
wzid = result.list[l].contentid
|
||||
console.log(`获取评论文章id=${wzid}`)
|
||||
console.log(`开始发布评论`)
|
||||
await fbpl();
|
||||
console.log(`延迟5秒`)
|
||||
await $.wait(5 * 1000);
|
||||
console.log(`删除评论`)
|
||||
await hqplid();
|
||||
console.log(`\n`)
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve()
|
||||
}
|
||||
}, timeout)
|
||||
|
||||
})
|
||||
}
|
||||
// 发布评论
|
||||
function fbpl(timeout = 0) {
|
||||
let axios = require('axios')
|
||||
axios
|
||||
.post(`https://app.site.10yan.com.cn/index.php?s=/Api/Article/artReply/&actiontype=12&contentid=${wzid}&reply=good!&sessionid=801cf37e86eaa651914b3cac0c756f9a&title=%%E6%%88%%91%%E5%%B8%%82%%E4%%B8%%80%%E5%%BD%%A9%%E5%%8F%%8B%%E5%%88%%AE%%E4%%B8%%AD%%E2%%80%%9C%%E5%%A5%%BD%%E8%%BF%%90%%E5%%8D%%81%%E5%%80%%8D%%E2%%80%%9D%%E5%%A4%%B4%%E5%%A5%%9640%%E4%%B8%%87&uid=${uid}&source=android&build=145`, {
|
||||
})
|
||||
.then(res => {
|
||||
// console.log(res.data)
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error)
|
||||
})
|
||||
}
|
||||
// 获取评论 rid 并 删除评论
|
||||
function hqplid(timeout = 0) {
|
||||
let axios = require('axios');
|
||||
let config = {
|
||||
method: 'get',
|
||||
url: `https://app.site.10yan.com.cn/index.php?s=/Api/Article/index/&contentid=${wzid}&page=1&uid=${uid}`,
|
||||
headers: { }
|
||||
};
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
// console.log(`===========`)
|
||||
// console.log(JSON.stringify(response.data));
|
||||
// pl_data =response.data.list
|
||||
// console.log(pl_data)
|
||||
for ( k = 0; k < response.data.list.length; k++) {
|
||||
usid = response.data.list[k].userid;
|
||||
// console.log(usid)
|
||||
if (usid == `${uid}`) {
|
||||
// console.log(`====rid 开始=====`)
|
||||
// console.log(response.data.list[k].pid)
|
||||
// console.log(`=====rid 结束=====`)
|
||||
// rid = response.data.list[i].pid
|
||||
rid = response.data.list[k].pid
|
||||
// console.log(`我是 rid ${rid}`)
|
||||
|
||||
// 删除评论
|
||||
let axios = require('axios');
|
||||
let qs = require('qs');
|
||||
let data = qs.stringify({
|
||||
'rid': `${rid}`,
|
||||
'uid': `${uid}`,
|
||||
// 'source': 'android',
|
||||
'ver': '6.2.3',
|
||||
'build': '145'
|
||||
});
|
||||
let config = {
|
||||
method: 'post',
|
||||
url: 'https://app.site.10yan.com.cn/index.php?s=/Api/Article/delReply/',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
data : data
|
||||
};
|
||||
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
// console.log(JSON.stringify(response.data));
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
// 分享任务部分
|
||||
// 分享
|
||||
function fxwz(timeout = 0) {
|
||||
// 获取分享文章列表 id
|
||||
return new Promise((resolve) => {
|
||||
let url = {
|
||||
url: `https://app.site.10yan.com.cn/index.php?s=/Api/Newsv4/newslist&page=1&type=share&ver=6.2.3`,
|
||||
headers: {},
|
||||
}
|
||||
// console.log(url);
|
||||
$.get(url, async (err, resp, data) => {
|
||||
try {
|
||||
// console.log(`输出 data开始===================`);
|
||||
// console.log(data);
|
||||
// console.log(`输出data结束===================`);
|
||||
result = JSON.parse(data);
|
||||
for (let m = 0; m < 3; m++) {
|
||||
// console.log(`我是m===== ${m}`)
|
||||
fxwzid = result.list[m].contentid
|
||||
console.log(`获取分享文章id=${fxwzid}`)
|
||||
console.log(`开始分享文章`)
|
||||
await fxwz1();
|
||||
console.log(`延迟5秒`)
|
||||
await $.wait(5 * 1000);
|
||||
console.log(`\n`)
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve()
|
||||
}
|
||||
}, timeout)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 文章分享调用函数
|
||||
function fxwz1(timeout = 0) {
|
||||
let axios = require('axios');
|
||||
let config = {
|
||||
method: 'get',
|
||||
url: `https://app.site.10yan.com.cn/index.php?s=/Api/Activityv1/getNewsShareTask&contentid=${fxwzid}&uid=${uid}&source=android&ver=6.2.3`,
|
||||
headers: { }
|
||||
};
|
||||
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
console.log(JSON.stringify(response.data));
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 帖子id
|
||||
function tzid(timeout = 0) {
|
||||
// 获取帖子 文章id
|
||||
return new Promise((resolve) => {
|
||||
let url = {
|
||||
url: `https://app.site.10yan.com.cn/index.php?s=/Api/Dynamic&isrecommend=1&page=1&uid=${uid}`,
|
||||
headers: {},
|
||||
}
|
||||
// console.log(url);
|
||||
$.get(url, async (err, resp, data) => {
|
||||
try {
|
||||
// console.log(`输出data开始===================`);
|
||||
// console.log(data);
|
||||
// console.log(`输出data结束===================`);
|
||||
result = JSON.parse(data);
|
||||
for (let n = 0; n < 3; n++) {
|
||||
tzid1 = result.data[n].id
|
||||
console.log(`开始回帖:id=${tzid1}`)
|
||||
await tzpl();
|
||||
console.log(`延迟5秒`)
|
||||
await $.wait(5 * 1000);
|
||||
console.log(`\n`)
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
// $.logErr(e, resp);
|
||||
} finally {
|
||||
resolve()
|
||||
}
|
||||
}, timeout)
|
||||
|
||||
})
|
||||
}
|
||||
// 帖子发布评论
|
||||
function tzpl(timeout = 0) {
|
||||
var axios = require('axios');
|
||||
var data = `content=%E5%A4%AA%E6%BC%82%E4%BA%AE%E4%BA%86%E9%B8%AD&pid=${tzid1}&uid=${uid}&source=android&ver=6.2.3&build=145`
|
||||
var config = {
|
||||
method: 'post',
|
||||
url: 'https://app.site.10yan.com.cn/index.php?s=/Api/Dynamic/reply',
|
||||
headers: {
|
||||
'content-type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
data : data
|
||||
};
|
||||
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
// console.log(JSON.stringify(response.data));
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//固定板块,无需动
|
||||
function Env(t, e) {
|
||||
class s {
|
||||
constructor(t) {
|
||||
this.env = t
|
||||
}
|
||||
|
||||
send(t, e = "GET") {
|
||||
t = "string" == typeof t ? {url: t} : t;
|
||||
let s = this.get;
|
||||
return "POST" === e && (s = this.post), new Promise((e, i) => {
|
||||
s.call(this, t, (t, s, r) => {
|
||||
t ? i(t) : e(s)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
get(t) {
|
||||
return this.send.call(this.env, t)
|
||||
}
|
||||
|
||||
post(t) {
|
||||
return this.send.call(this.env, t, "POST")
|
||||
}
|
||||
}
|
||||
|
||||
return new class {
|
||||
constructor(t, e) {
|
||||
this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.encoding = "utf-8", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `\ud83d\udd14${this.name}, \u5f00\u59cb!`)
|
||||
}
|
||||
|
||||
isNode() {
|
||||
return "undefined" != typeof module && !!module.exports
|
||||
}
|
||||
|
||||
isQuanX() {
|
||||
return "undefined" != typeof $task
|
||||
}
|
||||
|
||||
isSurge() {
|
||||
return "undefined" != typeof $httpClient && "undefined" == typeof $loon
|
||||
}
|
||||
|
||||
isLoon() {
|
||||
return "undefined" != typeof $loon
|
||||
}
|
||||
|
||||
isShadowrocket() {
|
||||
return "undefined" != typeof $rocket
|
||||
}
|
||||
|
||||
toObj(t, e = null) {
|
||||
try {
|
||||
return JSON.parse(t)
|
||||
} catch {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
toStr(t, e = null) {
|
||||
try {
|
||||
return JSON.stringify(t)
|
||||
} catch {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
getjson(t, e) {
|
||||
let s = e;
|
||||
const i = this.getdata(t);
|
||||
if (i) try {
|
||||
s = JSON.parse(this.getdata(t))
|
||||
} catch {
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
setjson(t, e) {
|
||||
try {
|
||||
return this.setdata(JSON.stringify(t), e)
|
||||
} catch {
|
||||
return !1
|
||||
}
|
||||
}
|
||||
|
||||
getScript(t) {
|
||||
return new Promise(e => {
|
||||
this.get({url: t}, (t, s, i) => e(i))
|
||||
})
|
||||
}
|
||||
|
||||
runScript(t, e) {
|
||||
return new Promise(s => {
|
||||
let i = this.getdata("@chavy_boxjs_userCfgs.httpapi");
|
||||
i = i ? i.replace(/\n/g, "").trim() : i;
|
||||
let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");
|
||||
r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r;
|
||||
const [o, h] = i.split("@"), n = {
|
||||
url: `http://${h}/v1/scripting/evaluate`,
|
||||
body: {script_text: t, mock_type: "cron", timeout: r},
|
||||
headers: {"X-Key": o, Accept: "*/*"}
|
||||
};
|
||||
this.post(n, (t, e, i) => s(i))
|
||||
}).catch(t => this.logErr(t))
|
||||
}
|
||||
|
||||
loaddata() {
|
||||
if (!this.isNode()) return {};
|
||||
{
|
||||
this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path");
|
||||
const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile),
|
||||
s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e);
|
||||
if (!s && !i) return {};
|
||||
{
|
||||
const i = s ? t : e;
|
||||
try {
|
||||
return JSON.parse(this.fs.readFileSync(i))
|
||||
} catch (t) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writedata() {
|
||||
if (this.isNode()) {
|
||||
this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path");
|
||||
const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile),
|
||||
s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data);
|
||||
s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r)
|
||||
}
|
||||
}
|
||||
|
||||
lodash_get(t, e, s) {
|
||||
const i = e.replace(/\[(\d+)\]/g, ".$1").split(".");
|
||||
let r = t;
|
||||
for (const t of i) if (r = Object(r)[t], void 0 === r) return s;
|
||||
return r
|
||||
}
|
||||
|
||||
lodash_set(t, e, s) {
|
||||
return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t)
|
||||
}
|
||||
|
||||
getdata(t) {
|
||||
let e = this.getval(t);
|
||||
if (/^@/.test(t)) {
|
||||
const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : "";
|
||||
if (r) try {
|
||||
const t = JSON.parse(r);
|
||||
e = t ? this.lodash_get(t, i, "") : e
|
||||
} catch (t) {
|
||||
e = ""
|
||||
}
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
setdata(t, e) {
|
||||
let s = !1;
|
||||
if (/^@/.test(e)) {
|
||||
const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i),
|
||||
h = i ? "null" === o ? null : o || "{}" : "{}";
|
||||
try {
|
||||
const e = JSON.parse(h);
|
||||
this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i)
|
||||
} catch (e) {
|
||||
const o = {};
|
||||
this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i)
|
||||
}
|
||||
} else s = this.setval(t, e);
|
||||
return s
|
||||
}
|
||||
|
||||
getval(t) {
|
||||
return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null
|
||||
}
|
||||
|
||||
setval(t, e) {
|
||||
return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null
|
||||
}
|
||||
|
||||
initGotEnv(t) {
|
||||
this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar))
|
||||
}
|
||||
|
||||
get(t, e = (() => {
|
||||
})) {
|
||||
if (t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, {"X-Surge-Skip-Scripting": !1})), $httpClient.get(t, (t, s, i) => {
|
||||
!t && s && (s.body = i, s.statusCode = s.status), e(t, s, i)
|
||||
}); else if (this.isQuanX()) this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, {hints: !1})), $task.fetch(t).then(t => {
|
||||
const {statusCode: s, statusCode: i, headers: r, body: o} = t;
|
||||
e(null, {status: s, statusCode: i, headers: r, body: o}, o)
|
||||
}, t => e(t)); else if (this.isNode()) {
|
||||
let s = require("iconv-lite");
|
||||
this.initGotEnv(t), this.got(t).on("redirect", (t, e) => {
|
||||
try {
|
||||
if (t.headers["set-cookie"]) {
|
||||
const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();
|
||||
s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar
|
||||
}
|
||||
} catch (t) {
|
||||
this.logErr(t)
|
||||
}
|
||||
}).then(t => {
|
||||
const {statusCode: i, statusCode: r, headers: o, rawBody: h} = t;
|
||||
e(null, {status: i, statusCode: r, headers: o, rawBody: h}, s.decode(h, this.encoding))
|
||||
}, t => {
|
||||
const {message: i, response: r} = t;
|
||||
e(i, r, r && s.decode(r.rawBody, this.encoding))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
post(t, e = (() => {
|
||||
})) {
|
||||
const s = t.method ? t.method.toLocaleLowerCase() : "post";
|
||||
if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, {"X-Surge-Skip-Scripting": !1})), $httpClient[s](t, (t, s, i) => {
|
||||
!t && s && (s.body = i, s.statusCode = s.status), e(t, s, i)
|
||||
}); else if (this.isQuanX()) t.method = s, this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, {hints: !1})), $task.fetch(t).then(t => {
|
||||
const {statusCode: s, statusCode: i, headers: r, body: o} = t;
|
||||
e(null, {status: s, statusCode: i, headers: r, body: o}, o)
|
||||
}, t => e(t)); else if (this.isNode()) {
|
||||
let i = require("iconv-lite");
|
||||
this.initGotEnv(t);
|
||||
const {url: r, ...o} = t;
|
||||
this.got[s](r, o).then(t => {
|
||||
const {statusCode: s, statusCode: r, headers: o, rawBody: h} = t;
|
||||
e(null, {status: s, statusCode: r, headers: o, rawBody: h}, i.decode(h, this.encoding))
|
||||
}, t => {
|
||||
const {message: s, response: r} = t;
|
||||
e(s, r, r && i.decode(r.rawBody, this.encoding))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
time(t, e = null) {
|
||||
const s = e ? new Date(e) : new Date;
|
||||
let i = {
|
||||
"M+": s.getMonth() + 1,
|
||||
"d+": s.getDate(),
|
||||
"H+": s.getHours(),
|
||||
"m+": s.getMinutes(),
|
||||
"s+": s.getSeconds(),
|
||||
"q+": Math.floor((s.getMonth() + 3) / 3),
|
||||
S: s.getMilliseconds()
|
||||
};
|
||||
/(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length)));
|
||||
for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length)));
|
||||
return t
|
||||
}
|
||||
|
||||
msg(e = t, s = "", i = "", r) {
|
||||
const o = t => {
|
||||
if (!t) return t;
|
||||
if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? {"open-url": t} : this.isSurge() ? {url: t} : void 0;
|
||||
if ("object" == typeof t) {
|
||||
if (this.isLoon()) {
|
||||
let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"];
|
||||
return {openUrl: e, mediaUrl: s}
|
||||
}
|
||||
if (this.isQuanX()) {
|
||||
let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl;
|
||||
return {"open-url": e, "media-url": s}
|
||||
}
|
||||
if (this.isSurge()) {
|
||||
let e = t.url || t.openUrl || t["open-url"];
|
||||
return {url: e}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) {
|
||||
let t = ["", "==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];
|
||||
t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t)
|
||||
}
|
||||
}
|
||||
|
||||
log(...t) {
|
||||
t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator))
|
||||
}
|
||||
|
||||
logErr(t, e) {
|
||||
const s = !this.isSurge() && !this.isQuanX() && !this.isLoon();
|
||||
s ? this.log("", `\u2757\ufe0f${this.name}, \u9519\u8bef!`, t.stack) : this.log("", `\u2757\ufe0f${this.name}, \u9519\u8bef!`, t)
|
||||
}
|
||||
|
||||
wait(t) {
|
||||
return new Promise(e => setTimeout(e, t))
|
||||
}
|
||||
|
||||
done(t = {}) {
|
||||
const e = (new Date).getTime(), s = (e - this.startTime) / 1e3;
|
||||
this.log("", `\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t)
|
||||
}
|
||||
}(t, e)
|
||||
}
|
||||
22
脚本库/web版/账密/60-交汇点新闻/2023-09-20_jhdxw_3ed9b56b.js
Normal file
22
脚本库/web版/账密/60-交汇点新闻/2023-09-20_jhdxw_3ed9b56b.js
Normal file
File diff suppressed because one or more lines are too long
21
脚本库/web版/账密/61-无锡观察/2023-09-20_wxgc_13b7d0c7.js
Normal file
21
脚本库/web版/账密/61-无锡观察/2023-09-20_wxgc_13b7d0c7.js
Normal file
File diff suppressed because one or more lines are too long
46
脚本库/web版/账密/65-资金盘-电动车/2023-09-20_xmddc_501152cc.js
Normal file
46
脚本库/web版/账密/65-资金盘-电动车/2023-09-20_xmddc_501152cc.js
Normal file
File diff suppressed because one or more lines are too long
23
脚本库/web版/账密/66-无限玉环/2023-09-20_wxyh_e5bb37fd.js
Normal file
23
脚本库/web版/账密/66-无限玉环/2023-09-20_wxyh_e5bb37fd.js
Normal file
File diff suppressed because one or more lines are too long
344
脚本库/web版/账密/68-小时工记账/2023-09-20_xsgjz_22259ffa.py
Normal file
344
脚本库/web版/账密/68-小时工记账/2023-09-20_xsgjz_22259ffa.py
Normal file
@@ -0,0 +1,344 @@
|
||||
# Source: https://github.com/xfmeng970526/ql/blob/main/xsgjz.py
|
||||
# Raw: https://raw.githubusercontent.com/xfmeng970526/ql/main/xsgjz.py
|
||||
# Repo: xfmeng970526/ql
|
||||
# Path: xsgjz.py
|
||||
# UploadedAt: 2023-09-20T12:13:28+08:00
|
||||
# SHA256: 22259ffaf306b5014daacf34cd5b01ffd38728cee07678abdc66b9fbc1bb9b1a
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
#变量xsgCookie,抓取小时工记账的authorization变量
|
||||
#定时调成5 6-18/6 * * *
|
||||
cron: 5 6-18/6 * * *
|
||||
new Env('68-小时工记账');
|
||||
项目名称:小时工记账
|
||||
from cgitb import text
|
||||
import json
|
||||
import time
|
||||
import requests as r
|
||||
import requests
|
||||
import re
|
||||
import json
|
||||
import os
|
||||
|
||||
#获取名字链接
|
||||
mzurl = "https://xsg-api.julanling.com/app/user/info"
|
||||
#获取金币数量链接
|
||||
jburl = "https://xsg-api.julanling.com/h5/api/activityThirdAccount/coin/getAccount"
|
||||
#签到链接
|
||||
signurl = "https://market-gateway.julanling.com/market-center/api2/signIn/signIn"
|
||||
#转盘链接
|
||||
zpurl = "https://market-gateway.julanling.com/market-center/api2/dial/luckyDraw"
|
||||
#转盘金币领奖链接
|
||||
zpljurl = "https://market-gateway.julanling.com/market-center/api2/dial/receiveDialCoin"
|
||||
#转盘宝箱领奖链接
|
||||
zpbxurl = "https://market-gateway.julanling.com/market-center/api2/dial/openBox"
|
||||
#转盘双倍卡链接
|
||||
zpsburl = "https://market-gateway.julanling.com/market-center/api2/dial/receiveDoubleCardBag"
|
||||
#获取宝箱状态
|
||||
bxzturl= "https://market-gateway.julanling.com/market-center/api2/dial/detailCore?appVersion=4.4.20"
|
||||
#刷新扭蛋状态
|
||||
ndsxurl = "https://market-gateway.julanling.com/market-center/api2/gacha/index?os=ANDROID&appVersion=4.4.20"
|
||||
#扭蛋链接
|
||||
ndurl = "https://market-gateway.julanling.com/market-center/api2/gacha/luckyDraw"
|
||||
#扭蛋广告链接
|
||||
ndadurl = "https://market-gateway.julanling.com/market-center/api2/gacha/finishGachaTask"
|
||||
#7次广告链接
|
||||
qiadurl = "https://market-gateway.julanling.com/market-center/api2/assignment/finishAssignment"
|
||||
|
||||
|
||||
|
||||
if os.environ.get("xsgCookie"):
|
||||
dvm = os.environ["xsgCookie"]
|
||||
if dvm != '':
|
||||
if "@" in dvm:
|
||||
Coo = dvm.split("@")
|
||||
elif "&" in dvm:
|
||||
Coo = dvm.split('&')
|
||||
else:
|
||||
Coo = dvm.split('\n')
|
||||
adv=1
|
||||
for i in Coo:
|
||||
headers = {
|
||||
"security": "cD1jb20uanVsYW5nbGluZy54c2dqeiZjPXhzZ2p6X3lpbmd5b25nYmFvJnY9NC40LjIwJmQ9MzU1MWU0MDFiYjQ0MWVlY2JiNDU5ZjkwMDE1MzJlMzEmdT1ZN2wyVitQNWdOd0RBRFZjR0huQ2VzbXAmdD0xNjczMDk4OTY5.7e9e9d0818df515f6a384d9d5debde40",
|
||||
"authorization": i,
|
||||
"user-agent": 'Mozilla/5.0 (Linux; Android 11; M2012K11AC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/107.0.5304.105 Mobile Safari/537.36;_android{"version":4420,"versionName":"4.4.20","userType":"1","sdkVersion":"30","statusBarHeight":29,"toolBarHeight":73,"imei":"","oaid":"ad58bc17b41a81c7","channel":"xsgjz_yingyongbao","uid":10522}_android',
|
||||
"content-type": "application/json;charset=UTF-8"
|
||||
}
|
||||
print(f'登录第{adv}个账号')
|
||||
adv=adv+1
|
||||
|
||||
#登录验证
|
||||
resp = r.post(mzurl, headers=headers)
|
||||
xx = json.loads(resp.text)
|
||||
if xx["results"] == "null":
|
||||
print("登录失败,请重新获取Authorization")
|
||||
continue
|
||||
else:
|
||||
print("用户ID:"+xx["results"]["nickname"])
|
||||
|
||||
#获取金币数量
|
||||
jb = r.post(jburl, headers=headers)
|
||||
xb = json.loads(jb.text)
|
||||
if xb["results"] == "null":
|
||||
print("获取金币失败,请检测Authorization是否可用")
|
||||
else:
|
||||
print("目前金币数量:"+str(xb["results"]["credits"]))
|
||||
print("可提现:"+str(xb["results"]["aboutAmount"]))
|
||||
print("今日赚取金币数量:"+str(xb["results"]["currentCredits"]))
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
#签到
|
||||
qdbody = {"os":"ANDROID","appVersion":"4.4.20","appChannel":"xsgjz_yingyongbao","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9"}
|
||||
qd = r.post(signurl, headers=headers, json=qdbody)
|
||||
qdd = json.loads(qd.text)
|
||||
print("开始签到")
|
||||
if qdd["errorCode"] == 0:
|
||||
print("签到成功获取金币:"+str(qdd["results"]["amount"]))
|
||||
else:
|
||||
print("签到失败原因:"+str(qdd["errorStr"]))
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
#转转盘
|
||||
nc=1
|
||||
zzpyz = r.get(bxzturl, headers=headers)
|
||||
zptz = json.loads(zzpyz.text)
|
||||
zpsycs = str(zptz["results"]["dialValidNum"])
|
||||
print("转盘剩余次数"+zpsycs)
|
||||
zpsycs=int(zpsycs)
|
||||
for o in range(zpsycs):
|
||||
print("开始第"+str(nc)+"次转盘")
|
||||
time.sleep(3)
|
||||
nc=nc+1
|
||||
body = {"appChannel":"xsgjz_yingyongbao","appVersion":"4.4.20","appPackage":"com.julangling.xsgjz","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","operatingSystem":"ANDROID"}
|
||||
zp = r.post(zpurl, headers=headers,json=body)
|
||||
zpp = json.loads(zp.text)
|
||||
if zpp["errorCode"] == 0:
|
||||
if zpp["results"]["awardType"] == "GOLD":
|
||||
biz = zpp["results"]["bizNo"]
|
||||
zpbody = {
|
||||
"bizNo":biz,
|
||||
"appChannel":"xsgjz_yingyongbao",
|
||||
"appVersion":"4.4.20",
|
||||
"appPackage":"com.julangling.xsgjz",
|
||||
"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9",
|
||||
"operatingSystem":"ANDROID"
|
||||
}
|
||||
time.sleep(3)
|
||||
lj = r.post(zpljurl, headers=headers,json=zpbody)
|
||||
ljj = json.loads(lj.text)
|
||||
print("抽到金币"+str(ljj["results"]["amount"]))
|
||||
|
||||
elif zpp["results"]["awardType"] == "DOUBLE_VIDEO":
|
||||
print("抽到双倍卡,需要观看广告")
|
||||
biz = zpp["results"]["bizNo"]
|
||||
zpbody = {
|
||||
"bizNo":biz,
|
||||
"appChannel":"xsgjz_yingyongbao",
|
||||
"appVersion":"4.4.20",
|
||||
"appPackage":"com.julangling.xsgjz",
|
||||
"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9",
|
||||
"operatingSystem":"ANDROID"
|
||||
}
|
||||
time.sleep(3)
|
||||
sb = r.post(zpsburl, headers=headers,json=zpbody)
|
||||
sbb = json.loads(sb.text)
|
||||
print("观看成功剩余翻倍奖励次数"+str(sbb["results"]["dialCardBag"]["DOUBLE"]))
|
||||
|
||||
print("转盘结束,查看可领取那些宝箱")
|
||||
#转盘5次宝箱奖励body
|
||||
bx1={"businessType":"XSG_BOX_ONE","appChannel":"xsgjz_yingyongbao","appVersion":"4.4.20","appPackage":"com.julangling.xsgjz","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","operatingSystem":"ANDROID"}
|
||||
#转盘18次宝箱奖励body
|
||||
bx2={"businessType":"XSG_BOX_TWO","appChannel":"xsgjz_yingyongbao","appVersion":"4.4.20","appPackage":"com.julangling.xsgjz","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","operatingSystem":"ANDROID"}
|
||||
#转盘30次宝箱奖励body
|
||||
bx3={"businessType":"XSG_BOX_THREE","appChannel":"xsgjz_yingyongbao","appVersion":"4.4.20","appPackage":"com.julangling.xsgjz","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","operatingSystem":"ANDROID"}
|
||||
#转盘55次宝箱奖励body
|
||||
bx4={"businessType":"XSG_BOX_FOUR","appChannel":"xsgjz_yingyongbao","appVersion":"4.4.20","appPackage":"com.julangling.xsgjz","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","operatingSystem":"ANDROID"}
|
||||
|
||||
#转盘宝箱领取
|
||||
time.sleep(3)
|
||||
print("开始领转盘5次箱子奖励")
|
||||
zpbx1 = r.post(zpbxurl, headers=headers,json=bx1)
|
||||
bxx1 = json.loads(zpbx1.text)
|
||||
if bxx1["errorCode"] == 0:
|
||||
results = bxx1['results']
|
||||
openBoxAwards = results['openBoxAwards']
|
||||
bx1jb = openBoxAwards[0]['amount']
|
||||
print("领取成功获得"+str(bx1jb)+"金币")
|
||||
else:
|
||||
print("领取失败,原因:"+str(bxx1["errorStr"]))
|
||||
time.sleep(3)
|
||||
|
||||
time.sleep(3)
|
||||
print("开始领转盘18次箱子奖励")
|
||||
zpbx2 = r.post(zpbxurl, headers=headers,json=bx2)
|
||||
bxx2 = json.loads(zpbx2.text)
|
||||
if bxx2["errorCode"] == 0:
|
||||
results2 = bxx2['results']
|
||||
openBoxAwards2 = results2['openBoxAwards']
|
||||
bx2jb = openBoxAwards2[0]['amount']
|
||||
print("领取成功获得"+str(bx2jb)+"金币")
|
||||
bxbizNo2 = bxx2['results']['openBoxAwards'][1]['bizNo']
|
||||
print("领取箱子双倍卡,需要观看广告")
|
||||
zpbody = {
|
||||
"bizNo":bxbizNo2,
|
||||
"appChannel":"xsgjz_yingyongbao",
|
||||
"appVersion":"4.4.20",
|
||||
"appPackage":"com.julangling.xsgjz",
|
||||
"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9",
|
||||
"operatingSystem":"ANDROID"
|
||||
}
|
||||
time.sleep(3)
|
||||
sb = r.post(zpsburl, headers=headers,json=zpbody)
|
||||
sbb = json.loads(sb.text)
|
||||
print("观看成功剩余翻倍奖励次数"+str(sbb["results"]["dialCardBag"]["DOUBLE"]))
|
||||
del bxx2
|
||||
del results2
|
||||
del openBoxAwards2
|
||||
del bx2jb
|
||||
del bxbizNo2
|
||||
del sb
|
||||
del sbb
|
||||
else:
|
||||
print("领取失败,原因:"+str(bxx2["errorStr"]))
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
time.sleep(5)
|
||||
print("开始领转盘30次箱子奖励")
|
||||
zpbx3 = r.post(zpbxurl, headers=headers,json=bx3)
|
||||
bxx3 = json.loads(zpbx3.text)
|
||||
if bxx3["errorCode"] == 0:
|
||||
results3 = bxx3['results']
|
||||
openBoxAwards3 = results3['openBoxAwards']
|
||||
bx3jb = openBoxAwards3[0]['amount']
|
||||
print("领取成功获得"+str(bx3jb)+"金币")
|
||||
bxbizNo3 = bxx3['results']['openBoxAwards'][1]['bizNo']
|
||||
print("领取箱子双倍卡,需要观看广告")
|
||||
zpbody = {
|
||||
"bizNo":bxbizNo3,
|
||||
"appChannel":"xsgjz_yingyongbao",
|
||||
"appVersion":"4.4.20",
|
||||
"appPackage":"com.julangling.xsgjz",
|
||||
"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9",
|
||||
"operatingSystem":"ANDROID"
|
||||
}
|
||||
time.sleep(3)
|
||||
sb = r.post(zpsburl, headers=headers,json=zpbody)
|
||||
sbb = json.loads(sb.text)
|
||||
print("观看成功剩余翻倍奖励次数"+str(sbb["results"]["dialCardBag"]["DOUBLE"]))
|
||||
del bxx3
|
||||
del results3
|
||||
del openBoxAwards3
|
||||
del bx3jb
|
||||
del bxbizNo3
|
||||
del sb
|
||||
del sbb
|
||||
else:
|
||||
print("领取失败,原因:"+str(bxx3["errorStr"]))
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
|
||||
time.sleep(3)
|
||||
print("开始领转盘55次箱子奖励")
|
||||
zpbx4 = r.post(zpbxurl, headers=headers,json=bx4)
|
||||
bxx4 = json.loads(zpbx4.text)
|
||||
if bxx4["errorCode"] == 0:
|
||||
results4 = bxx4['results']
|
||||
openBoxAwards4 = results4['openBoxAwards']
|
||||
bx4jb = openBoxAwards4[0]['amount']
|
||||
print("领取成功获得"+str(bx4jb)+"金币")
|
||||
bxbizNo4 = bxx4['results']['openBoxAwards'][1]['bizNo']
|
||||
print("领取箱子双倍卡,需要观看广告")
|
||||
zpbody = {
|
||||
"bizNo":bxbizNo4,
|
||||
"appChannel":"xsgjz_yingyongbao",
|
||||
"appVersion":"4.4.20",
|
||||
"appPackage":"com.julangling.xsgjz",
|
||||
"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9",
|
||||
"operatingSystem":"ANDROID"
|
||||
}
|
||||
time.sleep(3)
|
||||
sb = r.post(zpsburl, headers=headers,json=zpbody)
|
||||
sbb = json.loads(sb.text)
|
||||
print("观看成功剩余翻倍奖励次数"+str(sbb["results"]["dialCardBag"]["DOUBLE"]))
|
||||
del bxx4
|
||||
del results4
|
||||
del openBoxAwards4
|
||||
del bx4jb
|
||||
del bxbizNo4
|
||||
del sb
|
||||
del sbb
|
||||
else:
|
||||
print("领取失败,原因:"+str(bxx4["errorStr"]))
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
|
||||
#扭蛋
|
||||
vc=1
|
||||
bc=1
|
||||
#先刷新扭蛋列表
|
||||
ndsx = r.get(ndsxurl, headers=headers)
|
||||
ndsxx = json.loads(ndsx.text)
|
||||
#判断扭蛋广告可观看次数
|
||||
ndadcs= ndsxx["results"]["remainVideoTimes"]
|
||||
print("扭蛋广告剩余次数"+str(ndadcs))
|
||||
#观看扭蛋广告
|
||||
for o in range(ndadcs):
|
||||
print("开始第"+str(bc)+"次观看扭蛋广告")
|
||||
bc=bc+1
|
||||
time.sleep(3)
|
||||
ndadbody={"businessType":"XSG_DAILY_GACHA_INC_VIDEOS","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","version":"4.4.20","os":"ANDROID","appVersion":"4.4.20","appChannel":"unknow"}
|
||||
ndad = r.post(ndadurl, headers=headers,json=ndadbody)
|
||||
nddad = json.loads(ndad.text)
|
||||
if nddad['errorCode'] == 0:
|
||||
print("获得"+str(nddad["results"]["amount"])+"次抽奖次数")
|
||||
print("目前有"+str(nddad["results"]["remainTimes"])+"次抽奖次数")
|
||||
time.sleep(3)
|
||||
else:
|
||||
print("扭蛋失败原因"+nddad['errorStr'])
|
||||
|
||||
|
||||
ndsx = r.get(ndsxurl, headers=headers)
|
||||
ndsxx = json.loads(ndsx.text)
|
||||
#判断扭蛋次数
|
||||
ndsycs = ndsxx["results"]["remainTimes"]
|
||||
print("扭蛋剩余次数"+str(ndsycs))
|
||||
#开始扭蛋
|
||||
for o in range(ndsycs):
|
||||
print("开始第"+str(vc)+"次扭蛋")
|
||||
vc=vc+1
|
||||
time.sleep(3)
|
||||
ndbody={"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","version":"4.4.20","os":"ANDROID","appVersion":"4.4.20","appChannel":"unknow"}
|
||||
nd = r.post(ndurl, headers=headers,json=ndbody)
|
||||
ndd = json.loads(nd.text)
|
||||
if ndd['errorCode'] == 0:
|
||||
if ndd["results"]["awardType"] == 'ADVERT':
|
||||
print("抽到了空气广告")
|
||||
else:
|
||||
print("抽到"+str(ndd["results"]["name"]))
|
||||
else:
|
||||
print("扭蛋失败原因"+ndd['errorStr'])
|
||||
|
||||
time.sleep(3)
|
||||
#看广告7次
|
||||
for c in range(7):
|
||||
qiadbody={"businessType":"XSG_MONEY_CENTER_INCENTIVE_VIDEO","os":"ANDROID","appVersion":"4.4.20","appChannel":"xsgjz_yingyongbao","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9"}
|
||||
adws = r.post(qiadurl, headers=headers,json=qiadbody)
|
||||
adwss = json.loads(adws.text)
|
||||
if adwss['errorCode'] == 0:
|
||||
adwssjb = adwss["results"]["awardInfos"]
|
||||
adwssjbb = adwssjb[0]['amount']
|
||||
print("获得金币"+str(adwssjbb)+"个")
|
||||
print("等待20秒,才可以观看广告")
|
||||
time.sleep(21)
|
||||
else:
|
||||
|
||||
break
|
||||
|
||||
|
||||
|
||||
344
脚本库/web版/账密/68-小时工记账/2023-09-20_xsgjz_465b4e71.js
Normal file
344
脚本库/web版/账密/68-小时工记账/2023-09-20_xsgjz_465b4e71.js
Normal file
@@ -0,0 +1,344 @@
|
||||
// # Source: https://github.com/xfmeng970526/ql/blob/main/xsgjz.js
|
||||
// # Raw: https://raw.githubusercontent.com/xfmeng970526/ql/main/xsgjz.js
|
||||
// # Repo: xfmeng970526/ql
|
||||
// # Path: xsgjz.js
|
||||
// # UploadedAt: 2023-09-20T12:13:28+08:00
|
||||
// # SHA256: 465b4e71ad7980bc522a9279da88127790ea9fb64c263a088215d6d2010e0a91
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
#变量xsgCookie,抓取小时工记账的authorization变量
|
||||
cron: 5 6-18/6 * * *
|
||||
new Env('68-小时工记账');
|
||||
项目名称:小时工记账
|
||||
from cgitb import text
|
||||
import json
|
||||
import time
|
||||
import requests as r
|
||||
import requests
|
||||
import re
|
||||
import json
|
||||
import os
|
||||
|
||||
#获取名字链接
|
||||
mzurl = "https://xsg-api.julanling.com/app/user/info"
|
||||
#获取金币数量链接
|
||||
jburl = "https://xsg-api.julanling.com/h5/api/activityThirdAccount/coin/getAccount"
|
||||
#签到链接
|
||||
signurl = "https://market-gateway.julanling.com/market-center/api2/signIn/signIn"
|
||||
#转盘链接
|
||||
zpurl = "https://market-gateway.julanling.com/market-center/api2/dial/luckyDraw"
|
||||
#转盘金币领奖链接
|
||||
zpljurl = "https://market-gateway.julanling.com/market-center/api2/dial/receiveDialCoin"
|
||||
#转盘宝箱领奖链接
|
||||
zpbxurl = "https://market-gateway.julanling.com/market-center/api2/dial/openBox"
|
||||
#转盘双倍卡链接
|
||||
zpsburl = "https://market-gateway.julanling.com/market-center/api2/dial/receiveDoubleCardBag"
|
||||
#获取宝箱状态
|
||||
bxzturl= "https://market-gateway.julanling.com/market-center/api2/dial/detailCore?appVersion=4.4.20"
|
||||
#刷新扭蛋状态
|
||||
ndsxurl = "https://market-gateway.julanling.com/market-center/api2/gacha/index?os=ANDROID&appVersion=4.4.20"
|
||||
#扭蛋链接
|
||||
ndurl = "https://market-gateway.julanling.com/market-center/api2/gacha/luckyDraw"
|
||||
#扭蛋广告链接
|
||||
ndadurl = "https://market-gateway.julanling.com/market-center/api2/gacha/finishGachaTask"
|
||||
#7次广告链接
|
||||
qiadurl = "https://market-gateway.julanling.com/market-center/api2/assignment/finishAssignment"
|
||||
|
||||
|
||||
|
||||
if os.environ.get("xsgCookie"):
|
||||
dvm = os.environ["xsgCookie"]
|
||||
if dvm != '':
|
||||
if "@" in dvm:
|
||||
Coo = dvm.split("@")
|
||||
elif "&" in dvm:
|
||||
Coo = dvm.split('&')
|
||||
else:
|
||||
Coo = dvm.split('\n')
|
||||
adv=1
|
||||
for i in Coo:
|
||||
headers = {
|
||||
"security": "cD1jb20uanVsYW5nbGluZy54c2dqeiZjPXhzZ2p6X3lpbmd5b25nYmFvJnY9NC40LjIwJmQ9MzU1MWU0MDFiYjQ0MWVlY2JiNDU5ZjkwMDE1MzJlMzEmdT1ZN2wyVitQNWdOd0RBRFZjR0huQ2VzbXAmdD0xNjczMDk4OTY5.7e9e9d0818df515f6a384d9d5debde40",
|
||||
"authorization": i,
|
||||
"user-agent": 'Mozilla/5.0 (Linux; Android 11; M2012K11AC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/107.0.5304.105 Mobile Safari/537.36;_android{"version":4420,"versionName":"4.4.20","userType":"1","sdkVersion":"30","statusBarHeight":29,"toolBarHeight":73,"imei":"","oaid":"ad58bc17b41a81c7","channel":"xsgjz_yingyongbao","uid":10522}_android',
|
||||
"content-type": "application/json;charset=UTF-8"
|
||||
}
|
||||
print(f'登录第{adv}个账号')
|
||||
adv=adv+1
|
||||
|
||||
#登录验证
|
||||
resp = r.post(mzurl, headers=headers)
|
||||
xx = json.loads(resp.text)
|
||||
if xx["results"] == "null":
|
||||
print("登录失败,请重新获取Authorization")
|
||||
continue
|
||||
else:
|
||||
print("用户ID:"+xx["results"]["nickname"])
|
||||
|
||||
#获取金币数量
|
||||
jb = r.post(jburl, headers=headers)
|
||||
xb = json.loads(jb.text)
|
||||
if xb["results"] == "null":
|
||||
print("获取金币失败,请检测Authorization是否可用")
|
||||
else:
|
||||
print("目前金币数量:"+str(xb["results"]["credits"]))
|
||||
print("可提现:"+str(xb["results"]["aboutAmount"]))
|
||||
print("今日赚取金币数量:"+str(xb["results"]["currentCredits"]))
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
#签到
|
||||
qdbody = {"os":"ANDROID","appVersion":"4.4.20","appChannel":"xsgjz_yingyongbao","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9"}
|
||||
qd = r.post(signurl, headers=headers, json=qdbody)
|
||||
qdd = json.loads(qd.text)
|
||||
print("开始签到")
|
||||
if qdd["errorCode"] == 0:
|
||||
print("签到成功获取金币:"+str(qdd["results"]["amount"]))
|
||||
else:
|
||||
print("签到失败原因:"+str(qdd["errorStr"]))
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
#转转盘
|
||||
nc=1
|
||||
zzpyz = r.get(bxzturl, headers=headers)
|
||||
zptz = json.loads(zzpyz.text)
|
||||
zpsycs = str(zptz["results"]["dialValidNum"])
|
||||
print("转盘剩余次数"+zpsycs)
|
||||
zpsycs=int(zpsycs)
|
||||
for o in range(zpsycs):
|
||||
print("开始第"+str(nc)+"次转盘")
|
||||
time.sleep(3)
|
||||
nc=nc+1
|
||||
body = {"appChannel":"xsgjz_yingyongbao","appVersion":"4.4.20","appPackage":"com.julangling.xsgjz","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","operatingSystem":"ANDROID"}
|
||||
zp = r.post(zpurl, headers=headers,json=body)
|
||||
zpp = json.loads(zp.text)
|
||||
if zpp["errorCode"] == 0:
|
||||
if zpp["results"]["awardType"] == "GOLD":
|
||||
biz = zpp["results"]["bizNo"]
|
||||
zpbody = {
|
||||
"bizNo":biz,
|
||||
"appChannel":"xsgjz_yingyongbao",
|
||||
"appVersion":"4.4.20",
|
||||
"appPackage":"com.julangling.xsgjz",
|
||||
"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9",
|
||||
"operatingSystem":"ANDROID"
|
||||
}
|
||||
time.sleep(3)
|
||||
lj = r.post(zpljurl, headers=headers,json=zpbody)
|
||||
ljj = json.loads(lj.text)
|
||||
print("抽到金币"+str(ljj["results"]["amount"]))
|
||||
|
||||
elif zpp["results"]["awardType"] == "DOUBLE_VIDEO":
|
||||
print("抽到双倍卡,需要观看广告")
|
||||
biz = zpp["results"]["bizNo"]
|
||||
zpbody = {
|
||||
"bizNo":biz,
|
||||
"appChannel":"xsgjz_yingyongbao",
|
||||
"appVersion":"4.4.20",
|
||||
"appPackage":"com.julangling.xsgjz",
|
||||
"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9",
|
||||
"operatingSystem":"ANDROID"
|
||||
}
|
||||
time.sleep(3)
|
||||
sb = r.post(zpsburl, headers=headers,json=zpbody)
|
||||
sbb = json.loads(sb.text)
|
||||
print("观看成功剩余翻倍奖励次数"+str(sbb["results"]["dialCardBag"]["DOUBLE"]))
|
||||
|
||||
print("转盘结束,查看可领取那些宝箱")
|
||||
#转盘5次宝箱奖励body
|
||||
bx1={"businessType":"XSG_BOX_ONE","appChannel":"xsgjz_yingyongbao","appVersion":"4.4.20","appPackage":"com.julangling.xsgjz","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","operatingSystem":"ANDROID"}
|
||||
#转盘18次宝箱奖励body
|
||||
bx2={"businessType":"XSG_BOX_TWO","appChannel":"xsgjz_yingyongbao","appVersion":"4.4.20","appPackage":"com.julangling.xsgjz","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","operatingSystem":"ANDROID"}
|
||||
#转盘30次宝箱奖励body
|
||||
bx3={"businessType":"XSG_BOX_THREE","appChannel":"xsgjz_yingyongbao","appVersion":"4.4.20","appPackage":"com.julangling.xsgjz","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","operatingSystem":"ANDROID"}
|
||||
#转盘55次宝箱奖励body
|
||||
bx4={"businessType":"XSG_BOX_FOUR","appChannel":"xsgjz_yingyongbao","appVersion":"4.4.20","appPackage":"com.julangling.xsgjz","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","operatingSystem":"ANDROID"}
|
||||
|
||||
#转盘宝箱领取
|
||||
time.sleep(3)
|
||||
print("开始领转盘5次箱子奖励")
|
||||
zpbx1 = r.post(zpbxurl, headers=headers,json=bx1)
|
||||
bxx1 = json.loads(zpbx1.text)
|
||||
if bxx1["errorCode"] == 0:
|
||||
results = bxx1['results']
|
||||
openBoxAwards = results['openBoxAwards']
|
||||
bx1jb = openBoxAwards[0]['amount']
|
||||
print("领取成功获得"+str(bx1jb)+"金币")
|
||||
else:
|
||||
print("领取失败,原因:"+str(bxx1["errorStr"]))
|
||||
time.sleep(3)
|
||||
|
||||
time.sleep(3)
|
||||
print("开始领转盘18次箱子奖励")
|
||||
zpbx2 = r.post(zpbxurl, headers=headers,json=bx2)
|
||||
bxx2 = json.loads(zpbx2.text)
|
||||
if bxx2["errorCode"] == 0:
|
||||
results2 = bxx2['results']
|
||||
openBoxAwards2 = results2['openBoxAwards']
|
||||
bx2jb = openBoxAwards2[0]['amount']
|
||||
print("领取成功获得"+str(bx2jb)+"金币")
|
||||
bxbizNo2 = bxx2['results']['openBoxAwards'][1]['bizNo']
|
||||
print("领取箱子双倍卡,需要观看广告")
|
||||
zpbody = {
|
||||
"bizNo":bxbizNo2,
|
||||
"appChannel":"xsgjz_yingyongbao",
|
||||
"appVersion":"4.4.20",
|
||||
"appPackage":"com.julangling.xsgjz",
|
||||
"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9",
|
||||
"operatingSystem":"ANDROID"
|
||||
}
|
||||
time.sleep(3)
|
||||
sb = r.post(zpsburl, headers=headers,json=zpbody)
|
||||
sbb = json.loads(sb.text)
|
||||
print("观看成功剩余翻倍奖励次数"+str(sbb["results"]["dialCardBag"]["DOUBLE"]))
|
||||
del bxx2
|
||||
del results2
|
||||
del openBoxAwards2
|
||||
del bx2jb
|
||||
del bxbizNo2
|
||||
del sb
|
||||
del sbb
|
||||
else:
|
||||
print("领取失败,原因:"+str(bxx2["errorStr"]))
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
time.sleep(5)
|
||||
print("开始领转盘30次箱子奖励")
|
||||
zpbx3 = r.post(zpbxurl, headers=headers,json=bx3)
|
||||
bxx3 = json.loads(zpbx3.text)
|
||||
if bxx3["errorCode"] == 0:
|
||||
results3 = bxx3['results']
|
||||
openBoxAwards3 = results3['openBoxAwards']
|
||||
bx3jb = openBoxAwards3[0]['amount']
|
||||
print("领取成功获得"+str(bx3jb)+"金币")
|
||||
bxbizNo3 = bxx3['results']['openBoxAwards'][1]['bizNo']
|
||||
print("领取箱子双倍卡,需要观看广告")
|
||||
zpbody = {
|
||||
"bizNo":bxbizNo3,
|
||||
"appChannel":"xsgjz_yingyongbao",
|
||||
"appVersion":"4.4.20",
|
||||
"appPackage":"com.julangling.xsgjz",
|
||||
"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9",
|
||||
"operatingSystem":"ANDROID"
|
||||
}
|
||||
time.sleep(3)
|
||||
sb = r.post(zpsburl, headers=headers,json=zpbody)
|
||||
sbb = json.loads(sb.text)
|
||||
print("观看成功剩余翻倍奖励次数"+str(sbb["results"]["dialCardBag"]["DOUBLE"]))
|
||||
del bxx3
|
||||
del results3
|
||||
del openBoxAwards3
|
||||
del bx3jb
|
||||
del bxbizNo3
|
||||
del sb
|
||||
del sbb
|
||||
else:
|
||||
print("领取失败,原因:"+str(bxx3["errorStr"]))
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
|
||||
time.sleep(3)
|
||||
print("开始领转盘55次箱子奖励")
|
||||
zpbx4 = r.post(zpbxurl, headers=headers,json=bx4)
|
||||
bxx4 = json.loads(zpbx4.text)
|
||||
if bxx4["errorCode"] == 0:
|
||||
results4 = bxx4['results']
|
||||
openBoxAwards4 = results4['openBoxAwards']
|
||||
bx4jb = openBoxAwards4[0]['amount']
|
||||
print("领取成功获得"+str(bx4jb)+"金币")
|
||||
bxbizNo4 = bxx4['results']['openBoxAwards'][1]['bizNo']
|
||||
print("领取箱子双倍卡,需要观看广告")
|
||||
zpbody = {
|
||||
"bizNo":bxbizNo4,
|
||||
"appChannel":"xsgjz_yingyongbao",
|
||||
"appVersion":"4.4.20",
|
||||
"appPackage":"com.julangling.xsgjz",
|
||||
"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9",
|
||||
"operatingSystem":"ANDROID"
|
||||
}
|
||||
time.sleep(3)
|
||||
sb = r.post(zpsburl, headers=headers,json=zpbody)
|
||||
sbb = json.loads(sb.text)
|
||||
print("观看成功剩余翻倍奖励次数"+str(sbb["results"]["dialCardBag"]["DOUBLE"]))
|
||||
del bxx4
|
||||
del results4
|
||||
del openBoxAwards4
|
||||
del bx4jb
|
||||
del bxbizNo4
|
||||
del sb
|
||||
del sbb
|
||||
else:
|
||||
print("领取失败,原因:"+str(bxx4["errorStr"]))
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
|
||||
#扭蛋
|
||||
vc=1
|
||||
bc=1
|
||||
#先刷新扭蛋列表
|
||||
ndsx = r.get(ndsxurl, headers=headers)
|
||||
ndsxx = json.loads(ndsx.text)
|
||||
#判断扭蛋广告可观看次数
|
||||
ndadcs= ndsxx["results"]["remainVideoTimes"]
|
||||
print("扭蛋广告剩余次数"+str(ndadcs))
|
||||
#观看扭蛋广告
|
||||
for o in range(ndadcs):
|
||||
print("开始第"+str(bc)+"次观看扭蛋广告")
|
||||
bc=bc+1
|
||||
time.sleep(3)
|
||||
ndadbody={"businessType":"XSG_DAILY_GACHA_INC_VIDEOS","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","version":"4.4.20","os":"ANDROID","appVersion":"4.4.20","appChannel":"unknow"}
|
||||
ndad = r.post(ndadurl, headers=headers,json=ndadbody)
|
||||
nddad = json.loads(ndad.text)
|
||||
if nddad['errorCode'] == 0:
|
||||
print("获得"+str(nddad["results"]["amount"])+"次抽奖次数")
|
||||
print("目前有"+str(nddad["results"]["remainTimes"])+"次抽奖次数")
|
||||
time.sleep(3)
|
||||
else:
|
||||
print("扭蛋失败原因"+nddad['errorStr'])
|
||||
|
||||
|
||||
ndsx = r.get(ndsxurl, headers=headers)
|
||||
ndsxx = json.loads(ndsx.text)
|
||||
#判断扭蛋次数
|
||||
ndsycs = ndsxx["results"]["remainTimes"]
|
||||
print("扭蛋剩余次数"+str(ndsycs))
|
||||
#开始扭蛋
|
||||
for o in range(ndsycs):
|
||||
print("开始第"+str(vc)+"次扭蛋")
|
||||
vc=vc+1
|
||||
time.sleep(3)
|
||||
ndbody={"deviceToken":"19a9e4453155dcbc348f5fbff0c075c9","version":"4.4.20","os":"ANDROID","appVersion":"4.4.20","appChannel":"unknow"}
|
||||
nd = r.post(ndurl, headers=headers,json=ndbody)
|
||||
ndd = json.loads(nd.text)
|
||||
if ndd['errorCode'] == 0:
|
||||
if ndd["results"]["awardType"] == 'ADVERT':
|
||||
print("抽到了空气广告")
|
||||
else:
|
||||
print("抽到"+str(ndd["results"]["name"]))
|
||||
else:
|
||||
print("扭蛋失败原因"+ndd['errorStr'])
|
||||
|
||||
time.sleep(3)
|
||||
#看广告7次
|
||||
for c in range(7):
|
||||
qiadbody={"businessType":"XSG_MONEY_CENTER_INCENTIVE_VIDEO","os":"ANDROID","appVersion":"4.4.20","appChannel":"xsgjz_yingyongbao","deviceToken":"19a9e4453155dcbc348f5fbff0c075c9"}
|
||||
adws = r.post(qiadurl, headers=headers,json=qiadbody)
|
||||
adwss = json.loads(adws.text)
|
||||
if adwss['errorCode'] == 0:
|
||||
adwssjb = adwss["results"]["awardInfos"]
|
||||
adwssjbb = adwssjb[0]['amount']
|
||||
print("获得金币"+str(adwssjbb)+"个")
|
||||
print("等待20秒,才可以观看广告")
|
||||
time.sleep(21)
|
||||
else:
|
||||
|
||||
break
|
||||
|
||||
|
||||
|
||||
23
脚本库/web版/账密/7-喜爱帮/2023-09-20_xab_5e653254.js
Normal file
23
脚本库/web版/账密/7-喜爱帮/2023-09-20_xab_5e653254.js
Normal file
File diff suppressed because one or more lines are too long
36
脚本库/web版/账密/76-追书神器/2023-09-20_zssq_4b9401c4.js
Normal file
36
脚本库/web版/账密/76-追书神器/2023-09-20_zssq_4b9401c4.js
Normal file
File diff suppressed because one or more lines are too long
37
脚本库/web版/账密/77-长城炮/2023-09-20_ccp_a2cc1b7d.js
Normal file
37
脚本库/web版/账密/77-长城炮/2023-09-20_ccp_a2cc1b7d.js
Normal file
File diff suppressed because one or more lines are too long
22
脚本库/web版/账密/83-青岛新闻_0213/2023-09-20_qdxw_0213_efc01930.js
Normal file
22
脚本库/web版/账密/83-青岛新闻_0213/2023-09-20_qdxw_0213_efc01930.js
Normal file
File diff suppressed because one or more lines are too long
1491
脚本库/web版/账密/88-科技工作者之家/2023-09-20_keji_0227_aa3ef3ce.js
Normal file
1491
脚本库/web版/账密/88-科技工作者之家/2023-09-20_keji_0227_aa3ef3ce.js
Normal file
File diff suppressed because one or more lines are too long
1454
脚本库/web版/账密/88-科技工作者之家/2023-09-20_kjgzz_3cbe63dd.js
Normal file
1454
脚本库/web版/账密/88-科技工作者之家/2023-09-20_kjgzz_3cbe63dd.js
Normal file
File diff suppressed because one or more lines are too long
311
脚本库/web版/账密/OPPO商城/2025-04-28_sudojia_opposhop_d6fa1c86.js
Normal file
311
脚本库/web版/账密/OPPO商城/2025-04-28_sudojia_opposhop_d6fa1c86.js
Normal file
@@ -0,0 +1,311 @@
|
||||
// # Source: https://github.com/sudojia/AutoTaskScript/blob/script/src/client/sudojia_opposhop.js
|
||||
// # Raw: https://raw.githubusercontent.com/sudojia/AutoTaskScript/script/src/client/sudojia_opposhop.js
|
||||
// # Repo: sudojia/AutoTaskScript
|
||||
// # Path: src/client/sudojia_opposhop.js
|
||||
// # UploadedAt: 2025-04-28T19:26:13+08:00
|
||||
// # SHA256: d6fa1c866188a3794e41b934cbd49a4d18e795230809f23dd9d60583c7f61bfb
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/**
|
||||
* OPPO商城 APP
|
||||
*
|
||||
* 打开抓包、进入我的 - 签到任务
|
||||
* 抓包 URL:https://hd.opposhop.cn/api/cn/oapi/users/web/member/check?unpaid=0 获取 Cookie 和 User-Agent
|
||||
* export OPPOSHOP_COOKIE = 'xxxxxxxxx'
|
||||
* export OPPO_USER_AGENT = 'Mozilla/5.0 (Linux; Android 10; xxxxxxxxx'
|
||||
* export OPPO_ACTIVITY_IDS = '签到活动ID#任务列表活动ID'
|
||||
* OPPO Activity ID 获取说明:https://rh-docs.netlify.app/docs/list/client/opposhop/#%E8%8E%B7%E5%8F%96%E8%AF%B4%E6%98%8E
|
||||
* 多账号用 & 或换行
|
||||
*
|
||||
* @author Telegram@sudojia
|
||||
* @site https://blog.imzjw.cn
|
||||
* @date 2024/08/23
|
||||
*
|
||||
* const $ = new Env('OPPO商城')
|
||||
* cron: 25 12 * * *
|
||||
*/
|
||||
const initScript = require('../utils/initScript')
|
||||
const {$, notify, sudojia, checkUpdate} = initScript('OPPO商城');
|
||||
const oppoList = process.env.OPPOSHOP_COOKIE ? process.env.OPPOSHOP_COOKIE.split(/[\n&]/) : [];
|
||||
// UserAgent 配置
|
||||
const UserAgent = process.env.OPPO_USER_AGENT;
|
||||
// const UserAgent = 'Mozilla/5.0 (Linux; Android 9; OPPO R9s Build/PQ3A.190605.07291528; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36 oppostore/402700 ColorOS/ brand/OPPO model/OPPO R9s;kyc/h5face;kyc/2.0;netType:NETWORK_WIFI;appVersion:402700;packageName:com.oppo.store';
|
||||
// 消息推送
|
||||
let message = '';
|
||||
// 接口地址
|
||||
const baseUrl = 'https://hd.opposhop.cn'
|
||||
// 活动集合ID,签到活动ID#任务列表活动ID
|
||||
const activityIdsFromEnv = process.env.OPPO_ACTIVITY_IDS || '1838147945355288576#1838149802563739648';
|
||||
// 按照 # 分割字符串
|
||||
const activityIds = activityIdsFromEnv.split('#');
|
||||
// 签到活动ID
|
||||
const signActivityId = activityIds[0] || '1838147945355288576';
|
||||
// 任务列表活动ID
|
||||
const taskActivityId = activityIds[1] || '1838149802563739648';
|
||||
// 判断User-Agent
|
||||
if (!UserAgent) {
|
||||
console.error('请先填写OPPO商城的 User-Agent、变量名【OPPO_USER_AGENT】');
|
||||
process.exit(0);
|
||||
}
|
||||
// 请求头
|
||||
const headers = {
|
||||
'Host': 'hd.opposhop.cn',
|
||||
'User-Agent': UserAgent,
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
};
|
||||
// 签到天数对应奖励ID
|
||||
const signInDaysMap = {
|
||||
1327: 3,
|
||||
1328: 5,
|
||||
1329: 10,
|
||||
1330: 15
|
||||
};
|
||||
|
||||
!(async () => {
|
||||
await checkUpdate($.name, oppoList);
|
||||
for (let i = 0; i < oppoList.length; i++) {
|
||||
const index = i + 1;
|
||||
$.signDayNum = 1;
|
||||
headers.Cookie = oppoList[i];
|
||||
console.log(`\n*****第[${index}]个${$.name}账号*****`);
|
||||
if (!await isLogin()) {
|
||||
console.error('Cookie 已失效');
|
||||
await notify.sendNotify(`「Cookie失效通知」`, `${$.name}账号[${index}] Cookie 已失效,请重新登录获取 Cookie\n\n`);
|
||||
continue;
|
||||
}
|
||||
await $.wait(sudojia.getRandomWait(800, 1200))
|
||||
await main();
|
||||
await $.wait(sudojia.getRandomWait(2000, 2500));
|
||||
}
|
||||
if (message) {
|
||||
await notify.sendNotify(`「${$.name}」`, `${message}`);
|
||||
}
|
||||
})().catch((e) => $.logErr(e)).finally(() => $.done());
|
||||
|
||||
async function main() {
|
||||
await getUserInfo()
|
||||
await $.wait(sudojia.getRandomWait(1200, 2000));
|
||||
await getSignInStatus();
|
||||
await $.wait(sudojia.getRandomWait(1200, 2000));
|
||||
await getSignDays();
|
||||
await $.wait(sudojia.getRandomWait(1200, 2000));
|
||||
await getTaskList();
|
||||
// 领取累计签到奖励
|
||||
console.log(`当前累计签到[${$.signDayNum}]天\n`);
|
||||
for (const [awardId, days] of Object.entries(signInDaysMap)) {
|
||||
// 只有签到天数达到才领取
|
||||
if ($.signDayNum >= days) {
|
||||
console.log(`开始领取[${days}]天累计签到奖励`);
|
||||
await $.wait(sudojia.getRandomWait(1e3, 2e3));
|
||||
await receiveSignInAward(parseInt(awardId));
|
||||
} else {
|
||||
console.log(`不满足${days}天,跳过领取`)
|
||||
await $.wait(sudojia.getRandomWait(1e3, 2e3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测 Cookie 是否有效
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function isLogin() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/cn/oapi/marketing/task/isLogin`, 'get', headers);
|
||||
return 403 !== data.code;
|
||||
} catch (e) {
|
||||
console.error(`检测 Cookie 是否有效时发生异常 -> `, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
async function getUserInfo() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/cn/oapi/users/web/member/check?unpaid=0`, 'get', headers);
|
||||
if (data.data) {
|
||||
console.log(`OPPO会员:${data.data.name}`);
|
||||
message += `OPPO会员:${data.data.name}\n`;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`获取用户信息时发生异常 -> `, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取签到状态
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getSignInStatus() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/cn/oapi/marketing/cumulativeSignIn/getSignInDetail?activityId=${signActivityId}`, 'get', headers);
|
||||
if (data.data) {
|
||||
if (data.data.todaySignIn) {
|
||||
console.log('今日已签到');
|
||||
message += `今日已签到\n`;
|
||||
return;
|
||||
}
|
||||
await $.wait(sudojia.getRandomWait(1200, 1800));
|
||||
await sign();
|
||||
} else {
|
||||
console.error('获取签到状态失败 -> ', data);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`获取签到状态时发生异常 -> `, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function sign() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/cn/oapi/marketing/cumulativeSignIn/signIn`, 'post', headers, {
|
||||
"activityId": signActivityId
|
||||
});
|
||||
if (data.data) {
|
||||
console.log(`签到成功,积分+${data.data.awardValue}`);
|
||||
message += `签到成功\n`;
|
||||
} else {
|
||||
console.error('签到失败 -> ', data);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`签到时发生异常 -> `, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取签到天数
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getSignDays() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/cn/oapi/marketing/cumulativeSignIn/getSignInDetail?activityId=${signActivityId}`, 'get', headers);
|
||||
if (data.data) {
|
||||
$.signDayNum = data.data.signInDayNum;
|
||||
console.log(`已连续签到${$.signDayNum}天`);
|
||||
message += `已连续签到${$.signDayNum}天\n`;
|
||||
} else {
|
||||
console.error('获取签到天数失败 -> ', data);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`获取签到天数时发生异常 -> `, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务列表
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getTaskList() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/cn/oapi/marketing/task/queryTaskList?activityId=${taskActivityId}&source=c`, 'get', headers);
|
||||
if (data.data) {
|
||||
const taskList = data.data.taskDTOList;
|
||||
for (const task of taskList) {
|
||||
// 排除黑卡和购物
|
||||
if (6 === task.taskType) {
|
||||
continue;
|
||||
}
|
||||
console.log(`开始[${task.taskName}]任务...`);
|
||||
await $.wait(sudojia.getRandomWait(1000, 1500));
|
||||
|
||||
await completeTask(task.taskId, task.activityId);
|
||||
await $.wait(sudojia.getRandomWait(2e3, 4e3));
|
||||
|
||||
await receiveAward(task.taskName, task.taskId, task.activityId);
|
||||
await $.wait(sudojia.getRandomWait(1e3, 2e3));
|
||||
}
|
||||
message += `\n`;
|
||||
} else {
|
||||
console.error('获取任务列表失败 -> ', data.message);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`获取任务列表时发生异常 -> `, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 完成任务
|
||||
*
|
||||
* @param taskId
|
||||
* @param activityId
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function completeTask(taskId, activityId) {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/cn/oapi/marketing/taskReport/signInOrShareTask?taskId=${taskId}&activityId=${activityId}&taskType=1`, 'get', headers);
|
||||
if (data.data) {
|
||||
console.log(`${data.message}`);
|
||||
} else {
|
||||
console.error('操作失败 -> ', data.message);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`完成任务时发生异常 -> `, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取奖励
|
||||
*
|
||||
* @param taskName
|
||||
* @param taskId
|
||||
* @param activityId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function receiveAward(taskName, taskId, activityId) {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/cn/oapi/marketing/task/receiveAward?taskId=${taskId}&activityId=${activityId}`, 'get', headers);
|
||||
if (data.data) {
|
||||
message += `完成[${taskName}]任务,积分+${data.data.awardValue}\n`;
|
||||
console.log(`领取成功,积分+${data.data.awardValue}`);
|
||||
} else {
|
||||
console.error('领取失败 -> ', data.message);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`领取奖励时发生异常 -> `, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取连续签到奖励
|
||||
*
|
||||
* @param awardId 1327: 3天奖励
|
||||
* 1328: 5天奖励
|
||||
* 1329: 10天奖励
|
||||
* 1330: 15天奖励
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function receiveSignInAward(awardId) {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/api/cn/oapi/marketing/cumulativeSignIn/drawCumulativeAward`, 'post', headers, {
|
||||
"activityId": signActivityId,
|
||||
"awardId": awardId
|
||||
});
|
||||
if (data.data) {
|
||||
const days = signInDaysMap[awardId] || '未知';
|
||||
const awardValue = data.data.awardValue;
|
||||
if (awardValue.trim().length > 0) {
|
||||
console.log(`领取累计${days}天奖励成功,获得[${awardValue}]积分\n`);
|
||||
} else {
|
||||
console.log(`领取累计${days}天奖励成功,获得[${awardValue}]\n`);
|
||||
}
|
||||
} else {
|
||||
console.error('领取连续签到奖励失败 -> ', data.message);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`领取连续签到奖励时发生异常 -> `, e);
|
||||
}
|
||||
}
|
||||
125
脚本库/web版/账密/SSPANEL面板签到/2025-04-28_sudojia_sspanel_8bd3374a.js
Normal file
125
脚本库/web版/账密/SSPANEL面板签到/2025-04-28_sudojia_sspanel_8bd3374a.js
Normal file
@@ -0,0 +1,125 @@
|
||||
// # Source: https://github.com/sudojia/AutoTaskScript/blob/script/src/web/sudojia_sspanel.js
|
||||
// # Raw: https://raw.githubusercontent.com/sudojia/AutoTaskScript/script/src/web/sudojia_sspanel.js
|
||||
// # Repo: sudojia/AutoTaskScript
|
||||
// # Path: src/web/sudojia_sspanel.js
|
||||
// # UploadedAt: 2025-04-28T19:26:13+08:00
|
||||
// # SHA256: 8bd3374a2bddc90f5a4577c605285a665d61dde740ce6ae4eaad72eb42ea37a5
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/**
|
||||
* 机场每日签到
|
||||
*
|
||||
* 如何鉴别是 SSPANEL 面板?
|
||||
* 网站拉到最下面有 Powered by SSPANEL 就是 SSPANEL 面板框架的机场
|
||||
* 格式要求:网站1,邮箱1:密码1&网站2,邮箱2:密码2
|
||||
* export SITE_ACCOUNTS = 'https://paolu.com,abc@gmail.com:123456'
|
||||
* 多账号用 & 或换行
|
||||
*
|
||||
* @author Telegram@sudojia
|
||||
* @site https://blog.imzjw.cn
|
||||
* @date 2021/9/25
|
||||
* @lastModifyTime: 2024/09/16
|
||||
*
|
||||
* const $ = new Env('SSPANEL面板签到')
|
||||
* cron: 35 9 * * *
|
||||
*/
|
||||
const initScript = require('../utils/initScript')
|
||||
const {$, notify, sudojia, checkUpdate} = initScript('SSPANEL面板签到');
|
||||
const {default: axios} = require("axios");
|
||||
const accountList = process.env.SITE_ACCOUNTS ? process.env.SITE_ACCOUNTS.split(/[\n&]/) : [];
|
||||
// 消息推送
|
||||
let message = '';
|
||||
// 请求头
|
||||
const headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"User-Agent": sudojia.getRandomUserAgent('PC'),
|
||||
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
||||
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
||||
};
|
||||
|
||||
!(async () => {
|
||||
await checkUpdate($.name, accountList);
|
||||
console.log(`\n已随机分配 User-Agent\n\n${headers['user-agent'] || headers['User-Agent']}`);
|
||||
// 校验格式
|
||||
const isValidFormat = accountList.every(account => {
|
||||
const parts = account.split(',');
|
||||
if (parts.length !== 2) {
|
||||
return false;
|
||||
}
|
||||
const [site, credentials] = parts;
|
||||
const credParts = credentials.split(':');
|
||||
return !(credParts.length !== 2 || !site || !credentials);
|
||||
});
|
||||
if (!isValidFormat) {
|
||||
console.error('格式错误,请确保遵循要求格式:网站1,邮箱1:密码1&网站2,邮箱2:密码2');
|
||||
process.exit(0);
|
||||
}
|
||||
for (let i = 0; i < accountList.length; i++) {
|
||||
const index = i + 1;
|
||||
const [rawUrl, emailPwd] = accountList[i].split(',');
|
||||
const [email, pwd] = emailPwd.split(':');
|
||||
const url = rawUrl.endsWith('/') ? rawUrl.slice(0, -1) : rawUrl;
|
||||
console.log(`\n*****第[${index}]个${$.name}账号*****`);
|
||||
console.log(`设定的机场网站是:${url}`);
|
||||
await $.wait(sudojia.getRandomWait(300, 666));
|
||||
message += `📣====${$.name}账号[${index}]====📣\n`;
|
||||
await login(url, email, pwd);
|
||||
}
|
||||
if (message) {
|
||||
await notify.sendNotify(`「${$.name}」`, `${message}`);
|
||||
}
|
||||
})().catch((e) => $.logErr(e)).finally(() => $.done());
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @returns {*}
|
||||
*/
|
||||
async function login(url, email, pwd) {
|
||||
try {
|
||||
const options = {
|
||||
url: `${url}/auth/login`,
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
data: `email=${email}&passwd=${pwd}&code=`
|
||||
}
|
||||
const response = await axios(options);
|
||||
if (1 !== response.data.ret) {
|
||||
return console.error(`登录失败:${response.data.msg}`);
|
||||
}
|
||||
const cookies = response.headers['set-cookie'];
|
||||
headers.Cookie = cookies.join('; ');
|
||||
console.log('登录成功~');
|
||||
await $.wait(sudojia.getRandomWait(800, 1200));
|
||||
await checkin(url);
|
||||
} catch (e) {
|
||||
console.error(`登录时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到
|
||||
*
|
||||
* @returns {*}
|
||||
*/
|
||||
async function checkin(url) {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${url}/user/checkin`, 'post', headers, {});
|
||||
if (1 !== data.ret) {
|
||||
return console.error(`签到失败:${data.msg}`);
|
||||
}
|
||||
const {lastUsedTraffic, unUsedTraffic} = data.trafficInfo;
|
||||
console.log(`签到成功,${data.msg}`);
|
||||
console.log(`总套餐:${data.traffic}`);
|
||||
console.log(`已使用:${lastUsedTraffic}`);
|
||||
console.log(`剩余流量:${unUsedTraffic}`);
|
||||
message += `签到成功,${data.msg}\n`;
|
||||
message += `总套餐:${data.traffic}\n`;
|
||||
message += `已使用:${lastUsedTraffic}\n`;
|
||||
message += `剩余流量:${unUsedTraffic}\n\n`;
|
||||
} catch (e) {
|
||||
console.error(`签到时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
762
脚本库/web版/账密/SendNotify/2023-09-20_SendNotify_aec54ebb.py
Normal file
762
脚本库/web版/账密/SendNotify/2023-09-20_SendNotify_aec54ebb.py
Normal file
@@ -0,0 +1,762 @@
|
||||
# Source: https://github.com/xfmeng970526/ql/blob/main/SendNotify.py
|
||||
# Raw: https://raw.githubusercontent.com/xfmeng970526/ql/main/SendNotify.py
|
||||
# Repo: xfmeng970526/ql
|
||||
# Path: SendNotify.py
|
||||
# UploadedAt: 2023-09-20T12:13:28+08:00
|
||||
# SHA256: aec54ebb91cd04c64ac7b9a09fcbbd6e18c92cdac8e9cc74320b6c095650e452
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
import urllib.parse
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.header import Header
|
||||
from email.utils import formataddr
|
||||
|
||||
import requests
|
||||
|
||||
# 原先的 print 函数和主线程的锁
|
||||
_print = print
|
||||
mutex = threading.Lock()
|
||||
|
||||
|
||||
# 定义新的 print 函数
|
||||
def print(text, *args, **kw):
|
||||
"""
|
||||
使输出有序进行,不出现多线程同一时间输出导致错乱的问题。
|
||||
"""
|
||||
with mutex:
|
||||
_print(text, *args, **kw)
|
||||
|
||||
|
||||
# 通知服务
|
||||
# fmt: off
|
||||
push_config = {
|
||||
'HITOKOTO': False, # 启用一言(随机句子)
|
||||
|
||||
'BARK_PUSH': '', # bark IP 或设备码,例:https://api.day.app/DxHcxxxxxRxxxxxxcm/
|
||||
'BARK_ARCHIVE': '', # bark 推送是否存档
|
||||
'BARK_GROUP': '', # bark 推送分组
|
||||
'BARK_SOUND': '', # bark 推送声音
|
||||
'BARK_ICON': '', # bark 推送图标
|
||||
|
||||
'CONSOLE': True, # 控制台输出
|
||||
|
||||
'DD_BOT_SECRET': '', # 钉钉机器人的 DD_BOT_SECRET
|
||||
'DD_BOT_TOKEN': '', # 钉钉机器人的 DD_BOT_TOKEN
|
||||
|
||||
'FSKEY': '', # 飞书机器人的 FSKEY
|
||||
|
||||
'GOBOT_URL': '', # go-cqhttp
|
||||
# 推送到个人QQ:http://127.0.0.1/send_private_msg
|
||||
# 群:http://127.0.0.1/send_group_msg
|
||||
'GOBOT_QQ': '', # go-cqhttp 的推送群或用户
|
||||
# GOBOT_URL 设置 /send_private_msg 时填入 user_id=个人QQ
|
||||
# /send_group_msg 时填入 group_id=QQ群
|
||||
'GOBOT_TOKEN': '', # go-cqhttp 的 access_token
|
||||
|
||||
'GOTIFY_URL': '', # gotify地址,如https://push.example.de:8080
|
||||
'GOTIFY_TOKEN': '', # gotify的消息应用token
|
||||
'GOTIFY_PRIORITY': 0, # 推送消息优先级,默认为0
|
||||
|
||||
'IGOT_PUSH_KEY': '', # iGot 聚合推送的 IGOT_PUSH_KEY
|
||||
|
||||
'PUSH_KEY': '', # server 酱的 PUSH_KEY,兼容旧版与 Turbo 版
|
||||
|
||||
'DEER_KEY': '', # PushDeer 的 PUSHDEER_KEY
|
||||
'DEER_URL': '', # PushDeer 的 PUSHDEER_URL
|
||||
|
||||
'CHAT_URL': '', # synology chat url
|
||||
'CHAT_TOKEN': '', # synology chat token
|
||||
|
||||
'PUSH_PLUS_TOKEN': '', # push+ 微信推送的用户令牌
|
||||
'PUSH_PLUS_USER': '', # push+ 微信推送的群组编码
|
||||
|
||||
'QMSG_KEY': '', # qmsg 酱的 QMSG_KEY
|
||||
'QMSG_TYPE': '', # qmsg 酱的 QMSG_TYPE
|
||||
|
||||
'QYWX_ORIGIN': '', # 企业微信代理地址
|
||||
|
||||
'QYWX_AM': '', # 企业微信应用
|
||||
|
||||
'QYWX_KEY': '', # 企业微信机器人
|
||||
|
||||
'TG_BOT_TOKEN': '', # tg 机器人的 TG_BOT_TOKEN,例:1407203283:AAG9rt-6RDaaX0HBLZQq0laNOh898iFYaRQ
|
||||
'TG_USER_ID': '', # tg 机器人的 TG_USER_ID,例:1434078534
|
||||
'TG_API_HOST': '', # tg 代理 api
|
||||
'TG_PROXY_AUTH': '', # tg 代理认证参数
|
||||
'TG_PROXY_HOST': '', # tg 机器人的 TG_PROXY_HOST
|
||||
'TG_PROXY_PORT': '', # tg 机器人的 TG_PROXY_PORT
|
||||
|
||||
'AIBOTK_KEY': '', # 智能微秘书 个人中心的apikey 文档地址:http://wechat.aibotk.com/docs/about
|
||||
'AIBOTK_TYPE': '', # 智能微秘书 发送目标 room 或 contact
|
||||
'AIBOTK_NAME': '', # 智能微秘书 发送群名 或者好友昵称和type要对应好
|
||||
|
||||
'SMTP_SERVER': '', # SMTP 发送邮件服务器,形如 smtp.exmail.qq.com:465
|
||||
'SMTP_SSL': 'false', # SMTP 发送邮件服务器是否使用 SSL,填写 true 或 false
|
||||
'SMTP_EMAIL': '', # SMTP 收发件邮箱,通知将会由自己发给自己
|
||||
'SMTP_PASSWORD': '', # SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定
|
||||
'SMTP_NAME': '', # SMTP 收发件人姓名,可随意填写
|
||||
|
||||
'PUSHME_KEY': '', # PushMe 酱的 PUSHME_KEY
|
||||
}
|
||||
notify_function = []
|
||||
# fmt: on
|
||||
|
||||
# 首先读取 面板变量 或者 github action 运行变量
|
||||
for k in push_config:
|
||||
if os.getenv(k):
|
||||
v = os.getenv(k)
|
||||
push_config[k] = v
|
||||
|
||||
|
||||
def bark(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 bark 推送消息。
|
||||
"""
|
||||
if not push_config.get("BARK_PUSH"):
|
||||
print("bark 服务的 BARK_PUSH 未设置!!\n取消推送")
|
||||
return
|
||||
print("bark 服务启动")
|
||||
|
||||
if push_config.get("BARK_PUSH").startswith("http"):
|
||||
url = f'{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
|
||||
else:
|
||||
url = f'https://api.day.app/{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
|
||||
|
||||
bark_params = {
|
||||
"BARK_ARCHIVE": "isArchive",
|
||||
"BARK_GROUP": "group",
|
||||
"BARK_SOUND": "sound",
|
||||
"BARK_ICON": "icon",
|
||||
}
|
||||
params = ""
|
||||
for pair in filter(
|
||||
lambda pairs: pairs[0].startswith("BARK_")
|
||||
and pairs[0] != "BARK_PUSH"
|
||||
and pairs[1]
|
||||
and bark_params.get(pairs[0]),
|
||||
push_config.items(),
|
||||
):
|
||||
params += f"{bark_params.get(pair[0])}={pair[1]}&"
|
||||
if params:
|
||||
url = url + "?" + params.rstrip("&")
|
||||
response = requests.get(url).json()
|
||||
|
||||
if response["code"] == 200:
|
||||
print("bark 推送成功!")
|
||||
else:
|
||||
print("bark 推送失败!")
|
||||
|
||||
|
||||
def console(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 控制台 推送消息。
|
||||
"""
|
||||
# print(f"{title}\n\n{content}")
|
||||
|
||||
|
||||
def dingding_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 钉钉机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("DD_BOT_SECRET") or not push_config.get("DD_BOT_TOKEN"):
|
||||
print("钉钉机器人 服务的 DD_BOT_SECRET 或者 DD_BOT_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("钉钉机器人 服务启动")
|
||||
|
||||
timestamp = str(round(time.time() * 1000))
|
||||
secret_enc = push_config.get("DD_BOT_SECRET").encode("utf-8")
|
||||
string_to_sign = "{}\n{}".format(timestamp, push_config.get("DD_BOT_SECRET"))
|
||||
string_to_sign_enc = string_to_sign.encode("utf-8")
|
||||
hmac_code = hmac.new(
|
||||
secret_enc, string_to_sign_enc, digestmod=hashlib.sha256
|
||||
).digest()
|
||||
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
|
||||
url = f'https://oapi.dingtalk.com/robot/send?access_token={push_config.get("DD_BOT_TOKEN")}×tamp={timestamp}&sign={sign}'
|
||||
headers = {"Content-Type": "application/json;charset=utf-8"}
|
||||
data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
|
||||
response = requests.post(
|
||||
url=url, data=json.dumps(data), headers=headers, timeout=15
|
||||
).json()
|
||||
|
||||
if not response["errcode"]:
|
||||
print("钉钉机器人 推送成功!")
|
||||
else:
|
||||
print("钉钉机器人 推送失败!")
|
||||
|
||||
|
||||
def feishu_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 飞书机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("FSKEY"):
|
||||
print("飞书 服务的 FSKEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("飞书 服务启动")
|
||||
|
||||
url = f'https://open.feishu.cn/open-apis/bot/v2/hook/{push_config.get("FSKEY")}'
|
||||
data = {"msg_type": "text", "content": {"text": f"{title}\n\n{content}"}}
|
||||
response = requests.post(url, data=json.dumps(data)).json()
|
||||
|
||||
if response.get("StatusCode") == 0:
|
||||
print("飞书 推送成功!")
|
||||
else:
|
||||
print("飞书 推送失败!错误信息如下:\n", response)
|
||||
|
||||
|
||||
def go_cqhttp(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 go_cqhttp 推送消息。
|
||||
"""
|
||||
if not push_config.get("GOBOT_URL") or not push_config.get("GOBOT_QQ"):
|
||||
print("go-cqhttp 服务的 GOBOT_URL 或 GOBOT_QQ 未设置!!\n取消推送")
|
||||
return
|
||||
print("go-cqhttp 服务启动")
|
||||
|
||||
url = f'{push_config.get("GOBOT_URL")}?access_token={push_config.get("GOBOT_TOKEN")}&{push_config.get("GOBOT_QQ")}&message={title}\n{content}'
|
||||
response = requests.get(url).json()
|
||||
|
||||
if response["status"] == "ok":
|
||||
print("go-cqhttp 推送成功!")
|
||||
else:
|
||||
print("go-cqhttp 推送失败!")
|
||||
|
||||
|
||||
def gotify(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 gotify 推送消息。
|
||||
"""
|
||||
if not push_config.get("GOTIFY_URL") or not push_config.get("GOTIFY_TOKEN"):
|
||||
print("gotify 服务的 GOTIFY_URL 或 GOTIFY_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("gotify 服务启动")
|
||||
|
||||
url = f'{push_config.get("GOTIFY_URL")}/message?token={push_config.get("GOTIFY_TOKEN")}'
|
||||
data = {
|
||||
"title": title,
|
||||
"message": content,
|
||||
"priority": push_config.get("GOTIFY_PRIORITY"),
|
||||
}
|
||||
response = requests.post(url, data=data).json()
|
||||
|
||||
if response.get("id"):
|
||||
print("gotify 推送成功!")
|
||||
else:
|
||||
print("gotify 推送失败!")
|
||||
|
||||
|
||||
def iGot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 iGot 推送消息。
|
||||
"""
|
||||
if not push_config.get("IGOT_PUSH_KEY"):
|
||||
print("iGot 服务的 IGOT_PUSH_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("iGot 服务启动")
|
||||
|
||||
url = f'https://push.hellyw.com/{push_config.get("IGOT_PUSH_KEY")}'
|
||||
data = {"title": title, "content": content}
|
||||
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
||||
response = requests.post(url, data=data, headers=headers).json()
|
||||
|
||||
if response["ret"] == 0:
|
||||
print("iGot 推送成功!")
|
||||
else:
|
||||
print(f'iGot 推送失败!{response["errMsg"]}')
|
||||
|
||||
|
||||
def serverJ(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 serverJ 推送消息。
|
||||
"""
|
||||
if not push_config.get("PUSH_KEY"):
|
||||
print("serverJ 服务的 PUSH_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("serverJ 服务启动")
|
||||
|
||||
data = {"text": title, "desp": content.replace("\n", "\n\n")}
|
||||
if push_config.get("PUSH_KEY").find("SCT") != -1:
|
||||
url = f'https://sctapi.ftqq.com/{push_config.get("PUSH_KEY")}.send'
|
||||
else:
|
||||
url = f'https://sc.ftqq.com/{push_config.get("PUSH_KEY")}.send'
|
||||
response = requests.post(url, data=data).json()
|
||||
|
||||
if response.get("errno") == 0 or response.get("code") == 0:
|
||||
print("serverJ 推送成功!")
|
||||
else:
|
||||
print(f'serverJ 推送失败!错误码:{response["message"]}')
|
||||
|
||||
|
||||
def pushdeer(title: str, content: str) -> None:
|
||||
"""
|
||||
通过PushDeer 推送消息
|
||||
"""
|
||||
if not push_config.get("DEER_KEY"):
|
||||
print("PushDeer 服务的 DEER_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("PushDeer 服务启动")
|
||||
data = {
|
||||
"text": title,
|
||||
"desp": content,
|
||||
"type": "markdown",
|
||||
"pushkey": push_config.get("DEER_KEY"),
|
||||
}
|
||||
url = "https://api2.pushdeer.com/message/push"
|
||||
if push_config.get("DEER_URL"):
|
||||
url = push_config.get("DEER_URL")
|
||||
|
||||
response = requests.post(url, data=data).json()
|
||||
|
||||
if len(response.get("content").get("result")) > 0:
|
||||
print("PushDeer 推送成功!")
|
||||
else:
|
||||
print("PushDeer 推送失败!错误信息:", response)
|
||||
|
||||
|
||||
def chat(title: str, content: str) -> None:
|
||||
"""
|
||||
通过Chat 推送消息
|
||||
"""
|
||||
if not push_config.get("CHAT_URL") or not push_config.get("CHAT_TOKEN"):
|
||||
print("chat 服务的 CHAT_URL或CHAT_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("chat 服务启动")
|
||||
data = "payload=" + json.dumps({"text": title + "\n" + content})
|
||||
url = push_config.get("CHAT_URL") + push_config.get("CHAT_TOKEN")
|
||||
response = requests.post(url, data=data)
|
||||
|
||||
if response.status_code == 200:
|
||||
print("Chat 推送成功!")
|
||||
else:
|
||||
print("Chat 推送失败!错误信息:", response)
|
||||
|
||||
|
||||
def pushplus_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 push+ 推送消息。
|
||||
"""
|
||||
if not push_config.get("PUSH_PLUS_TOKEN"):
|
||||
print("PUSHPLUS 服务的 PUSH_PLUS_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("PUSHPLUS 服务启动")
|
||||
|
||||
url = "http://www.pushplus.plus/send"
|
||||
data = {
|
||||
"token": push_config.get("PUSH_PLUS_TOKEN"),
|
||||
"title": title,
|
||||
"content": content,
|
||||
"topic": push_config.get("PUSH_PLUS_USER"),
|
||||
}
|
||||
body = json.dumps(data).encode(encoding="utf-8")
|
||||
headers = {"Content-Type": "application/json"}
|
||||
response = requests.post(url=url, data=body, headers=headers).json()
|
||||
|
||||
if response["code"] == 200:
|
||||
print("PUSHPLUS 推送成功!")
|
||||
|
||||
else:
|
||||
url_old = "http://pushplus.hxtrip.com/send"
|
||||
headers["Accept"] = "application/json"
|
||||
response = requests.post(url=url_old, data=body, headers=headers).json()
|
||||
|
||||
if response["code"] == 200:
|
||||
print("PUSHPLUS(hxtrip) 推送成功!")
|
||||
|
||||
else:
|
||||
print("PUSHPLUS 推送失败!")
|
||||
|
||||
|
||||
def qmsg_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 qmsg 推送消息。
|
||||
"""
|
||||
if not push_config.get("QMSG_KEY") or not push_config.get("QMSG_TYPE"):
|
||||
print("qmsg 的 QMSG_KEY 或者 QMSG_TYPE 未设置!!\n取消推送")
|
||||
return
|
||||
print("qmsg 服务启动")
|
||||
|
||||
url = f'https://qmsg.zendee.cn/{push_config.get("QMSG_TYPE")}/{push_config.get("QMSG_KEY")}'
|
||||
payload = {"msg": f'{title}\n\n{content.replace("----", "-")}'.encode("utf-8")}
|
||||
response = requests.post(url=url, params=payload).json()
|
||||
|
||||
if response["code"] == 0:
|
||||
print("qmsg 推送成功!")
|
||||
else:
|
||||
print(f'qmsg 推送失败!{response["reason"]}')
|
||||
|
||||
|
||||
def wecom_app(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 企业微信 APP 推送消息。
|
||||
"""
|
||||
if not push_config.get("QYWX_AM"):
|
||||
print("QYWX_AM 未设置!!\n取消推送")
|
||||
return
|
||||
QYWX_AM_AY = re.split(",", push_config.get("QYWX_AM"))
|
||||
if 4 < len(QYWX_AM_AY) > 5:
|
||||
print("QYWX_AM 设置错误!!\n取消推送")
|
||||
return
|
||||
print("企业微信 APP 服务启动")
|
||||
|
||||
corpid = QYWX_AM_AY[0]
|
||||
corpsecret = QYWX_AM_AY[1]
|
||||
touser = QYWX_AM_AY[2]
|
||||
agentid = QYWX_AM_AY[3]
|
||||
try:
|
||||
media_id = QYWX_AM_AY[4]
|
||||
except IndexError:
|
||||
media_id = ""
|
||||
wx = WeCom(corpid, corpsecret, agentid)
|
||||
# 如果没有配置 media_id 默认就以 text 方式发送
|
||||
if not media_id:
|
||||
message = title + "\n\n" + content
|
||||
response = wx.send_text(message, touser)
|
||||
else:
|
||||
response = wx.send_mpnews(title, content, media_id, touser)
|
||||
|
||||
if response == "ok":
|
||||
print("企业微信推送成功!")
|
||||
else:
|
||||
print("企业微信推送失败!错误信息如下:\n", response)
|
||||
|
||||
|
||||
class WeCom:
|
||||
def __init__(self, corpid, corpsecret, agentid):
|
||||
self.CORPID = corpid
|
||||
self.CORPSECRET = corpsecret
|
||||
self.AGENTID = agentid
|
||||
self.ORIGIN = "https://qyapi.weixin.qq.com"
|
||||
if push_config.get("QYWX_ORIGIN"):
|
||||
self.ORIGIN = push_config.get("QYWX_ORIGIN")
|
||||
|
||||
def get_access_token(self):
|
||||
url = f"{self.ORIGIN}/cgi-bin/gettoken"
|
||||
values = {
|
||||
"corpid": self.CORPID,
|
||||
"corpsecret": self.CORPSECRET,
|
||||
}
|
||||
req = requests.post(url, params=values)
|
||||
data = json.loads(req.text)
|
||||
return data["access_token"]
|
||||
|
||||
def send_text(self, message, touser="@all"):
|
||||
send_url = f"{self.ORIGIN}/cgi-bin/message/send?access_token={self.get_access_token()}"
|
||||
send_values = {
|
||||
"touser": touser,
|
||||
"msgtype": "text",
|
||||
"agentid": self.AGENTID,
|
||||
"text": {"content": message},
|
||||
"safe": "0",
|
||||
}
|
||||
send_msges = bytes(json.dumps(send_values), "utf-8")
|
||||
respone = requests.post(send_url, send_msges)
|
||||
respone = respone.json()
|
||||
return respone["errmsg"]
|
||||
|
||||
def send_mpnews(self, title, message, media_id, touser="@all"):
|
||||
send_url = f"https://{self.HOST}/cgi-bin/message/send?access_token={self.get_access_token()}"
|
||||
send_values = {
|
||||
"touser": touser,
|
||||
"msgtype": "mpnews",
|
||||
"agentid": self.AGENTID,
|
||||
"mpnews": {
|
||||
"articles": [
|
||||
{
|
||||
"title": title,
|
||||
"thumb_media_id": media_id,
|
||||
"author": "Author",
|
||||
"content_source_url": "",
|
||||
"content": message.replace("\n", "<br/>"),
|
||||
"digest": message,
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
send_msges = bytes(json.dumps(send_values), "utf-8")
|
||||
respone = requests.post(send_url, send_msges)
|
||||
respone = respone.json()
|
||||
return respone["errmsg"]
|
||||
|
||||
|
||||
def wecom_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 企业微信机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("QYWX_KEY"):
|
||||
print("企业微信机器人 服务的 QYWX_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("企业微信机器人服务启动")
|
||||
|
||||
origin = "https://qyapi.weixin.qq.com"
|
||||
if push_config.get("QYWX_ORIGIN"):
|
||||
origin = push_config.get("QYWX_ORIGIN")
|
||||
|
||||
url = f"{origin}/cgi-bin/webhook/send?key={push_config.get('QYWX_KEY')}"
|
||||
headers = {"Content-Type": "application/json;charset=utf-8"}
|
||||
data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
|
||||
response = requests.post(
|
||||
url=url, data=json.dumps(data), headers=headers, timeout=15
|
||||
).json()
|
||||
|
||||
if response["errcode"] == 0:
|
||||
print("企业微信机器人推送成功!")
|
||||
else:
|
||||
print("企业微信机器人推送失败!")
|
||||
|
||||
|
||||
def telegram_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 telegram 机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("TG_BOT_TOKEN") or not push_config.get("TG_USER_ID"):
|
||||
print("tg 服务的 bot_token 或者 user_id 未设置!!\n取消推送")
|
||||
return
|
||||
print("tg 服务启动")
|
||||
|
||||
if push_config.get("TG_API_HOST"):
|
||||
url = f"https://{push_config.get('TG_API_HOST')}/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
|
||||
else:
|
||||
url = (
|
||||
f"https://api.telegram.org/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
|
||||
)
|
||||
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
||||
payload = {
|
||||
"chat_id": str(push_config.get("TG_USER_ID")),
|
||||
"text": f"{title}\n\n{content}",
|
||||
"disable_web_page_preview": "true",
|
||||
}
|
||||
proxies = None
|
||||
if push_config.get("TG_PROXY_HOST") and push_config.get("TG_PROXY_PORT"):
|
||||
if push_config.get("TG_PROXY_AUTH") is not None and "@" not in push_config.get(
|
||||
"TG_PROXY_HOST"
|
||||
):
|
||||
push_config["TG_PROXY_HOST"] = (
|
||||
push_config.get("TG_PROXY_AUTH")
|
||||
+ "@"
|
||||
+ push_config.get("TG_PROXY_HOST")
|
||||
)
|
||||
proxyStr = "http://{}:{}".format(
|
||||
push_config.get("TG_PROXY_HOST"), push_config.get("TG_PROXY_PORT")
|
||||
)
|
||||
proxies = {"http": proxyStr, "https": proxyStr}
|
||||
response = requests.post(
|
||||
url=url, headers=headers, params=payload, proxies=proxies
|
||||
).json()
|
||||
|
||||
if response["ok"]:
|
||||
print("tg 推送成功!")
|
||||
else:
|
||||
print("tg 推送失败!")
|
||||
|
||||
|
||||
def aibotk(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 智能微秘书 推送消息。
|
||||
"""
|
||||
if (
|
||||
not push_config.get("AIBOTK_KEY")
|
||||
or not push_config.get("AIBOTK_TYPE")
|
||||
or not push_config.get("AIBOTK_NAME")
|
||||
):
|
||||
print("智能微秘书 的 AIBOTK_KEY 或者 AIBOTK_TYPE 或者 AIBOTK_NAME 未设置!!\n取消推送")
|
||||
return
|
||||
print("智能微秘书 服务启动")
|
||||
|
||||
if push_config.get("AIBOTK_TYPE") == "room":
|
||||
url = "https://api-bot.aibotk.com/openapi/v1/chat/room"
|
||||
data = {
|
||||
"apiKey": push_config.get("AIBOTK_KEY"),
|
||||
"roomName": push_config.get("AIBOTK_NAME"),
|
||||
"message": {"type": 1, "content": f"【青龙快讯】\n\n{title}\n{content}"},
|
||||
}
|
||||
else:
|
||||
url = "https://api-bot.aibotk.com/openapi/v1/chat/contact"
|
||||
data = {
|
||||
"apiKey": push_config.get("AIBOTK_KEY"),
|
||||
"name": push_config.get("AIBOTK_NAME"),
|
||||
"message": {"type": 1, "content": f"【青龙快讯】\n\n{title}\n{content}"},
|
||||
}
|
||||
body = json.dumps(data).encode(encoding="utf-8")
|
||||
headers = {"Content-Type": "application/json"}
|
||||
response = requests.post(url=url, data=body, headers=headers).json()
|
||||
print(response)
|
||||
if response["code"] == 0:
|
||||
print("智能微秘书 推送成功!")
|
||||
else:
|
||||
print(f'智能微秘书 推送失败!{response["error"]}')
|
||||
|
||||
|
||||
def smtp(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 SMTP 邮件 推送消息。
|
||||
"""
|
||||
if (
|
||||
not push_config.get("SMTP_SERVER")
|
||||
or not push_config.get("SMTP_SSL")
|
||||
or not push_config.get("SMTP_EMAIL")
|
||||
or not push_config.get("SMTP_PASSWORD")
|
||||
or not push_config.get("SMTP_NAME")
|
||||
):
|
||||
print(
|
||||
"SMTP 邮件 的 SMTP_SERVER 或者 SMTP_SSL 或者 SMTP_EMAIL 或者 SMTP_PASSWORD 或者 SMTP_NAME 未设置!!\n取消推送"
|
||||
)
|
||||
return
|
||||
print("SMTP 邮件 服务启动")
|
||||
|
||||
message = MIMEText(content, "plain", "utf-8")
|
||||
message["From"] = formataddr(
|
||||
(
|
||||
Header(push_config.get("SMTP_NAME"), "utf-8").encode(),
|
||||
push_config.get("SMTP_EMAIL"),
|
||||
)
|
||||
)
|
||||
message["To"] = formataddr(
|
||||
(
|
||||
Header(push_config.get("SMTP_NAME"), "utf-8").encode(),
|
||||
push_config.get("SMTP_EMAIL"),
|
||||
)
|
||||
)
|
||||
message["Subject"] = Header(title, "utf-8")
|
||||
|
||||
try:
|
||||
smtp_server = (
|
||||
smtplib.SMTP_SSL(push_config.get("SMTP_SERVER"))
|
||||
if push_config.get("SMTP_SSL") == "true"
|
||||
else smtplib.SMTP(push_config.get("SMTP_SERVER"))
|
||||
)
|
||||
smtp_server.login(
|
||||
push_config.get("SMTP_EMAIL"), push_config.get("SMTP_PASSWORD")
|
||||
)
|
||||
smtp_server.sendmail(
|
||||
push_config.get("SMTP_EMAIL"),
|
||||
push_config.get("SMTP_EMAIL"),
|
||||
message.as_bytes(),
|
||||
)
|
||||
smtp_server.close()
|
||||
print("SMTP 邮件 推送成功!")
|
||||
except Exception as e:
|
||||
print(f"SMTP 邮件 推送失败!{e}")
|
||||
|
||||
|
||||
def pushme(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 PushMe 推送消息。
|
||||
"""
|
||||
if not push_config.get("PUSHME_KEY"):
|
||||
print("PushMe 服务的 PUSHME_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("PushMe 服务启动")
|
||||
|
||||
url = f'https://push.i-i.me/?push_key={push_config.get("PUSHME_KEY")}'
|
||||
data = {
|
||||
"title": title,
|
||||
"content": content,
|
||||
}
|
||||
response = requests.post(url, data=data)
|
||||
|
||||
if response.status_code == 200 and response.text == "success":
|
||||
print("PushMe 推送成功!")
|
||||
else:
|
||||
print(f"PushMe 推送失败!{response.status_code} {response.text}")
|
||||
|
||||
|
||||
def one() -> str:
|
||||
"""
|
||||
获取一条一言。
|
||||
:return:
|
||||
"""
|
||||
url = "https://v1.hitokoto.cn/"
|
||||
res = requests.get(url).json()
|
||||
return res["hitokoto"] + " ----" + res["from"]
|
||||
|
||||
|
||||
if push_config.get("BARK_PUSH"):
|
||||
notify_function.append(bark)
|
||||
if push_config.get("CONSOLE"):
|
||||
notify_function.append(console)
|
||||
if push_config.get("DD_BOT_TOKEN") and push_config.get("DD_BOT_SECRET"):
|
||||
notify_function.append(dingding_bot)
|
||||
if push_config.get("FSKEY"):
|
||||
notify_function.append(feishu_bot)
|
||||
if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"):
|
||||
notify_function.append(go_cqhttp)
|
||||
if push_config.get("GOTIFY_URL") and push_config.get("GOTIFY_TOKEN"):
|
||||
notify_function.append(gotify)
|
||||
if push_config.get("IGOT_PUSH_KEY"):
|
||||
notify_function.append(iGot)
|
||||
if push_config.get("PUSH_KEY"):
|
||||
notify_function.append(serverJ)
|
||||
if push_config.get("DEER_KEY"):
|
||||
notify_function.append(pushdeer)
|
||||
if push_config.get("CHAT_URL") and push_config.get("CHAT_TOKEN"):
|
||||
notify_function.append(chat)
|
||||
if push_config.get("PUSH_PLUS_TOKEN"):
|
||||
notify_function.append(pushplus_bot)
|
||||
if push_config.get("QMSG_KEY") and push_config.get("QMSG_TYPE"):
|
||||
notify_function.append(qmsg_bot)
|
||||
if push_config.get("QYWX_AM"):
|
||||
notify_function.append(wecom_app)
|
||||
if push_config.get("QYWX_KEY"):
|
||||
notify_function.append(wecom_bot)
|
||||
if push_config.get("TG_BOT_TOKEN") and push_config.get("TG_USER_ID"):
|
||||
notify_function.append(telegram_bot)
|
||||
if (
|
||||
push_config.get("AIBOTK_KEY")
|
||||
and push_config.get("AIBOTK_TYPE")
|
||||
and push_config.get("AIBOTK_NAME")
|
||||
):
|
||||
notify_function.append(aibotk)
|
||||
if (
|
||||
push_config.get("SMTP_SERVER")
|
||||
and push_config.get("SMTP_SSL")
|
||||
and push_config.get("SMTP_EMAIL")
|
||||
and push_config.get("SMTP_PASSWORD")
|
||||
and push_config.get("SMTP_NAME")
|
||||
):
|
||||
notify_function.append(smtp)
|
||||
if push_config.get("PUSHME_KEY"):
|
||||
notify_function.append(pushme)
|
||||
|
||||
|
||||
def send(title: str, content: str) -> None:
|
||||
if not content:
|
||||
print(f"{title} 推送内容为空!")
|
||||
return
|
||||
|
||||
# 根据标题跳过一些消息推送,环境变量:SKIP_PUSH_TITLE 用回车分隔
|
||||
skipTitle = os.getenv("SKIP_PUSH_TITLE")
|
||||
if skipTitle:
|
||||
if title in re.split("\n", skipTitle):
|
||||
print(f"{title} 在SKIP_PUSH_TITLE环境变量内,跳过推送!")
|
||||
return
|
||||
|
||||
hitokoto = push_config.get("HITOKOTO")
|
||||
|
||||
text = one() if hitokoto else ""
|
||||
content += "大自然的搬运工\nhttp://www.bedee.top/\n\n" + text
|
||||
|
||||
ts = [
|
||||
threading.Thread(target=mode, args=(title, content), name=mode.__name__)
|
||||
for mode in notify_function
|
||||
]
|
||||
[t.start() for t in ts]
|
||||
[t.join() for t in ts]
|
||||
|
||||
|
||||
def main():
|
||||
send("title", "content")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
164
脚本库/web版/账密/V2EX每日签到/2025-04-28_sudojia_v2ex_e79de91c.js
Normal file
164
脚本库/web版/账密/V2EX每日签到/2025-04-28_sudojia_v2ex_e79de91c.js
Normal file
@@ -0,0 +1,164 @@
|
||||
// # Source: https://github.com/sudojia/AutoTaskScript/blob/script/src/web/sudojia_v2ex.js
|
||||
// # Raw: https://raw.githubusercontent.com/sudojia/AutoTaskScript/script/src/web/sudojia_v2ex.js
|
||||
// # Repo: sudojia/AutoTaskScript
|
||||
// # Path: src/web/sudojia_v2ex.js
|
||||
// # UploadedAt: 2025-04-28T19:26:13+08:00
|
||||
// # SHA256: e79de91c9a8a74b74490bd2e55f3dadbc876f960a00be966caf61fde2f50c7ae
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/**
|
||||
* v2ex 每日签到 https://www.v2ex.com/
|
||||
*
|
||||
* export V2EX_COOKIE = 'xxxxx'
|
||||
* 多账号用 & 或换行
|
||||
*
|
||||
* @author Telegram@sudojia
|
||||
* @site https://blog.imzjw.cn
|
||||
* @date 2024/5/22
|
||||
*
|
||||
* const $ = new Env('V2EX每日签到')
|
||||
* cron: 0 9 * * *
|
||||
*/
|
||||
const initScript = require('../utils/initScript')
|
||||
const {$, notify, sudojia, checkUpdate} = initScript('V2EX每日签到');
|
||||
const cheerio = require('cheerio');
|
||||
const v2exList = process.env.V2EX_COOKIE ? process.env.V2EX_COOKIE.split(/[\n&]/) : [];
|
||||
let message = '';
|
||||
// 接口地址
|
||||
const baseUrl = 'https://www.v2ex.com';
|
||||
// 请求头
|
||||
const headers = {
|
||||
'Accept-Encoding': `gzip, deflate, br`,
|
||||
'Connection': `keep-alive`,
|
||||
'Accept': `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`,
|
||||
"User-Agent": sudojia.getRandomUserAgent('PC'),
|
||||
};
|
||||
!(async () => {
|
||||
await checkUpdate($.name, v2exList);
|
||||
console.log(`\n已随机分配 User-Agent\n\n${headers['user-agent'] || headers['User-Agent']}`);
|
||||
for (let i = 0; i < v2exList.length; i++) {
|
||||
const index = i + 1;
|
||||
headers.Cookie = v2exList[i];
|
||||
console.log(`\n*****第[${index}]个${$.name}账号*****`);
|
||||
const isCookie = await checkCookie();
|
||||
if (!isCookie) {
|
||||
console.error('Cookie 已失效');
|
||||
await notify.sendNotify(`「Cookie失效通知」`, `${$.name}账号[${index}] Cookie 已失效,请重新登录获取 Cookie\n\n`);
|
||||
continue;
|
||||
}
|
||||
message += `📣====${$.name}账号[${index}]====📣\n`;
|
||||
await $.wait(sudojia.getRandomWait(800, 1200));
|
||||
await main();
|
||||
await $.wait(sudojia.getRandomWait(2000, 3000));
|
||||
}
|
||||
if (message) {
|
||||
await notify.sendNotify(`「${$.name}」`, `${message}`);
|
||||
}
|
||||
})().catch((e) => $.logErr(e)).finally(() => $.done());
|
||||
|
||||
async function main() {
|
||||
await getOnce();
|
||||
await wait();
|
||||
await getInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测 Cookie 有效返回 true
|
||||
*
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
async function checkCookie() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest('https://v2ex.com/', 'get', headers);
|
||||
return data.indexOf('登出') > -1;
|
||||
} catch (e) {
|
||||
console.error(`检测 Cookie 状态发生异常:${e}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取once
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getOnce() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/mission/daily`, 'GET', headers, {})
|
||||
const $ = cheerio.load(data);
|
||||
const targetLink = $('a.top').eq(1);
|
||||
const userName = targetLink.text();
|
||||
message += `【用户名称】${userName}\n`
|
||||
if (data.indexOf('每日登录奖励已领取') < 0) {
|
||||
console.log('开始签到...')
|
||||
const once = $('input[type="button"]')[0].attribs['onclick'].match(/once=(\d+)/)[1];
|
||||
await wait();
|
||||
await checkIn(once);
|
||||
} else {
|
||||
message += `【签到状态】已经签到过了\n`
|
||||
console.log('已经签到过了');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`获取 once 发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到
|
||||
*
|
||||
* @param once
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function checkIn(once) {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/mission/daily/redeem?once=${once}`, 'GET', headers, {})
|
||||
if (data.indexOf('每日登录奖励已领取') > -1) {
|
||||
console.log('签到成功');
|
||||
message += `【签到状态】签到成功!\n`
|
||||
const continueDays = data.match(/已连续登录 (\d+?) 天/)[1];
|
||||
message += `【签到统计】已连续签到${continueDays}天\n`
|
||||
} else {
|
||||
console.log('签到失败');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`签到时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async function getInfo() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/balance`, 'GET', headers, {})
|
||||
const $ = cheerio.load(data);
|
||||
const balanceArea = $('.balance_area').first();
|
||||
// 提取文本内容
|
||||
const text = balanceArea.text();
|
||||
// 使用正则表达式匹配数字
|
||||
const matches = text.match(/\d+/g);
|
||||
let goldAmount = 0;
|
||||
let silverAmount = 0;
|
||||
let bronzeAmount = 0;
|
||||
// 如果匹配到三个数字,则分别赋值给金币、银币和铜币
|
||||
if (matches && matches.length === 3) {
|
||||
goldAmount = parseInt(matches[0], 10);
|
||||
silverAmount = parseInt(matches[1], 10);
|
||||
bronzeAmount = parseInt(matches[2], 10);
|
||||
} else if (matches && matches.length === 2) {
|
||||
silverAmount = parseInt(matches[0], 10);
|
||||
bronzeAmount = parseInt(matches[1], 10);
|
||||
}
|
||||
message += `【账户余额】${goldAmount}金币 ${silverAmount}银币 ${bronzeAmount}铜币\n\n`
|
||||
} catch (e) {
|
||||
console.error(`获取获取用户信息时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function wait() {
|
||||
await $.wait(sudojia.getRandomWait(2000, 3000));
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
11
脚本库/web版/账密/kstx/2023-09-20_kstx_62ad20ab.js
Normal file
11
脚本库/web版/账密/kstx/2023-09-20_kstx_62ad20ab.js
Normal file
File diff suppressed because one or more lines are too long
694
脚本库/web版/账密/notify/2025-10-28_notify_fef1ad81.py
Normal file
694
脚本库/web版/账密/notify/2025-10-28_notify_fef1ad81.py
Normal file
@@ -0,0 +1,694 @@
|
||||
# Source: https://github.com/NaroisCool/naro-scripts/blob/master/notify.py
|
||||
# Raw: https://raw.githubusercontent.com/NaroisCool/naro-scripts/master/notify.py
|
||||
# Repo: NaroisCool/naro-scripts
|
||||
# Path: notify.py
|
||||
# UploadedAt: 2025-10-28T05:54:28+08:00
|
||||
# SHA256: fef1ad8139e93869700df4511cb0027799e5341762d312d1e23e98ff74fcca36
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
import urllib.parse
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.header import Header
|
||||
from email.utils import formataddr
|
||||
|
||||
import requests
|
||||
|
||||
# 原先的 print 函数和主线程的锁
|
||||
_print = print
|
||||
mutex = threading.Lock()
|
||||
|
||||
|
||||
# 定义新的 print 函数
|
||||
def print(text, *args, **kw):
|
||||
"""
|
||||
使输出有序进行,不出现多线程同一时间输出导致错乱的问题。
|
||||
"""
|
||||
with mutex:
|
||||
_print(text, *args, **kw)
|
||||
|
||||
|
||||
# 通知服务
|
||||
# fmt: off
|
||||
push_config = {
|
||||
'HITOKOTO': False, # 启用一言(随机句子)
|
||||
|
||||
'BARK_PUSH': '', # bark IP 或设备码,例:https://api.day.app/DxHcxxxxxRxxxxxxcm/
|
||||
'BARK_ARCHIVE': '', # bark 推送是否存档
|
||||
'BARK_GROUP': '', # bark 推送分组
|
||||
'BARK_SOUND': '', # bark 推送声音
|
||||
'BARK_ICON': '', # bark 推送图标
|
||||
|
||||
'CONSOLE': True, # 控制台输出
|
||||
|
||||
'DD_BOT_SECRET': '', # 钉钉机器人的 DD_BOT_SECRET
|
||||
'DD_BOT_TOKEN': '', # 钉钉机器人的 DD_BOT_TOKEN
|
||||
|
||||
'FSKEY': '', # 飞书机器人的 FSKEY
|
||||
|
||||
'GOBOT_URL': '', # go-cqhttp
|
||||
# 推送到个人QQ:http://127.0.0.1/send_private_msg
|
||||
# 群:http://127.0.0.1/send_group_msg
|
||||
'GOBOT_QQ': '', # go-cqhttp 的推送群或用户
|
||||
# GOBOT_URL 设置 /send_private_msg 时填入 user_id=个人QQ
|
||||
# /send_group_msg 时填入 group_id=QQ群
|
||||
'GOBOT_TOKEN': '', # go-cqhttp 的 access_token
|
||||
|
||||
'GOTIFY_URL': '', # gotify地址,如https://push.example.de:8080
|
||||
'GOTIFY_TOKEN': '', # gotify的消息应用token
|
||||
'GOTIFY_PRIORITY': 0, # 推送消息优先级,默认为0
|
||||
|
||||
'IGOT_PUSH_KEY': '', # iGot 聚合推送的 IGOT_PUSH_KEY
|
||||
|
||||
'PUSH_KEY': '', # server 酱的 PUSH_KEY,兼容旧版与 Turbo 版
|
||||
|
||||
'DEER_KEY': '', # PushDeer 的 PUSHDEER_KEY
|
||||
'DEER_URL': '', # PushDeer 的 PUSHDEER_URL
|
||||
|
||||
'CHAT_URL': '', # synology chat url
|
||||
'CHAT_TOKEN': '', # synology chat token
|
||||
|
||||
'PUSH_PLUS_TOKEN': '', # push+ 微信推送的用户令牌
|
||||
'PUSH_PLUS_USER': '', # push+ 微信推送的群组编码
|
||||
|
||||
'QMSG_KEY': '', # qmsg 酱的 QMSG_KEY
|
||||
'QMSG_TYPE': '', # qmsg 酱的 QMSG_TYPE
|
||||
|
||||
'QYWX_AM': '', # 企业微信应用
|
||||
|
||||
'QYWX_KEY': '', # 企业微信机器人
|
||||
|
||||
'TG_BOT_TOKEN': '', # tg 机器人的 TG_BOT_TOKEN,例:1407203283:AAG9rt-6RDaaX0HBLZQq0laNOh898iFYaRQ
|
||||
'TG_USER_ID': '', # tg 机器人的 TG_USER_ID,例:1434078534
|
||||
'TG_API_HOST': '', # tg 代理 api
|
||||
'TG_PROXY_AUTH': '', # tg 代理认证参数
|
||||
'TG_PROXY_HOST': '', # tg 机器人的 TG_PROXY_HOST
|
||||
'TG_PROXY_PORT': '', # tg 机器人的 TG_PROXY_PORT
|
||||
|
||||
'AIBOTK_KEY': '', # 智能微秘书 个人中心的apikey 文档地址:http://wechat.aibotk.com/docs/about
|
||||
'AIBOTK_TYPE': '', # 智能微秘书 发送目标 room 或 contact
|
||||
'AIBOTK_NAME': '', # 智能微秘书 发送群名 或者好友昵称和type要对应好
|
||||
|
||||
'SMTP_SERVER': '', # SMTP 发送邮件服务器,形如 smtp.exmail.qq.com:465
|
||||
'SMTP_SSL': 'false', # SMTP 发送邮件服务器是否使用 SSL,填写 true 或 false
|
||||
'SMTP_EMAIL': '', # SMTP 收发件邮箱,通知将会由自己发给自己
|
||||
'SMTP_PASSWORD': '', # SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定
|
||||
'SMTP_NAME': '', # SMTP 收发件人姓名,可随意填写
|
||||
}
|
||||
notify_function = []
|
||||
# fmt: on
|
||||
|
||||
# 首先读取 面板变量 或者 github action 运行变量
|
||||
for k in push_config:
|
||||
if os.getenv(k):
|
||||
v = os.getenv(k)
|
||||
push_config[k] = v
|
||||
|
||||
|
||||
def bark(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 bark 推送消息。
|
||||
"""
|
||||
if not push_config.get("BARK_PUSH"):
|
||||
print("bark 服务的 BARK_PUSH 未设置!!\n取消推送")
|
||||
return
|
||||
print("bark 服务启动")
|
||||
|
||||
if push_config.get("BARK_PUSH").startswith("http"):
|
||||
url = f'{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
|
||||
else:
|
||||
url = f'https://api.day.app/{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
|
||||
|
||||
bark_params = {
|
||||
"BARK_ARCHIVE": "isArchive",
|
||||
"BARK_GROUP": "group",
|
||||
"BARK_SOUND": "sound",
|
||||
"BARK_ICON": "icon",
|
||||
}
|
||||
params = ""
|
||||
for pair in filter(
|
||||
lambda pairs: pairs[0].startswith("BARK_")
|
||||
and pairs[0] != "BARK_PUSH"
|
||||
and pairs[1]
|
||||
and bark_params.get(pairs[0]),
|
||||
push_config.items(),
|
||||
):
|
||||
params += f"{bark_params.get(pair[0])}={pair[1]}&"
|
||||
if params:
|
||||
url = url + "?" + params.rstrip("&")
|
||||
response = requests.get(url).json()
|
||||
|
||||
if response["code"] == 200:
|
||||
print("bark 推送成功!")
|
||||
else:
|
||||
print("bark 推送失败!")
|
||||
|
||||
|
||||
def console(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 控制台 推送消息。
|
||||
"""
|
||||
print(f"{title}\n\n{content}")
|
||||
|
||||
|
||||
def dingding_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 钉钉机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("DD_BOT_SECRET") or not push_config.get("DD_BOT_TOKEN"):
|
||||
print("钉钉机器人 服务的 DD_BOT_SECRET 或者 DD_BOT_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("钉钉机器人 服务启动")
|
||||
|
||||
timestamp = str(round(time.time() * 1000))
|
||||
secret_enc = push_config.get("DD_BOT_SECRET").encode("utf-8")
|
||||
string_to_sign = "{}\n{}".format(
|
||||
timestamp, push_config.get("DD_BOT_SECRET"))
|
||||
string_to_sign_enc = string_to_sign.encode("utf-8")
|
||||
hmac_code = hmac.new(
|
||||
secret_enc, string_to_sign_enc, digestmod=hashlib.sha256
|
||||
).digest()
|
||||
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
|
||||
url = f'https://oapi.dingtalk.com/robot/send?access_token={push_config.get("DD_BOT_TOKEN")}×tamp={timestamp}&sign={sign}'
|
||||
headers = {"Content-Type": "application/json;charset=utf-8"}
|
||||
data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
|
||||
response = requests.post(
|
||||
url=url, data=json.dumps(data), headers=headers, timeout=15
|
||||
).json()
|
||||
|
||||
if not response["errcode"]:
|
||||
print("钉钉机器人 推送成功!")
|
||||
else:
|
||||
print("钉钉机器人 推送失败!")
|
||||
|
||||
|
||||
def feishu_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 飞书机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("FSKEY"):
|
||||
print("飞书 服务的 FSKEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("飞书 服务启动")
|
||||
|
||||
url = f'https://open.feishu.cn/open-apis/bot/v2/hook/{push_config.get("FSKEY")}'
|
||||
data = {"msg_type": "text", "content": {"text": f"{title}\n\n{content}"}}
|
||||
response = requests.post(url, data=json.dumps(data)).json()
|
||||
|
||||
if response.get("StatusCode") == 0:
|
||||
print("飞书 推送成功!")
|
||||
else:
|
||||
print("飞书 推送失败!错误信息如下:\n", response)
|
||||
|
||||
|
||||
def go_cqhttp(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 go_cqhttp 推送消息。
|
||||
"""
|
||||
if not push_config.get("GOBOT_URL") or not push_config.get("GOBOT_QQ"):
|
||||
print("go-cqhttp 服务的 GOBOT_URL 或 GOBOT_QQ 未设置!!\n取消推送")
|
||||
return
|
||||
print("go-cqhttp 服务启动")
|
||||
|
||||
url = f'{push_config.get("GOBOT_URL")}?access_token={push_config.get("GOBOT_TOKEN")}&{push_config.get("GOBOT_QQ")}&message=标题:{title}\n内容:{content}'
|
||||
response = requests.get(url).json()
|
||||
|
||||
if response["status"] == "ok":
|
||||
print("go-cqhttp 推送成功!")
|
||||
else:
|
||||
print("go-cqhttp 推送失败!")
|
||||
|
||||
|
||||
def gotify(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 gotify 推送消息。
|
||||
"""
|
||||
if not push_config.get("GOTIFY_URL") or not push_config.get("GOTIFY_TOKEN"):
|
||||
print("gotify 服务的 GOTIFY_URL 或 GOTIFY_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("gotify 服务启动")
|
||||
|
||||
url = f'{push_config.get("GOTIFY_URL")}/message?token={push_config.get("GOTIFY_TOKEN")}'
|
||||
data = {"title": title, "message": content,
|
||||
"priority": push_config.get("GOTIFY_PRIORITY")}
|
||||
response = requests.post(url, data=data).json()
|
||||
|
||||
if response.get("id"):
|
||||
print("gotify 推送成功!")
|
||||
else:
|
||||
print("gotify 推送失败!")
|
||||
|
||||
|
||||
def iGot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 iGot 推送消息。
|
||||
"""
|
||||
if not push_config.get("IGOT_PUSH_KEY"):
|
||||
print("iGot 服务的 IGOT_PUSH_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("iGot 服务启动")
|
||||
|
||||
url = f'https://push.hellyw.com/{push_config.get("IGOT_PUSH_KEY")}'
|
||||
data = {"title": title, "content": content}
|
||||
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
||||
response = requests.post(url, data=data, headers=headers).json()
|
||||
|
||||
if response["ret"] == 0:
|
||||
print("iGot 推送成功!")
|
||||
else:
|
||||
print(f'iGot 推送失败!{response["errMsg"]}')
|
||||
|
||||
|
||||
def serverJ(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 serverJ 推送消息。
|
||||
"""
|
||||
if not push_config.get("PUSH_KEY"):
|
||||
print("serverJ 服务的 PUSH_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("serverJ 服务启动")
|
||||
|
||||
data = {"text": title, "desp": content.replace("\n", "\n\n")}
|
||||
if push_config.get("PUSH_KEY").find("SCT") != -1:
|
||||
url = f'https://sctapi.ftqq.com/{push_config.get("PUSH_KEY")}.send'
|
||||
else:
|
||||
url = f'https://sc.ftqq.com/{push_config.get("PUSH_KEY")}.send'
|
||||
response = requests.post(url, data=data).json()
|
||||
|
||||
if response.get("errno") == 0 or response.get("code") == 0:
|
||||
print("serverJ 推送成功!")
|
||||
else:
|
||||
print(f'serverJ 推送失败!错误码:{response["message"]}')
|
||||
|
||||
|
||||
def pushdeer(title: str, content: str) -> None:
|
||||
"""
|
||||
通过PushDeer 推送消息
|
||||
"""
|
||||
if not push_config.get("DEER_KEY"):
|
||||
print("PushDeer 服务的 DEER_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("PushDeer 服务启动")
|
||||
data = {"text": title, "desp": content, "type": "markdown",
|
||||
"pushkey": push_config.get("DEER_KEY")}
|
||||
url = 'https://api2.pushdeer.com/message/push'
|
||||
if push_config.get("DEER_URL"):
|
||||
url = push_config.get("DEER_URL")
|
||||
|
||||
response = requests.post(url, data=data).json()
|
||||
|
||||
if len(response.get("content").get("result")) > 0:
|
||||
print("PushDeer 推送成功!")
|
||||
else:
|
||||
print("PushDeer 推送失败!错误信息:", response)
|
||||
|
||||
|
||||
def chat(title: str, content: str) -> None:
|
||||
"""
|
||||
通过Chat 推送消息
|
||||
"""
|
||||
if not push_config.get("CHAT_URL") or not push_config.get("CHAT_TOKEN"):
|
||||
print("chat 服务的 CHAT_URL或CHAT_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("chat 服务启动")
|
||||
data = 'payload=' + json.dumps({'text': title + '\n' + content})
|
||||
url = push_config.get("CHAT_URL") + push_config.get("CHAT_TOKEN")
|
||||
response = requests.post(url, data=data)
|
||||
|
||||
if response.status_code == 200:
|
||||
print("Chat 推送成功!")
|
||||
else:
|
||||
print("Chat 推送失败!错误信息:", response)
|
||||
|
||||
|
||||
def pushplus_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 push+ 推送消息。
|
||||
"""
|
||||
if not push_config.get("PUSH_PLUS_TOKEN"):
|
||||
print("PUSHPLUS 服务的 PUSH_PLUS_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("PUSHPLUS 服务启动")
|
||||
|
||||
url = "http://www.pushplus.plus/send"
|
||||
data = {
|
||||
"token": push_config.get("PUSH_PLUS_TOKEN"),
|
||||
"title": title,
|
||||
"content": content,
|
||||
"topic": push_config.get("PUSH_PLUS_USER"),
|
||||
}
|
||||
body = json.dumps(data).encode(encoding="utf-8")
|
||||
headers = {"Content-Type": "application/json"}
|
||||
response = requests.post(url=url, data=body, headers=headers).json()
|
||||
|
||||
if response["code"] == 200:
|
||||
print("PUSHPLUS 推送成功!")
|
||||
|
||||
else:
|
||||
|
||||
url_old = "http://pushplus.hxtrip.com/send"
|
||||
headers["Accept"] = "application/json"
|
||||
response = requests.post(
|
||||
url=url_old, data=body, headers=headers).json()
|
||||
|
||||
if response["code"] == 200:
|
||||
print("PUSHPLUS(hxtrip) 推送成功!")
|
||||
|
||||
else:
|
||||
print("PUSHPLUS 推送失败!")
|
||||
|
||||
|
||||
def qmsg_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 qmsg 推送消息。
|
||||
"""
|
||||
if not push_config.get("QMSG_KEY") or not push_config.get("QMSG_TYPE"):
|
||||
print("qmsg 的 QMSG_KEY 或者 QMSG_TYPE 未设置!!\n取消推送")
|
||||
return
|
||||
print("qmsg 服务启动")
|
||||
|
||||
url = f'https://qmsg.zendee.cn/{push_config.get("QMSG_TYPE")}/{push_config.get("QMSG_KEY")}'
|
||||
payload = {
|
||||
"msg": f'{title}\n\n{content.replace("----", "-")}'.encode("utf-8")}
|
||||
response = requests.post(url=url, params=payload).json()
|
||||
|
||||
if response["code"] == 0:
|
||||
print("qmsg 推送成功!")
|
||||
else:
|
||||
print(f'qmsg 推送失败!{response["reason"]}')
|
||||
|
||||
|
||||
def wecom_app(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 企业微信 APP 推送消息。
|
||||
"""
|
||||
if not push_config.get("QYWX_AM"):
|
||||
print("QYWX_AM 未设置!!\n取消推送")
|
||||
return
|
||||
QYWX_AM_AY = re.split(",", push_config.get("QYWX_AM"))
|
||||
if 4 < len(QYWX_AM_AY) > 5:
|
||||
print("QYWX_AM 设置错误!!\n取消推送")
|
||||
return
|
||||
print("企业微信 APP 服务启动")
|
||||
|
||||
corpid = QYWX_AM_AY[0]
|
||||
corpsecret = QYWX_AM_AY[1]
|
||||
touser = QYWX_AM_AY[2]
|
||||
agentid = QYWX_AM_AY[3]
|
||||
try:
|
||||
media_id = QYWX_AM_AY[4]
|
||||
except IndexError:
|
||||
media_id = ""
|
||||
wx = WeCom(corpid, corpsecret, agentid)
|
||||
# 如果没有配置 media_id 默认就以 text 方式发送
|
||||
if not media_id:
|
||||
message = title + "\n\n" + content
|
||||
response = wx.send_text(message, touser)
|
||||
else:
|
||||
response = wx.send_mpnews(title, content, media_id, touser)
|
||||
|
||||
if response == "ok":
|
||||
print("企业微信推送成功!")
|
||||
else:
|
||||
print("企业微信推送失败!错误信息如下:\n", response)
|
||||
|
||||
|
||||
class WeCom:
|
||||
def __init__(self, corpid, corpsecret, agentid):
|
||||
self.CORPID = corpid
|
||||
self.CORPSECRET = corpsecret
|
||||
self.AGENTID = agentid
|
||||
|
||||
def get_access_token(self):
|
||||
url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
|
||||
values = {
|
||||
"corpid": self.CORPID,
|
||||
"corpsecret": self.CORPSECRET,
|
||||
}
|
||||
req = requests.post(url, params=values)
|
||||
data = json.loads(req.text)
|
||||
return data["access_token"]
|
||||
|
||||
def send_text(self, message, touser="@all"):
|
||||
send_url = (
|
||||
"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
|
||||
+ self.get_access_token()
|
||||
)
|
||||
send_values = {
|
||||
"touser": touser,
|
||||
"msgtype": "text",
|
||||
"agentid": self.AGENTID,
|
||||
"text": {"content": message},
|
||||
"safe": "0",
|
||||
}
|
||||
send_msges = bytes(json.dumps(send_values), "utf-8")
|
||||
respone = requests.post(send_url, send_msges)
|
||||
respone = respone.json()
|
||||
return respone["errmsg"]
|
||||
|
||||
def send_mpnews(self, title, message, media_id, touser="@all"):
|
||||
send_url = (
|
||||
"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
|
||||
+ self.get_access_token()
|
||||
)
|
||||
send_values = {
|
||||
"touser": touser,
|
||||
"msgtype": "mpnews",
|
||||
"agentid": self.AGENTID,
|
||||
"mpnews": {
|
||||
"articles": [
|
||||
{
|
||||
"title": title,
|
||||
"thumb_media_id": media_id,
|
||||
"author": "Author",
|
||||
"content_source_url": "",
|
||||
"content": message.replace("\n", "<br/>"),
|
||||
"digest": message,
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
send_msges = bytes(json.dumps(send_values), "utf-8")
|
||||
respone = requests.post(send_url, send_msges)
|
||||
respone = respone.json()
|
||||
return respone["errmsg"]
|
||||
|
||||
|
||||
def wecom_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 企业微信机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("QYWX_KEY"):
|
||||
print("企业微信机器人 服务的 QYWX_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("企业微信机器人服务启动")
|
||||
|
||||
url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={push_config.get('QYWX_KEY')}"
|
||||
headers = {"Content-Type": "application/json;charset=utf-8"}
|
||||
data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
|
||||
response = requests.post(
|
||||
url=url, data=json.dumps(data), headers=headers, timeout=15
|
||||
).json()
|
||||
|
||||
if response["errcode"] == 0:
|
||||
print("企业微信机器人推送成功!")
|
||||
else:
|
||||
print("企业微信机器人推送失败!")
|
||||
|
||||
|
||||
def telegram_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 telegram 机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("TG_BOT_TOKEN") or not push_config.get("TG_USER_ID"):
|
||||
print("tg 服务的 bot_token 或者 user_id 未设置!!\n取消推送")
|
||||
return
|
||||
print("tg 服务启动")
|
||||
|
||||
if push_config.get("TG_API_HOST"):
|
||||
url = f"https://{push_config.get('TG_API_HOST')}/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
|
||||
else:
|
||||
url = (
|
||||
f"https://api.telegram.org/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
|
||||
)
|
||||
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
||||
payload = {
|
||||
"chat_id": str(push_config.get("TG_USER_ID")),
|
||||
"text": f"{title}\n\n{content}",
|
||||
"disable_web_page_preview": "true",
|
||||
}
|
||||
proxies = None
|
||||
if push_config.get("TG_PROXY_HOST") and push_config.get("TG_PROXY_PORT"):
|
||||
if push_config.get("TG_PROXY_AUTH") is not None and "@" not in push_config.get(
|
||||
"TG_PROXY_HOST"
|
||||
):
|
||||
push_config["TG_PROXY_HOST"] = (
|
||||
push_config.get("TG_PROXY_AUTH")
|
||||
+ "@"
|
||||
+ push_config.get("TG_PROXY_HOST")
|
||||
)
|
||||
proxyStr = "http://{}:{}".format(
|
||||
push_config.get("TG_PROXY_HOST"), push_config.get("TG_PROXY_PORT")
|
||||
)
|
||||
proxies = {"http": proxyStr, "https": proxyStr}
|
||||
response = requests.post(
|
||||
url=url, headers=headers, params=payload, proxies=proxies
|
||||
).json()
|
||||
|
||||
if response["ok"]:
|
||||
print("tg 推送成功!")
|
||||
else:
|
||||
print("tg 推送失败!")
|
||||
|
||||
|
||||
def aibotk(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 智能微秘书 推送消息。
|
||||
"""
|
||||
if not push_config.get("AIBOTK_KEY") or not push_config.get("AIBOTK_TYPE") or not push_config.get("AIBOTK_NAME"):
|
||||
print("智能微秘书 的 AIBOTK_KEY 或者 AIBOTK_TYPE 或者 AIBOTK_NAME 未设置!!\n取消推送")
|
||||
return
|
||||
print("智能微秘书 服务启动")
|
||||
|
||||
if push_config.get("AIBOTK_TYPE") == 'room':
|
||||
url = "https://api-bot.aibotk.com/openapi/v1/chat/room"
|
||||
data = {
|
||||
"apiKey": push_config.get("AIBOTK_KEY"),
|
||||
"roomName": push_config.get("AIBOTK_NAME"),
|
||||
"message": {"type": 1, "content": f'【青龙快讯】\n\n{title}\n{content}'}
|
||||
}
|
||||
else:
|
||||
url = "https://api-bot.aibotk.com/openapi/v1/chat/contact"
|
||||
data = {
|
||||
"apiKey": push_config.get("AIBOTK_KEY"),
|
||||
"name": push_config.get("AIBOTK_NAME"),
|
||||
"message": {"type": 1, "content": f'【青龙快讯】\n\n{title}\n{content}'}
|
||||
}
|
||||
body = json.dumps(data).encode(encoding="utf-8")
|
||||
headers = {"Content-Type": "application/json"}
|
||||
response = requests.post(url=url, data=body, headers=headers).json()
|
||||
print(response)
|
||||
if response["code"] == 0:
|
||||
print("智能微秘书 推送成功!")
|
||||
else:
|
||||
print(f'智能微秘书 推送失败!{response["error"]}')
|
||||
|
||||
|
||||
def smtp(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 SMTP 邮件 推送消息。
|
||||
"""
|
||||
if not push_config.get("SMTP_SERVER") or not push_config.get("SMTP_SSL") or not push_config.get("SMTP_EMAIL") or not push_config.get("SMTP_PASSWORD") or not push_config.get("SMTP_NAME"):
|
||||
print("SMTP 邮件 的 SMTP_SERVER 或者 SMTP_SSL 或者 SMTP_EMAIL 或者 SMTP_PASSWORD 或者 SMTP_NAME 未设置!!\n取消推送")
|
||||
return
|
||||
print("SMTP 邮件 服务启动")
|
||||
|
||||
message = MIMEText(content, 'plain', 'utf-8')
|
||||
message['From'] = formataddr((Header(push_config.get(
|
||||
"SMTP_NAME"), 'utf-8').encode(), push_config.get("SMTP_EMAIL")))
|
||||
message['To'] = formataddr((Header(push_config.get(
|
||||
"SMTP_NAME"), 'utf-8').encode(), push_config.get("SMTP_EMAIL")))
|
||||
message['Subject'] = Header(title, 'utf-8')
|
||||
|
||||
try:
|
||||
smtp_server = smtplib.SMTP_SSL(push_config.get("SMTP_SERVER")) if push_config.get(
|
||||
"SMTP_SSL") == 'true' else smtplib.SMTP(push_config.get("SMTP_SERVER"))
|
||||
smtp_server.login(push_config.get("SMTP_EMAIL"),
|
||||
push_config.get("SMTP_PASSWORD"))
|
||||
smtp_server.sendmail(push_config.get("SMTP_EMAIL"),
|
||||
push_config.get("SMTP_EMAIL"), message.as_bytes())
|
||||
smtp_server.close()
|
||||
print("SMTP 邮件 推送成功!")
|
||||
except Exception as e:
|
||||
print(f'SMTP 邮件 推送失败!{e}')
|
||||
|
||||
|
||||
def one() -> str:
|
||||
"""
|
||||
获取一条一言。
|
||||
:return:
|
||||
"""
|
||||
url = "https://v1.hitokoto.cn/"
|
||||
res = requests.get(url).json()
|
||||
return res["hitokoto"] + " ----" + res["from"]
|
||||
|
||||
|
||||
if push_config.get("BARK_PUSH"):
|
||||
notify_function.append(bark)
|
||||
if push_config.get("CONSOLE"):
|
||||
notify_function.append(console)
|
||||
if push_config.get("DD_BOT_TOKEN") and push_config.get("DD_BOT_SECRET"):
|
||||
notify_function.append(dingding_bot)
|
||||
if push_config.get("FSKEY"):
|
||||
notify_function.append(feishu_bot)
|
||||
if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"):
|
||||
notify_function.append(go_cqhttp)
|
||||
if push_config.get("GOTIFY_URL") and push_config.get("GOTIFY_TOKEN"):
|
||||
notify_function.append(gotify)
|
||||
if push_config.get("IGOT_PUSH_KEY"):
|
||||
notify_function.append(iGot)
|
||||
if push_config.get("PUSH_KEY"):
|
||||
notify_function.append(serverJ)
|
||||
if push_config.get("DEER_KEY"):
|
||||
notify_function.append(pushdeer)
|
||||
if push_config.get("CHAT_URL") and push_config.get("CHAT_TOKEN"):
|
||||
notify_function.append(chat)
|
||||
if push_config.get("PUSH_PLUS_TOKEN"):
|
||||
notify_function.append(pushplus_bot)
|
||||
if push_config.get("QMSG_KEY") and push_config.get("QMSG_TYPE"):
|
||||
notify_function.append(qmsg_bot)
|
||||
if push_config.get("QYWX_AM"):
|
||||
notify_function.append(wecom_app)
|
||||
if push_config.get("QYWX_KEY"):
|
||||
notify_function.append(wecom_bot)
|
||||
if push_config.get("TG_BOT_TOKEN") and push_config.get("TG_USER_ID"):
|
||||
notify_function.append(telegram_bot)
|
||||
if push_config.get("AIBOTK_KEY") and push_config.get("AIBOTK_TYPE") and push_config.get("AIBOTK_NAME"):
|
||||
notify_function.append(aibotk)
|
||||
if push_config.get("SMTP_SERVER") and push_config.get("SMTP_SSL") and push_config.get("SMTP_EMAIL") and push_config.get("SMTP_PASSWORD") and push_config.get("SMTP_NAME"):
|
||||
notify_function.append(smtp)
|
||||
|
||||
|
||||
def send(title: str, content: str) -> None:
|
||||
if not content:
|
||||
print(f"{title} 推送内容为空!")
|
||||
return
|
||||
|
||||
# 根据标题跳过一些消息推送,环境变量:SKIP_PUSH_TITLE 用回车分隔
|
||||
skipTitle = os.getenv("SKIP_PUSH_TITLE")
|
||||
if skipTitle:
|
||||
if (title in re.split("\n", skipTitle)):
|
||||
print(f"{title} 在SKIP_PUSH_TITLE环境变量内,跳过推送!")
|
||||
return
|
||||
|
||||
hitokoto = push_config.get("HITOKOTO")
|
||||
|
||||
text = one() if hitokoto else ""
|
||||
content += "\n\n" + text
|
||||
|
||||
ts = [
|
||||
threading.Thread(target=mode, args=(
|
||||
title, content), name=mode.__name__)
|
||||
for mode in notify_function
|
||||
]
|
||||
[t.start() for t in ts]
|
||||
[t.join() for t in ts]
|
||||
|
||||
|
||||
def main():
|
||||
send("title", "content")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
585
脚本库/web版/账密/司机社/2025-08-27_司机社_1e5eeeaf.py
Normal file
585
脚本库/web版/账密/司机社/2025-08-27_司机社_1e5eeeaf.py
Normal file
@@ -0,0 +1,585 @@
|
||||
# Source: https://github.com/LinYuanovo/AutoTaskScripts/blob/main/web/%E5%8F%B8%E6%9C%BA%E7%A4%BE.py
|
||||
# Raw: https://raw.githubusercontent.com/LinYuanovo/AutoTaskScripts/main/web/%E5%8F%B8%E6%9C%BA%E7%A4%BE.py
|
||||
# Repo: LinYuanovo/AutoTaskScripts
|
||||
# Path: web/司机社.py
|
||||
# UploadedAt: 2025-08-27T15:31:08+08:00
|
||||
# SHA256: 1e5eeeaf1e385c86b5a73c385a7bcae653c01fda214429c626e720e8b3fa1b54
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
作者: 临渊
|
||||
日期: 2025/6/17
|
||||
name: 司机社
|
||||
入口: 网站 (https://sjs47.com/)
|
||||
功能: 登录、签到
|
||||
变量: sijishe='邮箱&密码' 或者 'cookie'
|
||||
自动检测,多个账号用换行分割
|
||||
使用邮箱密码将会进行登录(必须有ocr服务地址)
|
||||
使用cookie将会直接使用
|
||||
定时: 一天两次
|
||||
cron: 10 9,10 * * *
|
||||
------------更新日志------------
|
||||
2025/6/17 V1.0 初始化,完成签到功能
|
||||
2025/7/28 V1.1 修改头部注释,以便拉库
|
||||
2025/8/27 V1.2 增加尝试获取最新域名
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import re
|
||||
import urllib.parse
|
||||
import logging
|
||||
import traceback
|
||||
import base64
|
||||
import random
|
||||
import time
|
||||
import json
|
||||
from bs4 import BeautifulSoup
|
||||
from datetime import datetime
|
||||
|
||||
DDDD_OCR_URL = os.getenv("DDDD_OCR_URL") or "" # dddd_ocr地址
|
||||
DEFAULT_GUIDE_URL = "https://47447.net/" # 默认发布地址
|
||||
DEFAULT_HOST = "sjs47.com" # 默认域名
|
||||
|
||||
class AutoTask:
|
||||
def __init__(self, site_name, default_host):
|
||||
"""
|
||||
初始化自动任务类
|
||||
:param site_name: 站点名称,用于日志显示
|
||||
:param default_host: 默认域名
|
||||
"""
|
||||
self.site_name = site_name
|
||||
self.default_host = default_host
|
||||
self.cookie_file = f"{site_name}_cookie.json"
|
||||
self.setup_logging()
|
||||
|
||||
def setup_logging(self):
|
||||
"""
|
||||
配置日志系统
|
||||
"""
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s\t- %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S',
|
||||
handlers=[
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
|
||||
def check_env(self):
|
||||
"""
|
||||
检查环境变量
|
||||
:return: 邮箱和密码,或者cookie
|
||||
"""
|
||||
try:
|
||||
env = os.getenv("sijishe")
|
||||
if not env:
|
||||
logging.error("[检查环境变量]没有找到环境变量sijishe")
|
||||
return
|
||||
envs = env.split('\n')
|
||||
for env in envs:
|
||||
if '&' in env:
|
||||
email, password = env.split('&')
|
||||
yield email, password, None
|
||||
else:
|
||||
yield None, None, env
|
||||
except Exception as e:
|
||||
logging.error(f"[检查环境变量]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
raise
|
||||
|
||||
def get_host(self):
|
||||
"""
|
||||
获取最新域名
|
||||
:return: 域名
|
||||
"""
|
||||
try:
|
||||
url = DEFAULT_GUIDE_URL
|
||||
response = requests.get(url)
|
||||
response.encoding = 'utf-8'
|
||||
soup = BeautifulSoup(response.text, 'html.parser')
|
||||
links = soup.find_all('a')
|
||||
for link in links:
|
||||
link_text = link.get_text(strip=True)
|
||||
if re.search(r'打开网站', link_text):
|
||||
href_value = link.get('href')
|
||||
if href_value.startswith("http"):
|
||||
host = href_value.split("//")[1]
|
||||
logging.info(f"[获取最新域名]最新域名: {host}")
|
||||
return host
|
||||
else:
|
||||
return href_value
|
||||
return DEFAULT_HOST
|
||||
except Exception as e:
|
||||
logging.error(f"[获取最新域名]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return DEFAULT_HOST
|
||||
|
||||
def get_param(self, host, session):
|
||||
"""
|
||||
获取参数
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: formhash, seccodehash, loginhash
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/member.php?mod=logging&action=login&infloat=yes&frommessage&inajax=1&ajaxtarget=messagelogin"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
pattern = r'name="formhash" value="([a-zA-Z0-9]{8})"'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
formhash = match.group(1)
|
||||
else:
|
||||
logging.error("[获取formhash]无法获取formhash")
|
||||
return None, None, None
|
||||
|
||||
pattern = r'seccode_([a-zA-Z0-9]{6})'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
seccodehash = match.group(1)
|
||||
else:
|
||||
logging.error("[获取seccodehash]无法获取seccodehash")
|
||||
return None, None, None
|
||||
|
||||
pattern = r'main_messaqge_([a-zA-Z0-9]{5})'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
loginhash = match.group(1)
|
||||
else:
|
||||
logging.error("[获取loginhash]无法获取loginhash")
|
||||
return None, None, None
|
||||
|
||||
return formhash, seccodehash, loginhash
|
||||
except requests.RequestException as e:
|
||||
logging.warning(f"[获取参数]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None, None, None
|
||||
except Exception as e:
|
||||
logging.error(f"[获取参数]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None, None, None
|
||||
|
||||
def get_captcha_img(self, host, seccodehash, session):
|
||||
"""
|
||||
获取验证码图片
|
||||
:param host: 域名
|
||||
:param seccodehash: seccodehash
|
||||
:param session: 会话对象
|
||||
:return: 验证码图片
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/misc.php?mod=seccode&update={random.randint(10000, 99999)}&idhash={seccodehash}"
|
||||
headers = {
|
||||
'referer': f'https://{host}/member.php?mod=logging&action=login',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
img_base64 = base64.b64encode(response.content).decode('utf-8')
|
||||
return img_base64
|
||||
except Exception as e:
|
||||
logging.error(f"[获取验证码图片]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def get_captcha_text(self, img_base64, ocr_url):
|
||||
"""
|
||||
获取验证码文字
|
||||
:param img_base64: 验证码base64
|
||||
:param ocr_url: OCR服务地址
|
||||
:return: 验证码文字
|
||||
"""
|
||||
try:
|
||||
payload = {
|
||||
'image': img_base64
|
||||
}
|
||||
response = requests.post(ocr_url, data=payload).json()
|
||||
if response['code'] == 200:
|
||||
return response['data']
|
||||
else:
|
||||
logging.error(f"[获取验证码]发生错误: {response['message']}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f"[获取验证码]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def check_captcha(self, host, captcha, session, seccodehash):
|
||||
"""
|
||||
检查验证码
|
||||
:param host: 域名
|
||||
:param captcha: 验证码文字
|
||||
:param session: 会话对象
|
||||
:param seccodehash: seccodehash
|
||||
:return: 是否正确
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/misc.php?mod=seccode&action=check&inajax=1&modid=member::logging&idhash={seccodehash}&secverify={captcha}"
|
||||
headers = {
|
||||
'referer': f'https://{host}/member.php?mod=logging&action=login',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
pattern = r'<!\[CDATA\[(.*?)\]\]>'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
text = match.group(1)
|
||||
if "succeed" in text:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
logging.warning("[检查验证码]响应格式异常")
|
||||
return False
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[检查验证码]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logging.error(f"[检查验证码]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def login_in(self, host, username, password, formhash, captcha, session, loginhash, seccodehash):
|
||||
"""
|
||||
登录
|
||||
:param host: 域名
|
||||
:param username: 邮箱
|
||||
:param password: 密码
|
||||
:param formhash: formhash
|
||||
:param captcha: 验证码文字
|
||||
:param session: 会话对象
|
||||
:param loginhash: loginhash
|
||||
:param seccodehash: seccodehash
|
||||
:return: 是否成功
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/member.php?mod=logging&action=login&loginsubmit=yes&loginhash={loginhash}&inajax=1"
|
||||
payload = f"formhash={formhash}&referer=https://{host}/home.php?mod=spacecp&ac=credit&showcredit=1&loginfield=email&username={username}&password={password}&questionid=0&answer=&seccodehash={seccodehash}&seccodemodid=member::logging&seccodeverify={captcha}&cookietime=2592000"
|
||||
headers = {
|
||||
'Referer': f'https://{host}/home.php?mod=spacecp&ac=credit&showcredit=1',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
payload = urllib.parse.quote(payload, safe='=&')
|
||||
response = session.post(url, headers=headers, data=payload)
|
||||
response.raise_for_status()
|
||||
pattern = r'<!\[CDATA\[(.*?)\]\]>'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
text = match.group(1)
|
||||
if "欢迎您回来" in text:
|
||||
username_pattern = r'欢迎您回来,(.*?),现在将转入登录前页面'
|
||||
username_match = re.search(username_pattern, text)
|
||||
if username_match:
|
||||
pattern = r'<font color="#00FFCC">(.*?)</font> (.*?)'
|
||||
match = re.search(pattern, text)
|
||||
if match:
|
||||
level = match.group(1)
|
||||
nickname = match.group(2)
|
||||
logging.info(f"[登录]成功,当前账号: {level} {nickname}")
|
||||
else:
|
||||
logging.info(f"[登录]成功,当前账号: {username_match.group(1)}")
|
||||
return True
|
||||
else:
|
||||
logging.warning("[登录]登录失败")
|
||||
return False
|
||||
else:
|
||||
logging.warning("[登录]响应格式异常")
|
||||
return False
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[登录]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logging.error(f"[登录]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def read_cookie_file(self):
|
||||
"""
|
||||
读取cookie文件
|
||||
:return: cookie字符串或None
|
||||
"""
|
||||
try:
|
||||
if os.path.exists(self.cookie_file):
|
||||
with open(self.cookie_file, 'r', encoding='utf-8') as f:
|
||||
cookie_data = json.load(f)
|
||||
if cookie_data.get('accounts'):
|
||||
logging.info(f"[读取Cookie文件]成功读取{self.cookie_file}")
|
||||
return cookie_data['accounts']
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f"[读取Cookie文件]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def write_cookie_file(self, cookies, email=None):
|
||||
"""
|
||||
写入cookie文件
|
||||
:param cookies: cookie字符串
|
||||
:param email: 账号邮箱,用于标识不同账号
|
||||
"""
|
||||
try:
|
||||
# 读取现有cookie文件
|
||||
existing_data = {}
|
||||
if os.path.exists(self.cookie_file):
|
||||
with open(self.cookie_file, 'r', encoding='utf-8') as f:
|
||||
existing_data = json.load(f)
|
||||
|
||||
# 准备新的cookie数据
|
||||
cookie_data = {
|
||||
'site_name': self.site_name,
|
||||
'host': self.default_host,
|
||||
'accounts': existing_data.get('accounts', {}),
|
||||
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
# 更新或添加账号cookie
|
||||
if email:
|
||||
cookie_data['accounts'][email] = {
|
||||
'cookies': cookies,
|
||||
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
else:
|
||||
# 如果没有提供email,使用默认键
|
||||
cookie_data['accounts']['default'] = {
|
||||
'cookies': cookies,
|
||||
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
with open(self.cookie_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(cookie_data, f, ensure_ascii=False, indent=2)
|
||||
logging.info(f"[写入Cookie文件]成功写入{self.cookie_file}")
|
||||
except Exception as e:
|
||||
logging.error(f"[写入Cookie文件]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
def get_session_cookies(self, session):
|
||||
"""
|
||||
获取session的cookies字符串
|
||||
:param session: 会话对象
|
||||
:return: cookie字符串
|
||||
"""
|
||||
try:
|
||||
cookies = []
|
||||
for cookie in session.cookies:
|
||||
cookies.append(f"{cookie.name}={cookie.value}")
|
||||
return '; '.join(cookies)
|
||||
except Exception as e:
|
||||
logging.error(f"[获取Session Cookies]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def check_cookie_valid(self, host, session):
|
||||
"""
|
||||
检查cookie是否有效
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: 是否有效
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/home.php?mod=space"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
if "请先登录" in response.text:
|
||||
logging.warning("[Cookie检测]Cookie已失效")
|
||||
return False
|
||||
logging.info("[Cookie检测]Cookie有效")
|
||||
return True
|
||||
except Exception as e:
|
||||
logging.error(f"[Cookie检测]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def get_sign_hash(self, host, session):
|
||||
"""
|
||||
获取签到hash
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: 签到hash
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/k_misign-sign.html"
|
||||
headers = {
|
||||
'priority': 'u=1, i',
|
||||
'x-requested-with': 'XMLHttpRequest',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host,
|
||||
'Connection': 'keep-alive'
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
pattern = r'formhash=([a-zA-Z0-9]{8})'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
formhash = match.group(1)
|
||||
return formhash
|
||||
else:
|
||||
logging.warning("[获取签到hash]无法获取签到hash")
|
||||
return None
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[获取签到hash]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def signin(self, host, session, sign_hash):
|
||||
"""
|
||||
签到
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:param sign_hash: 签到hash
|
||||
"""
|
||||
try:
|
||||
if not sign_hash:
|
||||
logging.error("sign_hash为空,无法进行签到")
|
||||
return
|
||||
|
||||
url = f"https://{host}/k_misign-sign.html?operation=qiandao&format=button&formhash={sign_hash}&inajax=1&ajaxtarget=midaben_sign"
|
||||
payload = {}
|
||||
headers = {
|
||||
'priority': 'u=1, i',
|
||||
'x-requested-with': 'XMLHttpRequest',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host,
|
||||
'Connection': 'keep-alive'
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
# 使用正则表达式匹配CDATA中的内容
|
||||
if "签到成功" in response.text:
|
||||
# 获得随机奖励 248车票 和 。 </p>
|
||||
pattern = r'获得随机奖励 (.*?)车票 和 (.*?)。'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
logging.info(f"[签到]成功,获得{match.group(1)}车票和{match.group(2)}车票")
|
||||
else:
|
||||
logging.info("[签到]成功")
|
||||
elif "今日已签" in response.text:
|
||||
logging.info("[签到]今日已签到")
|
||||
else:
|
||||
logging.warning(f"[签到]失败,返回内容: {response.text}")
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[签到]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
except Exception as e:
|
||||
logging.error(f"[签到]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
|
||||
def run(self, ocr_url):
|
||||
"""
|
||||
执行登录任务的主函数
|
||||
:param ocr_url: OCR服务地址
|
||||
"""
|
||||
try:
|
||||
logging.info(f"【{self.site_name}】开始执行任务")
|
||||
self.default_host = self.get_host()
|
||||
|
||||
# 首先尝试读取cookie文件
|
||||
accounts = self.read_cookie_file()
|
||||
if accounts:
|
||||
logging.info("[Cookie文件]检测到cookie文件,将尝试使用")
|
||||
for email, account_data in accounts.items():
|
||||
session = requests.Session()
|
||||
for cookie_item in account_data['cookies'].split(';'):
|
||||
key, value = cookie_item.split('=', 1)
|
||||
session.cookies.set(key.strip(), value.strip())
|
||||
|
||||
# 检查cookie是否有效
|
||||
if self.check_cookie_valid(self.default_host, session):
|
||||
logging.info(f"[Cookie文件]账号 {email} 的Cookie有效")
|
||||
# 执行签到任务
|
||||
sign_hash = self.get_sign_hash(self.default_host, session)
|
||||
if sign_hash:
|
||||
self.signin(self.default_host, session, sign_hash)
|
||||
return session
|
||||
else:
|
||||
logging.warning(f"[Cookie文件]账号 {email} 的Cookie已失效")
|
||||
|
||||
logging.info("[Cookie文件]所有账号的Cookie都已失效,尝试使用邮箱密码登录")
|
||||
# 检查环境变量中是否有邮箱密码
|
||||
env = os.getenv("sijishe")
|
||||
if not env or '&' not in env:
|
||||
logging.error("[Cookie文件]所有Cookie已失效且环境变量中未找到邮箱密码,无法继续")
|
||||
return None
|
||||
# 删除失效的cookie文件
|
||||
try:
|
||||
os.remove(self.cookie_file)
|
||||
logging.info(f"[Cookie文件]已删除失效的cookie文件: {self.cookie_file}")
|
||||
except Exception as e:
|
||||
logging.error(f"[Cookie文件]删除失效cookie文件失败: {str(e)}")
|
||||
|
||||
for index, (email, password, cookie) in enumerate(self.check_env(), 1):
|
||||
logging.info("")
|
||||
logging.info(f"------【账号{index}】开始执行任务------")
|
||||
|
||||
session = requests.Session()
|
||||
|
||||
if cookie:
|
||||
logging.info(f"[检查环境变量]检测到cookie,将直接使用并保存到文件")
|
||||
for cookie_item in cookie.split(';'):
|
||||
key, value = cookie_item.split('=', 1)
|
||||
session.cookies.set(key.strip(), value.strip())
|
||||
self.write_cookie_file(cookie, email)
|
||||
|
||||
# 检查cookie是否有效
|
||||
if self.check_cookie_valid(self.default_host, session):
|
||||
logging.info(f"[Cookie]账号 {email} 的Cookie有效")
|
||||
# 执行签到任务
|
||||
sign_hash = self.get_sign_hash(self.default_host, session)
|
||||
if sign_hash:
|
||||
self.signin(self.default_host, session, sign_hash)
|
||||
return session
|
||||
else:
|
||||
logging.warning(f"[Cookie]账号 {email} 的Cookie已失效")
|
||||
continue
|
||||
else:
|
||||
logging.info(f"[检查环境变量]检测到邮箱密码,将进行登录")
|
||||
formhash, seccodehash, loginhash = self.get_param(self.default_host, session)
|
||||
if not all([formhash, seccodehash, loginhash]):
|
||||
logging.error("获取参数失败,跳过当前账号")
|
||||
continue
|
||||
|
||||
max_retries = 3
|
||||
retry_count = 0
|
||||
while retry_count < max_retries:
|
||||
login_in_captcha = self.get_captcha_img(self.default_host, seccodehash, session)
|
||||
login_in_captcha_text = self.get_captcha_text(login_in_captcha, ocr_url)
|
||||
if self.check_captcha(self.default_host, login_in_captcha_text, session, seccodehash):
|
||||
break
|
||||
|
||||
retry_count += 1
|
||||
if retry_count < max_retries:
|
||||
logging.warning(f"[验证码]验证失败,第{retry_count}次重试")
|
||||
time.sleep(5)
|
||||
else:
|
||||
logging.error("[验证码]验证失败,已达到最大重试次数")
|
||||
continue
|
||||
|
||||
if not self.login_in(self.default_host, email, password, formhash, login_in_captcha_text, session, loginhash, seccodehash):
|
||||
logging.error("登录失败,跳过当前账号")
|
||||
continue
|
||||
|
||||
# 登录成功后保存cookie到文件
|
||||
cookies = self.get_session_cookies(session)
|
||||
if cookies:
|
||||
self.write_cookie_file(cookies, email)
|
||||
|
||||
# 登录成功后执行签到任务
|
||||
sign_hash = self.get_sign_hash(self.default_host, session)
|
||||
if sign_hash:
|
||||
self.signin(self.default_host, session, sign_hash)
|
||||
|
||||
logging.info(f"------【账号{index}】执行任务完成------")
|
||||
logging.info("")
|
||||
return session
|
||||
except Exception as e:
|
||||
logging.error(f"【{self.site_name}】执行过程中发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
if __name__ == "__main__":
|
||||
site_name = "司机社"
|
||||
ocr_url = DDDD_OCR_URL
|
||||
|
||||
auto_task = AutoTask(site_name, DEFAULT_HOST)
|
||||
session = auto_task.run(ocr_url)
|
||||
430
脚本库/web版/账密/嘤嘤怪之家/2025-08-27_嘤嘤怪之家_9e2e2ee0.py
Normal file
430
脚本库/web版/账密/嘤嘤怪之家/2025-08-27_嘤嘤怪之家_9e2e2ee0.py
Normal file
@@ -0,0 +1,430 @@
|
||||
# Source: https://github.com/LinYuanovo/AutoTaskScripts/blob/main/web/%E5%98%A4%E5%98%A4%E6%80%AA%E4%B9%8B%E5%AE%B6.py
|
||||
# Raw: https://raw.githubusercontent.com/LinYuanovo/AutoTaskScripts/main/web/%E5%98%A4%E5%98%A4%E6%80%AA%E4%B9%8B%E5%AE%B6.py
|
||||
# Repo: LinYuanovo/AutoTaskScripts
|
||||
# Path: web/嘤嘤怪之家.py
|
||||
# UploadedAt: 2025-08-27T15:31:08+08:00
|
||||
# SHA256: 9e2e2ee0614b254534faf4e169de569e3d9bbc058a01ef97defe9b330fc9dd90
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
作者: 临渊
|
||||
日期: 2025/6/8
|
||||
name: 嘤嘤怪之家
|
||||
入口: 网站 (https://yyg.app/)
|
||||
功能: 登录、签到、评论(每日上限30积分)
|
||||
变量: yyg='账号&密码' 多个账号用换行分割
|
||||
DDDD_OCR_URL (dddd_ocr地址)
|
||||
定时: 一天两次
|
||||
cron: 10 9,10 * * *
|
||||
------------更新日志------------
|
||||
2025/6/8 V1.0 初始化,完成签到功能
|
||||
2025/6/10 V1.1 添加评论功能
|
||||
2025/6/11 V1.2 优化代码结构,使用session管理cookie,添加查询积分功能(不一定成功)
|
||||
2025/7/23 V1.3 更新域名
|
||||
2025/7/28 V1.4 修改头部注释,以便拉库
|
||||
2025/8/27 V1.5 增加尝试获取最新域名
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import re
|
||||
import urllib.parse
|
||||
import time
|
||||
import random
|
||||
import logging
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
DDDD_OCR_URL = os.getenv("DDDD_OCR_URL") or "" # dddd_ocr地址
|
||||
DEFAULT_GUIDE_URL = "https://yyg.autos/" # 默认发布地址
|
||||
DEFAULT_HOST = "yyg.app" # 默认域名
|
||||
|
||||
class AutoTask:
|
||||
def __init__(self, site_name):
|
||||
"""
|
||||
初始化自动任务类
|
||||
:param site_name: 站点名称,用于日志显示
|
||||
"""
|
||||
self.site_name = site_name
|
||||
self.setup_logging()
|
||||
|
||||
def setup_logging(self):
|
||||
"""
|
||||
配置日志系统
|
||||
"""
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s\t- %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S',
|
||||
handlers=[
|
||||
# logging.FileHandler(f'{self.site_name}_{datetime.now().strftime("%Y%m%d")}.log', encoding='utf-8'), # 保存日志
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
|
||||
def check_cookie(self):
|
||||
"""
|
||||
检查cookie
|
||||
:return: 用户名和密码
|
||||
"""
|
||||
try:
|
||||
# 从环境变量获取cookie
|
||||
cookie = os.getenv(f"yyg")
|
||||
if not cookie:
|
||||
logging.error(f"[检查cookie]没有找到环境变量yyg")
|
||||
return
|
||||
# 多个账号用换行分割
|
||||
cookies = cookie.split('\n')
|
||||
for cookie in cookies:
|
||||
# 解析cookie字符串,提取用户名和密码
|
||||
username, password = cookie.split('&')
|
||||
yield username, password
|
||||
except Exception as e:
|
||||
logging.error(f"[检查cookie]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
raise
|
||||
|
||||
def get_host(self):
|
||||
"""
|
||||
获取最新域名
|
||||
:return: 域名
|
||||
"""
|
||||
try:
|
||||
url = DEFAULT_GUIDE_URL
|
||||
response = requests.get(url)
|
||||
response.encoding = 'utf-8'
|
||||
soup = BeautifulSoup(response.text, 'html.parser')
|
||||
links = soup.find_all('a')
|
||||
for link in links:
|
||||
link_text = link.get_text(strip=True)
|
||||
if re.search(r'访问最新域名', link_text):
|
||||
href_value = link.get('href')
|
||||
if href_value.startswith("http"):
|
||||
host = href_value.split("//")[1]
|
||||
logging.info(f"[获取最新域名]最新域名: {host}")
|
||||
return host
|
||||
else:
|
||||
return href_value
|
||||
return DEFAULT_HOST
|
||||
except Exception as e:
|
||||
logging.error(f"[获取最新域名]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return DEFAULT_HOST
|
||||
|
||||
def get_captcha_img(self, host, session, type):
|
||||
"""
|
||||
获取验证码图片
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:param type: 验证码类型
|
||||
:return: 验证码base64
|
||||
"""
|
||||
max_retries = 3 # 最大重试次数
|
||||
retry_count = 0
|
||||
|
||||
while retry_count < max_retries:
|
||||
try:
|
||||
url = f"https://{host}/wp-content/themes/zibll/action/captcha.php?type=image&id={type}"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'
|
||||
}
|
||||
response = session.get(url, headers=headers).json()
|
||||
if 'img' in response:
|
||||
return response['img']
|
||||
else:
|
||||
retry_count += 1
|
||||
logging.warning(f"[获取验证码]第{retry_count}次获取失败,正在重试...")
|
||||
continue
|
||||
except Exception as e:
|
||||
retry_count += 1
|
||||
if retry_count >= max_retries:
|
||||
logging.error(f"[获取验证码]重试次数已达上限")
|
||||
return None
|
||||
continue
|
||||
|
||||
return None
|
||||
|
||||
def get_captcha_text(self, img):
|
||||
"""
|
||||
获取验证码文字
|
||||
:param img: 验证码图片base64
|
||||
:return: 验证码
|
||||
"""
|
||||
try:
|
||||
url = DDDD_OCR_URL
|
||||
payload = {
|
||||
'image': img
|
||||
}
|
||||
response = requests.post(url, data=payload).json()
|
||||
if response['code'] == 200:
|
||||
return response['data']
|
||||
else:
|
||||
logging.error(f"[获取验证码]发生错误: {response['message']}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f"[获取验证码]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def login_in(self, host, username, password, text, session):
|
||||
"""
|
||||
登录
|
||||
:param host: 域名
|
||||
:param username: 用户名
|
||||
:param password: 密码
|
||||
:param text: 验证码
|
||||
:param session: 会话对象
|
||||
:return: 是否成功
|
||||
"""
|
||||
max_retries = 3 # 最大重试次数
|
||||
retry_count = 0
|
||||
|
||||
while retry_count < max_retries:
|
||||
try:
|
||||
url = f"https://{host}/wp-admin/admin-ajax.php"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36',
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
|
||||
}
|
||||
payload = f"username={username}&password={password}&canvas_yz={text}&remember=forever&action=user_signin"
|
||||
response = session.post(url, headers=headers, data=payload)
|
||||
response_json = response.json()
|
||||
|
||||
if response_json['error'] == 0:
|
||||
logging.info(f"[登录]成功")
|
||||
return True
|
||||
else:
|
||||
logging.error(f"[登录]失败: {response_json['msg']}")
|
||||
if "重新获取" in response_json['msg'] or "请输入图形验证码" in response_json['msg']:
|
||||
retry_count += 1
|
||||
if retry_count >= max_retries:
|
||||
logging.error(f"[登录]验证码重试次数已达上限")
|
||||
return False
|
||||
|
||||
img = self.get_captcha_img(host, session, "img_yz_signin")
|
||||
while not img:
|
||||
img = self.get_captcha_img(host, session, "img_yz_signin")
|
||||
text = self.get_captcha_text(img)
|
||||
if not text:
|
||||
logging.error(f"[登录]获取验证码文字失败")
|
||||
return False
|
||||
continue
|
||||
return False
|
||||
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[登录]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logging.error(f"[登录]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def sign_in(self, host, session):
|
||||
"""
|
||||
执行签到
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: 是否签到成功
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/wp-admin/admin-ajax.php"
|
||||
headers = {
|
||||
'Host': host,
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'
|
||||
}
|
||||
payload = "action=user_checkin"
|
||||
response = session.post(url, headers=headers, data=payload)
|
||||
response_json = response.json()
|
||||
# 处理响应
|
||||
logging.info(f"[签到]{response_json['msg']}")
|
||||
return response_json['msg']
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[签到]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logging.error(f"[签到]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def get_post_id(self, host, session, retry_count=0):
|
||||
"""
|
||||
获取帖子id
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:param retry_count: 重试次数
|
||||
:return: 帖子id列表
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/category/pcgame?orderby=modified" # 最新排列
|
||||
headers = {
|
||||
'Host': host,
|
||||
'Referer': f"https://{host}/category/pcgame",
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
soup = BeautifulSoup(response.text, 'html.parser')
|
||||
|
||||
post_ids = []
|
||||
for i in range(3,7):
|
||||
# 找到所有posts元素
|
||||
links = soup.select(f'body > main > div > div > div:nth-child(2) > posts:nth-child({i}) > div.item-body.flex.xx.flex1.jsb > h2 > a')
|
||||
if links: # 如果找到了链接
|
||||
link = links[0] # 获取第一个链接
|
||||
# 提取帖子ID
|
||||
if link.get('href'):
|
||||
# 从URL中提取ID (例如从 https://yyg.boats/14819.html 提取 14819)
|
||||
post_id = link['href'].split('/')[-1].replace('.html', '')
|
||||
post_ids.append(post_id)
|
||||
|
||||
# 如果没有获取到帖子ID且重试次数小于3次,则重试
|
||||
if not post_ids and retry_count < 3:
|
||||
logging.info(f"[获取帖子ID]未获取到帖子ID,第{retry_count + 1}次重试")
|
||||
time.sleep(random.randint(5, 10))
|
||||
return self.get_post_id(host, session, retry_count + 1)
|
||||
elif not post_ids and retry_count >= 3:
|
||||
post_ids = ['14818', '14817', '14816', '14815']
|
||||
logging.warning(f"[获取帖子ID]三次未获取到帖子ID,使用默认帖子ID: {post_ids}")
|
||||
|
||||
logging.info(f"[获取帖子ID]成功获取到 {len(post_ids)} 个帖子ID: {post_ids}")
|
||||
return post_ids
|
||||
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[获取帖子ID]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return []
|
||||
except Exception as e:
|
||||
logging.error(f"[获取帖子ID]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return []
|
||||
|
||||
def submit_comment(self, host, session, captcha, post_id, retry_count=0):
|
||||
"""
|
||||
提交评论
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:param captcha: 验证码
|
||||
:param post_id: 帖子ID
|
||||
:param retry_count: 重试次数
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/wp-admin/admin-ajax.php"
|
||||
headers = {
|
||||
'Host': host,
|
||||
'Referer': f"https://{host}/{post_id}.html",
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'
|
||||
}
|
||||
payload = f"comment=%E6%84%9F%E8%B0%A2%E5%88%86%E4%BA%AB&canvas_yz={captcha}&comment_post_ID={post_id}&comment_parent=0&action=submit_comment"
|
||||
response = session.post(url, headers=headers, data=payload)
|
||||
response_json = response.json()
|
||||
logging.info(f"[评论帖子{post_id}]{response_json['msg']}")
|
||||
|
||||
if "图形验证码错误" in response_json['msg']:
|
||||
if retry_count >= 3:
|
||||
logging.warning(f"[评论{post_id}]验证码错误重试次数已达上限,跳过此评论")
|
||||
return False
|
||||
|
||||
logging.info(f"[评论帖子{post_id}]验证码错误,第{retry_count + 1}次重试")
|
||||
submit_comment_captcha = self.get_captcha_img(host, session, "submit_comment")
|
||||
while not submit_comment_captcha:
|
||||
submit_comment_captcha = self.get_captcha_img(host, session, "submit_comment")
|
||||
submit_comment_text = self.get_captcha_text(submit_comment_captcha)
|
||||
if not submit_comment_text:
|
||||
logging.error(f"[评论帖子{post_id}]获取验证码文字失败")
|
||||
return False
|
||||
return self.submit_comment(host, session, submit_comment_text, post_id, retry_count + 1)
|
||||
|
||||
return response_json['msg']
|
||||
except Exception as e:
|
||||
logging.error(f"[评论帖子{post_id}]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def get_user_balance(self, host, session):
|
||||
"""
|
||||
获取用户积分
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: 用户积分
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/user/balance"
|
||||
headers = {
|
||||
'Host': host,
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
# 正则匹配积分记录里第一个,即 积分: xxx
|
||||
balance = re.search(r'积分: (\d+)', response.text)
|
||||
if balance:
|
||||
return balance.group(1)
|
||||
else:
|
||||
logging.error(f"[获取用户积分]未找到积分记录")
|
||||
return 0
|
||||
except Exception as e:
|
||||
logging.error(f"[获取用户积分]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return 0
|
||||
|
||||
def do_task(self, host, session):
|
||||
"""
|
||||
执行任务
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
"""
|
||||
# 执行签到
|
||||
self.sign_in(host, session)
|
||||
# 获取帖子id
|
||||
post_ids = self.get_post_id(host, session)
|
||||
# 获取评论验证码图片(四次)
|
||||
for post_id in post_ids:
|
||||
captcha = self.get_captcha_img(host, session, "submit_comment")
|
||||
while not captcha:
|
||||
captcha = self.get_captcha_img(host, session, "submit_comment")
|
||||
text = self.get_captcha_text(captcha)
|
||||
if not text:
|
||||
logging.error(f"[评论{post_id}]获取验证码文字失败")
|
||||
continue
|
||||
# 提交评论
|
||||
self.submit_comment(host, session, text, post_id)
|
||||
time.sleep(random.randint(16, 30))
|
||||
# 获取用户积分
|
||||
balance = self.get_user_balance(host, session)
|
||||
logging.info(f"[账号]当前积分: {balance}")
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
运行任务
|
||||
"""
|
||||
try:
|
||||
logging.info(f"【{self.site_name}】开始执行任务")
|
||||
host = self.get_host()
|
||||
|
||||
for index, (username, password) in enumerate(self.check_cookie(), 1):
|
||||
logging.info("")
|
||||
logging.info(f"------【账号{index}】开始执行任务------")
|
||||
|
||||
# 创建会话
|
||||
session = requests.Session()
|
||||
|
||||
# 获取登录验证码图片
|
||||
login_in_img = self.get_captcha_img(host, session, "img_yz_signin")
|
||||
while not login_in_img:
|
||||
login_in_img = self.get_captcha_img(host, session, "img_yz_signin")
|
||||
# 获取登录验证码文字
|
||||
login_in_text = self.get_captcha_text(login_in_img)
|
||||
if not login_in_text:
|
||||
logging.error(f"[{self.site_name}]获取登录验证码文字失败")
|
||||
continue
|
||||
|
||||
# 登录
|
||||
if self.login_in(host, username, password, login_in_text, session):
|
||||
# 执行任务
|
||||
self.do_task(host, session)
|
||||
|
||||
logging.info(f"------【账号{index}】执行任务完成------")
|
||||
logging.info("")
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"【{self.site_name}】执行过程中发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
auto_task = AutoTask("嘤嘤怪之家")
|
||||
auto_task.run()
|
||||
649
脚本库/web版/账密/尚香书苑/2025-08-27_尚香书苑_d2391787.py
Normal file
649
脚本库/web版/账密/尚香书苑/2025-08-27_尚香书苑_d2391787.py
Normal file
@@ -0,0 +1,649 @@
|
||||
# Source: https://github.com/LinYuanovo/AutoTaskScripts/blob/main/web/%E5%B0%9A%E9%A6%99%E4%B9%A6%E8%8B%91.py
|
||||
# Raw: https://raw.githubusercontent.com/LinYuanovo/AutoTaskScripts/main/web/%E5%B0%9A%E9%A6%99%E4%B9%A6%E8%8B%91.py
|
||||
# Repo: LinYuanovo/AutoTaskScripts
|
||||
# Path: web/尚香书苑.py
|
||||
# UploadedAt: 2025-08-27T15:31:08+08:00
|
||||
# SHA256: d239178748199491eac1ccb8d3adeb971977e5caabe96f2f633de43739e492e2
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
作者: 临渊
|
||||
日期: 2025/6/8
|
||||
name: 尚香书苑
|
||||
入口: 网站 (https://sxsy19.com/)
|
||||
功能: 登录、签到
|
||||
变量: sxsy='邮箱&密码' 或者 'cookie'
|
||||
自动检测,多个账号用换行分割
|
||||
使用邮箱密码将会进行登录(必须有ocr服务地址)
|
||||
使用cookie将会直接使用
|
||||
定时: 一天两次
|
||||
cron: 10 9,10 * * *
|
||||
------------更新日志------------
|
||||
2025/6/8 V1.0 初始化,完成签到功能
|
||||
2025/6/11 V1.1 变量增加邮箱密码支持
|
||||
2025/6/17 V1.2 增加cookie存储功能
|
||||
2025/7/28 V1.3 修改头部注释,以便拉库
|
||||
2025/8/27 V1.4 修改默认域名
|
||||
"""
|
||||
|
||||
DEFAULT_HOST = "sxsy21.com" # 默认域名
|
||||
|
||||
import requests
|
||||
import os
|
||||
import re
|
||||
import urllib.parse
|
||||
import logging
|
||||
import traceback
|
||||
import base64
|
||||
import random
|
||||
import time
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
DDDD_OCR_URL = os.getenv("DDDD_OCR_URL") or "" # dddd_ocr地址
|
||||
|
||||
class AutoTask:
|
||||
def __init__(self, site_name):
|
||||
"""
|
||||
初始化自动任务类
|
||||
:param site_name: 站点名称,用于日志显示
|
||||
"""
|
||||
self.site_name = site_name
|
||||
self.cookie_file = f"{site_name}_cookie.json"
|
||||
self.setup_logging()
|
||||
|
||||
def setup_logging(self):
|
||||
"""
|
||||
配置日志系统
|
||||
"""
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s\t- %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S',
|
||||
handlers=[
|
||||
# logging.FileHandler(f'{self.site_name}_{datetime.now().strftime("%Y%m%d")}.log', encoding='utf-8'), # 保存日志
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
|
||||
def check_env(self):
|
||||
"""
|
||||
检查环境变量
|
||||
:return: 邮箱和密码,或者cookie
|
||||
"""
|
||||
try:
|
||||
env = os.getenv("sxsy")
|
||||
if not env:
|
||||
logging.error("[检查环境变量]没有找到环境变量sxsy")
|
||||
return
|
||||
# 多个账号用换行分割
|
||||
envs = env.split('\n')
|
||||
for env in envs:
|
||||
if '&' in env:
|
||||
# 解析cookie字符串,提取邮箱和密码
|
||||
email, password = env.split('&')
|
||||
yield email, password, None
|
||||
else:
|
||||
# 直接使用cookie
|
||||
yield None, None, env
|
||||
except Exception as e:
|
||||
logging.error(f"[检查环境变量]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
raise
|
||||
|
||||
def get_host(self):
|
||||
"""
|
||||
获取host
|
||||
:return: host
|
||||
"""
|
||||
try:
|
||||
# 访问发布页
|
||||
url = "https://sxsy.org/"
|
||||
payload = {}
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': 'sxsy.org'
|
||||
}
|
||||
response = requests.request("GET", url, headers=headers, data=payload)
|
||||
response.raise_for_status() # 检查响应状态
|
||||
|
||||
# 使用正则表达式匹配host
|
||||
pattern = r'href="https://(.*?)/'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
host = match.group(1)
|
||||
logging.info(f"[获取host]{host}")
|
||||
return host
|
||||
logging.warning("[获取host]无法获取host,使用默认域名")
|
||||
return DEFAULT_HOST # 如果无法获取,返回默认域名
|
||||
except requests.RequestException as e:
|
||||
logging.warning(f"[获取host]发生网络错误,使用默认域名")
|
||||
return DEFAULT_HOST
|
||||
except Exception as e:
|
||||
logging.error(f"[获取host]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return DEFAULT_HOST
|
||||
|
||||
def get_param(self, host, session):
|
||||
"""
|
||||
获取参数
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: formhash, seccodehash, loginhash
|
||||
"""
|
||||
try:
|
||||
# 访问首页
|
||||
url = f"https://{host}/member.php?mod=logging&action=login&infloat=yes&frommessage&inajax=1&ajaxtarget=messagelogin"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
# 使用正则表达式匹配
|
||||
# formhash 格式: name="formhash" value="5448b1bc"
|
||||
pattern = r'name="formhash" value="([a-zA-Z0-9]{8})"'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
formhash = match.group(1)
|
||||
else:
|
||||
logging.error("[获取formhash]无法获取formhash")
|
||||
return None, None, None
|
||||
# seccodehash 格式: seccode_cSAbDg cSAbDg
|
||||
pattern = r'seccode_([a-zA-Z0-9]{6})'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
seccodehash = match.group(1)
|
||||
else:
|
||||
logging.error("[获取seccodehash]无法获取seccodehash")
|
||||
return None, None, None
|
||||
# loginhash 格式: main_messaqge_LCpo4 LCpo4
|
||||
pattern = r'main_messaqge_([a-zA-Z0-9]{5})'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
loginhash = match.group(1)
|
||||
else:
|
||||
logging.error("[获取loginhash]无法获取loginhash")
|
||||
return None, None, None
|
||||
return formhash, seccodehash, loginhash
|
||||
except requests.RequestException as e:
|
||||
logging.warning(f"[获取参数]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None, None, None
|
||||
except Exception as e:
|
||||
logging.error(f"[获取参数]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None, None, None
|
||||
|
||||
def get_captcha_img(self, host, seccodehash, session):
|
||||
"""
|
||||
获取验证码图片
|
||||
:param host: 域名
|
||||
:param seccodehash: seccodehash
|
||||
:param session: 会话对象
|
||||
:return: 验证码图片
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/misc.php?mod=seccode&update={random.randint(10000, 99999)}&idhash={seccodehash}"
|
||||
headers = {
|
||||
'referer': f'https://{host}/member.php?mod=logging&action=login',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
# 图片转为base64
|
||||
img_base64 = base64.b64encode(response.content).decode('utf-8')
|
||||
return img_base64
|
||||
except Exception as e:
|
||||
logging.error(f"[获取验证码图片]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def get_captcha_text(self, img_base64):
|
||||
"""
|
||||
获取验证码文字
|
||||
:param img_base64: 验证码base64
|
||||
:return: 验证码文字
|
||||
"""
|
||||
try:
|
||||
url = DDDD_OCR_URL
|
||||
payload = {
|
||||
'image': img_base64
|
||||
}
|
||||
response = requests.post(url, data=payload).json()
|
||||
if response['code'] == 200:
|
||||
return response['data']
|
||||
else:
|
||||
logging.error(f"[获取验证码]发生错误: {response['message']}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f"[获取验证码]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def check_captcha(self, host, captcha, session, seccodehash):
|
||||
"""
|
||||
检查验证码
|
||||
:param host: 域名
|
||||
:param captcha: 验证码文字
|
||||
:param session: 会话对象
|
||||
:param seccodehash: seccodehash
|
||||
:return: 是否正确
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/misc.php?mod=seccode&action=check&inajax=1&modid=member::logging&idhash={seccodehash}&secverify={captcha}"
|
||||
headers = {
|
||||
'referer': f'https://{host}/member.php?mod=logging&action=login',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
pattern = r'<!\[CDATA\[(.*?)\]\]>'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
text = match.group(1)
|
||||
if "succeed" in text:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
logging.warning("[检查验证码]响应格式异常")
|
||||
return False
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[检查验证码]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logging.error(f"[检查验证码]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def login_in(self, host, username, password, formhash, captcha, session, loginhash, seccodehash):
|
||||
"""
|
||||
登录
|
||||
:param host: 域名
|
||||
:param username: 邮箱
|
||||
:param password: 密码
|
||||
:param formhash: formhash
|
||||
:param captcha: 验证码文字
|
||||
:param session: 会话对象
|
||||
:param loginhash: loginhash
|
||||
:param seccodehash: seccodehash
|
||||
:return: 是否成功
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/member.php?mod=logging&action=login&loginsubmit=yes&loginhash={loginhash}&inajax=1"
|
||||
payload = f"formhash={formhash}&referer=https://{host}/home.php?mod=spacecp&ac=credit&showcredit=1&loginfield=email&username={username}&password={password}&questionid=0&answer=&seccodehash={seccodehash}&seccodemodid=member::logging&seccodeverify={captcha}&cookietime=2592000"
|
||||
headers = {
|
||||
'Referer': f'https://{host}/home.php?mod=spacecp&ac=credit&showcredit=1',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
# payload转为url编码,/替换为%2F
|
||||
payload = urllib.parse.quote(payload, safe='=&')
|
||||
response = session.post(url, headers=headers, data=payload)
|
||||
response.raise_for_status()
|
||||
pattern = r'<!\[CDATA\[(.*?)\]\]>'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
text = match.group(1)
|
||||
if "欢迎您回来" in text:
|
||||
# 匹配
|
||||
username_pattern = r'欢迎您回来,(.*?),现在将转入登录前页面'
|
||||
username_match = re.search(username_pattern, text)
|
||||
if username_match:
|
||||
matched_username = username_match.group(1)
|
||||
logging.info(f"[登录]成功,当前账号: {matched_username}")
|
||||
return True
|
||||
else:
|
||||
logging.warning("[登录]登录失败")
|
||||
return False
|
||||
else:
|
||||
logging.warning("[登录]响应格式异常")
|
||||
return False
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[登录]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logging.error(f"[登录]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def get_sign_hash(self, host, session):
|
||||
"""
|
||||
获取签到hash
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: 签到hash
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/plugin.php?id=k_misign:sign"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
pattern = r'formhash=([a-zA-Z0-9]{8})'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
formhash = match.group(1)
|
||||
return formhash
|
||||
else:
|
||||
logging.warning("[获取签到hash]无法获取签到hash")
|
||||
return None
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[获取签到hash]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def signin(self, host, session, sign_hash):
|
||||
"""
|
||||
签到
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:param sign_hash: 签到hash
|
||||
"""
|
||||
try:
|
||||
if not sign_hash:
|
||||
logging.error("sign_hash为空,无法进行签到")
|
||||
return
|
||||
|
||||
url = f"https://{host}/plugin.php?id=k_misign:sign&operation=qiandao&format=global_usernav_extra&formhash={sign_hash}&inajax=1&ajaxtarget=k_misign_topb"
|
||||
payload = {}
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
# 使用正则表达式匹配CDATA中的内容
|
||||
pattern = r'<!\[CDATA\[(.*?)\]\]>'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
text = match.group(1)
|
||||
logging.info(f"[签到]{text}")
|
||||
else:
|
||||
logging.warning("[签到]响应格式异常")
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[签到]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
except Exception as e:
|
||||
logging.error(f"[签到]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
def get_user_info(self, host, session, print_info=False):
|
||||
"""
|
||||
获取用户信息
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:param print_info: 是否打印信息
|
||||
:return: uid
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/home.php?mod=spacecp&ac=credit&showcredit=1"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
# 使用正则表达式匹配金钱数量
|
||||
money_pattern = r'金钱: </em>(\d+)'
|
||||
match = re.search(money_pattern, response.text)
|
||||
uid_pattern = r'uid=(\d+)'
|
||||
uid_match = re.search(uid_pattern, response.text)
|
||||
if match:
|
||||
money = match.group(1)
|
||||
uid = uid_match.group(1)
|
||||
if print_info:
|
||||
logging.info(f"[用户{uid}]现有金钱 {money}")
|
||||
return uid
|
||||
logging.warning("[获取用户信息]无法获取用户金钱信息")
|
||||
return None
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[获取用户信息]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f"[获取用户信息]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def get_promotion_reward(self, host, uid):
|
||||
"""
|
||||
获取推广奖励
|
||||
:param host: 域名
|
||||
:param uid: uid
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/?fromuid={uid}"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host,
|
||||
'Referer': f'https://{host}/fromuid={uid}'
|
||||
}
|
||||
# 不带cookie直接访问
|
||||
response = requests.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[获取推广奖励]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
except Exception as e:
|
||||
logging.error(f"[获取推广奖励]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
def do_task(self, host, session):
|
||||
"""
|
||||
执行任务
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
"""
|
||||
try:
|
||||
sign_hash = self.get_sign_hash(host, session)
|
||||
if sign_hash:
|
||||
self.signin(host, session, sign_hash)
|
||||
uid = self.get_user_info(host, session)
|
||||
self.get_promotion_reward(host, uid)
|
||||
self.get_user_info(host, session, print_info=True)
|
||||
except Exception as e:
|
||||
logging.error(f"[执行任务]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
def read_cookie_file(self):
|
||||
"""
|
||||
读取cookie文件
|
||||
:return: cookie字符串或None
|
||||
"""
|
||||
try:
|
||||
if os.path.exists(self.cookie_file):
|
||||
with open(self.cookie_file, 'r', encoding='utf-8') as f:
|
||||
cookie_data = json.load(f)
|
||||
if cookie_data.get('accounts'):
|
||||
logging.info(f"[读取Cookie文件]成功读取{self.cookie_file}")
|
||||
return cookie_data['accounts']
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f"[读取Cookie文件]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def write_cookie_file(self, cookies, email=None):
|
||||
"""
|
||||
写入cookie文件
|
||||
:param cookies: cookie字符串
|
||||
:param email: 账号邮箱,用于标识不同账号
|
||||
"""
|
||||
try:
|
||||
# 读取现有cookie文件
|
||||
existing_data = {}
|
||||
if os.path.exists(self.cookie_file):
|
||||
with open(self.cookie_file, 'r', encoding='utf-8') as f:
|
||||
existing_data = json.load(f)
|
||||
|
||||
# 准备新的cookie数据
|
||||
cookie_data = {
|
||||
'site_name': self.site_name,
|
||||
'host': DEFAULT_HOST,
|
||||
'accounts': existing_data.get('accounts', {}),
|
||||
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
# 更新或添加账号cookie
|
||||
if email:
|
||||
cookie_data['accounts'][email] = {
|
||||
'cookies': cookies,
|
||||
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
else:
|
||||
# 如果没有提供email,使用默认键
|
||||
cookie_data['accounts']['default'] = {
|
||||
'cookies': cookies,
|
||||
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
with open(self.cookie_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(cookie_data, f, ensure_ascii=False, indent=2)
|
||||
logging.info(f"[写入Cookie文件]成功写入{self.cookie_file}")
|
||||
except Exception as e:
|
||||
logging.error(f"[写入Cookie文件]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
def get_session_cookies(self, session):
|
||||
"""
|
||||
获取session的cookies字符串
|
||||
:param session: 会话对象
|
||||
:return: cookie字符串
|
||||
"""
|
||||
try:
|
||||
cookies = []
|
||||
for cookie in session.cookies:
|
||||
cookies.append(f"{cookie.name}={cookie.value}")
|
||||
return '; '.join(cookies)
|
||||
except Exception as e:
|
||||
logging.error(f"[获取Session Cookies]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def check_cookie_valid(self, host, session):
|
||||
"""
|
||||
检查cookie是否有效
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: 是否有效
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/home.php?mod=space"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
if "请先登录" in response.text:
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
logging.error(f"[Cookie检测]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
执行签到任务的主函数
|
||||
"""
|
||||
try:
|
||||
logging.info(f"【{self.site_name}】开始执行签到任务")
|
||||
|
||||
# 首先尝试读取cookie文件
|
||||
accounts = self.read_cookie_file()
|
||||
if accounts:
|
||||
logging.info("[Cookie文件]检测到cookie文件,将尝试使用")
|
||||
for email, account_data in accounts.items():
|
||||
session = requests.Session()
|
||||
for cookie_item in account_data['cookies'].split(';'):
|
||||
key, value = cookie_item.split('=', 1)
|
||||
session.cookies.set(key.strip(), value.strip())
|
||||
|
||||
# 检查cookie是否有效
|
||||
if self.check_cookie_valid(DEFAULT_HOST, session):
|
||||
logging.info("")
|
||||
logging.info(f"[Cookie检测]账号 {email} 的Cookie有效")
|
||||
# 执行签到任务
|
||||
self.do_task(DEFAULT_HOST, session)
|
||||
logging.info("")
|
||||
# 如果是最后一个账号,执行return
|
||||
if email == list(accounts.keys())[-1]:
|
||||
return
|
||||
else:
|
||||
logging.warning(f"[Cookie文件]账号 {email} 的Cookie已失效")
|
||||
|
||||
logging.info("[Cookie文件]所有账号的Cookie都已失效,尝试使用邮箱密码登录")
|
||||
# 检查环境变量中是否有邮箱密码
|
||||
env = os.getenv("sxsy")
|
||||
if not env or '&' not in env:
|
||||
logging.error("[Cookie文件]所有Cookie已失效且环境变量中未找到邮箱密码,无法继续")
|
||||
return
|
||||
# 删除失效的cookie文件
|
||||
try:
|
||||
os.remove(self.cookie_file)
|
||||
logging.info(f"[Cookie文件]已删除失效的cookie文件: {self.cookie_file}")
|
||||
except Exception as e:
|
||||
logging.error(f"[Cookie文件]删除失效cookie文件失败: {str(e)}")
|
||||
|
||||
host = self.get_host()
|
||||
for index, (email, password, cookie) in enumerate(self.check_env(), 1):
|
||||
logging.info("")
|
||||
logging.info(f"------【账号{index}】开始执行任务------")
|
||||
|
||||
# 创建会话
|
||||
session = requests.Session()
|
||||
|
||||
if cookie:
|
||||
# 直接使用cookie
|
||||
logging.info(f"[检查环境变量]检测到cookie,将直接使用并保存到文件")
|
||||
for cookie_item in cookie.split(';'):
|
||||
key, value = cookie_item.split('=', 1)
|
||||
session.cookies.set(key.strip(), value.strip())
|
||||
self.write_cookie_file(cookie, email)
|
||||
|
||||
# 检查cookie是否有效
|
||||
if self.check_cookie_valid(host, session):
|
||||
logging.info(f"[Cookie]账号 {email} 的Cookie有效")
|
||||
# 执行签到任务
|
||||
self.do_task(host, session)
|
||||
return
|
||||
else:
|
||||
logging.warning(f"[Cookie]账号 {email} 的Cookie已失效")
|
||||
continue
|
||||
else:
|
||||
logging.info(f"[检查环境变量]检测到邮箱密码,将进行登录")
|
||||
# 获取参数
|
||||
formhash, seccodehash, loginhash = self.get_param(host, session)
|
||||
if not all([formhash, seccodehash, loginhash]):
|
||||
logging.error("获取参数失败,跳过当前账号")
|
||||
continue
|
||||
|
||||
# 验证码重试逻辑
|
||||
max_retries = 3
|
||||
retry_count = 0
|
||||
while retry_count < max_retries:
|
||||
login_in_captcha = self.get_captcha_img(host, seccodehash, session)
|
||||
login_in_captcha_text = self.get_captcha_text(login_in_captcha)
|
||||
if self.check_captcha(host, login_in_captcha_text, session, seccodehash):
|
||||
break
|
||||
|
||||
retry_count += 1
|
||||
if retry_count < max_retries:
|
||||
logging.warning(f"[验证码]验证失败,第{retry_count}次重试")
|
||||
time.sleep(5)
|
||||
else:
|
||||
logging.error("[验证码]验证失败,已达到最大重试次数")
|
||||
continue
|
||||
|
||||
if not self.login_in(host, email, password, formhash, login_in_captcha_text, session, loginhash, seccodehash):
|
||||
logging.error("登录失败,跳过当前账号")
|
||||
continue
|
||||
|
||||
# 登录成功后保存cookie到文件
|
||||
cookies = self.get_session_cookies(session)
|
||||
if cookies:
|
||||
self.write_cookie_file(cookies, email)
|
||||
|
||||
# 登录成功后执行签到任务
|
||||
self.do_task(host, session)
|
||||
|
||||
logging.info(f"------【账号{index}】执行任务完成------")
|
||||
logging.info("")
|
||||
except Exception as e:
|
||||
logging.error(f"【{self.site_name}】执行过程中发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
auto_task = AutoTask("尚香书苑")
|
||||
auto_task.run()
|
||||
568
脚本库/web版/账密/快萌论坛/2025-08-27_快萌论坛_27c922da.py
Normal file
568
脚本库/web版/账密/快萌论坛/2025-08-27_快萌论坛_27c922da.py
Normal file
@@ -0,0 +1,568 @@
|
||||
# Source: https://github.com/LinYuanovo/AutoTaskScripts/blob/main/web/%E5%BF%AB%E8%90%8C%E8%AE%BA%E5%9D%9B.py
|
||||
# Raw: https://raw.githubusercontent.com/LinYuanovo/AutoTaskScripts/main/web/%E5%BF%AB%E8%90%8C%E8%AE%BA%E5%9D%9B.py
|
||||
# Repo: LinYuanovo/AutoTaskScripts
|
||||
# Path: web/快萌论坛.py
|
||||
# UploadedAt: 2025-08-27T15:31:08+08:00
|
||||
# SHA256: 27c922da7d88c924dc93984f676b53b226e5342f04bf8d1ec9710b312ff88d24
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
作者: 临渊
|
||||
日期: 2025/6/8
|
||||
name: 快萌论坛
|
||||
入口: 网站 (https://kmacg20.com/)
|
||||
功能: 登录、签到
|
||||
变量: kmacg='邮箱&密码' 或者 'cookie'
|
||||
自动检测,多个账号用换行分割
|
||||
使用邮箱密码将会进行登录(必须有ocr服务地址)
|
||||
使用cookie将会直接使用
|
||||
定时: 一天两次
|
||||
cron: 10 9,10 * * *
|
||||
------------更新日志------------
|
||||
2025/6/8 V1.0 初始化,完成签到功能
|
||||
2025/7/28 V1.1 修改头部注释,以便拉库
|
||||
"""
|
||||
|
||||
DEFAULT_HOST = "kmacg20.com" # 默认域名
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
import requests
|
||||
import os
|
||||
import re
|
||||
import urllib.parse
|
||||
import logging
|
||||
import traceback
|
||||
import base64
|
||||
import random
|
||||
import time
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
DDDD_OCR_URL = os.getenv("DDDD_OCR_URL") or "" # dddd_ocr地址
|
||||
|
||||
class AutoTask:
|
||||
def __init__(self, site_name):
|
||||
"""
|
||||
初始化自动任务类
|
||||
:param site_name: 站点名称,用于日志显示
|
||||
"""
|
||||
self.site_name = site_name
|
||||
self.cookie_file = f"{site_name}_cookie.json"
|
||||
self.setup_logging()
|
||||
|
||||
def setup_logging(self):
|
||||
"""
|
||||
配置日志系统
|
||||
"""
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s\t- %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S',
|
||||
handlers=[
|
||||
# logging.FileHandler(f'{self.site_name}_{datetime.now().strftime("%Y%m%d")}.log', encoding='utf-8'), # 保存日志
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
|
||||
def check_env(self):
|
||||
"""
|
||||
检查环境变量
|
||||
:return: 邮箱和密码,或者cookie
|
||||
"""
|
||||
try:
|
||||
env = os.getenv("kmacg")
|
||||
if not env:
|
||||
logging.error("[检查环境变量]没有找到环境变量kmacg")
|
||||
return
|
||||
# 多个账号用换行分割
|
||||
envs = env.split('\n')
|
||||
for env in envs:
|
||||
if '&' in env:
|
||||
# 解析cookie字符串,提取邮箱和密码
|
||||
email, password = env.split('&')
|
||||
yield email, password, None
|
||||
else:
|
||||
# 直接使用cookie
|
||||
yield None, None, env
|
||||
except Exception as e:
|
||||
logging.error(f"[检查环境变量]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
raise
|
||||
|
||||
def get_param(self, host, session):
|
||||
"""
|
||||
获取参数
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: formhash, seccodehash, loginhash
|
||||
"""
|
||||
try:
|
||||
# 访问首页
|
||||
url = f"https://{host}/member.php?mod=logging&action=login"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
# 使用正则表达式匹配
|
||||
# formhash 格式: name="formhash" value="5448b1bc"
|
||||
pattern = r'name="formhash" value="([a-zA-Z0-9]{8})"'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
formhash = match.group(1)
|
||||
else:
|
||||
logging.error("[获取formhash]无法获取formhash")
|
||||
return None, None, None
|
||||
# # seccodehash 格式: seccode_cSAbDg cSAbDg
|
||||
# pattern = r'seccode_([a-zA-Z0-9]{6})'
|
||||
# match = re.search(pattern, response.text)
|
||||
# if match:
|
||||
# seccodehash = match.group(1)
|
||||
# else:
|
||||
# logging.error("[获取seccodehash]无法获取seccodehash")
|
||||
# return None, None, None
|
||||
# loginhash 格式: main_messaqge_LCpo4 LCpo4
|
||||
seccodehash = 'test'
|
||||
pattern = r'main_messaqge_([a-zA-Z0-9]{5})'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
loginhash = match.group(1)
|
||||
else:
|
||||
logging.error("[获取loginhash]无法获取loginhash")
|
||||
return None, None, None
|
||||
return formhash, seccodehash, loginhash
|
||||
except requests.RequestException as e:
|
||||
logging.warning(f"[获取参数]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None, None, None
|
||||
except Exception as e:
|
||||
logging.error(f"[获取参数]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None, None, None
|
||||
|
||||
def get_captcha_img(self, host, seccodehash, session):
|
||||
"""
|
||||
获取验证码图片
|
||||
:param host: 域名
|
||||
:param seccodehash: seccodehash
|
||||
:param session: 会话对象
|
||||
:return: 验证码图片
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/misc.php?mod=seccode&update={random.randint(10000, 99999)}&idhash={seccodehash}"
|
||||
headers = {
|
||||
'referer': f'https://{host}/member.php?mod=logging&action=login',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
# 图片转为base64
|
||||
img_base64 = base64.b64encode(response.content).decode('utf-8')
|
||||
return img_base64
|
||||
except Exception as e:
|
||||
logging.error(f"[获取验证码图片]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def get_captcha_text(self, img_base64):
|
||||
"""
|
||||
获取验证码文字
|
||||
:param img_base64: 验证码base64
|
||||
:return: 验证码文字
|
||||
"""
|
||||
try:
|
||||
url = DDDD_OCR_URL
|
||||
payload = {
|
||||
'image': img_base64
|
||||
}
|
||||
response = requests.post(url, data=payload).json()
|
||||
if response['code'] == 200:
|
||||
return response['data']
|
||||
else:
|
||||
logging.error(f"[获取验证码]发生错误: {response['message']}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f"[获取验证码]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def check_captcha(self, host, captcha, session, seccodehash):
|
||||
"""
|
||||
检查验证码
|
||||
:param host: 域名
|
||||
:param captcha: 验证码文字
|
||||
:param session: 会话对象
|
||||
:param seccodehash: seccodehash
|
||||
:return: 是否正确
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/misc.php?mod=seccode&action=check&inajax=1&modid=member::logging&idhash={seccodehash}&secverify={captcha}"
|
||||
headers = {
|
||||
'referer': f'https://{host}/member.php?mod=logging&action=login',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
pattern = r'<!\[CDATA\[(.*?)\]\]>'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
text = match.group(1)
|
||||
if "succeed" in text:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
logging.warning("[检查验证码]响应格式异常")
|
||||
return False
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[检查验证码]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logging.error(f"[检查验证码]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def login_in(self, host, username, password, formhash, captcha, session, loginhash, seccodehash):
|
||||
"""
|
||||
登录
|
||||
:param host: 域名
|
||||
:param username: 邮箱
|
||||
:param password: 密码
|
||||
:param formhash: formhash
|
||||
:param captcha: 验证码文字
|
||||
:param session: 会话对象
|
||||
:param loginhash: loginhash
|
||||
:param seccodehash: seccodehash
|
||||
:return: 是否成功
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/member.php?mod=logging&action=login&loginsubmit=yes&loginhash={loginhash}&inajax=1"
|
||||
payload = f"formhash={formhash}&referer=https://{host}/home.php?mod=spacecp&ac=credit&showcredit=1&loginfield=email&username={username}&password={password}&questionid=0&answer=&seccodehash={seccodehash}&seccodemodid=member::logging&seccodeverify={captcha}&cookietime=2592000"
|
||||
headers = {
|
||||
'Referer': f'https://{host}/home.php?mod=spacecp&ac=credit&showcredit=1',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
# payload转为url编码,/替换为%2F
|
||||
payload = urllib.parse.quote(payload, safe='=&')
|
||||
response = session.post(url, headers=headers, data=payload)
|
||||
response.raise_for_status()
|
||||
pattern = r'<!\[CDATA\[(.*?)\]\]>'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
text = match.group(1)
|
||||
if "欢迎您回来" in text:
|
||||
# 匹配
|
||||
username_pattern = r'欢迎您回来,(.*?),现在将转入登录前页面'
|
||||
username_match = re.search(username_pattern, text)
|
||||
if username_match:
|
||||
matched_username = username_match.group(1)
|
||||
logging.info(f"[登录]成功,当前账号: {matched_username}")
|
||||
return True
|
||||
else:
|
||||
logging.warning("[登录]登录失败")
|
||||
return False
|
||||
else:
|
||||
logging.warning("[登录]响应格式异常")
|
||||
return False
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[登录]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logging.error(f"[登录]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def get_sign_hash(self, host, session):
|
||||
"""
|
||||
获取签到hash
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: 签到hash
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/dsu_paulsign-sign.html"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
pattern = r'formhash=([a-zA-Z0-9]{8})'
|
||||
match = re.search(pattern, response.text)
|
||||
if match:
|
||||
formhash = match.group(1)
|
||||
return formhash
|
||||
else:
|
||||
logging.warning("[获取签到hash]无法获取签到hash")
|
||||
return None
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[获取签到hash]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def get_sign_result(self, html):
|
||||
"""
|
||||
获取签到结果
|
||||
:param html: 签到结果
|
||||
:return: 签到结果
|
||||
"""
|
||||
# 提取CDATA中的HTML内容
|
||||
start_cdata = html.find('<![CDATA[') + len('<![CDATA[')
|
||||
end_cdata = html.find(']]>')
|
||||
html_content = html[start_cdata:end_cdata]
|
||||
soup = BeautifulSoup(html_content, 'html.parser')
|
||||
sign_res = soup.find('div', class_='c')
|
||||
if sign_res:
|
||||
return sign_res.text.strip()
|
||||
else:
|
||||
return None
|
||||
|
||||
def signin(self, host, session, sign_hash):
|
||||
"""
|
||||
签到
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:param sign_hash: 签到hash
|
||||
"""
|
||||
try:
|
||||
if not sign_hash:
|
||||
logging.error("sign_hash为空,无法进行签到")
|
||||
return
|
||||
|
||||
url = f"https://{host}/plugin.php?id=dsu_paulsign:sign&operation=qiandao&infloat=1&inajax=1"
|
||||
payload = f"formhash={sign_hash}&qdxq=ym&qdmode=2&todaysay=&fastreply=0"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host,
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Referer': f'https://{host}/dsu_paulsign-sign.html'
|
||||
}
|
||||
response = session.post(url, headers=headers, data=payload)
|
||||
response.raise_for_status()
|
||||
sign_result = self.get_sign_result(response.text)
|
||||
logging.info(f"[签到]签到结果: {sign_result}")
|
||||
except requests.RequestException as e:
|
||||
logging.error(f"[签到]发生网络错误: {str(e)}\n{traceback.format_exc()}")
|
||||
except Exception as e:
|
||||
logging.error(f"[签到]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
def do_task(self, host, session):
|
||||
"""
|
||||
执行任务
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
"""
|
||||
try:
|
||||
sign_hash = self.get_sign_hash(host, session)
|
||||
if sign_hash:
|
||||
self.signin(host, session, sign_hash)
|
||||
except Exception as e:
|
||||
logging.error(f"[执行任务]发生未知错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
def read_cookie_file(self):
|
||||
"""
|
||||
读取cookie文件
|
||||
:return: cookie字符串或None
|
||||
"""
|
||||
try:
|
||||
if os.path.exists(self.cookie_file):
|
||||
with open(self.cookie_file, 'r', encoding='utf-8') as f:
|
||||
cookie_data = json.load(f)
|
||||
if cookie_data.get('accounts'):
|
||||
logging.info(f"[读取Cookie文件]成功读取{self.cookie_file}")
|
||||
return cookie_data['accounts']
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f"[读取Cookie文件]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def write_cookie_file(self, cookies, email=None):
|
||||
"""
|
||||
写入cookie文件
|
||||
:param cookies: cookie字符串
|
||||
:param email: 账号邮箱,用于标识不同账号
|
||||
"""
|
||||
try:
|
||||
# 读取现有cookie文件
|
||||
existing_data = {}
|
||||
if os.path.exists(self.cookie_file):
|
||||
with open(self.cookie_file, 'r', encoding='utf-8') as f:
|
||||
existing_data = json.load(f)
|
||||
|
||||
# 准备新的cookie数据
|
||||
cookie_data = {
|
||||
'site_name': self.site_name,
|
||||
'host': DEFAULT_HOST,
|
||||
'accounts': existing_data.get('accounts', {}),
|
||||
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
# 更新或添加账号cookie
|
||||
if email:
|
||||
cookie_data['accounts'][email] = {
|
||||
'cookies': cookies,
|
||||
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
else:
|
||||
# 如果没有提供email,使用默认键
|
||||
cookie_data['accounts']['default'] = {
|
||||
'cookies': cookies,
|
||||
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
with open(self.cookie_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(cookie_data, f, ensure_ascii=False, indent=2)
|
||||
logging.info(f"[写入Cookie文件]成功写入{self.cookie_file}")
|
||||
except Exception as e:
|
||||
logging.error(f"[写入Cookie文件]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
def get_session_cookies(self, session):
|
||||
"""
|
||||
获取session的cookies字符串
|
||||
:param session: 会话对象
|
||||
:return: cookie字符串
|
||||
"""
|
||||
try:
|
||||
cookies = []
|
||||
for cookie in session.cookies:
|
||||
cookies.append(f"{cookie.name}={cookie.value}")
|
||||
return '; '.join(cookies)
|
||||
except Exception as e:
|
||||
logging.error(f"[获取Session Cookies]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return None
|
||||
|
||||
def check_cookie_valid(self, host, session):
|
||||
"""
|
||||
检查cookie是否有效
|
||||
:param host: 域名
|
||||
:param session: 会话对象
|
||||
:return: 是否有效
|
||||
"""
|
||||
try:
|
||||
url = f"https://{host}/home.php?mod=space"
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0',
|
||||
'Host': host
|
||||
}
|
||||
response = session.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
if "请先登录" in response.text:
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
logging.error(f"[Cookie检测]发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
执行签到任务的主函数
|
||||
"""
|
||||
try:
|
||||
logging.info(f"【{self.site_name}】开始执行签到任务")
|
||||
|
||||
# 首先尝试读取cookie文件
|
||||
accounts = self.read_cookie_file()
|
||||
if accounts:
|
||||
logging.info("[Cookie文件]检测到cookie文件,将尝试使用")
|
||||
for email, account_data in accounts.items():
|
||||
session = requests.Session()
|
||||
for cookie_item in account_data['cookies'].split(';'):
|
||||
key, value = cookie_item.split('=', 1)
|
||||
session.cookies.set(key.strip(), value.strip())
|
||||
|
||||
# 检查cookie是否有效
|
||||
if self.check_cookie_valid(DEFAULT_HOST, session):
|
||||
logging.info("")
|
||||
logging.info(f"[Cookie检测]账号 {email} 的Cookie有效")
|
||||
# 执行签到任务
|
||||
self.do_task(DEFAULT_HOST, session)
|
||||
logging.info("")
|
||||
# 如果是最后一个账号,执行return
|
||||
if email == list(accounts.keys())[-1]:
|
||||
return
|
||||
else:
|
||||
logging.warning(f"[Cookie文件]账号 {email} 的Cookie已失效")
|
||||
|
||||
logging.info("[Cookie文件]所有账号的Cookie都已失效,尝试使用邮箱密码登录")
|
||||
# 检查环境变量中是否有邮箱密码
|
||||
env = os.getenv("kmacg")
|
||||
if not env or '&' not in env:
|
||||
logging.error("[Cookie文件]所有Cookie已失效且环境变量中未找到邮箱密码,无法继续")
|
||||
return
|
||||
# 删除失效的cookie文件
|
||||
try:
|
||||
os.remove(self.cookie_file)
|
||||
logging.info(f"[Cookie文件]已删除失效的cookie文件: {self.cookie_file}")
|
||||
except Exception as e:
|
||||
logging.error(f"[Cookie文件]删除失效cookie文件失败: {str(e)}")
|
||||
|
||||
host = DEFAULT_HOST
|
||||
for index, (email, password, cookie) in enumerate(self.check_env(), 1):
|
||||
logging.info("")
|
||||
logging.info(f"------【账号{index}】开始执行任务------")
|
||||
|
||||
# 创建会话
|
||||
session = requests.Session()
|
||||
|
||||
if cookie:
|
||||
# 直接使用cookie
|
||||
logging.info(f"[检查环境变量]检测到cookie,将直接使用并保存到文件")
|
||||
for cookie_item in cookie.split(';'):
|
||||
key, value = cookie_item.split('=', 1)
|
||||
session.cookies.set(key.strip(), value.strip())
|
||||
self.write_cookie_file(cookie, email)
|
||||
|
||||
# 检查cookie是否有效
|
||||
if self.check_cookie_valid(host, session):
|
||||
logging.info(f"[Cookie]账号 {email} 的Cookie有效")
|
||||
# 执行签到任务
|
||||
self.do_task(host, session)
|
||||
return
|
||||
else:
|
||||
logging.warning(f"[Cookie]账号 {email} 的Cookie已失效")
|
||||
continue
|
||||
else:
|
||||
logging.info(f"[检查环境变量]检测到邮箱密码,将进行登录")
|
||||
# 获取参数
|
||||
formhash, seccodehash, loginhash = self.get_param(host, session)
|
||||
if not all([formhash, seccodehash, loginhash]):
|
||||
logging.error("获取参数失败,跳过当前账号")
|
||||
continue
|
||||
|
||||
# 验证码重试逻辑
|
||||
max_retries = 3
|
||||
retry_count = 0
|
||||
while retry_count < max_retries:
|
||||
login_in_captcha = self.get_captcha_img(host, seccodehash, session)
|
||||
login_in_captcha_text = self.get_captcha_text(login_in_captcha)
|
||||
if self.check_captcha(host, login_in_captcha_text, session, seccodehash):
|
||||
break
|
||||
|
||||
retry_count += 1
|
||||
if retry_count < max_retries:
|
||||
logging.warning(f"[验证码]验证失败,第{retry_count}次重试")
|
||||
time.sleep(5)
|
||||
else:
|
||||
logging.error("[验证码]验证失败,已达到最大重试次数")
|
||||
continue
|
||||
|
||||
if not self.login_in(host, email, password, formhash, login_in_captcha_text, session, loginhash, seccodehash):
|
||||
logging.error("登录失败,跳过当前账号")
|
||||
continue
|
||||
|
||||
# 登录成功后保存cookie到文件
|
||||
cookies = self.get_session_cookies(session)
|
||||
if cookies:
|
||||
self.write_cookie_file(cookies, email)
|
||||
|
||||
# 登录成功后执行签到任务
|
||||
self.do_task(host, session)
|
||||
|
||||
logging.info(f"------【账号{index}】执行任务完成------")
|
||||
logging.info("")
|
||||
except Exception as e:
|
||||
logging.error(f"【{self.site_name}】执行过程中发生错误: {str(e)}\n{traceback.format_exc()}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
auto_task = AutoTask("快萌论坛")
|
||||
auto_task.run()
|
||||
512
脚本库/web版/账密/新电信抢话费/2025-07-19_7月1日0点权益_836d9038.py
Normal file
512
脚本库/web版/账密/新电信抢话费/2025-07-19_7月1日0点权益_836d9038.py
Normal file
@@ -0,0 +1,512 @@
|
||||
# Source: https://gitee.com/jdqlscript/yyt/blob/master/%E7%94%B5%E4%BF%A1/7%E6%9C%881%E6%97%A50%E7%82%B9%E6%9D%83%E7%9B%8A.py
|
||||
# Raw: https://gitee.com/jdqlscript/yyt/raw/master/%E7%94%B5%E4%BF%A1/7%E6%9C%881%E6%97%A50%E7%82%B9%E6%9D%83%E7%9B%8A.py
|
||||
# Repo: jdqlscript/yyt
|
||||
# Path: 电信/7月1日0点权益.py
|
||||
# UploadedAt: 2025-07-19T22:58:22+08:00
|
||||
# SHA256: 836d9038a2cd640748364a75830ebfa3c3871d8b00292d32f96f4436a90e55f3
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
新电信抢话费
|
||||
|
||||
群里发的,未测试好,自测
|
||||
修改内容如下“
|
||||
1.删除内置的一个手机账号
|
||||
2.修改环境变量名保持和拉菲电信金豆本环境变量一致
|
||||
3.恢复瑞数通杀.js调用地址,确实也不知道是啥。398、399行注释
|
||||
|
||||
环境变量chinaTelecomAccount,值为:账号#密码
|
||||
|
||||
cron: 57 9,13,23 * * *
|
||||
const $ = new Env("新电信抢话费");
|
||||
|
||||
"""
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import ssl
|
||||
import time
|
||||
import json
|
||||
import execjs
|
||||
import base64
|
||||
import random
|
||||
import certifi
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import certifi
|
||||
import datetime
|
||||
import requests
|
||||
import binascii
|
||||
from lxml import etree
|
||||
from http import cookiejar
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Cipher import DES3
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import PKCS1_v1_5
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
from aiohttp import ClientSession, TCPConnector
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
import subprocess
|
||||
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
import _locale
|
||||
_locale._getdefaultlocale = (lambda *args: ['zh_CN', 'utf8'])
|
||||
|
||||
run_num=os.environ.get('reqNUM') or "1"
|
||||
|
||||
MAX_RETRIES = 3
|
||||
RATE_LIMIT = 10 # 每秒请求数限制
|
||||
|
||||
class RateLimiter:
|
||||
def __init__(self, rate_limit):
|
||||
self.rate_limit = rate_limit
|
||||
self.tokens = rate_limit
|
||||
self.updated_at = time.monotonic()
|
||||
|
||||
async def acquire(self):
|
||||
while self.tokens < 1:
|
||||
self.add_new_tokens()
|
||||
await asyncio.sleep(0.1)
|
||||
self.tokens -= 1
|
||||
|
||||
def add_new_tokens(self):
|
||||
now = time.monotonic()
|
||||
time_since_update = now - self.updated_at
|
||||
new_tokens = time_since_update * self.rate_limit
|
||||
if new_tokens > 1:
|
||||
self.tokens = min(self.tokens + new_tokens, self.rate_limit)
|
||||
self.updated_at = now
|
||||
|
||||
class AsyncSessionManager:
|
||||
def __init__(self):
|
||||
self.session = None
|
||||
self.connector = None
|
||||
|
||||
async def __aenter__(self):
|
||||
ssl_context = ssl.create_default_context(cafile=certifi.where())
|
||||
ssl_context.set_ciphers('DEFAULT@SECLEVEL=1')
|
||||
self.connector = TCPConnector(ssl=ssl_context, limit=1000)
|
||||
self.session = ClientSession(connector=self.connector)
|
||||
return self.session
|
||||
|
||||
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
||||
await self.session.close()
|
||||
await self.connector.close()
|
||||
|
||||
async def retry_request(session, method, url, **kwargs):
|
||||
for attempt in range(MAX_RETRIES):
|
||||
try:
|
||||
await asyncio.sleep(1)
|
||||
async with session.request(method, url, **kwargs) as response:
|
||||
return await response.json()
|
||||
# return await response.json()
|
||||
|
||||
except (aiohttp.ClientConnectionError, aiohttp.ServerTimeoutError) as e:
|
||||
print(f"请求失败,第 {attempt + 1} 次重试: {e}")
|
||||
if attempt == MAX_RETRIES - 1:
|
||||
raise
|
||||
await asyncio.sleep(2 ** attempt)
|
||||
|
||||
class BlockAll(cookiejar.CookiePolicy):
|
||||
return_ok = set_ok = domain_return_ok = path_return_ok = lambda self, *args, **kwargs: False
|
||||
netscape = True
|
||||
rfc2965 = hide_cookie2 = False
|
||||
|
||||
def printn(m):
|
||||
current_time = datetime.datetime.now().strftime("%H:%M:%S.%f")[:-3]
|
||||
print(f'\n[{current_time}] {m}')
|
||||
|
||||
context = ssl.create_default_context()
|
||||
context.set_ciphers('DEFAULT@SECLEVEL=1') # 低安全级别0/1
|
||||
context.check_hostname = False # 禁用主机
|
||||
context.verify_mode = ssl.CERT_NONE # 禁用证书
|
||||
|
||||
class DESAdapter(requests.adapters.HTTPAdapter):
|
||||
def init_poolmanager(self, *args, **kwargs):
|
||||
kwargs['ssl_context'] = context
|
||||
return super().init_poolmanager(*args, **kwargs)
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
# urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
ss = requests.session()
|
||||
ss.headers={"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","Referer":"https://wapact.189.cn:9001/JinDouMall/JinDouMall_independentDetails.html"}
|
||||
ss.mount('https://', DESAdapter())
|
||||
ss.cookies.set_policy(BlockAll())
|
||||
runTime = 0
|
||||
key = b'1234567`90koiuyhgtfrdews'
|
||||
iv = 8 * b'\0'
|
||||
|
||||
public_key_b64 = '''-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBkLT15ThVgz6/NOl6s8GNPofdWzWbCkWnkaAm7O2LjkM1H7dMvzkiqdxU02jamGRHLX/ZNMCXHnPcW/sDhiFCBN18qFvy8g6VYb9QtroI09e176s+ZCtiv7hbin2cCTj99iUpnEloZm19lwHyo69u5UMiPMpq0/XKBO8lYhN/gwIDAQAB
|
||||
-----END PUBLIC KEY-----'''
|
||||
|
||||
public_key_data = '''-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+ugG5A8cZ3FqUKDwM57GM4io6JGcStivT8UdGt67PEOihLZTw3P7371+N47PrmsCpnTRzbTgcupKtUv8ImZalYk65dU8rjC/ridwhw9ffW2LBwvkEnDkkKKRi2liWIItDftJVBiWOh17o6gfbPoNrWORcAdcbpk2L+udld5kZNwIDAQAB
|
||||
-----END PUBLIC KEY-----'''
|
||||
|
||||
def get_first_three(value):
|
||||
# 处理数字情况
|
||||
if isinstance(value, (int, float)):
|
||||
return int(str(value)[:3])
|
||||
elif isinstance(value, str):
|
||||
return str(value)[:3]
|
||||
else:
|
||||
raise TypeError("error")
|
||||
|
||||
def run_Time(hour,miute,second):
|
||||
date = datetime.datetime.now()
|
||||
date_zero = datetime.datetime.now().replace(year=date.year, month=date.month, day=date.day, hour=hour, minute=miute, second=second)
|
||||
date_zero_time = int(time.mktime(date_zero.timetuple()))
|
||||
return date_zero_time
|
||||
|
||||
def encrypt(text):
|
||||
cipher = DES3.new(key, DES3.MODE_CBC, iv)
|
||||
ciphertext = cipher.encrypt(pad(text.encode(), DES3.block_size))
|
||||
return ciphertext.hex()
|
||||
|
||||
def decrypt(text):
|
||||
ciphertext = bytes.fromhex(text)
|
||||
cipher = DES3.new(key, DES3.MODE_CBC, iv)
|
||||
plaintext = unpad(cipher.decrypt(ciphertext), DES3.block_size)
|
||||
return plaintext.decode()
|
||||
|
||||
def b64(plaintext):
|
||||
public_key = RSA.import_key(public_key_b64)
|
||||
cipher = PKCS1_v1_5.new(public_key)
|
||||
ciphertext = cipher.encrypt(plaintext.encode())
|
||||
return base64.b64encode(ciphertext).decode()
|
||||
|
||||
def encrypt_para(plaintext):
|
||||
if not isinstance(plaintext, str):
|
||||
plaintext = json.dumps(plaintext)
|
||||
public_key = RSA.import_key(public_key_data)
|
||||
cipher = PKCS1_v1_5.new(public_key)
|
||||
ciphertext = cipher.encrypt(plaintext.encode())
|
||||
return binascii.hexlify(ciphertext).decode()
|
||||
|
||||
def encrypt_paraNew(p):
|
||||
k = RSA.import_key(public_key_data)
|
||||
c = PKCS1_v1_5.new(k)
|
||||
s = k.size_in_bytes() - 11
|
||||
d = p.encode() if isinstance(p, str) else json.dumps(p).encode()
|
||||
return binascii.hexlify(b''.join(c.encrypt(d[i:i+s]) for i in range(0, len(d), s))).decode()
|
||||
|
||||
def encode_phone(text):
|
||||
encoded_chars = []
|
||||
for char in text:
|
||||
encoded_chars.append(chr(ord(char) + 2))
|
||||
return ''.join(encoded_chars)
|
||||
|
||||
|
||||
def getApiTime(api_url):
|
||||
try:
|
||||
with requests.get(api_url) as response:
|
||||
if(not response or not response.text):
|
||||
return time.time()
|
||||
json_data = json.loads(response.text)
|
||||
if (json_data.get("api")and json_data.get("api")not in("time") ):
|
||||
timestamp_str = json_data.get('data', {}).get('t', '')
|
||||
else:
|
||||
timestamp_str = json_data.get('currentTime', {})
|
||||
timestamp = int(timestamp_str) / 1000.0 # 将毫秒转为秒
|
||||
difftime=time.time()-timestamp
|
||||
return difftime;
|
||||
except Exception as e:
|
||||
print(f"获取时间失败: {e}")
|
||||
return 0;
|
||||
|
||||
|
||||
def userLoginNormal(phone,password):
|
||||
alphabet = 'abcdef0123456789'
|
||||
uuid = [''.join(random.sample(alphabet, 8)),''.join(random.sample(alphabet, 4)),'4'+''.join(random.sample(alphabet, 3)),''.join(random.sample(alphabet, 4)),''.join(random.sample(alphabet, 12))]
|
||||
timestamp=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
loginAuthCipherAsymmertric = 'iPhone 14 15.4.' + uuid[0] + uuid[1] + phone + timestamp + password[:6] + '0$$$0.'
|
||||
#r = ss.post('https://appgologin.189.cn:9031/login/client/userLoginNormal',json={"headerInfos": {"code": "userLoginNormal", "timestamp": timestamp, "broadAccount": "", "broadToken": "", "clientType": "#9.6.1#channel50#iPhone 14 Pro Max#", "shopId": "20002", "source": "110003", "sourcePassword": "Sid98s", "token": "", "userLoginName": phone}, "content": {"attach": "test", "fieldData": {"loginType": "4", "accountType": "", "loginAuthCipherAsymmertric": b64(loginAuthCipherAsymmertric), "deviceUid": uuid[0] + uuid[1] + uuid[2], "phoneNum": encode_phone(phone), "isChinatelecom": "0", "systemVersion": "15.4.0", "authentication": password}}},verify=certifi.where()).json()
|
||||
r = ss.post('https://appgologin.189.cn:9031/login/client/userLoginNormal',json={"headerInfos": {"code": "userLoginNormal", "timestamp": timestamp, "broadAccount": "", "broadToken": "", "clientType": "#11.3.0#channel35#Xiaomi Redmi K30 Pro#", "shopId": "20002", "source": "110003", "sourcePassword": "Sid98s", "token": "", "userLoginName": encode_phone(phone)}, "content": {"attach": "test", "fieldData": {"loginType": "4", "accountType": "", "loginAuthCipherAsymmertric": b64(loginAuthCipherAsymmertric), "deviceUid": uuid[0] + uuid[1] + uuid[2], "phoneNum": encode_phone(phone), "isChinatelecom": "0", "systemVersion": "12", "authentication": encode_phone(password)}}},verify=certifi.where()).json()
|
||||
l = r['responseData']['data']['loginSuccessResult']
|
||||
if l:
|
||||
ticket = get_ticket(phone,l['userId'],l['token'])
|
||||
return ticket
|
||||
return False
|
||||
|
||||
async def exchangeForDay(phone, session, run_num, rid, stime, accId):
|
||||
async def delayed_conversion(delay):
|
||||
await asyncio.sleep(delay)
|
||||
await conversionRights(phone, rid, session, accId)
|
||||
tasks = [asyncio.create_task(delayed_conversion(i * stime)) for i in range(int(run_num))]
|
||||
await asyncio.gather(*tasks)
|
||||
def get_ticket(phone,userId,token):
|
||||
r = ss.post('https://appgologin.189.cn:9031/map/clientXML',data='<Request><HeaderInfos><Code>getSingle</Code><Timestamp>'+datetime.datetime.now().strftime("%Y%m%d%H%M%S")+'</Timestamp><BroadAccount></BroadAccount><BroadToken></BroadToken><ClientType>#9.6.1#channel50#iPhone 14 Pro Max#</ClientType><ShopId>20002</ShopId><Source>110003</Source><SourcePassword>Sid98s</SourcePassword><Token>'+token+'</Token><UserLoginName>'+phone+'</UserLoginName></HeaderInfos><Content><Attach>test</Attach><FieldData><TargetId>'+encrypt(userId)+'</TargetId><Url>4a6862274835b451</Url></FieldData></Content></Request>',headers={'user-agent': 'CtClient;10.4.1;Android;13;22081212C;NTQzNzgx!#!MTgwNTg1'},verify=certifi.where())
|
||||
tk = re.findall('<Ticket>(.*?)</Ticket>',r.text)
|
||||
if len(tk) == 0:
|
||||
return False
|
||||
return decrypt(tk[0])
|
||||
|
||||
async def exchange(s, phone, title, rid,jsexec, ckvalue):
|
||||
try:
|
||||
url="https://wapact.189.cn:9001/gateway/standExchange/detailNew/exchange"
|
||||
|
||||
get_url = await asyncio.to_thread(jsexec.call,"getUrl", "POST",url)
|
||||
async with s.post(get_url, cookies=ckvalue, json={"activityId": rid}) as response:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
|
||||
async def check(s,item,ckvalue):
|
||||
checkGoods = s.get('https://wapact.189.cn:9001/gateway/stand/detailNew/check?activityId=' + item, cookies=ckvalue).json()
|
||||
return checkGoods
|
||||
|
||||
async def conversionRights(phone, rid, session, accId):
|
||||
try:
|
||||
# 获取 Ruishu cookies
|
||||
ruishu_cookies = get_ruishu_cookies()
|
||||
if not ruishu_cookies:
|
||||
print(f"{get_first_three(phone)}: 无法获取 Ruishu cookies")
|
||||
return
|
||||
|
||||
value = {
|
||||
"id": rid,
|
||||
"accId": accId,
|
||||
"showType": "9003",
|
||||
"showEffect": "8",
|
||||
"czValue": "0"
|
||||
}
|
||||
paraV = encrypt_paraNew(value)
|
||||
|
||||
printn(f"{get_first_three(phone)}:开始兑换")
|
||||
|
||||
# 使用 Ruishu cookies 发送请求
|
||||
response = session.post(
|
||||
'https://wappark.189.cn/jt-sign/paradise/receiverRights',
|
||||
json={"para": paraV},
|
||||
cookies=ruishu_cookies
|
||||
)
|
||||
|
||||
login = response.json()
|
||||
printn(f"{get_first_three(phone)}:{login}")
|
||||
|
||||
if '兑换成功' in response.text:
|
||||
QLAPI.notify(get_first_three(phone), login['resoultMsg'])
|
||||
exit(0)
|
||||
|
||||
except Exception as e:
|
||||
printn(f"{get_first_three(phone)}: 兑换请求发生错误: {str(e)}")
|
||||
# 可以选择是否在这里添加重试逻辑
|
||||
|
||||
async def getLevelRightsList(phone, session, accId):
|
||||
try:
|
||||
# 获取 Ruishu cookies
|
||||
ruishu_cookies = get_ruishu_cookies()
|
||||
if not ruishu_cookies:
|
||||
print("无法获取 Ruishu cookies")
|
||||
return None
|
||||
|
||||
value = {
|
||||
"type": "hg_qd_djqydh",
|
||||
"accId": accId,
|
||||
"shopId": "20001"
|
||||
}
|
||||
paraV = encrypt_paraNew(value)
|
||||
|
||||
# 使用 Ruishu cookies 发送请求
|
||||
response = session.post(
|
||||
'https://wappark.189.cn/jt-sign/paradise/queryLevelRightInfo',
|
||||
json={"para": paraV},
|
||||
cookies=ruishu_cookies
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
if data.get('code') == 401:
|
||||
print(f"获取失败:{data},原因大概是sign过期了")
|
||||
return None
|
||||
|
||||
current_level = int(data['currentLevel'])
|
||||
key_name = 'V' + str(current_level)
|
||||
ids = [item['activityId'] for item in data.get(key_name, []) if '话费' in item.get('title',"")]
|
||||
return ids
|
||||
|
||||
except Exception as e:
|
||||
print(f"获取失败,重试一次: {str(e)}")
|
||||
try:
|
||||
# 重试时重新获取 Ruishu cookies
|
||||
ruishu_cookies = get_ruishu_cookies()
|
||||
if not ruishu_cookies:
|
||||
print("重试时无法获取 Ruishu cookies")
|
||||
return None
|
||||
|
||||
paraV = encrypt_para(value)
|
||||
response = session.post(
|
||||
'https://wappark.189.cn/jt-sign/paradise/getLevelRightsList',
|
||||
json={"para": paraV},
|
||||
cookies=ruishu_cookies
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
if data.get('code') == 401:
|
||||
print(f"重试获取失败:{data},原因大概是sign过期了")
|
||||
return None
|
||||
|
||||
current_level = int(data['currentLevel'])
|
||||
key_name = 'V' + str(current_level)
|
||||
ids = [item['activityId'] for item in data.get(key_name, []) if '话费' in item.get('title',"")]
|
||||
return ids
|
||||
|
||||
except Exception as e:
|
||||
print(f"重试也失败了: {str(e)}")
|
||||
return None
|
||||
|
||||
def get_ruishu_cookies():
|
||||
try:
|
||||
# 获取当前文件所在目录
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ruishu_path = os.path.join(current_dir, 'Ruishu.py')
|
||||
|
||||
# 执行 Ruishu.py 并获取输出
|
||||
result = subprocess.run([sys.executable, ruishu_path],
|
||||
capture_output=True,
|
||||
text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
print(f"Ruishu.py 执行错误: {result.stderr}")
|
||||
return None
|
||||
|
||||
# 解析输出的 JSON
|
||||
cookies = json.loads(result.stdout.strip())
|
||||
return cookies
|
||||
|
||||
except Exception as e:
|
||||
print(f"获取 Ruishu cookies 时发生错误: {str(e)}")
|
||||
return None
|
||||
|
||||
async def getSign(ticket, session):
|
||||
try:
|
||||
# 获取 Ruishu cookies
|
||||
ruishu_cookies = get_ruishu_cookies()
|
||||
if not ruishu_cookies:
|
||||
print("无法获取 Ruishu cookies")
|
||||
return None
|
||||
|
||||
# 合并现有的 cookies 和 Ruishu cookies
|
||||
cookies = {**ruishu_cookies}
|
||||
|
||||
# 使用合并后的 cookies 发送请求
|
||||
response = session.get(
|
||||
'https://wappark.189.cn/jt-sign/ssoHomLogin?ticket=' + ticket,
|
||||
cookies=cookies,headers = {'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"}
|
||||
).json()
|
||||
|
||||
if response.get('resoultCode') == '0':
|
||||
sign = response.get('sign')
|
||||
accId = response.get('accId')
|
||||
return sign ,accId
|
||||
else:
|
||||
print(f"获取sign失败[{response.get('resoultCode')}]: {response}")
|
||||
except Exception as e:
|
||||
print(f"getSign 发生错误: {str(e)}")
|
||||
return None
|
||||
|
||||
async def qgNight(phone, ticket, timeDiff,isTrue):
|
||||
if isTrue:
|
||||
runTime = run_Time(23,59,3)
|
||||
else:
|
||||
# runTime = run_Time(0,0,0) + 0.65
|
||||
runTime = 0
|
||||
|
||||
if runTime >(time.time()+timeDiff):
|
||||
difftime = runTime - time.time() - timeDiff
|
||||
print(f"当前时间:{str(datetime.datetime.now())[11:23]},跟设定的时间不同,等待{difftime}秒开始兑换每天一次的")
|
||||
await asyncio.sleep(difftime)
|
||||
session = requests.Session()
|
||||
session.mount('https://', DESAdapter())
|
||||
session.verify = False # 禁用证书验证
|
||||
signx =await getSign(ticket,session)
|
||||
sign =signx[0]
|
||||
accId =signx[1]
|
||||
if sign:
|
||||
# print(f"当前时间:{str(datetime.datetime.now())[11:23]}获取到了Sign:"+sign)
|
||||
session.headers={"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","sign":sign}
|
||||
else:
|
||||
print("未获取sign。")
|
||||
return
|
||||
rightsId =await getLevelRightsList(phone,session,accId)
|
||||
if rightsId:
|
||||
print("获取到了rightsId:"+rightsId[0])
|
||||
else:
|
||||
print("未能获取rightsId。")
|
||||
return
|
||||
# await asyncio.sleep(10)直接延迟也行,或者用下面的等待一段时间。之所以这样是要先获取sign省一些步骤。
|
||||
if isTrue:
|
||||
runTime2 = run_Time(23,59,59) + 0.3
|
||||
difftime = runTime2 - time.time() - timeDiff
|
||||
printn(f"等待{difftime}s")
|
||||
await asyncio.sleep(difftime)
|
||||
await exchangeForDay(phone,session,run_num,rightsId[0],0.1,accId)
|
||||
async def qgDay(phone, ticket, timeDiff, isTrue):
|
||||
async with AsyncSessionManager() as s:
|
||||
pass
|
||||
async def main(timeDiff,isTRUE,hour):
|
||||
tasks = []
|
||||
PHONES=os.environ.get('chinaTelecomAccount')
|
||||
phone_list = PHONES.split('&')
|
||||
for phoneV in phone_list:
|
||||
value = phoneV.split('#')
|
||||
phone, password = value[0], value[1]
|
||||
printn(f'{get_first_three(phone)}开始登录')
|
||||
|
||||
# 添加重试逻辑
|
||||
max_retries = 3
|
||||
retry_count = 0
|
||||
ticket = None
|
||||
|
||||
while retry_count < max_retries and not ticket:
|
||||
ticket = userLoginNormal(phone,password)
|
||||
if not ticket:
|
||||
printn(f'{get_first_three(phone)} 第{retry_count+1}次登录失败,准备重试')
|
||||
retry_count += 1
|
||||
await asyncio.sleep(1) # 添加1秒延迟避免频繁请求
|
||||
|
||||
if ticket:
|
||||
# hour=datetime.datetime.now().hour
|
||||
# hour=23
|
||||
if hour > 15:
|
||||
tasks.append(qgNight(phone, ticket, timeDiff, isTRUE))
|
||||
else: #十点//十四点场次
|
||||
tasks.append(qgNight(phone, ticket, timeDiff, isTRUE))
|
||||
else:
|
||||
printn(f'{get_first_three(phone)} 登录失败,已达最大重试次数{max_retries}次')
|
||||
|
||||
await asyncio.gather(*tasks)
|
||||
|
||||
if __name__ == "__main__":
|
||||
h = datetime.datetime.now().hour
|
||||
#h=20 #手动设置场次的时间
|
||||
print("当前小时为: "+str(h))
|
||||
if 10 >h >0:
|
||||
print("当前小时为: "+str(h)+"已过0点但未到10点开始准备抢十点场次")
|
||||
wttime= run_Time(9,59,8) #抢十点场次
|
||||
elif 14 >= h >=10:
|
||||
print("当前小时为: "+str(h) +"已过10点但未到14点开始准备抢十四点场次")
|
||||
wttime= run_Time(13,59,8) #抢十四点场次
|
||||
else:
|
||||
print("当前小时为: "+str(h)+"已过14点开始准备抢凌晨")
|
||||
wttime= run_Time(23,58,58) #抢凌晨
|
||||
#isTRUE=False
|
||||
isTRUE=True
|
||||
#isTRUE等于False则表示忽略所有限制直接运行。这个参数一般用于测试。实际生产一定要设置为True。
|
||||
if(wttime >time.time()) :
|
||||
wTime=wttime-time.time()
|
||||
print("未到时间,计算后差异:"+str(wTime)+"秒")
|
||||
if isTRUE:
|
||||
print("一定要先测试,根据自身 设定的重发和多号,不然会出问题,抢购过早或者过晚。")
|
||||
print("开始等待:")
|
||||
time.sleep(wTime)
|
||||
# timeValue = getApiTime("https://f.m.suning.com/api/ct.do")
|
||||
timeValue = 0
|
||||
timeDiff = timeValue if timeValue > 0 else 0
|
||||
asyncio.run(main(timeDiff, isTRUE,h))
|
||||
print("所有任务都已执行完毕!")
|
||||
149
脚本库/web版/账密/机场签到/2025-10-28_机场签到_9f07b241.py
Normal file
149
脚本库/web版/账密/机场签到/2025-10-28_机场签到_9f07b241.py
Normal file
@@ -0,0 +1,149 @@
|
||||
# Source: https://github.com/NaroisCool/naro-scripts/blob/master/%E6%9C%BA%E5%9C%BA%E7%AD%BE%E5%88%B0.py
|
||||
# Raw: https://raw.githubusercontent.com/NaroisCool/naro-scripts/master/%E6%9C%BA%E5%9C%BA%E7%AD%BE%E5%88%B0.py
|
||||
# Repo: NaroisCool/naro-scripts
|
||||
# Path: 机场签到.py
|
||||
# UploadedAt: 2025-10-28T05:54:28+08:00
|
||||
# SHA256: 9f07b2418f8b79135f85915156e878e42ab114c82b05adae49df87fc6dbbf8f2
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
import json
|
||||
import os
|
||||
from urllib.parse import quote
|
||||
import httpx
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
import notify
|
||||
|
||||
"""
|
||||
百变小樱机场自动签到领流量
|
||||
机场注册地址☞ https://dash.bbxy.buzz/auth/register?code=G9we
|
||||
脚本执行要求安装python依赖bs4和httpx;填入变量BBXY_EMAIL(邮箱账号)和BBXY_PASSWORD(登录密码)
|
||||
感谢原作者Admsec,
|
||||
经NaroisCool改进,将从百变小樱官方永久地址发布网站(http://bbxy88.com/)上爬取最新的国内访问地址,以及其他方法内的逻辑改动。
|
||||
"""
|
||||
|
||||
|
||||
class BBXYSign:
|
||||
|
||||
def __init__(self):
|
||||
self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0"}
|
||||
self.session = httpx.Client()
|
||||
self.originUrl = ""
|
||||
self.loginUrl = ""
|
||||
self.email = os.environ.get("BBXY_EMAIL")
|
||||
self.password = os.environ.get("BBXY_PASSWORD")
|
||||
self.params = {"email": self.email, "passwd": self.password, "remember-me": '0'}
|
||||
self.signSuccessOrNot = False
|
||||
self.signSuccessMsg = ""
|
||||
|
||||
def check_websites_sync(self, websites):
|
||||
with httpx.Client(headers=self.headers) as client:
|
||||
print(f"总共{len(websites)}个网站")
|
||||
count = 1
|
||||
for site in websites:
|
||||
try:
|
||||
response = client.get(site)
|
||||
if response.status_code == 200 :
|
||||
print(f"这个链接可以访问,暂定:{site}")
|
||||
self.loginUrl = site + "/auth/login"
|
||||
self.originUrl = site
|
||||
#进行登录测试
|
||||
flag = self.login()
|
||||
if flag:
|
||||
print(f"这个链接可以登录,锁定:{site}")
|
||||
count = count +1
|
||||
if count>len(websites):
|
||||
notify.send('BBXY签到结果!','所有网站登录测试失败,请重新运行一遍!')
|
||||
return site
|
||||
else :
|
||||
print(f'登录失败,尝试下一个链接')
|
||||
print('-----------------')
|
||||
count = count +1
|
||||
if count>len(websites):
|
||||
notify.send('BBXY签到结果!','所有网站登录测试失败,请重新运行一遍!')
|
||||
continue
|
||||
except httpx.RequestError as e:
|
||||
print(f"这个链接不能用,避一避: {site} - {e}")
|
||||
print('-----------------')
|
||||
count = count +1
|
||||
if count>len(websites):
|
||||
notify.send('BBXY签到结果!','所有网站登录测试失败,请重新运行一遍!')
|
||||
continue
|
||||
|
||||
'''
|
||||
登录
|
||||
'''
|
||||
|
||||
def login(self):
|
||||
print('开始登录测试...')
|
||||
try:
|
||||
r = self.session.post(url=self.loginUrl, params=self.params, headers=self.headers)
|
||||
response = json.loads(r.text)
|
||||
if response['ret'] != 1:
|
||||
print(f"登录失败, 原因:{response['msg']}")
|
||||
return False
|
||||
else:
|
||||
print("登录成功")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
"""
|
||||
签到
|
||||
"""
|
||||
|
||||
def sign(self):
|
||||
try:
|
||||
client = self.session.post(url=self.originUrl + "/user/checkin", params=self.params, headers=self.headers)
|
||||
response = json.loads(client.text)
|
||||
if response['ret'] != 1:
|
||||
print(f"签到失败了,原因是{response['msg']}")
|
||||
notify.send('BBXY签到结果:',response['msg'])
|
||||
return False
|
||||
self.signSuccessMsg = response
|
||||
self.signSuccessOrNot = True
|
||||
#result = self.signSuccessMsg['msg'].decode('unicode_escape')
|
||||
msg = (f"签到成功:{self.signSuccessMsg['msg']}\n总流量{self.signSuccessMsg['traffic']}\n"
|
||||
f"今日已用{self.signSuccessMsg['trafficInfo'].get('todayUsedTraffic')}\n"
|
||||
f"总共已用{self.signSuccessMsg['trafficInfo'].get('lastUsedTraffic')}\n"
|
||||
f"剩余流量{self.signSuccessMsg['trafficInfo'].get('unUsedTraffic')}\n")
|
||||
if self.signSuccessOrNot:
|
||||
notify.send('BBXY签到结果!',msg)
|
||||
return True
|
||||
else:
|
||||
notify.send('BBXY签到结果!',msg)
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
"""
|
||||
消息模板,顺便发送消息到微信公众号
|
||||
"""
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
"""
|
||||
主程序
|
||||
从http://bbxy88.com/上爬取最新国内的入口地址
|
||||
"""
|
||||
print("*****\n"
|
||||
"百变小樱机场自动签到领流量\n"
|
||||
"机场注册地址☞ https://bbxy.life/auth/register?code=G9we\n"
|
||||
"脚本执行要求填入变量BBXY_EMAIL(邮箱账号)和BBXY_PASSWORD(登录密码)\n"
|
||||
"感谢原作者Admsec,\n"
|
||||
"经NaroisCool改进,将从百变小樱官方永久地址发布网站(http://bbxy88.com/)上爬取最新的国内访问地址,以及其他方法内的逻辑改动。\n"
|
||||
"*****")
|
||||
url = 'http://bbxy88.com/'
|
||||
response = requests.get(url)
|
||||
soup = BeautifulSoup(response.text, 'html.parser')
|
||||
links = [link.get('href') for link in soup.find_all('a')]
|
||||
additional_links = ['https://dash.bbxy.buzz/','https://baibianxiaoying.top/']
|
||||
websites = links+additional_links
|
||||
a = BBXYSign()
|
||||
a.check_websites_sync(websites)
|
||||
a.sign()
|
||||
298
脚本库/web版/账密/江淮卡友/2025-04-28_sudojia_jhcard_2102df5a.js
Normal file
298
脚本库/web版/账密/江淮卡友/2025-04-28_sudojia_jhcard_2102df5a.js
Normal file
@@ -0,0 +1,298 @@
|
||||
// # Source: https://github.com/sudojia/AutoTaskScript/blob/script/src/client/sudojia_jhcard.js
|
||||
// # Raw: https://raw.githubusercontent.com/sudojia/AutoTaskScript/script/src/client/sudojia_jhcard.js
|
||||
// # Repo: sudojia/AutoTaskScript
|
||||
// # Path: src/client/sudojia_jhcard.js
|
||||
// # UploadedAt: 2025-04-28T19:26:13+08:00
|
||||
// # SHA256: 2102df5ae5cc0c0d7fe510d4345f65068d692fcde84713647c8150124ec21af2
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/**
|
||||
* 江淮卡友APP
|
||||
*
|
||||
* 抓包 URL:http://jacwxmp.starnetah.com:18280/v2driver/v2/login 获取该 URL 的请求体,不要美化,不要自动换行,选择原始数据(Raw)
|
||||
* export JHCARD_BODY = '{"phone":"18888888888","password":"539281948b12751a942459aacb4a9ec1","sendMessageKey":"1aorcomF5n2EVd7Tc6w","deviceType":"1","appType":"0","sign":"XXXXXX"}'
|
||||
* 如需开启评论请在最后面加 true,以 # 分割
|
||||
* 示例:"sign":"XXXXXX"}#true
|
||||
* 多账号用 & 或换行
|
||||
*
|
||||
* @author Telegram@sudojia
|
||||
* @site https://blog.imzjw.cn
|
||||
* @date 2024/09/27
|
||||
*
|
||||
* const $ = new Env('江淮卡友')
|
||||
* cron: 55 5 * * *
|
||||
*/
|
||||
const initScript = require('../utils/initScript')
|
||||
const {$, notify, sudojia, checkUpdate} = initScript('江淮卡友');
|
||||
const moment = require("moment");
|
||||
const jhCardList = process.env.JHCARD_BODY ? process.env.JHCARD_BODY.split(/[\n&]/) : [];
|
||||
// 消息推送
|
||||
let message = '';
|
||||
// 接口地址
|
||||
const baseUrl = 'http://jacwxmp.starnetah.com'
|
||||
// 请求头
|
||||
const headers = {
|
||||
'User-Agent': sudojia.getRandomUserAgent('H5'),
|
||||
'Accept-Encoding': 'gzip',
|
||||
'Content-Type': 'application/json',
|
||||
'appType': '0'
|
||||
};
|
||||
|
||||
!(async () => {
|
||||
await checkUpdate($.name, jhCardList);
|
||||
console.log(`\n已随机分配 User-Agent\n\n${headers['user-agent'] || headers['User-Agent']}`);
|
||||
for (let i = 0; i < jhCardList.length; i++) {
|
||||
const index = i + 1;
|
||||
const [jsonBody, comment] = jhCardList[i].split('#');
|
||||
$.isLogin = true;
|
||||
$.loginBody = JSON.parse(jsonBody);
|
||||
$.isComment = comment || false;
|
||||
console.log(`\n*****第[${index}]个${$.name}账号*****`);
|
||||
await login();
|
||||
if (!$.isLogin) {
|
||||
continue;
|
||||
}
|
||||
message += `📣====${$.name}账号[${index}]====📣\n`;
|
||||
await $.wait(sudojia.getRandomWait(800, 1200));
|
||||
await main();
|
||||
await $.wait(sudojia.getRandomWait(2000, 2500));
|
||||
}
|
||||
if (message) {
|
||||
await notify.sendNotify(`「${$.name}」`, `${message}`);
|
||||
}
|
||||
})().catch((e) => $.logErr(e)).finally(() => $.done());
|
||||
|
||||
async function main() {
|
||||
await getUserInfo();
|
||||
await $.wait(sudojia.getRandomWait(1000, 1500));
|
||||
await signIn();
|
||||
await $.wait(sudojia.getRandomWait(1000, 1500));
|
||||
await querySignNumber();
|
||||
await $.wait(sudojia.getRandomWait(1000, 1500));
|
||||
await modifyUserInfo();
|
||||
await $.wait(sudojia.getRandomWait(1000, 1500));
|
||||
await getPoints();
|
||||
if (!$.isComment) {
|
||||
console.log('\n检测到你未开启评论任务,本次将跳过评论任务');
|
||||
return;
|
||||
}
|
||||
await $.wait(sudojia.getRandomWait(1000, 1500));
|
||||
await getInvitationList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function login() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}:18280/v2driver/v2/login`, 'post', headers, $.loginBody);
|
||||
if (200 !== data.resultCode) {
|
||||
console.error(data.message);
|
||||
$.isLogin = false;
|
||||
return;
|
||||
}
|
||||
headers.token = data.data.token;
|
||||
$.uid = data.data.userId;
|
||||
} catch (e) {
|
||||
console.error('登录时发生异常 ->', e.response.data);
|
||||
$.isLogin = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getUserInfo() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}:18280/v2driver/getUserInfo`, 'post', headers, {
|
||||
uc_id: $.uid
|
||||
});
|
||||
if (200 !== data.resultCode) {
|
||||
return console.error(`获取用户信息失败:${data.message}`);
|
||||
}
|
||||
console.log(`${data.data.name}(${data.data.phone})`);
|
||||
message += `${data.data.name}(${data.data.phone})\n`;
|
||||
$.isSign = data.data.isSign;
|
||||
} catch (e) {
|
||||
console.error('获取用户信息时发生异常 ->', e.response.data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function signIn() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}:18280/v2driver/signIn`, 'post', headers, {
|
||||
ucId: $.uid
|
||||
});
|
||||
if (200 !== data.resultCode) {
|
||||
message += `${data.message}\n`;
|
||||
return console.error(`签到失败:${data.message}`);
|
||||
}
|
||||
console.log(`签到成功!积分+${data.data.score}`);
|
||||
message += `签到成功!积分+${data.data.score}\n`;
|
||||
} catch (e) {
|
||||
console.error('签到时发生异常 ->', e.response.data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询签到天数
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function querySignNumber() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}:18280/v2driver/querySignNumber`, 'post', headers, {
|
||||
year: moment().year(),
|
||||
month: moment().month() + 1,
|
||||
ucId: $.uid
|
||||
});
|
||||
if (200 !== data.resultCode) {
|
||||
return console.error(`查询签到天数失败:${data.message}`);
|
||||
}
|
||||
console.log(`已连续签到${data.data.continueTime}天`);
|
||||
message += `已连续签到${data.data.continueTime}天\n`;
|
||||
} catch (e) {
|
||||
console.error('查询签到天数时发生异常 ->', e.response.data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 完善个人信息
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function modifyUserInfo() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}:18280/v2driver/modifyUserInfo`, 'post', headers, {
|
||||
"ucId": $.uid,
|
||||
"name": "菜狗联盟",
|
||||
"signature": "这个人很帅,什么都没有留下",
|
||||
"sex": "0",
|
||||
"interest": "看书",
|
||||
"birthday": "1949-10-01",
|
||||
"drivingAge": 10,
|
||||
"provinceDesc": "北京市",
|
||||
"cityDesc": "北京直辖市",
|
||||
"jianghuaiStaff": "0",
|
||||
})
|
||||
if (200 !== data.resultCode) {
|
||||
return console.error(`完善个人信息失败:${data.message}`);
|
||||
}
|
||||
console.log(`完善个人信息成功`);
|
||||
} catch (e) {
|
||||
console.error('完善个人信息时发生异常 ->', e.response.data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getPoints() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}:18280/v2driver/queryIntegral`, 'post', headers, {
|
||||
uc_id: $.uid
|
||||
});
|
||||
if (200 !== data.resultCode) {
|
||||
return console.error(`获取积分失败:${data.message}`);
|
||||
}
|
||||
console.log(`当前积分:${data.data.integralCounts}`);
|
||||
message += `当前积分:${data.data.integralCounts}\n\n`;
|
||||
} catch (e) {
|
||||
console.error('获取积分时发生异常 ->', e.response.data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文案
|
||||
*
|
||||
* @returns {Promise<*|null>}
|
||||
*/
|
||||
async function getWenAn() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest('https://api.vvhan.com/api/ian/wenxue?type=json', 'get', {
|
||||
'User-Agent': sudojia.getRandomUserAgent('PC'),
|
||||
'Accept-Encoding': 'gzip, deflate, br, zstd'
|
||||
});
|
||||
if (!data.success) {
|
||||
console.error('获取文案失败 ->', data);
|
||||
return null;
|
||||
}
|
||||
return data.data.content;
|
||||
} catch (e) {
|
||||
console.error('获取文案时发生异常 ->', e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取帖子列表
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getInvitationList() {
|
||||
try {
|
||||
console.log('你真勇,居然开启了评论任务');
|
||||
console.log('❗❗❗❗❗❗');
|
||||
console.log('准备开始评论任务,如账号被冻结,损失的一切都与作者(@sudojia)无关\n');
|
||||
for (let i = 0; i < 5; i++) {
|
||||
console.log(`第${i + 1}次评论...`);
|
||||
const data = await sudojia.sendRequest(`${baseUrl}:18180/jac/bbs/api/invitationInfo/getInvitationList`, 'post', headers, {
|
||||
"bbsType": "image",
|
||||
"forumId": "30",
|
||||
"page": 1,
|
||||
"size": 30
|
||||
})
|
||||
if (200 !== data.resultCode) {
|
||||
return console.error(`获取帖子列表失败:${data.message}`);
|
||||
}
|
||||
// 获取帖子对象
|
||||
const posts = data.data.records[Math.floor(Math.random() * 30) + 1];
|
||||
// 获取帖子ID
|
||||
const invitationId = posts.invitationCommentInfo.invitationId;
|
||||
await $.wait(sudojia.getRandomWait(5000, 8000));
|
||||
await postComment(invitationId);
|
||||
await $.wait(sudojia.getRandomWait(1000, 2000));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取帖子列表时发生异常 ->', e.response.data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论
|
||||
*
|
||||
* @param invitationId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function postComment(invitationId) {
|
||||
try {
|
||||
const content = await getWenAn();
|
||||
if (!content) {
|
||||
return console.error('获取文案失败,暂不发表评论!');
|
||||
}
|
||||
console.log(`获取到的文案 ->\n${content}`);
|
||||
const data = await sudojia.sendRequest(`${baseUrl}:18180/jac/bbs/api/invitationComment/newInvitationComment`, 'post', headers, {
|
||||
commentContent: content,
|
||||
invitationId: invitationId,
|
||||
});
|
||||
if (200 !== data.resultCode) {
|
||||
return console.error(`评论失败:${data.message}`);
|
||||
}
|
||||
console.log('评论成功\n');
|
||||
} catch (e) {
|
||||
console.error('评论时发生异常 ->', e.response.data);
|
||||
}
|
||||
}
|
||||
488
脚本库/web版/账密/电信权益/2025-07-19_电信权益_579e6e7f.py
Normal file
488
脚本库/web版/账密/电信权益/2025-07-19_电信权益_579e6e7f.py
Normal file
@@ -0,0 +1,488 @@
|
||||
# Source: https://gitee.com/jdqlscript/yyt/blob/master/%E7%94%B5%E4%BF%A1old/%E7%94%B5%E4%BF%A12/%E7%94%B5%E4%BF%A1%E6%9D%83%E7%9B%8A.py
|
||||
# Raw: https://gitee.com/jdqlscript/yyt/raw/master/%E7%94%B5%E4%BF%A1old/%E7%94%B5%E4%BF%A12/%E7%94%B5%E4%BF%A1%E6%9D%83%E7%9B%8A.py
|
||||
# Repo: jdqlscript/yyt
|
||||
# Path: 电信old/电信2/电信权益.py
|
||||
# UploadedAt: 2025-07-19T22:58:22+08:00
|
||||
# SHA256: 579e6e7f9f9fc531fc1c7cfd1778dd8e05800269395d45faaefd48fb9f5eddab
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
新电信抢话费
|
||||
|
||||
群里发的,未测试好,自测
|
||||
修改内容如下“
|
||||
1.删除内置的一个手机账号
|
||||
2.修改环境变量名保持和拉菲电信金豆本环境变量一致
|
||||
3.恢复瑞数通杀.js调用地址,确实也不知道是啥。398、399行注释
|
||||
|
||||
环境变量dxqy,值为:账号#密码 多账号 123123#45456&123123#45456
|
||||
|
||||
cron: 30 59 23 * * *
|
||||
const $ = new Env("电信权益");
|
||||
|
||||
"""
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import ssl
|
||||
import time
|
||||
import json
|
||||
import execjs
|
||||
import base64
|
||||
import random
|
||||
import certifi
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import certifi
|
||||
import datetime
|
||||
import requests
|
||||
import binascii
|
||||
from lxml import etree
|
||||
from http import cookiejar
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Cipher import DES3
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import PKCS1_v1_5
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
from aiohttp import ClientSession, TCPConnector
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
import subprocess
|
||||
|
||||
run_num=os.environ.get('reqNUM') or "2"
|
||||
|
||||
MAX_RETRIES = 3
|
||||
RATE_LIMIT = 10 # 每秒请求数限制
|
||||
|
||||
class RateLimiter:
|
||||
def __init__(self, rate_limit):
|
||||
self.rate_limit = rate_limit
|
||||
self.tokens = rate_limit
|
||||
self.updated_at = time.monotonic()
|
||||
|
||||
async def acquire(self):
|
||||
while self.tokens < 1:
|
||||
self.add_new_tokens()
|
||||
await asyncio.sleep(0.1)
|
||||
self.tokens -= 1
|
||||
|
||||
def add_new_tokens(self):
|
||||
now = time.monotonic()
|
||||
time_since_update = now - self.updated_at
|
||||
new_tokens = time_since_update * self.rate_limit
|
||||
if new_tokens > 1:
|
||||
self.tokens = min(self.tokens + new_tokens, self.rate_limit)
|
||||
self.updated_at = now
|
||||
|
||||
class AsyncSessionManager:
|
||||
def __init__(self):
|
||||
self.session = None
|
||||
self.connector = None
|
||||
|
||||
async def __aenter__(self):
|
||||
ssl_context = ssl.create_default_context(cafile=certifi.where())
|
||||
ssl_context.set_ciphers('DEFAULT@SECLEVEL=1')
|
||||
self.connector = TCPConnector(ssl=ssl_context, limit=1000)
|
||||
self.session = ClientSession(connector=self.connector)
|
||||
return self.session
|
||||
|
||||
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
||||
await self.session.close()
|
||||
await self.connector.close()
|
||||
|
||||
async def retry_request(session, method, url, **kwargs):
|
||||
for attempt in range(MAX_RETRIES):
|
||||
try:
|
||||
await asyncio.sleep(1)
|
||||
async with session.request(method, url, **kwargs) as response:
|
||||
return await response.json()
|
||||
# return await response.json()
|
||||
|
||||
except (aiohttp.ClientConnectionError, aiohttp.ServerTimeoutError) as e:
|
||||
print(f"请求失败,第 {attempt + 1} 次重试: {e}")
|
||||
if attempt == MAX_RETRIES - 1:
|
||||
raise
|
||||
await asyncio.sleep(2 ** attempt)
|
||||
|
||||
class BlockAll(cookiejar.CookiePolicy):
|
||||
return_ok = set_ok = domain_return_ok = path_return_ok = lambda self, *args, **kwargs: False
|
||||
netscape = True
|
||||
rfc2965 = hide_cookie2 = False
|
||||
|
||||
def printn(m):
|
||||
current_time = datetime.datetime.now().strftime("%H:%M:%S.%f")[:-3]
|
||||
print(f'\n[{current_time}] {m}')
|
||||
|
||||
context = ssl.create_default_context()
|
||||
context.set_ciphers('DEFAULT@SECLEVEL=1') # 低安全级别0/1
|
||||
context.check_hostname = False # 禁用主机
|
||||
context.verify_mode = ssl.CERT_NONE # 禁用证书
|
||||
|
||||
class DESAdapter(requests.adapters.HTTPAdapter):
|
||||
def init_poolmanager(self, *args, **kwargs):
|
||||
kwargs['ssl_context'] = context
|
||||
return super().init_poolmanager(*args, **kwargs)
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
# urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
ss = requests.session()
|
||||
ss.headers={"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","Referer":"https://wapact.189.cn:9001/JinDouMall/JinDouMall_independentDetails.html"}
|
||||
ss.mount('https://', DESAdapter())
|
||||
ss.cookies.set_policy(BlockAll())
|
||||
runTime = 0
|
||||
key = b'1234567`90koiuyhgtfrdews'
|
||||
iv = 8 * b'\0'
|
||||
|
||||
public_key_b64 = '''-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBkLT15ThVgz6/NOl6s8GNPofdWzWbCkWnkaAm7O2LjkM1H7dMvzkiqdxU02jamGRHLX/ZNMCXHnPcW/sDhiFCBN18qFvy8g6VYb9QtroI09e176s+ZCtiv7hbin2cCTj99iUpnEloZm19lwHyo69u5UMiPMpq0/XKBO8lYhN/gwIDAQAB
|
||||
-----END PUBLIC KEY-----'''
|
||||
|
||||
public_key_data = '''-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+ugG5A8cZ3FqUKDwM57GM4io6JGcStivT8UdGt67PEOihLZTw3P7371+N47PrmsCpnTRzbTgcupKtUv8ImZalYk65dU8rjC/ridwhw9ffW2LBwvkEnDkkKKRi2liWIItDftJVBiWOh17o6gfbPoNrWORcAdcbpk2L+udld5kZNwIDAQAB
|
||||
-----END PUBLIC KEY-----'''
|
||||
|
||||
def get_first_three(value):
|
||||
# 处理数字情况
|
||||
if isinstance(value, (int, float)):
|
||||
return int(str(value)[:11])
|
||||
elif isinstance(value, str):
|
||||
return str(value)[:11]
|
||||
else:
|
||||
raise TypeError("error")
|
||||
|
||||
def run_Time(hour,miute,second):
|
||||
date = datetime.datetime.now()
|
||||
date_zero = datetime.datetime.now().replace(year=date.year, month=date.month, day=date.day, hour=hour, minute=miute, second=second)
|
||||
date_zero_time = int(time.mktime(date_zero.timetuple()))
|
||||
return date_zero_time
|
||||
|
||||
def encrypt(text):
|
||||
cipher = DES3.new(key, DES3.MODE_CBC, iv)
|
||||
ciphertext = cipher.encrypt(pad(text.encode(), DES3.block_size))
|
||||
return ciphertext.hex()
|
||||
|
||||
def decrypt(text):
|
||||
ciphertext = bytes.fromhex(text)
|
||||
cipher = DES3.new(key, DES3.MODE_CBC, iv)
|
||||
plaintext = unpad(cipher.decrypt(ciphertext), DES3.block_size)
|
||||
return plaintext.decode()
|
||||
|
||||
def b64(plaintext):
|
||||
public_key = RSA.import_key(public_key_b64)
|
||||
cipher = PKCS1_v1_5.new(public_key)
|
||||
ciphertext = cipher.encrypt(plaintext.encode())
|
||||
return base64.b64encode(ciphertext).decode()
|
||||
|
||||
def encrypt_para(plaintext):
|
||||
if not isinstance(plaintext, str):
|
||||
plaintext = json.dumps(plaintext)
|
||||
public_key = RSA.import_key(public_key_data)
|
||||
cipher = PKCS1_v1_5.new(public_key)
|
||||
ciphertext = cipher.encrypt(plaintext.encode())
|
||||
return binascii.hexlify(ciphertext).decode()
|
||||
|
||||
def encode_phone(text):
|
||||
encoded_chars = []
|
||||
for char in text:
|
||||
encoded_chars.append(chr(ord(char) + 2))
|
||||
return ''.join(encoded_chars)
|
||||
|
||||
|
||||
def getApiTime(api_url):
|
||||
try:
|
||||
with requests.get(api_url) as response:
|
||||
if(not response or not response.text):
|
||||
return time.time()
|
||||
json_data = json.loads(response.text)
|
||||
if (json_data.get("api")and json_data.get("api")not in("time") ):
|
||||
timestamp_str = json_data.get('data', {}).get('t', '')
|
||||
else:
|
||||
timestamp_str = json_data.get('currentTime', {})
|
||||
timestamp = int(timestamp_str) / 1000.0 # 将毫秒转为秒
|
||||
difftime=time.time()-timestamp
|
||||
return difftime;
|
||||
except Exception as e:
|
||||
print(f"获取时间失败: {e}")
|
||||
return 0;
|
||||
|
||||
|
||||
def userLoginNormal(phone,password):
|
||||
alphabet = 'abcdef0123456789'
|
||||
uuid = [''.join(random.sample(alphabet, 8)),''.join(random.sample(alphabet, 4)),'4'+''.join(random.sample(alphabet, 3)),''.join(random.sample(alphabet, 4)),''.join(random.sample(alphabet, 12))]
|
||||
timestamp=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
loginAuthCipherAsymmertric = 'iPhone 14 15.4.' + uuid[0] + uuid[1] + phone + timestamp + password[:6] + '0$$$0.'
|
||||
r = ss.post('https://appgologin.189.cn:9031/login/client/userLoginNormal',json={"headerInfos": {"code": "userLoginNormal", "timestamp": timestamp, "broadAccount": "", "broadToken": "", "clientType": "#9.6.1#channel50#iPhone 14 Pro Max#", "shopId": "20002", "source": "110003", "sourcePassword": "Sid98s", "token": "", "userLoginName": phone}, "content": {"attach": "test", "fieldData": {"loginType": "4", "accountType": "", "loginAuthCipherAsymmertric": b64(loginAuthCipherAsymmertric), "deviceUid": uuid[0] + uuid[1] + uuid[2], "phoneNum": encode_phone(phone), "isChinatelecom": "0", "systemVersion": "15.4.0", "authentication": password}}},verify=certifi.where()).json()
|
||||
l = r['responseData']['data']['loginSuccessResult']
|
||||
if l:
|
||||
ticket = get_ticket(phone,l['userId'],l['token'])
|
||||
return ticket
|
||||
return False
|
||||
|
||||
async def exchangeForDay(phone, session, run_num, rid, stime):
|
||||
async def delayed_conversion(delay):
|
||||
await asyncio.sleep(delay)
|
||||
await conversionRights(phone, rid,session)
|
||||
tasks = [asyncio.create_task(delayed_conversion(i * stime)) for i in range(int(run_num))]
|
||||
await asyncio.gather(*tasks)
|
||||
def get_ticket(phone,userId,token):
|
||||
r = ss.post('https://appgologin.189.cn:9031/map/clientXML',data='<Request><HeaderInfos><Code>getSingle</Code><Timestamp>'+datetime.datetime.now().strftime("%Y%m%d%H%M%S")+'</Timestamp><BroadAccount></BroadAccount><BroadToken></BroadToken><ClientType>#9.6.1#channel50#iPhone 14 Pro Max#</ClientType><ShopId>20002</ShopId><Source>110003</Source><SourcePassword>Sid98s</SourcePassword><Token>'+token+'</Token><UserLoginName>'+phone+'</UserLoginName></HeaderInfos><Content><Attach>test</Attach><FieldData><TargetId>'+encrypt(userId)+'</TargetId><Url>4a6862274835b451</Url></FieldData></Content></Request>',headers={'user-agent': 'CtClient;10.4.1;Android;13;22081212C;NTQzNzgx!#!MTgwNTg1'},verify=certifi.where())
|
||||
tk = re.findall('<Ticket>(.*?)</Ticket>',r.text)
|
||||
if len(tk) == 0:
|
||||
return False
|
||||
return decrypt(tk[0])
|
||||
|
||||
async def exchange(s, phone, title, aid,jsexec, ckvalue):
|
||||
try:
|
||||
url="https://wapact.189.cn:9001/gateway/standExchange/detailNew/exchange"
|
||||
# getck = await asyncio.to_thread(jsexec.call, "getck") # 两种方式,一种用ck,一种用后缀
|
||||
# getck = getck.split(';')[0].split('=')
|
||||
# ckvalue[getck[0]] = getck[1]
|
||||
|
||||
# async with s.post(url, cookies=ckvalue, json={"activityId": aid}) as response:
|
||||
|
||||
# 通过 retry_request 实现重试机制
|
||||
# response = await retry_request(s, 'POST', get_url, cookies=ckvalue, json={"activityId": aid})
|
||||
|
||||
get_url = await asyncio.to_thread(jsexec.call,"getUrl", "POST",url)
|
||||
async with s.post(get_url, cookies=ckvalue, json={"activityId": aid}) as response:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
|
||||
async def check(s,item,ckvalue):
|
||||
checkGoods = s.get('https://wapact.189.cn:9001/gateway/stand/detailNew/check?activityId=' + item, cookies=ckvalue).json()
|
||||
return checkGoods
|
||||
|
||||
async def conversionRights(phone, aid, session):
|
||||
try:
|
||||
# 获取 Ruishu cookies
|
||||
ruishu_cookies = get_ruishu_cookies()
|
||||
if not ruishu_cookies:
|
||||
print(f"{get_first_three(phone)}: 无法获取 Ruishu cookies")
|
||||
return
|
||||
|
||||
value = {
|
||||
"phone": phone,
|
||||
"rightsId": aid
|
||||
}
|
||||
paraV = encrypt_para(value)
|
||||
|
||||
printn(f"{get_first_three(phone)}:开始兑换")
|
||||
|
||||
# 使用 Ruishu cookies 发送请求
|
||||
response = session.post(
|
||||
'https://wappark.189.cn/jt-sign/paradise/conversionRights',
|
||||
json={"para": paraV},
|
||||
cookies=ruishu_cookies
|
||||
)
|
||||
|
||||
login = response.json()
|
||||
printn(f"{get_first_three(phone)}:{login}")
|
||||
|
||||
if '兑换成功' in response.text:
|
||||
QLAPI.notify(get_first_three(phone), login['resoultMsg'])
|
||||
exit(0)
|
||||
|
||||
except Exception as e:
|
||||
printn(f"{get_first_three(phone)}: 兑换请求发生错误: {str(e)}")
|
||||
# 可以选择是否在这里添加重试逻辑
|
||||
|
||||
async def getLevelRightsList(phone, session):
|
||||
try:
|
||||
# 获取 Ruishu cookies
|
||||
ruishu_cookies = get_ruishu_cookies()
|
||||
if not ruishu_cookies:
|
||||
print("无法获取 Ruishu cookies")
|
||||
return None
|
||||
|
||||
value = {
|
||||
"phone": phone
|
||||
}
|
||||
paraV = encrypt_para(value)
|
||||
|
||||
# 使用 Ruishu cookies 发送请求
|
||||
response = session.post(
|
||||
'https://wappark.189.cn/jt-sign/paradise/getLevelRightsList',
|
||||
json={"para": paraV},
|
||||
cookies=ruishu_cookies
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
if data.get('code') == 401:
|
||||
print(f"获取失败:{data},原因大概是sign过期了")
|
||||
return None
|
||||
|
||||
current_level = int(data['currentLevel'])
|
||||
key_name = 'V' + str(current_level)
|
||||
ids = [item['id'] for item in data.get(key_name, []) if item.get('name') == '话费']
|
||||
return ids
|
||||
|
||||
except Exception as e:
|
||||
print(f"获取失败,重试一次: {str(e)}")
|
||||
try:
|
||||
# 重试时重新获取 Ruishu cookies
|
||||
ruishu_cookies = get_ruishu_cookies()
|
||||
if not ruishu_cookies:
|
||||
print("重试时无法获取 Ruishu cookies")
|
||||
return None
|
||||
|
||||
paraV = encrypt_para(value)
|
||||
response = session.post(
|
||||
'https://wappark.189.cn/jt-sign/paradise/getLevelRightsList',
|
||||
json={"para": paraV},
|
||||
cookies=ruishu_cookies
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
if data.get('code') == 401:
|
||||
print(f"重试获取失败:{data},原因大概是sign过期了")
|
||||
return None
|
||||
|
||||
current_level = int(data['currentLevel'])
|
||||
key_name = 'V' + str(current_level)
|
||||
ids = [item['id'] for item in data.get(key_name, []) if item.get('name') == '话费']
|
||||
return ids
|
||||
|
||||
except Exception as e:
|
||||
print(f"重试也失败了: {str(e)}")
|
||||
return None
|
||||
|
||||
def get_ruishu_cookies():
|
||||
try:
|
||||
# 获取当前文件所在目录
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
ruishu_path = os.path.join(current_dir, 'Ruishu.py')
|
||||
|
||||
# 执行 Ruishu.py 并获取输出
|
||||
result = subprocess.run([sys.executable, ruishu_path],
|
||||
capture_output=True,
|
||||
text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
print(f"Ruishu.py 执行错误: {result.stderr}")
|
||||
return None
|
||||
|
||||
# 解析输出的 JSON
|
||||
cookies = json.loads(result.stdout.strip())
|
||||
return cookies
|
||||
|
||||
except Exception as e:
|
||||
print(f"获取 Ruishu cookies 时发生错误: {str(e)}")
|
||||
return None
|
||||
|
||||
async def getSign(ticket, session):
|
||||
try:
|
||||
# 获取 Ruishu cookies
|
||||
ruishu_cookies = get_ruishu_cookies()
|
||||
if not ruishu_cookies:
|
||||
print("无法获取 Ruishu cookies")
|
||||
return None
|
||||
|
||||
# 合并现有的 cookies 和 Ruishu cookies
|
||||
cookies = {**ruishu_cookies}
|
||||
|
||||
# 使用合并后的 cookies 发送请求
|
||||
response = session.get(
|
||||
'https://wappark.189.cn/jt-sign/ssoHomLogin?ticket=' + ticket,
|
||||
cookies=cookies
|
||||
).json()
|
||||
|
||||
if response.get('resoultCode') == '0':
|
||||
sign = response.get('sign')
|
||||
return sign
|
||||
else:
|
||||
print(f"获取sign失败[{response.get('resoultCode')}]: {response}")
|
||||
except Exception as e:
|
||||
print(f"getSign 发生错误: {str(e)}")
|
||||
return None
|
||||
|
||||
async def qgNight(phone, ticket, timeDiff,isTrue):
|
||||
if isTrue:
|
||||
runTime = run_Time(23,59,3)
|
||||
else:
|
||||
# runTime = run_Time(0,0,0) + 0.65
|
||||
runTime = 0
|
||||
|
||||
if runTime >(time.time()+timeDiff):
|
||||
difftime = runTime - time.time() - timeDiff
|
||||
print(f"当前时间:{str(datetime.datetime.now())[11:23]},跟设定的时间不同,等待{difftime}秒开始兑换每天一次的")
|
||||
await asyncio.sleep(difftime)
|
||||
session = requests.Session()
|
||||
session.mount('https://', DESAdapter())
|
||||
session.verify = False # 禁用证书验证
|
||||
sign =await getSign(ticket,session)
|
||||
if sign:
|
||||
# print(f"当前时间:{str(datetime.datetime.now())[11:23]}获取到了Sign:"+sign)
|
||||
session.headers={"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","sign":sign}
|
||||
else:
|
||||
print("未获取sign。")
|
||||
return
|
||||
rightsId =await getLevelRightsList(phone,session)
|
||||
if rightsId:
|
||||
print("获取到了rightsId:"+rightsId[0])
|
||||
else:
|
||||
print("未能获取rightsId。")
|
||||
return
|
||||
# await asyncio.sleep(10)直接延迟也行,或者用下面的等待一段时间。之所以这样是要先获取sign省一些步骤。
|
||||
if isTrue:
|
||||
runTime2 = run_Time(23,59,59) + 0.7
|
||||
difftime = runTime2 - time.time() - timeDiff
|
||||
printn(f"等待{difftime}s")
|
||||
await asyncio.sleep(difftime)
|
||||
await exchangeForDay(phone,session,run_num,rightsId[0],0.1)
|
||||
async def qgDay(phone, ticket, timeDiff, isTrue):
|
||||
async with AsyncSessionManager() as s:
|
||||
pass
|
||||
async def main(timeDiff,isTRUE,hour):
|
||||
tasks = []
|
||||
PHONES=os.environ.get('dxqy')
|
||||
phone_list = PHONES.split('&')
|
||||
for phoneV in phone_list:
|
||||
value = phoneV.split('#')
|
||||
phone, password = value[0], value[1]
|
||||
printn(f'{get_first_three(phone)}开始登录')
|
||||
ticket = userLoginNormal(phone,password)
|
||||
if ticket:
|
||||
# hour=datetime.datetime.now().hour
|
||||
# hour=23
|
||||
if hour > 15:
|
||||
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)
|
||||
|
||||
if __name__ == "__main__":
|
||||
h = datetime.datetime.now().hour
|
||||
# h=15 #手动设置场次的时间
|
||||
print("当前小时为: "+str(h))
|
||||
if 10 >h >0:
|
||||
print("当前小时为: "+str(h)+"已过0点但未到10点开始准备抢十点场次")
|
||||
wttime= run_Time(9,59,8) #抢十点场次
|
||||
elif 14 >= h >=10:
|
||||
print("当前小时为: "+str(h) +"已过10点但未到14点开始准备抢十四点场次")
|
||||
wttime= run_Time(13,59,8) #抢十四点场次
|
||||
else:
|
||||
print("当前小时为: "+str(h)+"已过14点开始准备抢凌晨")
|
||||
wttime= run_Time(23,58,58) #抢凌晨
|
||||
#isTRUE=False
|
||||
isTRUE=True
|
||||
#isTRUE等于False则表示忽略所有限制直接运行。这个参数一般用于测试。实际生产一定要设置为True。
|
||||
if(wttime >time.time()) :
|
||||
wTime=wttime-time.time()
|
||||
print("未到时间,计算后差异:"+str(wTime)+"秒")
|
||||
if isTRUE:
|
||||
print("一定要先测试,根据自身 设定的重发和多号,不然会出问题,抢购过早或者过晚。")
|
||||
print("开始等待:")
|
||||
time.sleep(wTime)
|
||||
# timeValue = getApiTime("https://f.m.suning.com/api/ct.do")
|
||||
timeValue = 0
|
||||
timeDiff = timeValue if timeValue > 0 else 0
|
||||
asyncio.run(main(timeDiff, isTRUE,h))
|
||||
print("所有任务都已执行完毕!")
|
||||
731
脚本库/web版/账密/电信金豆兑换话费/2025-07-19_7月1日金豆换话费_6ac467d0.py
Normal file
731
脚本库/web版/账密/电信金豆兑换话费/2025-07-19_7月1日金豆换话费_6ac467d0.py
Normal file
@@ -0,0 +1,731 @@
|
||||
# Source: https://gitee.com/jdqlscript/yyt/blob/master/%E7%94%B5%E4%BF%A1/7%E6%9C%881%E6%97%A5%E9%87%91%E8%B1%86%E6%8D%A2%E8%AF%9D%E8%B4%B9.py
|
||||
# Raw: https://gitee.com/jdqlscript/yyt/raw/master/%E7%94%B5%E4%BF%A1/7%E6%9C%881%E6%97%A5%E9%87%91%E8%B1%86%E6%8D%A2%E8%AF%9D%E8%B4%B9.py
|
||||
# Repo: jdqlscript/yyt
|
||||
# Path: 电信/7月1日金豆换话费.py
|
||||
# UploadedAt: 2025-07-19T22:58:22+08:00
|
||||
# SHA256: 6ac467d0a0bf44c28e3c9619647bad1e67686357d0fe8a19603ae6c45c35704f
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
cron: 0 59 9,13 * * *
|
||||
new Env('电信金豆兑换话费');
|
||||
"""
|
||||
import subprocess
|
||||
import sys
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import os
|
||||
import execjs
|
||||
import requests
|
||||
import re
|
||||
import time as time_module # 重命名导入以避免冲突
|
||||
import json
|
||||
import random
|
||||
import datetime
|
||||
import base64
|
||||
import ssl
|
||||
import certifi
|
||||
import traceback
|
||||
from bs4 import BeautifulSoup
|
||||
from loguru import logger
|
||||
from lxml import etree
|
||||
import gjc
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import PKCS1_v1_5
|
||||
from Crypto.Cipher import DES3
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
from Crypto.Util.strxor import strxor
|
||||
from Crypto.Cipher import AES
|
||||
from http import cookiejar # Python 2: import cookielib as cookiejar
|
||||
from requests.adapters import HTTPAdapter
|
||||
from requests.packages.urllib3.util.ssl_ import create_urllib3_context
|
||||
|
||||
|
||||
def get_network_time():
|
||||
"""从淘宝接口获取网络时间"""
|
||||
url = "https://acs.m.taobao.com/gw/mtop.common.getTimestamp/"
|
||||
try:
|
||||
response = requests.get(url)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if "data" in data and "t" in data["data"]:
|
||||
timestamp = int(data["data"]["t"]) # 获取时间戳
|
||||
return datetime.datetime.fromtimestamp(timestamp / 1000) # 转换为 datetime 对象
|
||||
else:
|
||||
raise ValueError("接口返回数据格式错误")
|
||||
else:
|
||||
raise Exception(f"获取网络时间失败,状态码: {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"{str(get_network_time())[11:22]} 获取网络时间失败: {e}")
|
||||
return datetime.datetime.now() # 如果失败,使用本地时间作为备选
|
||||
|
||||
|
||||
# 获取本地时间和网络时间
|
||||
local_time = datetime.datetime.now()
|
||||
network_time = get_network_time()
|
||||
|
||||
# 计算时间差
|
||||
time_diff = network_time - local_time
|
||||
|
||||
# 输出时间差,精确到微秒
|
||||
print(f"本地时间: {local_time.strftime('%Y-%m-%d %H:%M:%S.%f')}")
|
||||
print(f"网络时间: {network_time.strftime('%Y-%m-%d %H:%M:%S.%f')}")
|
||||
print(f"时间差: {time_diff.total_seconds():.6f} 秒")
|
||||
|
||||
# 默认兑换策略
|
||||
MEXZ = os.getenv("MEXZ")
|
||||
|
||||
# 定义时间段
|
||||
morning_start = datetime.time(9, 30, 3)
|
||||
morning_end = datetime.time(10, 0, 30)
|
||||
afternoon_start = datetime.time(13, 30, 3)
|
||||
afternoon_end = datetime.time(14, 0, 30)
|
||||
|
||||
# 获取当前时间
|
||||
now = get_network_time().time()
|
||||
|
||||
# 判断当前时间是否在指定的时间段内
|
||||
if (morning_start <= now <= morning_end) or (afternoon_start <= now <= afternoon_end):
|
||||
# 在指定时间段内,使用环境变量中的 MEXZ 配置
|
||||
if not MEXZ:
|
||||
MEXZ = "0.5,5,6;1,10,3"
|
||||
else:
|
||||
# 不在指定时间段内,使用默认策略
|
||||
MEXZ = "0.5,5,6;1,10,3"
|
||||
|
||||
# 解析 MEXZ 配置
|
||||
morning_exchanges, afternoon_exchanges = MEXZ.split(';')
|
||||
morning_exchanges = [f"{x}元话费" for x in morning_exchanges.split(',')]
|
||||
afternoon_exchanges = [f"{x}元话费" for x in afternoon_exchanges.split(',')]
|
||||
|
||||
|
||||
# 从环境变量中获取代理池地址
|
||||
DY_PROXY = os.getenv("DY_PROXY123")
|
||||
|
||||
|
||||
async def get_proxy_from_pool():
|
||||
"""从代理池获取代理IP"""
|
||||
if not DY_PROXY:
|
||||
raise ValueError("DY_PROXY 环境变量未设置")
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(DY_PROXY) as response:
|
||||
if response.status != 200:
|
||||
raise Exception(f"从代理池获取代理IP失败,状态码: {response.status}")
|
||||
proxy_ip = await response.text()
|
||||
return proxy_ip.strip() # 去除可能的空白字符
|
||||
|
||||
|
||||
class BlockAll(cookiejar.CookiePolicy):
|
||||
return_ok = set_ok = domain_return_ok = path_return_ok = lambda self, *args, **kwargs: False
|
||||
netscape = True
|
||||
rfc2965 = hide_cookie2 = False
|
||||
|
||||
|
||||
def printn(m):
|
||||
print(f'\n{m}')
|
||||
|
||||
def print_time_log(m):
|
||||
print(f'{str(get_network_time())[11:22]} {m}')
|
||||
|
||||
|
||||
ORIGIN_CIPHERS = ('DEFAULT@SECLEVEL=1')
|
||||
|
||||
|
||||
class DESAdapter(HTTPAdapter):
|
||||
def __init__(self, *args, **kwargs):
|
||||
CIPHERS = ORIGIN_CIPHERS.split(':')
|
||||
random.shuffle(CIPHERS)
|
||||
CIPHERS = ':'.join(CIPHERS)
|
||||
self.CIPHERS = CIPHERS + ':!aNULL:!eNULL:!MD5'
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def init_poolmanager(self, *args, **kwargs):
|
||||
context = create_urllib3_context(ciphers=self.CIPHERS)
|
||||
context.check_hostname = False
|
||||
kwargs['ssl_context'] = context
|
||||
|
||||
return super(DESAdapter, self).init_poolmanager(*args, **kwargs)
|
||||
|
||||
def proxy_manager_for(self, *args, **kwargs):
|
||||
context = create_urllib3_context(ciphers=self.CIPHERS)
|
||||
context.check_hostname = False
|
||||
kwargs['ssl_context'] = context
|
||||
return super(DESAdapter, self).proxy_manager_for(*args, **kwargs)
|
||||
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
ssl_context = ssl.create_default_context()
|
||||
ssl_context.set_ciphers("DEFAULT@SECLEVEL=1") # Set security level to allow smaller DH keys
|
||||
ss = requests.session()
|
||||
ss.verify = certifi.where()
|
||||
ss.headers = {
|
||||
"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",
|
||||
"Referer": "https://wapact.189.cn:9001/JinDouMall/JinDouMall_independentDetails.html"
|
||||
}
|
||||
ss.mount('https://', DESAdapter())
|
||||
ss.cookies.set_policy(BlockAll())
|
||||
yc = 1
|
||||
wt = 0
|
||||
kswt = 0.1
|
||||
yf = get_network_time().strftime("%Y%m")
|
||||
ip_list = []
|
||||
jp = {"9": {}, "13": {}}
|
||||
try:
|
||||
with open('电信金豆换话费.log') as fr:
|
||||
dhjl = json.load(fr)
|
||||
except:
|
||||
dhjl = {}
|
||||
if yf not in dhjl:
|
||||
dhjl[yf] = {}
|
||||
load_token_file = 'chinaTelecom_cache.json'
|
||||
try:
|
||||
with open(load_token_file, 'r') as f:
|
||||
load_token = json.load(f)
|
||||
except:
|
||||
load_token = {}
|
||||
|
||||
errcode = {
|
||||
"0": "兑换成功",
|
||||
"412": "兑换次数已达上限",
|
||||
"413": "商品已兑完",
|
||||
"420": "未知错误",
|
||||
"410": "该活动未开始",
|
||||
"501": "服务器处理错误",
|
||||
"Y0001": "当前等级不足,去升级兑当前话费",
|
||||
"Y0002": "使用翼相连网络600分钟或连接并拓展网络500分钟可兑换此奖品",
|
||||
"Y0003": "使用翼相连共享流量400M或共享WIFI:2GB可兑换此奖品",
|
||||
"Y0004": "使用翼相连共享流量2GB可兑换此奖品",
|
||||
"Y0005": "当前等级不足,去升级兑当前话费",
|
||||
"E0001": "您的网龄不足10年,暂不能兑换"
|
||||
}
|
||||
|
||||
key = b'1234567`90koiuyhgtfrdews'
|
||||
iv = 8 * b'\0'
|
||||
|
||||
public_key_b64 = '''-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBkLT15ThVgz6/NOl6s8GNPofdWzWbCkWnkaAm7O2LjkM1H7dMvzkiqdxU02jamGRHLX/ZNMCXHnPcW/sDhiFCBN18qFvy8g6VYb9QtroI09e176s+ZCtiv7hbin2cCTj99iUpnEloZm19lwHyo69u5UMiPMpq0/XKBO8lYhN/gwIDAQAB
|
||||
-----END PUBLIC KEY-----'''
|
||||
|
||||
public_key_data = '''-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+ugG5A8cZ3FqUKDwM57GM4io6JGcStivT8UdGt67PEOihLZTw3P7371+N47PrmsCpnTRzbTgcupKtUv8ImZalYk65dU8rjC/ridwhw9ffW2LBwvkEnDkkKKRi2liWIItDftJVBiWOh17o6gfbPoNrWORcAdcbpk2L+udld5kZNwIDAQAB
|
||||
-----END PUBLIC KEY-----'''
|
||||
|
||||
|
||||
def t(h):
|
||||
date = get_network_time()
|
||||
date_zero = date.replace(hour=h, minute=59, second=20)
|
||||
date_zero_time = time_module.mktime(date_zero.timetuple()) # 使用 timetuple() 转换为 struct_time
|
||||
return date_zero_time
|
||||
|
||||
|
||||
def encrypt(text):
|
||||
cipher = DES3.new(key, DES3.MODE_CBC, iv)
|
||||
ciphertext = cipher.encrypt(pad(text.encode(), DES3.block_size))
|
||||
return ciphertext.hex()
|
||||
|
||||
|
||||
def decrypt(text):
|
||||
ciphertext = bytes.fromhex(text)
|
||||
cipher = DES3.new(key, DES3.MODE_CBC, iv)
|
||||
plaintext = unpad(cipher.decrypt(ciphertext), DES3.block_size)
|
||||
return plaintext.decode()
|
||||
|
||||
|
||||
def b64(plaintext):
|
||||
public_key = RSA.import_key(public_key_b64)
|
||||
cipher = PKCS1_v1_5.new(public_key)
|
||||
ciphertext = cipher.encrypt(plaintext.encode())
|
||||
return base64.b64encode(ciphertext).decode()
|
||||
|
||||
|
||||
def encrypt_para(plaintext):
|
||||
public_key = RSA.import_key(public_key_data)
|
||||
cipher = PKCS1_v1_5.new(public_key)
|
||||
ciphertext = cipher.encrypt(plaintext.encode())
|
||||
return ciphertext.hex()
|
||||
|
||||
|
||||
def encode_phone(text):
|
||||
encoded_chars = []
|
||||
for char in text:
|
||||
encoded_chars.append(chr(ord(char) + 2))
|
||||
return ''.join(encoded_chars)
|
||||
|
||||
|
||||
def ophone(t):
|
||||
key = b'34d7cb0bcdf07523'
|
||||
utf8_key = key.decode('utf-8')
|
||||
utf8_t = t.encode('utf-8')
|
||||
cipher = AES.new(key, AES.MODE_ECB)
|
||||
ciphertext = cipher.encrypt(pad(utf8_t, AES.block_size))
|
||||
return ciphertext.hex()
|
||||
|
||||
|
||||
def send(uid, content):
|
||||
appToken = os.getenv("WXPUSHER_APP_TOKEN") # 从环境变量中获取 appToken
|
||||
uid = os.getenv("WXPUSHER_UID") # 从环境变量中获取 uid
|
||||
|
||||
if not appToken or not uid:
|
||||
raise ValueError("WXPUSHER_APP_TOKEN 或 WXPUSHER_UID 未设置")
|
||||
|
||||
r = requests.post('https://wxpusher.zjiecode.com/api/send/message', json={"appToken": appToken, "content": content, "contentType": 1, "uids": [uid]}).json()
|
||||
return r
|
||||
|
||||
|
||||
def userLoginNormal(phone, password):
|
||||
alphabet = 'abcdef0123456789'
|
||||
uuid = [''.join(random.sample(alphabet, 8)), ''.join(random.sample(alphabet, 4)), '4' + ''.join(random.sample(alphabet, 3)), ''.join(random.sample(alphabet, 4)), ''.join(random.sample(alphabet, 12))]
|
||||
timestamp = get_network_time().strftime("%Y%m%d%H%M%S")
|
||||
loginAuthCipherAsymmertric = 'iPhone 14 15.4.' + uuid[0] + uuid[1] + phone + timestamp + password[:6] + '0$$$0.'
|
||||
|
||||
try:
|
||||
r = ss.post('https://appgologin.189.cn:9031/login/client/userLoginNormal',json={"headerInfos": {"code": "userLoginNormal", "timestamp": timestamp, "broadAccount": "", "broadToken": "", "clientType": "#11.3.0#channel35#Xiaomi Redmi K30 Pro#", "shopId": "20002", "source": "110003", "sourcePassword": "Sid98s", "token": "", "userLoginName": encode_phone(phone)}, "content": {"attach": "test", "fieldData": {"loginType": "4", "accountType": "", "loginAuthCipherAsymmertric": b64(loginAuthCipherAsymmertric), "deviceUid": uuid[0] + uuid[1] + uuid[2], "phoneNum": encode_phone(phone), "isChinatelecom": "0", "systemVersion": "12", "authentication": encode_phone(password)}}},verify=certifi.where()).json()
|
||||
#r = ss.post('https://appgologin.189.cn:9031/login/client/userLoginNormal', json={"headerInfos": {"code": "userLoginNormal", "timestamp": timestamp, "broadAccount": "", "broadToken": "", "clientType": "#9.6.1#channel50#iPhone 14 Pro Max#", "shopId": "20002", "source": "110003", "sourcePassword": "Sid98s", "token": "", "userLoginName": phone}, "content": {"attach": "test", "fieldData": {"loginType": "4", "accountType": "", "loginAuthCipherAsymmertric": b64(loginAuthCipherAsymmertric), "deviceUid": uuid[0] + uuid[1] + uuid[2], "phoneNum": encode_phone(phone), "isChinatelecom": "0", "systemVersion": "15.4.0", "authentication": password}}}).json()
|
||||
except Exception as e:
|
||||
print(f"登录请求失败,错误信息: {e}")
|
||||
return False
|
||||
|
||||
# 添加错误处理逻辑
|
||||
if r is None:
|
||||
print(f"登录请求失败,返回值为 None")
|
||||
return False
|
||||
|
||||
if 'responseData' not in r or r['responseData'] is None:
|
||||
print(f"登录请求失败,responseData 不存在或为 None: {r}")
|
||||
return False
|
||||
|
||||
if 'data' not in r['responseData'] or r['responseData']['data'] is None:
|
||||
print(f"登录请求失败,data 不存在或为 None: {r}")
|
||||
return False
|
||||
|
||||
if 'loginSuccessResult' not in r['responseData']['data']:
|
||||
print(f"登录请求失败,loginSuccessResult 不存在: {r}")
|
||||
return False
|
||||
|
||||
l = r['responseData']['data']['loginSuccessResult']
|
||||
|
||||
print(l)
|
||||
|
||||
if l:
|
||||
load_token[phone] = l
|
||||
with open(load_token_file, 'w') as f:
|
||||
json.dump(load_token, f)
|
||||
ticket = get_ticket(phone, l['userId'], l['token'])
|
||||
return ticket
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def get_ticket(phone, userId, token):
|
||||
r = ss.post('https://appgologin.189.cn:9031/map/clientXML', data='<Request><HeaderInfos><Code>getSingle</Code><Timestamp>' + get_network_time().strftime("%Y%m%d%H%M%S") + '</Timestamp><BroadAccount></BroadAccount><BroadToken></BroadToken><ClientType>#9.6.1#channel50#iPhone 14 Pro Max#</ClientType><ShopId>20002</ShopId><Source>110003</Source><SourcePassword>Sid98s</SourcePassword><Token>' + token + '</Token><UserLoginName>' + phone + '</UserLoginName></HeaderInfos><Content><Attach>test</Attach><FieldData><TargetId>' + encrypt(userId) + '</TargetId><Url>4a6862274835b451</Url></FieldData></Content></Request>', headers={'user-agent': 'CtClient;10.4.1;Android;13;22081212C;NTQzNzgx!#!MTgwNTg1'})
|
||||
|
||||
tk = re.findall('<Ticket>(.*?)</Ticket>', r.text)
|
||||
if len(tk) == 0:
|
||||
return False
|
||||
# print(tk)
|
||||
return decrypt(tk[0])
|
||||
|
||||
|
||||
async def exchange(phone, s, title, aid, uid, amount):
|
||||
global h # 使用全局变量 h
|
||||
masked_phone = phone[:3] + '****' + phone[-4:]
|
||||
try:
|
||||
# 第一次请求:获取 cookie
|
||||
tt = time_module.time()
|
||||
start_time = time_module.time() # 记录开始时间
|
||||
cookies = await gjc.get_rs('https://wapact.189.cn:9001/gateway/standExchange/detailNew/exchange', s, md='post')
|
||||
end_time = time_module.time() # 记录结束时间
|
||||
print_time_log(f"{masked_phone} 获取到 {title} 的cookies 用时: {end_time - start_time:.3f} 秒")
|
||||
|
||||
# 获取当前时间
|
||||
now = get_network_time()
|
||||
|
||||
# 如果 h 没有赋值,则使用当前时间的小时数
|
||||
if h is None:
|
||||
h = now.hour
|
||||
|
||||
# 设置第一次等待的目标时间(9:59:50 或 13:59:50)
|
||||
if h == 9:
|
||||
first_target_time = now.replace(hour=h, minute=59, second=30, microsecond=0)
|
||||
elif h == 13:
|
||||
first_target_time = now.replace(hour=h, minute=59, second=30, microsecond=0)
|
||||
|
||||
# 计算第一次等待的时间差
|
||||
first_time_diff = (first_target_time - now).total_seconds()
|
||||
|
||||
# 如果第一次等待的时间差在 0 到 300 秒之间,则等待到第一次目标时间
|
||||
if 0 <= first_time_diff <= 300:
|
||||
print_time_log(f"{masked_phone} 等待 {first_time_diff:.2f} 秒...")
|
||||
await asyncio.sleep(first_time_diff)
|
||||
|
||||
# 判断当前时间是否在指定的时间段内
|
||||
morning_start = datetime.time(9, 30, 50)
|
||||
morning_end = datetime.time(10, 0, 5)
|
||||
afternoon_start = datetime.time(13, 30, 40)
|
||||
afternoon_end = datetime.time(14, 0, 5)
|
||||
current_time = now.time()
|
||||
|
||||
if (morning_start <= current_time <= morning_end) or (afternoon_start <= current_time <= afternoon_end):
|
||||
# 在指定时间段内,根据 DY_PROXY 是否设置来决定使用代理或本地 IP
|
||||
if DY_PROXY:
|
||||
try:
|
||||
proxy_ip = await get_proxy_from_pool()
|
||||
proxy = f"http://{proxy_ip}" # 根据代理池返回的格式调整
|
||||
print_time_log(f"{masked_phone} 从代理池获取到代理IP: {proxy_ip}")
|
||||
except ValueError as e:
|
||||
print_time_log(f"{masked_phone} {e} 使用本地 IP ")
|
||||
proxy = None # 设置为 None,表示使用本地 IP
|
||||
else:
|
||||
print_time_log(f"{masked_phone} DY_PROXY 未设置,使用本地 IP")
|
||||
proxy = None # 设置为 None,表示使用本地 IP
|
||||
else:
|
||||
# 不在指定时间段内,直接使用本地 IP
|
||||
print_time_log(f"{masked_phone} 不在指定时间段内,使用本地 IP")
|
||||
proxy = None # 设置为 None,表示使用本地 IP
|
||||
|
||||
# 设置第二次等待的目标时间(9:59:59 或 13:59:59)
|
||||
if h == 9:
|
||||
second_target_time = now.replace(hour=h, minute=59, second=55, microsecond=803600)
|
||||
elif h == 13:
|
||||
second_target_time = now.replace(hour=h, minute=59, second=55, microsecond=793600)
|
||||
|
||||
# 计算第二次等待的时间差
|
||||
second_time_diff = (second_target_time - get_network_time()).total_seconds()
|
||||
|
||||
# 如果第二次等待的时间差在 0 到 300 秒之间,则等待到第二次目标时间
|
||||
if 0 <= second_time_diff <= 300:
|
||||
print_time_log(f"{masked_phone} 等待 {second_time_diff:.2f} 秒...")
|
||||
await asyncio.sleep(second_time_diff)
|
||||
|
||||
# 打印是否使用了代理
|
||||
if proxy:
|
||||
print_time_log(f"{masked_phone} 正在使用代理IP: {proxy}")
|
||||
else:
|
||||
print_time_log(f"{masked_phone} 正在使用本地 IP")
|
||||
|
||||
# 第二次请求:发送兑换请求,使用代理 IP 或本地 IP
|
||||
url = "https://wapact.189.cn:9001/gateway/standExchange/detailNew/exchange"
|
||||
|
||||
# 记录请求开始时间
|
||||
request_start_time = datetime.datetime.now() # 获取当前时间,精确到微秒
|
||||
|
||||
# 发送请求
|
||||
async with s.post(url, json={"activityId": aid}, cookies=cookies, proxy=proxy) as r:
|
||||
# 记录请求结束时间
|
||||
request_end_time = datetime.datetime.now() # 获取当前时间,精确到微秒
|
||||
|
||||
print(f'\n{str(get_network_time())[11:22]}')
|
||||
print(f"{masked_phone} 发送兑换请求的时间: {request_start_time.strftime('%Y-%m-%d %H:%M:%S.%f')}")
|
||||
|
||||
# 打印请求耗时,精确到微秒
|
||||
print(f"{masked_phone} 请求耗时: {(request_end_time - request_start_time).total_seconds():.6f} 秒")
|
||||
|
||||
# 处理响应
|
||||
if r.status == 412:
|
||||
print(f"{masked_phone} 遇到连续 412 错误,已终止本次兑换!")
|
||||
return
|
||||
print(f"{masked_phone} 响应码: {r.status} {await r.text()}")
|
||||
if r.status == 200:
|
||||
r_json = await r.json()
|
||||
if r_json["code"] == 0:
|
||||
if r_json["biz"] != {} and r_json["biz"]["resultCode"] in errcode:
|
||||
print(f'{masked_phone} ------ {str(get_network_time())[11:22]} ------ {title} {errcode[r_json["biz"]["resultCode"]]}')
|
||||
|
||||
if r_json["biz"]["resultCode"] in ["0", "412"]:
|
||||
if r_json["biz"]["resultCode"] == "0":
|
||||
msg = phone + ":" + title + "兑换成功"
|
||||
send(uid, msg) # 发送推送通知
|
||||
if phone not in dhjl[yf][title]:
|
||||
dhjl[yf][title] += "#" + phone
|
||||
with open('电信金豆换话费.log', 'w') as f:
|
||||
json.dump(dhjl, f, ensure_ascii=False)
|
||||
else:
|
||||
print_time_log(f'{masked_phone} {r_json}')
|
||||
else:
|
||||
print_time_log(f"{masked_phone} 兑换请求失败: {await r.text()}")
|
||||
|
||||
except Exception as e:
|
||||
print_time_log(f"{masked_phone} 发生错误: {e}")
|
||||
# print(f"详细错误信息: {traceback.format_exc()}") # 打印详细的错误堆栈
|
||||
|
||||
|
||||
async def dh(phone, s, title, aid, wt, uid):
|
||||
global h # 使用全局变量 h
|
||||
masked_phone = phone[:3] + '****' + phone[-4:]
|
||||
print_time_log(f"{masked_phone} {title} 【开始兑换】")
|
||||
cs = 0
|
||||
tasks = []
|
||||
creat_start_time = datetime.datetime.now() # 获取当前时间,精确到微秒
|
||||
while cs < 1:
|
||||
# 提取金额
|
||||
amount = title.split('元')[0]
|
||||
if (h == 9 and title in morning_exchanges) or (h == 13 and title in afternoon_exchanges):
|
||||
tasks.append(exchange(phone, s, title, aid, uid, amount))
|
||||
else:
|
||||
print_time_log(f"{masked_phone} 商品:{title} 不在兑换时间范围内,跳过兑换")
|
||||
cs += 1
|
||||
await asyncio.sleep(0.1)
|
||||
creat_end_time = datetime.datetime.now() # 获取当前时间,精确到微秒
|
||||
print_time_log(f"{masked_phone} 创建了【{cs}】次并发任务 耗时:{(creat_end_time - creat_start_time).total_seconds():.6f}秒")
|
||||
while wt > get_network_time().timestamp():
|
||||
await asyncio.sleep(1)
|
||||
await asyncio.gather(*tasks)
|
||||
|
||||
def aes_ecb_encrypt(plaintext, key):
|
||||
key = key.encode('utf-8')
|
||||
if len(key) not in [16, 24, 32]:
|
||||
raise ValueError("密钥长度必须为16/24/32字节")
|
||||
|
||||
# 对明文进行PKCS7填充
|
||||
padded_data = pad(plaintext.encode('utf-8'), AES.block_size)
|
||||
#padded_data = plaintext.encode('utf-8')
|
||||
# 创建AES ECB加密器
|
||||
cipher = AES.new(key, AES.MODE_ECB)
|
||||
|
||||
# 加密并返回Base64编码结果
|
||||
ciphertext = cipher.encrypt(padded_data)
|
||||
return base64.b64encode(ciphertext).decode('utf-8')
|
||||
|
||||
async def ks(phone, ticket, uid):
|
||||
global h, wt # 使用全局变量 h 和 wt
|
||||
masked_phone = phone[:3] + '****' + phone[-4:]
|
||||
headers = {
|
||||
"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",
|
||||
"Referer": "https://wapact.189.cn:9001/JinDouMall/JinDouMall_independentDetails.html"
|
||||
}
|
||||
|
||||
timeout = aiohttp.ClientTimeout(total=20) # 设置超时时间
|
||||
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context), headers=headers, timeout=timeout) as s:
|
||||
try:
|
||||
cookies = await gjc.get_rs('https://wapact.189.cn:9001/gateway/standExchange/detailNew/exchange', session=s)
|
||||
|
||||
s.cookie_jar.update_cookies(cookies)
|
||||
login_data = {
|
||||
"ticket": ticket,
|
||||
"backUrl": "https%3A%2F%2Fwapact.189.cn%3A9001",
|
||||
"platformCode": "P201010301",
|
||||
"loginType": 2
|
||||
}
|
||||
encrypted_data = aes_ecb_encrypt(json.dumps(login_data), 'telecom_wap_2018')
|
||||
# 登录请求
|
||||
max_retries = 3 # 最大重试次数
|
||||
retries = 0
|
||||
while retries < max_retries:
|
||||
try:
|
||||
login_response = await s.post(
|
||||
'https://wapact.189.cn:9001/unified/user/login',
|
||||
data=encrypted_data,
|
||||
headers={
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
"Accept": "application/json, text/javascript, */*; q=0.01"
|
||||
}
|
||||
)
|
||||
|
||||
# 处理登录响应
|
||||
if login_response.status == 200:
|
||||
login = await login_response.json()
|
||||
break # 如果成功,跳出循环
|
||||
elif login_response.status == 412:
|
||||
print_time_log(f"{masked_phone} 登录请求失败,HTTP状态码: {login_response.status}, 直接重新调用 ks 函数...")
|
||||
return await ks(phone, ticket, uid) # 直接从头开始调用 ks 函数
|
||||
else:
|
||||
print_time_log(f"{masked_phone} 登录请求失败,HTTP状态码: {login_response.status}")
|
||||
print_time_log(f"响应内容: {await login_response.text()}")
|
||||
|
||||
except (aiohttp.ClientError, asyncio.TimeoutError) as e:
|
||||
retries += 1
|
||||
print_time_log(f"{masked_phone} 登录请求失败,重试 {retries}/{max_retries}... 错误信息: {e}")
|
||||
await asyncio.sleep(2 ** retries) # 指数退避算法等待时间
|
||||
|
||||
if retries == max_retries:
|
||||
print_time_log(f"{masked_phone} 登录失败,达到最大重试次数. 尝试重新调用 ks 函数...")
|
||||
return await ks(phone, ticket, uid) # 递归调用 ks 函数
|
||||
|
||||
if 'login' in locals() and login['code'] == 0:
|
||||
s.headers["Authorization"] = "Bearer " + login["biz"]["token"]
|
||||
|
||||
r = await s.get('https://wapact.189.cn:9001/gateway/golden/api/queryInfo')
|
||||
r_json = await r.json()
|
||||
amountTotal = r_json["biz"]["amountTotal"]
|
||||
print_time_log(f'{masked_phone} 金豆余额:{amountTotal}')
|
||||
|
||||
queryBigDataAppGetOrInfo = await s.get('https://wapact.189.cn:9001/gateway/golden/goldGoods/getGoodsList?floorType=0&userType=1&page=1&order=3&tabOrder=')
|
||||
queryBigDataAppGetOrInfo_json = await queryBigDataAppGetOrInfo.json()
|
||||
|
||||
# 检查列表是否为空
|
||||
if "biz" in queryBigDataAppGetOrInfo_json and "ExchangeGoodslist" in queryBigDataAppGetOrInfo_json["biz"]:
|
||||
for i in queryBigDataAppGetOrInfo_json["biz"]["ExchangeGoodslist"]:
|
||||
if '话费' not in i["title"]:
|
||||
continue
|
||||
for j in morning_exchanges:
|
||||
if j in i["title"]:
|
||||
jp["9"][j] = i["id"]
|
||||
for j in afternoon_exchanges:
|
||||
if j in i["title"]:
|
||||
jp["13"][j] = i["id"]
|
||||
else:
|
||||
print_time_log(f"{masked_phone} 获取兑换商品列表失败")
|
||||
|
||||
h = get_network_time().hour
|
||||
if 11 > h:
|
||||
h = 9
|
||||
else:
|
||||
h = 13
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
h = int(sys.argv[1])
|
||||
|
||||
d = jp[str(h)]
|
||||
|
||||
wt = t(h) + kswt
|
||||
|
||||
tasks = []
|
||||
for di in sorted(d.keys(), key=lambda x: float(x.replace('元话费', '')), reverse=True):
|
||||
if di not in dhjl[yf]:
|
||||
dhjl[yf][di] = ""
|
||||
if phone in dhjl[yf][di]:
|
||||
print_time_log(f"{masked_phone} {di} 【已兑换】")
|
||||
print_time_log(f"{masked_phone} {di} 【跳过兑换】")
|
||||
else:
|
||||
print_time_log(f"{masked_phone} {di} 【未兑换】")
|
||||
if wt - time_module.time() > 30 * 60:
|
||||
print_time_log(f"等待时间超过30分钟,退出运行")
|
||||
return
|
||||
|
||||
tasks.append(dh(phone, s, di, d[di], wt, uid))
|
||||
print_time_log(f"{masked_phone} 共计【{len(tasks)}】个兑换任务 正在进行中~")
|
||||
await asyncio.gather(*tasks)
|
||||
else:
|
||||
print_time_log(f"{masked_phone} 获取token失败, 错误信息: {login['message']}")
|
||||
except Exception as e:
|
||||
print_time_log(f"{masked_phone} 发生错误: {e}")
|
||||
return # 跳过当前账户,继续处理其他账户
|
||||
|
||||
|
||||
async def main():
|
||||
global wt, rs, h # 使用全局变量 wt, rs, h
|
||||
headers = {
|
||||
"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",
|
||||
"Referer": "https://wapact.189.cn:9001/JinDouMall/JinDouMall_independentDetails.html"
|
||||
}
|
||||
|
||||
timeout = aiohttp.ClientTimeout(total=20) # 设置超时时间
|
||||
|
||||
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context), headers=headers, timeout=timeout) as ss:
|
||||
r = await ss.get('https://wapact.189.cn:9001/gateway/standExchange/detailNew/exchange')
|
||||
|
||||
if '$_ts=window' in await r.text():
|
||||
rs = 1
|
||||
# first_request()
|
||||
else:
|
||||
rs = 0
|
||||
|
||||
# 获取账号列表
|
||||
chinaTelecomAccount = os.environ.get('chinaTelecomAccount')
|
||||
if not chinaTelecomAccount:
|
||||
print("未检测到账号")
|
||||
return
|
||||
|
||||
accounts = chinaTelecomAccount.split('&')
|
||||
account_count = len(accounts)
|
||||
print_time_log(f"检测到 【{account_count}】 个账号")
|
||||
|
||||
# 分批次处理账号,每批次20个账号
|
||||
batch_size = 20
|
||||
for i in range(0, account_count, batch_size):
|
||||
batch_accounts = accounts[i:i + batch_size]
|
||||
tasks = []
|
||||
for account in batch_accounts:
|
||||
account_info = account.split('#')
|
||||
phone = account_info[0]
|
||||
password = account_info[1]
|
||||
uid = account_info[-1]
|
||||
ticket = False
|
||||
masked_phone = phone[:3] + '****' + phone[-4:]
|
||||
if phone in load_token:
|
||||
print_time_log(f'{masked_phone} 使用缓存登录')
|
||||
ticket = get_ticket(phone, load_token[phone]['userId'], load_token[phone]['token'])
|
||||
|
||||
if not ticket:
|
||||
print_time_log(f'{masked_phone} 使用密码登录')
|
||||
ticket = userLoginNormal(phone, password)
|
||||
|
||||
if ticket:
|
||||
tasks.append(ks(phone, ticket, uid))
|
||||
else:
|
||||
print_time_log(f'{masked_phone} ️登录失败')
|
||||
continue # 跳过登录失败的账号
|
||||
|
||||
# 等待到设定时间
|
||||
while wt > datetime.datetime.now().timestamp():
|
||||
await asyncio.sleep(1)
|
||||
|
||||
await asyncio.gather(*tasks)
|
||||
print_time_log(f"完成批次 {i // batch_size + 1} 的账号处理")
|
||||
|
||||
# 等待一段时间再处理下一个批次
|
||||
await asyncio.sleep(2) # 等待2秒
|
||||
|
||||
|
||||
START_LOG = rf'''
|
||||
+--------------------------------------------------------------------+
|
||||
话费兑换本,有几个需要根据自己机器配置来调整的地方:
|
||||
|
||||
1.打开脚本,找到第二次等待时间,大概381和383行,根据情况调整secone秒数,一般58秒。
|
||||
|
||||
2.次数改一下,找到cs < 1,那一行,1就是次数,可以修改5次看看。
|
||||
+--------------------------------------------------------------------+
|
||||
'''
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(START_LOG)
|
||||
print(f" 提醒:程序将提前【{kswt} 秒】启动兑换流程")
|
||||
if len(sys.argv) > 1:
|
||||
h = int(sys.argv[1])
|
||||
else:
|
||||
h = None # 默认值为 None
|
||||
asyncio.run(main())
|
||||
|
||||
# 获取当前月份
|
||||
current_month = get_network_time().strftime("%Y%m")
|
||||
|
||||
# 读取原始日志文件
|
||||
try:
|
||||
with open('电信金豆换话费.log', 'r') as fr:
|
||||
dhjl = json.load(fr)
|
||||
except FileNotFoundError:
|
||||
dhjl = {}
|
||||
|
||||
# 初始化新的日志结构
|
||||
dhjl2 = {}
|
||||
|
||||
# 只处理当前月份的数据
|
||||
if current_month in dhjl:
|
||||
records = dhjl[current_month]
|
||||
for fee, phones in records.items():
|
||||
phone_list = phones.strip('#').split('#')
|
||||
for phone in phone_list:
|
||||
if phone not in dhjl2:
|
||||
dhjl2[phone] = {}
|
||||
if current_month not in dhjl2[phone]:
|
||||
dhjl2[phone][current_month] = []
|
||||
dhjl2[phone][current_month].append(fee)
|
||||
|
||||
# 写入新的日志文件
|
||||
with open('电信金豆换话费2.log', 'w') as fw:
|
||||
json.dump(dhjl2, fw, ensure_ascii=False, indent=4)
|
||||
|
||||
# 检查当前时间是否在10:05:10到11:00:00或14:05:10到15:00:00之间
|
||||
current_time = get_network_time()
|
||||
start_time_1 = current_time.replace(hour=10, minute=0, second=00)
|
||||
end_time_1 = current_time.replace(hour=10, minute=20, second=0)
|
||||
start_time_2 = current_time.replace(hour=14, minute=0, second=00)
|
||||
end_time_2 = current_time.replace(hour=14, minute=20, second=0)
|
||||
|
||||
if (start_time_1 <= current_time < end_time_1) or (start_time_2 <= current_time < end_time_2):
|
||||
# 运行汇总推送脚本
|
||||
subprocess.run(["python", "汇总推送.py"])
|
||||
else:
|
||||
print("当前不在推送时间,不运行汇总推送脚本。")
|
||||
540
脚本库/web版/账密/电信金豆换话费/2025-07-19_电信金豆换话费_57a582c0.py
Normal file
540
脚本库/web版/账密/电信金豆换话费/2025-07-19_电信金豆换话费_57a582c0.py
Normal file
@@ -0,0 +1,540 @@
|
||||
# Source: https://gitee.com/jdqlscript/yyt/blob/master/%E7%94%B5%E4%BF%A1old/%E7%94%B5%E4%BF%A12/%E7%94%B5%E4%BF%A1%E9%87%91%E8%B1%86%E6%8D%A2%E8%AF%9D%E8%B4%B9.py
|
||||
# Raw: https://gitee.com/jdqlscript/yyt/raw/master/%E7%94%B5%E4%BF%A1old/%E7%94%B5%E4%BF%A12/%E7%94%B5%E4%BF%A1%E9%87%91%E8%B1%86%E6%8D%A2%E8%AF%9D%E8%B4%B9.py
|
||||
# Repo: jdqlscript/yyt
|
||||
# Path: 电信old/电信2/电信金豆换话费.py
|
||||
# UploadedAt: 2025-07-19T22:58:22+08:00
|
||||
# SHA256: 57a582c067ad187f7c88e0eb8f1fe18b927452b258ac0e935e0ed8ac61699429
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
|
||||
'''
|
||||
变量:chinaTelecomAccount
|
||||
变量格式: 手机号#服务密码
|
||||
多号创建多个变量&隔开
|
||||
'''
|
||||
import requests
|
||||
import re
|
||||
import time
|
||||
import json
|
||||
import random
|
||||
import datetime
|
||||
import base64
|
||||
import threading
|
||||
import ssl
|
||||
import execjs
|
||||
import os
|
||||
import sys
|
||||
import certifi
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import PKCS1_v1_5
|
||||
from Crypto.Cipher import DES3
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
from Crypto.Util.strxor import strxor
|
||||
from Crypto.Cipher import AES
|
||||
from http import cookiejar # Python 2: import cookielib as cookiejar
|
||||
from requests.adapters import HTTPAdapter
|
||||
from requests.packages.urllib3.util.ssl_ import create_urllib3_context
|
||||
|
||||
|
||||
class BlockAll(cookiejar.CookiePolicy):
|
||||
return_ok = set_ok = domain_return_ok = path_return_ok = lambda self, *args, **kwargs: False
|
||||
netscape = True
|
||||
rfc2965 = hide_cookie2 = False
|
||||
|
||||
def printn(m):
|
||||
print(f'\n{m}')
|
||||
ORIGIN_CIPHERS = ('DEFAULT@SECLEVEL=1')
|
||||
|
||||
ip_list = []
|
||||
class DESAdapter(HTTPAdapter):
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
A TransportAdapter that re-enables 3DES support in Requests.
|
||||
"""
|
||||
CIPHERS = ORIGIN_CIPHERS.split(':')
|
||||
random.shuffle(CIPHERS)
|
||||
CIPHERS = ':'.join(CIPHERS)
|
||||
self.CIPHERS = CIPHERS + ':!aNULL:!eNULL:!MD5'
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def init_poolmanager(self, *args, **kwargs):
|
||||
context = create_urllib3_context(ciphers=self.CIPHERS)
|
||||
kwargs['ssl_context'] = context
|
||||
return super(DESAdapter, self).init_poolmanager(*args, **kwargs)
|
||||
|
||||
def proxy_manager_for(self, *args, **kwargs):
|
||||
context = create_urllib3_context(ciphers=self.CIPHERS)
|
||||
kwargs['ssl_context'] = context
|
||||
return super(DESAdapter, self).proxy_manager_for(*args, **kwargs)
|
||||
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
ssl_context = ssl.create_default_context()
|
||||
ssl_context.check_hostname = False
|
||||
ssl_context.verify_mode = ssl.CERT_NONE
|
||||
ssl_context.set_ciphers('DEFAULT@SECLEVEL=0')
|
||||
ss = requests.session()
|
||||
ss.verify = certifi.where()
|
||||
ss.ssl=ssl_context
|
||||
ss.headers={"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","Referer":"https://wapact.189.cn:9001/JinDouMall/JinDouMall_independentDetails.html"}
|
||||
ss.mount('https://', DESAdapter())
|
||||
yc = 0.1
|
||||
wt = 0
|
||||
kswt = -3
|
||||
yf = datetime.datetime.now().strftime("%Y%m")
|
||||
|
||||
|
||||
jp = {"9":{},"12":{},"13":{},"23":{}}
|
||||
|
||||
|
||||
try:
|
||||
with open('电信金豆换话费.log') as fr:
|
||||
dhjl = json.load(fr)
|
||||
except:
|
||||
dhjl = {}
|
||||
if yf not in dhjl:
|
||||
dhjl[yf] = {}
|
||||
|
||||
|
||||
|
||||
|
||||
wxp={}
|
||||
errcode = {
|
||||
"0":"兑换成功",
|
||||
"412":"兑换次数已达上限",
|
||||
"413":"商品已兑完",
|
||||
"420":"未知错误",
|
||||
"410":"该活动已失效~",
|
||||
"Y0001":"当前等级不足,去升级兑当前话费",
|
||||
"Y0002":"使用翼相连网络600分钟或连接并拓展网络500分钟可兑换此奖品",
|
||||
"Y0003":"使用翼相连共享流量400M或共享WIFI:2GB可兑换此奖品",
|
||||
"Y0004":"使用翼相连共享流量2GB可兑换此奖品",
|
||||
"Y0005":"当前等级不足,去升级兑当前话费",
|
||||
"E0001":"您的网龄不足10年,暂不能兑换"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#加密参数
|
||||
key = b'1234567`90koiuyhgtfrdews'
|
||||
iv = 8 * b'\0'
|
||||
|
||||
public_key_b64 = '''-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBkLT15ThVgz6/NOl6s8GNPofdWzWbCkWnkaAm7O2LjkM1H7dMvzkiqdxU02jamGRHLX/ZNMCXHnPcW/sDhiFCBN18qFvy8g6VYb9QtroI09e176s+ZCtiv7hbin2cCTj99iUpnEloZm19lwHyo69u5UMiPMpq0/XKBO8lYhN/gwIDAQAB
|
||||
-----END PUBLIC KEY-----'''
|
||||
|
||||
public_key_data = '''-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+ugG5A8cZ3FqUKDwM57GM4io6JGcStivT8UdGt67PEOihLZTw3P7371+N47PrmsCpnTRzbTgcupKtUv8ImZalYk65dU8rjC/ridwhw9ffW2LBwvkEnDkkKKRi2liWIItDftJVBiWOh17o6gfbPoNrWORcAdcbpk2L+udld5kZNwIDAQAB
|
||||
-----END PUBLIC KEY-----'''
|
||||
|
||||
|
||||
def t(h):
|
||||
date = datetime.datetime.now()
|
||||
date_zero = datetime.datetime.now().replace(year=date.year, month=date.month, day=date.day, hour=h, minute=59, second=59)
|
||||
date_zero_time = int(time.mktime(date_zero.timetuple()))
|
||||
return date_zero_time
|
||||
|
||||
|
||||
|
||||
def encrypt(text):
|
||||
cipher = DES3.new(key, DES3.MODE_CBC, iv)
|
||||
ciphertext = cipher.encrypt(pad(text.encode(), DES3.block_size))
|
||||
return ciphertext.hex()
|
||||
|
||||
def decrypt(text):
|
||||
ciphertext = bytes.fromhex(text)
|
||||
cipher = DES3.new(key, DES3.MODE_CBC, iv)
|
||||
plaintext = unpad(cipher.decrypt(ciphertext), DES3.block_size)
|
||||
return plaintext.decode()
|
||||
|
||||
|
||||
|
||||
def b64(plaintext):
|
||||
public_key = RSA.import_key(public_key_b64)
|
||||
cipher = PKCS1_v1_5.new(public_key)
|
||||
ciphertext = cipher.encrypt(plaintext.encode())
|
||||
return base64.b64encode(ciphertext).decode()
|
||||
|
||||
def encrypt_para(plaintext):
|
||||
public_key = RSA.import_key(public_key_data)
|
||||
cipher = PKCS1_v1_5.new(public_key)
|
||||
ciphertext = cipher.encrypt(plaintext.encode())
|
||||
return ciphertext.hex()
|
||||
|
||||
|
||||
def encode_phone(text):
|
||||
encoded_chars = []
|
||||
for char in text:
|
||||
encoded_chars.append(chr(ord(char) + 2))
|
||||
return ''.join(encoded_chars)
|
||||
|
||||
def ophone(t):
|
||||
key = b'34d7cb0bcdf07523'
|
||||
utf8_key = key.decode('utf-8')
|
||||
utf8_t = t.encode('utf-8')
|
||||
cipher = AES.new(key, AES.MODE_ECB)
|
||||
ciphertext = cipher.encrypt(pad(utf8_t, AES.block_size))
|
||||
return ciphertext.hex()
|
||||
|
||||
def send(uid,content):
|
||||
r = requests.post('https://wxpusher.zjiecode.com/api/send/message',json={"appToken":appToken,"content":content,"contentType":1,"uids":[uid]}).json()
|
||||
return r
|
||||
|
||||
|
||||
def userLoginNormal(phone,password):
|
||||
alphabet = 'abcdef0123456789'
|
||||
uuid = [''.join(random.sample(alphabet, 8)),''.join(random.sample(alphabet, 4)),'4'+''.join(random.sample(alphabet, 3)),''.join(random.sample(alphabet, 4)),''.join(random.sample(alphabet, 12))]
|
||||
timestamp=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
loginAuthCipherAsymmertric = 'iPhone 14 15.4.' + uuid[0] + uuid[1] + phone + timestamp + password[:6] + '0$$$0.'
|
||||
login_date = {
|
||||
"headerInfos": {
|
||||
"code": "userLoginNormal",
|
||||
"timestamp": timestamp,
|
||||
"broadAccount": "",
|
||||
"broadToken": "",
|
||||
"clientType": "#10.5.0#channel50#iPhone 14 Pro Max#",
|
||||
"shopId": "20002",
|
||||
"source": "110003",
|
||||
"sourcePassword": "Sid98s",
|
||||
"token": "",
|
||||
"userLoginName": encode_phone(phone)
|
||||
},
|
||||
"content": {
|
||||
"attach": "test",
|
||||
"fieldData": {
|
||||
"loginType": "4",
|
||||
"accountType": "",
|
||||
"loginAuthCipherAsymmertric": b64(loginAuthCipherAsymmertric),
|
||||
"deviceUid": uuid[0] + uuid[1] + uuid[2],
|
||||
"phoneNum": encode_phone(phone),
|
||||
"isChinatelecom": "0",
|
||||
"systemVersion": "15.4.0",
|
||||
"authentication": encode_phone(password)
|
||||
}
|
||||
}
|
||||
}
|
||||
r = ss.post('https://appgologin.189.cn:9031/login/client/userLoginNormal', json=login_date).json()
|
||||
|
||||
|
||||
|
||||
l = r['responseData']['data']['loginSuccessResult']
|
||||
|
||||
if l:
|
||||
load_token[phone] = l
|
||||
with open(load_token_file, 'w') as f:
|
||||
json.dump(load_token, f)
|
||||
ticket = get_ticket(phone,l['userId'],l['token'])
|
||||
return ticket
|
||||
|
||||
return False
|
||||
def get_ticket(phone,userId,token):
|
||||
r = ss.post('https://appgologin.189.cn:9031/map/clientXML',data='<Request><HeaderInfos><Code>getSingle</Code><Timestamp>'+datetime.datetime.now().strftime("%Y%m%d%H%M%S")+'</Timestamp><BroadAccount></BroadAccount><BroadToken></BroadToken><ClientType>#9.6.1#channel50#iPhone 14 Pro Max#</ClientType><ShopId>20002</ShopId><Source>110003</Source><SourcePassword>Sid98s</SourcePassword><Token>'+token+'</Token><UserLoginName>'+phone+'</UserLoginName></HeaderInfos><Content><Attach>test</Attach><FieldData><TargetId>'+encrypt(userId)+'</TargetId><Url>4a6862274835b451</Url></FieldData></Content></Request>',headers={'user-agent': 'CtClient;10.4.1;Android;13;22081212C;NTQzNzgx!#!MTgwNTg1'})
|
||||
|
||||
#printn(phone, '获取ticket', re.findall('<Reason>(.*?)</Reason>',r.text)[0])
|
||||
|
||||
tk = re.findall('<Ticket>(.*?)</Ticket>',r.text)
|
||||
if len(tk) == 0:
|
||||
return False
|
||||
|
||||
|
||||
return decrypt(tk[0])
|
||||
|
||||
|
||||
|
||||
def queryInfo(phone,s):
|
||||
global rs
|
||||
a = 1
|
||||
while a < 2:
|
||||
if rs:
|
||||
bd = js.call('main').split('=')
|
||||
ck[bd[0]] = bd[1]
|
||||
|
||||
r = s.get('https://wapact.189.cn:9001/gateway/golden/api/queryInfo',cookies=ck).json()
|
||||
|
||||
try:
|
||||
printn(f'{phone} 金豆余额 {r["biz"]["amountTotal"]}')
|
||||
amountTotal= r["biz"]["amountTotal"]
|
||||
except:
|
||||
amountTotal = 0
|
||||
if amountTotal< 3000:
|
||||
if rs == 1:
|
||||
bd = js.call('main').split('=')
|
||||
ck [bd[0]] = bd[1]
|
||||
|
||||
|
||||
res = s.post('http://wapact.189.cn:9000/gateway/stand/detail/exchange',json={"activityId":jdaid},cookies=ck).text
|
||||
printn(res)
|
||||
if '$_ts=window' in res:
|
||||
first_request()
|
||||
rs = 1
|
||||
|
||||
time.sleep(3)
|
||||
else:
|
||||
return r
|
||||
a += 1
|
||||
|
||||
|
||||
return r
|
||||
|
||||
|
||||
def exchange(phone,s,title,aid, uid):
|
||||
|
||||
try:
|
||||
bd = js.call('main').split('=')
|
||||
ck [bd[0]] = bd[1]
|
||||
r = s.post('https://wapact.189.cn:9001/gateway/standExchange/detailNew/exchange',json={"activityId":aid},cookies=ck)
|
||||
printn(f"响应码: {r.status_code}")
|
||||
|
||||
if '$_ts=window' in r.text:
|
||||
|
||||
first_request(r.text)
|
||||
return
|
||||
r = r.json()
|
||||
|
||||
if r["code"] == 0:
|
||||
if r["biz"] != {} and r["biz"]["resultCode"] in errcode:
|
||||
#printn(str(datetime.datetime.now())[11:22], phone, title,errcode[r["biz"]["resultCode"]])
|
||||
printn(f'{str(datetime.datetime.now())[11:22]} {phone} {title} {errcode[r["biz"]["resultCode"]]}')
|
||||
|
||||
|
||||
if r["biz"]["resultCode"] in ["0","412"]:
|
||||
if r["biz"]["resultCode"] == "0":
|
||||
msg = phone+":"+title+"兑换成功"
|
||||
|
||||
send(uid, msg)
|
||||
if phone not in dhjl[yf][title]:
|
||||
dhjl[yf][title] += "#"+phone
|
||||
with open('电信金豆换话费.log', 'w') as f:
|
||||
json.dump(dhjl, f, ensure_ascii=False)
|
||||
|
||||
|
||||
else:
|
||||
#printn(str(datetime.datetime.now())[11:22], phone, r["message"])
|
||||
printn(f'{str(datetime.datetime.now())[11:22]} {phone} {r}')
|
||||
|
||||
except Exception as e:
|
||||
#print(e)
|
||||
pass
|
||||
|
||||
|
||||
def dh(phone,s,title,aid,wt, uid):
|
||||
|
||||
while wt > time.time():
|
||||
pass
|
||||
|
||||
printn(f"{str(datetime.datetime.now())[11:22]} {phone} {title} 开始兑换")
|
||||
|
||||
if rs:
|
||||
bd = js.call('main').split('=')
|
||||
ck [bd[0]] = bd[1]
|
||||
for cs in range(cfcs):
|
||||
threading.Thread(target=exchange,args=(phone,s,title,aid, uid)).start()
|
||||
#time.sleep(5)
|
||||
|
||||
|
||||
|
||||
def lottery(s):
|
||||
for cishu in range(3):
|
||||
try:
|
||||
if rs:
|
||||
bd = js.call('main').split('=')
|
||||
ck [bd[0]] = bd[1]
|
||||
else:
|
||||
cookie = {}
|
||||
r = s.post('https://wapact.189.cn:9001/gateway/golden/api/lottery',json={"activityId":"6384b49b1e44396da4f1e4a3"},cookies=ck)
|
||||
except:
|
||||
pass
|
||||
time.sleep(3)
|
||||
|
||||
def aes_ecb_encrypt(plaintext, key):
|
||||
key = key.encode('utf-8')
|
||||
if len(key) not in [16, 24, 32]:
|
||||
raise ValueError("密钥长度必须为16/24/32字节")
|
||||
|
||||
# 对明文进行PKCS7填充
|
||||
padded_data = pad(plaintext.encode('utf-8'), AES.block_size)
|
||||
#padded_data = plaintext.encode('utf-8')
|
||||
# 创建AES ECB加密器
|
||||
cipher = AES.new(key, AES.MODE_ECB)
|
||||
|
||||
# 加密并返回Base64编码结果
|
||||
ciphertext = cipher.encrypt(padded_data)
|
||||
return base64.b64encode(ciphertext).decode('utf-8')
|
||||
def ks(phone, ticket, uid):
|
||||
global wt
|
||||
wxp[phone] = uid
|
||||
s = requests.session()
|
||||
s.headers={"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","Referer":"https://wapact.189.cn:9001/JinDouMall/JinDouMall_independentDetails.html"}
|
||||
s.cookies.set_policy(BlockAll())
|
||||
s.mount('https://', DESAdapter())
|
||||
s.timeout = 30
|
||||
if rs:
|
||||
bd = js.call('main').split('=')
|
||||
ck [bd[0]] = bd[1]
|
||||
|
||||
data = aes_ecb_encrypt(json.dumps({"ticket":ticket,"backUrl":"https%3A%2F%2Fwapact.189.cn%3A9001","platformCode":"P201010301","loginType":2}), 'telecom_wap_2018')
|
||||
|
||||
login = ss.post('https://wapact.189.cn:9001/unified/user/login',data=data, headers={"Content-Type":"application/json;charset=UTF-8","Accept":"application/json, text/javascript, */*; q=0.01"}, cookies=ck).json()
|
||||
# login = s.post('https://wapact.189.cn:9001/unified/user/login',json={"ticket":ticket,"backUrl":"https%3A%2F%2Fwapact.189.cn%3A9001","platformCode":"P201010301","loginType":2}, cookies=ck).json()
|
||||
if login['code'] == 0:
|
||||
printn(phone+" 获取token成功")
|
||||
s.headers["Authorization"] = "Bearer " + login["biz"]["token"]
|
||||
|
||||
queryInfo(phone,s)
|
||||
|
||||
|
||||
if rs:
|
||||
bd = js.call('main').split('=')
|
||||
ck [bd[0]] = bd[1]
|
||||
queryBigDataAppGetOrInfo = s.get('https://waphub.189.cn/gateway/golden/goldGoods/getGoodsList??floorType=0&userType=1&page&1&order=3&tabOrder=',cookies=ck).json()
|
||||
for i in queryBigDataAppGetOrInfo["biz"]["ExchangeGoodslist"]:
|
||||
if '话费' not in i["title"]:continue
|
||||
|
||||
if '0.5元' in i["title"] or '5元' in i["title"]:
|
||||
jp["9"][i["title"]] = i["id"]
|
||||
elif '1元' in i["title"] or '10元' in i["title"]:
|
||||
jp["13"][i["title"]] = i["id"]
|
||||
else:
|
||||
jp["12"][i["title"]] = i["id"]
|
||||
|
||||
|
||||
|
||||
h = datetime.datetime.now().hour
|
||||
if 11 > h > 1:
|
||||
h = 9
|
||||
|
||||
elif 23 > h > 1:
|
||||
h = 13
|
||||
|
||||
else:
|
||||
h = 23
|
||||
|
||||
if len(sys.argv) ==2:
|
||||
h = int(sys.argv[1])
|
||||
#h=23
|
||||
d = jp[str(h)]
|
||||
|
||||
wt = t(h) + kswt
|
||||
|
||||
if jp["12"] != {}:
|
||||
d.update(jp["12"])
|
||||
wt = 0
|
||||
|
||||
for di in d:
|
||||
#if '5' in di:
|
||||
if di not in dhjl[yf]:
|
||||
dhjl[yf][di] = ""
|
||||
if phone in dhjl[yf][di] :
|
||||
printn(f"{phone} {di} 已兑换")
|
||||
|
||||
else:
|
||||
|
||||
printn(f"{phone} {di}")
|
||||
if wt - time.time() > 20 * 60:
|
||||
print("等待时间超过20分钟")
|
||||
return
|
||||
|
||||
|
||||
threading.Thread(target=dh,args=(phone,s,di,d[di],wt, uid)).start()
|
||||
|
||||
|
||||
else:
|
||||
|
||||
printn(f"{phone} 获取token {login['message']}")
|
||||
|
||||
|
||||
|
||||
def first_request(res=''):
|
||||
global js, fw
|
||||
url = 'https://wapact.189.cn:9001/gateway/stand/detail/exchange'
|
||||
if res == '':
|
||||
response = ss.get(url)
|
||||
res = response.text
|
||||
soup = BeautifulSoup(res, 'html.parser')
|
||||
scripts = soup.find_all('script')
|
||||
for script in scripts:
|
||||
if 'src' in str(script):
|
||||
rsurl = re.findall('src="([^"]+)"', str(script))[0]
|
||||
|
||||
if '$_ts=window' in script.get_text():
|
||||
ts_code = script.get_text()
|
||||
|
||||
|
||||
urls = url.split('/')
|
||||
rsurl = urls[0] + '//' + urls[2] + rsurl
|
||||
#print(rsurl)
|
||||
ts_code += ss.get(rsurl).text
|
||||
content_code = soup.find_all('meta')[1].get('content')
|
||||
with open("瑞数通杀.js") as f:
|
||||
js_code_ym = f.read()
|
||||
js_code = js_code_ym.replace('content_code', content_code).replace("'ts_code'", ts_code)
|
||||
js = execjs.compile(js_code)
|
||||
for cookie in ss.cookies:
|
||||
ck[cookie.name] = cookie.value
|
||||
return content_code, ts_code, ck
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
print()
|
||||
global wt,rs
|
||||
r = ss.get('https://wapact.189.cn:9001/gateway/stand/detailNew/exchange')
|
||||
if '$_ts=window' in r.text:
|
||||
rs = 1
|
||||
print("瑞数加密已开启")
|
||||
first_request()
|
||||
else:
|
||||
print("瑞数加密已关闭")
|
||||
rs = 0
|
||||
if os.environ.get('chinaTelecomAccount')!= None:
|
||||
chinaTelecomAccount = os.environ.get('chinaTelecomAccount')
|
||||
else:
|
||||
chinaTelecomAccount = jdhf
|
||||
for i in chinaTelecomAccount.split('&'):
|
||||
|
||||
i = i.split('#')
|
||||
phone = i[0]
|
||||
password = i[1]
|
||||
uid = i[-1]
|
||||
ticket = False
|
||||
|
||||
if phone in load_token:
|
||||
printn(f'{phone} 使用缓存登录')
|
||||
ticket = get_ticket(phone,load_token[phone]['userId'],load_token[phone]['token'])
|
||||
|
||||
if ticket == False:
|
||||
printn(f'{phone} 使用密码登录')
|
||||
ticket = userLoginNormal(phone,password)
|
||||
|
||||
if ticket:
|
||||
threading.Thread(target=ks,args=(phone, ticket, uid)).start()
|
||||
|
||||
time.sleep(1)
|
||||
else:
|
||||
printn(f'{phone} 登录失败')
|
||||
|
||||
#手机号@密码@wxpusheruid
|
||||
jdhf = ""
|
||||
#重发次数
|
||||
cfcs = 15
|
||||
#wxpusher推送appToken
|
||||
appToken = ""
|
||||
jdaid = '60dd79533dc03d3c76bdde30'
|
||||
ck = {}
|
||||
load_token_file = 'chinaTelecom_cache.json'
|
||||
try:
|
||||
with open(load_token_file, 'r') as f:
|
||||
load_token = json.load(f)
|
||||
except:
|
||||
load_token = {}
|
||||
main()
|
||||
164
脚本库/web版/账密/稀土掘金/2025-04-28_sudojia_juejin_72513420.js
Normal file
164
脚本库/web版/账密/稀土掘金/2025-04-28_sudojia_juejin_72513420.js
Normal file
@@ -0,0 +1,164 @@
|
||||
// # Source: https://github.com/sudojia/AutoTaskScript/blob/script/src/web/sudojia_juejin.js
|
||||
// # Raw: https://raw.githubusercontent.com/sudojia/AutoTaskScript/script/src/web/sudojia_juejin.js
|
||||
// # Repo: sudojia/AutoTaskScript
|
||||
// # Path: src/web/sudojia_juejin.js
|
||||
// # UploadedAt: 2025-04-28T19:26:13+08:00
|
||||
// # SHA256: 7251342054b8f13aaaca34394af2829506de2ae87455cf13251f68775d831fef
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/**
|
||||
* 稀土掘金 https://juejin.cn/
|
||||
*
|
||||
* 仅每日签到(不维护了)
|
||||
* 获取 Cookie、只要 sessionid 的值和手动签到之后抓取 https://api.juejin.cn/growth_api/v1/check_in 的 url 拼接的 uuid=123456&spider=0&msToken=xxxxxx&a_bogus=xxxxxx 用 # 分开
|
||||
* 填写示例:
|
||||
* export JUEJIN_COOKIE = 'sessionid#uuid=123456&spider=0&msToken=xxxxxx&a_bogus=xxxxxx'
|
||||
* 多账号用换行,不要用 &
|
||||
*
|
||||
* @author Telegram@sudojia
|
||||
* @site https://blog.imzjw.cn
|
||||
* @date 2022/01/19
|
||||
* @lastModify 2024/08/16
|
||||
*
|
||||
* const $ = new Env('稀土掘金')
|
||||
* cron: 5 10 * * *
|
||||
*/
|
||||
const initScript = require('../utils/initScript')
|
||||
const {$, notify, sudojia, checkUpdate} = initScript('稀土掘金');
|
||||
const jueJinList = process.env.JUEJIN_COOKIE ? process.env.JUEJIN_COOKIE.split(/\n/) : [];
|
||||
let message = '';
|
||||
// 接口地址
|
||||
const baseUrl = 'https://api.juejin.cn';
|
||||
// 请求头
|
||||
const headers = {
|
||||
'Accept': '*/*',
|
||||
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
||||
"Content-type": "application/json",
|
||||
'Referer': 'https://juejin.cn/',
|
||||
'Origin': 'https://juejin.cn',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
|
||||
};
|
||||
|
||||
!(async () => {
|
||||
await checkUpdate($.name, jueJinList);
|
||||
// console.log(`\n已随机分配 User-Agent\n\n${headers['user-agent'] || headers['User-Agent']}`);
|
||||
for (let i = 0; i < jueJinList.length; i++) {
|
||||
const [juejinCookie, urlList] = jueJinList[i].split('#');
|
||||
headers.Cookie = `sid_tt=${juejinCookie}; sessionid=${juejinCookie}; sessionid_ss=${juejinCookie}`;
|
||||
const index = i + 1;
|
||||
console.log(`\n*****第[${index}]个${$.name}账号*****`);
|
||||
if (await checkStatus()) {
|
||||
console.error('Cookie 已失效');
|
||||
await notify.sendNotify(`「Cookie失效通知」`, `${$.name}账号[${index}] Cookie 已失效,请重新登录获取 Cookie\n\n`);
|
||||
continue;
|
||||
}
|
||||
message += `📣====${$.name}账号[${index}]====📣\n`;
|
||||
await $.wait(sudojia.getRandomWait(800, 1200));
|
||||
await main(urlList);
|
||||
await $.wait(sudojia.getRandomWait(2000, 2500));
|
||||
}
|
||||
if (message) {
|
||||
await notify.sendNotify(`「${$.name}」`, `${message}`);
|
||||
}
|
||||
})().catch((e) => $.logErr(e)).finally(() => $.done());
|
||||
|
||||
/**
|
||||
* 主函数
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function main(urlList) {
|
||||
await getUserName();
|
||||
await $.wait(sudojia.getRandomWait(2300, 2700));
|
||||
await checkIn(urlList);
|
||||
await $.wait(sudojia.getRandomWait(3000, 3500));
|
||||
await getOreNum(urlList);
|
||||
await $.wait(sudojia.getRandomWait(3000, 3500));
|
||||
await getCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
async function getUserName() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(baseUrl + '/user_api/v1/user/get_info_pack?aid=2608', 'post', headers, {
|
||||
"pack_req": {
|
||||
"user_counter": true,
|
||||
"user_growth_info": true,
|
||||
"user": true
|
||||
}
|
||||
});
|
||||
// 用户昵称
|
||||
const userName = data.data.user_basic.user_name;
|
||||
message += `【账号昵称】${userName}\n`;
|
||||
console.log(`【账号昵称】${userName}`);
|
||||
} catch (e) {
|
||||
console.error(`获取用户信息发生异常: ${e.response.data}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查状态
|
||||
*
|
||||
* @return {Promise<*>}
|
||||
*/
|
||||
async function checkStatus() {
|
||||
const data = await sudojia.sendRequest(baseUrl + '/growth_api/v1/get_today_status', 'get', headers);
|
||||
return 403 === data.err_no;
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到函数
|
||||
*
|
||||
* @returns {*}
|
||||
*/
|
||||
async function checkIn(urlList) {
|
||||
try {
|
||||
// uuid=7402961076386793000&spider=0&msToken=6N7P3ETmcpkVBSBdIEAoOvIE5TlEhnAmt382dbZpa1tNLnKhYR8QkGIKTJINouJxXGwc-JkvcwmUPhinCBGBtXg7ZsNn5LZzJtOpR4PSuRejD4spLQYUJ3tJdEurDng%3D&a_bogus=mX-QkcZ8Msm1Zhvtkhkz9GWEeOm0YWRkgZENqN9HUUo7
|
||||
const data = await sudojia.sendRequest(baseUrl + `/growth_api/v1/check_in?aid=2608&${urlList}`, 'post', headers);
|
||||
if (15001 === data.err_no) {
|
||||
console.log(data.err_msg);
|
||||
message += `【签到信息】${data.err_msg}\n`
|
||||
return;
|
||||
}
|
||||
console.log(`签到成功,获得 ${data.data.incr_point} 矿石`);
|
||||
message += `【签到信息】签到成功, 获得 ${data.data.incr_point} 矿石\n`
|
||||
} catch (e) {
|
||||
console.error(`签到时发生异常: ${e.response.data}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取总账号矿石数
|
||||
*/
|
||||
async function getOreNum(urlList) {
|
||||
const data = await sudojia.sendRequest(baseUrl + `/growth_api/v1/get_cur_point?aid=2608&${urlList}`, 'get', headers);
|
||||
console.log(`当前矿石数:${data.data}`);
|
||||
message += `【总矿石数】${data.data} 矿石\n`
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询免费抽奖次数
|
||||
*/
|
||||
async function queryFreeLuckyDrawCount(urlList) {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(baseUrl + `/growth_api/v1/lottery_config/get?aid=2608&${urlList}`, 'get', headers);
|
||||
// 获取免费抽奖次数
|
||||
return data.data.free_count;
|
||||
} catch (e) {
|
||||
console.error(`查询免费抽奖次数时发生异常: ${e.response.data}`);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计签到天数, 没什么用~
|
||||
*/
|
||||
async function getCount() {
|
||||
const data = await sudojia.sendRequest(baseUrl + '/growth_api/v1/get_counts?aid=2608', 'get', headers);
|
||||
console.log(`已连续签到${data.data.cont_count}天、累计签到${data.data.sum_count}天`);
|
||||
message += `【签到统计】已连续签到${data.data.cont_count}天、累计签到${data.data.sum_count}天\n`
|
||||
}
|
||||
85
脚本库/web版/账密/精易论坛/2023-10-25_jylt_48cbf2c9.py
Normal file
85
脚本库/web版/账密/精易论坛/2023-10-25_jylt_48cbf2c9.py
Normal file
@@ -0,0 +1,85 @@
|
||||
# Source: https://gitee.com/yangro/ql/blob/main/jylt.py
|
||||
# Raw: https://gitee.com/yangro/ql/raw/main/jylt.py
|
||||
# Repo: yangro/ql
|
||||
# Path: jylt.py
|
||||
# UploadedAt: 2023-10-25T14:45:53+08:00
|
||||
# SHA256: 48cbf2c964d538f8d9d2cb09d9cd35ee691e4d7dad7e962c8f18e2c2ae7d7bf4
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
# coding=utf-8
|
||||
"""
|
||||
每日7:25
|
||||
cron: 0 25 7 * * ?
|
||||
new Env("精易论坛")
|
||||
"""
|
||||
import urllib
|
||||
from urllib import parse
|
||||
import requests
|
||||
import notify
|
||||
import time
|
||||
import re
|
||||
import random
|
||||
|
||||
import utils.tool as TOOL
|
||||
import utils.getCookie as getCookie
|
||||
|
||||
global msg
|
||||
|
||||
msg = """
|
||||
名称|累计|本月|总获得|总精币|状态
|
||||
:--:|:--:|:--:|:--:|:--:|:--:
|
||||
"""
|
||||
|
||||
|
||||
def main():
|
||||
users = getCookie.GetQlEnvs().getCookies('JYLT_COOKIE')
|
||||
print("🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉\n")
|
||||
print("获取到: " + str(len(users)) + " 个用户")
|
||||
print("-------------------------------------------")
|
||||
|
||||
for user in users:
|
||||
signIn(user)
|
||||
|
||||
|
||||
# 签到
|
||||
def signIn(user):
|
||||
global msg
|
||||
url = "https://bbs.125.la/plugin.php?id=dsu_paulsign:sign"
|
||||
data = 'formhash=926371b6&submit=1&operation=qiandao&qdxq=kx&ajax=1&infloat=0'
|
||||
headers = {
|
||||
"Host": "bbs.125.la",
|
||||
"accept": "*/*",
|
||||
"origin": "//bbs.125.la",
|
||||
"x-requested-with": "XMLHttpRequest",
|
||||
"user-agent": "Mozilla/5.0 (Linux; U; Android 11; zh-cn; M2011K2C Build/RKQ1.200826.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.147 Mobile Safari/537.36 XiaoMi/MiuiBrowser/14.3.21",
|
||||
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"sec-fetch-site": "same-origin",
|
||||
"accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
|
||||
"cookie": "lDlk_ecc9_saltkey=gypyB1q2;lDlk_ecc9_lastvisit=1671591615;lDlk_ecc9_con_request_uri=http%3A%2F%2Fbbs.125.la%2Fconnect.php%3Fmod%3Dlogin%26op%3Dcallback%26referer%3Dindex.php;lDlk_ecc9_client_token=AB463AA7680A8BC46D64C58FC637960E;lDlk_ecc9_connect_is_bind=1;lDlk_ecc9_connect_uin=AB463AA7680A8BC46D64C58FC637960E;lDlk_ecc9_nofavfid=1;lDlk_ecc9_lastcheckfeed=662770%7C1672326032;__ancc_token=eDy0p0n5DsQMBJ8B4yxj2Q==;lDlk_ecc9_seccode=507.0542e4feff0318d6c5;lDlk_ecc9_client_created=1673829175;lDlk_ecc9_auth=ef18YFNYII0asASPE2u3U3ONRNbDuqTWo7sjRti9VkzdZlSFHETzOce8M877vlXg;lDlk_ecc9_connect_login=1;lDlk_ecc9_st_p=662770%7C1673829595%7Cdaec851af652b5d3c0199aabc791c7b5;lDlk_ecc9_visitedfid=202D81D168D147D51D206D178D98D27D100;lDlk_ecc9_viewid=tid_13957193;lDlk_ecc9_sid=CkKWXF;lDlk_ecc9_lip=117.163.248.13%2C1673870449;lDlk_ecc9_ulastactivity=d7e0Jr%2B9TDmtxrJE2j8MVjtkAPIeX18rnTbBp4ZnRjSeb8U5qjDz;lDlk_ecc9_home_diymode=1;lDlk_ecc9_lastact=1673948276%09plugin.php%09"
|
||||
}
|
||||
res = requests.post(url=url, data=data, headers=headers)
|
||||
try:
|
||||
json = res.json()
|
||||
if (json['status'] == 1):
|
||||
# seccess
|
||||
print(user['name'] + " ---> " + "签到成功" + "\n")
|
||||
msg += user['name'] + "|" + str(json['data']['days']) + "|" + str(json['data']['modays']) + "|" + str(
|
||||
json['data']['reward']) + "|5000|" + "seccess" + "\n\n"
|
||||
else:
|
||||
# err
|
||||
print(user['name'] + " ---> " + str(json['msg']) + "\n")
|
||||
msg += user['name'] + "|||||" + str(json['msg']) + "\n\n"
|
||||
|
||||
except Exception as e:
|
||||
print(user['name'] + " ---> " + "json err" + "\n")
|
||||
msg += user['name'] + "|||||" + "json err" + "\n\n"
|
||||
|
||||
print("-------------------------------------------\n")
|
||||
|
||||
|
||||
main()
|
||||
|
||||
print("🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉")
|
||||
|
||||
notify.send("精易论坛", msg)
|
||||
87
脚本库/web版/账密/阿里云盘签到/2023-09-20_alypqd_cc872d59.py
Normal file
87
脚本库/web版/账密/阿里云盘签到/2023-09-20_alypqd_cc872d59.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# Source: https://github.com/xfmeng970526/ql/blob/main/alypqd.py
|
||||
# Raw: https://raw.githubusercontent.com/xfmeng970526/ql/main/alypqd.py
|
||||
# Repo: xfmeng970526/ql
|
||||
# Path: alypqd.py
|
||||
# UploadedAt: 2023-09-20T12:13:28+08:00
|
||||
# SHA256: cc872d595fe25f177c8ab54389fe8fd68d4405340c15dd0557e07914985d486c
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
#!/usr/bin/python3
|
||||
# -- coding: utf-8 --
|
||||
# @Time : 2023/4/8 10:23
|
||||
# -------------------------------
|
||||
# cron "30 5 * * *" script-path=xxx.py,tag=匹配cron用
|
||||
# const $ = new Env('阿里云盘签到');
|
||||
# cron: 25 2,21 * * *
|
||||
# new Env('126-阿里云盘签到');
|
||||
import json
|
||||
import requests
|
||||
import os
|
||||
|
||||
##变量export ali_refresh_token=''
|
||||
ali_refresh_token=os.getenv("ali_refresh_token").split('&')
|
||||
#refresh_token是一成不变的呢,我们使用它来更新签到需要的access_token
|
||||
# ali_refresh_token = os.getenv("ali_refresh_token")
|
||||
# 推送加
|
||||
plustoken = os.getenv("plustoken")
|
||||
|
||||
|
||||
#推送函数
|
||||
def Push(contents):
|
||||
# 推送加
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
json = {"token": plustoken, 'title': 'aliyun签到', 'content': contents.replace('\n', '<br>'), "template": "json"}
|
||||
resp = requests.post(f'http://www.pushplus.plus/send', json=json, headers=headers).json()
|
||||
print('push+推送成功' if resp['code'] == 200 else 'push+推送失败')
|
||||
|
||||
#签到函数
|
||||
for i in range(len(ali_refresh_token)):
|
||||
print(f'开始帐号{i+1}签到')
|
||||
def daily_check(access_token):
|
||||
url = 'https://member.aliyundrive.com/v1/activity/sign_in_list'
|
||||
headers = {
|
||||
'Authorization': access_token
|
||||
}
|
||||
response = requests.post(url=url, headers=headers, json={}).text
|
||||
result = json.loads(response)
|
||||
if 'success' in result:
|
||||
print('签到成功')
|
||||
for i, j in enumerate(result['result']['signInLogs']):
|
||||
if j['status'] == 'miss':
|
||||
day_json = result['result']['signInLogs'][i-1]
|
||||
# print(day_json)
|
||||
if not day_json['isReward']:
|
||||
contents = '签到成功,今日未获得奖励'
|
||||
else:
|
||||
contents = '本月累计签到{}天,今日签到获得{}{}'.format(result['result']['signInCount'],
|
||||
day_json['reward']['name'],
|
||||
day_json['reward']['description'])
|
||||
print(contents)
|
||||
|
||||
return contents
|
||||
|
||||
|
||||
# 使用refresh_token更新access_token
|
||||
def update_token(refresh_token):
|
||||
url = 'https://auth.aliyundrive.com/v2/account/token'
|
||||
data = {
|
||||
'grant_type': 'refresh_token',
|
||||
'refresh_token': ali_refresh_token[i]
|
||||
}
|
||||
response = requests.post(url=url, json=data).json()
|
||||
access_token = response['access_token']
|
||||
# print('获取的access_token为{}'.format(access_token))
|
||||
return access_token
|
||||
|
||||
|
||||
def mian():
|
||||
# print('更新access_token')
|
||||
access_token = update_token(ali_refresh_token)
|
||||
# print('更新成功,开始进行签到')
|
||||
content = daily_check(access_token)
|
||||
if plustoken != '':
|
||||
Push(content)
|
||||
|
||||
if __name__ == '__main__':
|
||||
mian()
|
||||
195
脚本库/web版/账密/飞牛私有云/2025-04-28_sudojia_fnnas_5d809252.js
Normal file
195
脚本库/web版/账密/飞牛私有云/2025-04-28_sudojia_fnnas_5d809252.js
Normal file
@@ -0,0 +1,195 @@
|
||||
// # Source: https://github.com/sudojia/AutoTaskScript/blob/script/src/web/sudojia_fnnas.js
|
||||
// # Raw: https://raw.githubusercontent.com/sudojia/AutoTaskScript/script/src/web/sudojia_fnnas.js
|
||||
// # Repo: sudojia/AutoTaskScript
|
||||
// # Path: src/web/sudojia_fnnas.js
|
||||
// # UploadedAt: 2025-04-28T19:26:13+08:00
|
||||
// # SHA256: 5d80925231190e241d959facb5f7ae099c4bb2122c415e04975ba821f3c30271
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/**
|
||||
* 飞牛私有云
|
||||
*
|
||||
* 官网:https://club.fnnas.com
|
||||
* 获取 Cookie,格式:pvRK_2132_auth=46exxxxxxxx; pvRK_2132_saltkey=F3xxxxx
|
||||
* export FN_NAS_COOKIE = 'pvRK_2132_auth=46exxxxxxxx; pvRK_2132_saltkey=F3xxxxx'
|
||||
* 多账号用 & 或换行
|
||||
*
|
||||
* @author Telegram@sudojia
|
||||
* @site https://blog.imzjw.cn
|
||||
* @date 2024/09/20
|
||||
*
|
||||
* const $ = new Env('飞牛私有云')
|
||||
* cron: 10 0 * * *
|
||||
*/
|
||||
const initScript = require('../utils/initScript')
|
||||
const {$, notify, sudojia, checkUpdate} = initScript('飞牛私有云');
|
||||
const cheerio = require("cheerio");
|
||||
const fnNasList = process.env.FN_NAS_COOKIE ? process.env.FN_NAS_COOKIE.split(/[\n&]/) : [];
|
||||
// 消息推送
|
||||
let message = '';
|
||||
// 获取配置信息
|
||||
let formHash, signLink, uid;
|
||||
// 接口地址
|
||||
const baseUrl = 'https://club.fnnas.com'
|
||||
// 请求头
|
||||
const headers = {
|
||||
'User-Agent': sudojia.getRandomUserAgent('PC'),
|
||||
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
||||
};
|
||||
|
||||
!(async () => {
|
||||
await checkUpdate($.name, fnNasList);
|
||||
console.log(`\n已随机分配 User-Agent\n\n${headers['user-agent'] || headers['User-Agent']}`);
|
||||
for (let i = 0; i < fnNasList.length; i++) {
|
||||
const index = i + 1;
|
||||
headers.Cookie = fnNasList[i];
|
||||
console.log(`\n*****第[${index}]个${$.name}账号*****`);
|
||||
message += `📣====${$.name}账号[${index}]====📣\n`;
|
||||
await main();
|
||||
await $.wait(sudojia.getRandomWait(2000, 2500));
|
||||
}
|
||||
if (message) {
|
||||
await notify.sendNotify(`「${$.name}」`, `${message}`);
|
||||
}
|
||||
})().catch((e) => $.logErr(e)).finally(() => $.done());
|
||||
|
||||
async function main() {
|
||||
await getUidAndUserName();
|
||||
await $.wait(sudojia.getRandomWait(800, 1200));
|
||||
await follow();
|
||||
await $.wait(sudojia.getRandomWait(1200, 1800));
|
||||
await checkIn();
|
||||
await $.wait(sudojia.getRandomWait(1200, 1800));
|
||||
await getCount();
|
||||
await $.wait(sudojia.getRandomWait(1200, 1800));
|
||||
await getPoints();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取重要信息
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getUidAndUserName() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}`, 'get', headers);
|
||||
const $ = cheerio.load(data);
|
||||
uid = $('a', '.icon_msg').attr('href').match(/uid=(\d+)/)[1];
|
||||
const userName = $('.quater_phone_nav .z').text().trim();
|
||||
console.log(`${userName}(${uid})`);
|
||||
// 拿到 formhash 和签到地址
|
||||
const logoutLink = $('li.l4 a').attr('href');
|
||||
formHash = logoutLink.split('formhash=')[1];
|
||||
signLink = $('a[href*="plugin.php?id=zqlj_sign"]').attr('href');
|
||||
message += `${userName}(${uid})\n`;
|
||||
} catch (e) {
|
||||
console.error('获取重要信息时发生异常:', e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function checkIn() {
|
||||
try {
|
||||
let data = await sudojia.sendRequest(`${baseUrl}/${signLink}`, 'get', headers);
|
||||
if (!data.includes('点击打卡')) {
|
||||
console.log('今日已打卡');
|
||||
return;
|
||||
}
|
||||
await $.wait(sudojia.getRandomWait(800, 1200));
|
||||
data = await sudojia.sendRequest(`${baseUrl}/${signLink}&sign=${formHash}`, 'get', headers);
|
||||
console.log('打卡成功!');
|
||||
message += `打卡成功\n`;
|
||||
} catch (e) {
|
||||
console.error('签到时发生异常:', e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计信息
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getCount() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/${signLink}`, 'get', headers);
|
||||
const $ = cheerio.load(data);
|
||||
const items = {};
|
||||
// 使用选择器提取信息
|
||||
$('.xl li').each((index, element) => {
|
||||
const text = $(element).text().trim();
|
||||
switch (text.substring(0, 4)) {
|
||||
case '最近打卡':
|
||||
items['zjdk'] = text.substring(5).trim();
|
||||
break;
|
||||
case '本月打卡':
|
||||
items['bydk'] = text.substring(5).trim();
|
||||
break;
|
||||
case '连续打卡':
|
||||
items['lxdk'] = text.substring(5).trim();
|
||||
break;
|
||||
case '累计打卡':
|
||||
items['ljdk'] = text.substring(5).trim();
|
||||
break;
|
||||
case '累计奖励':
|
||||
items['ljjl'] = text.substring(5).trim();
|
||||
break;
|
||||
case '最近奖励':
|
||||
items['zjjl'] = text.substring(5).trim();
|
||||
break;
|
||||
case '当前打卡':
|
||||
items['currenDkLevel'] = text.substring(7).trim();
|
||||
break;
|
||||
}
|
||||
});
|
||||
console.log(`最近打卡:${items.zjdk}\n本月打卡:${items.bydk}\n连续打卡:${items.lxdk}\n累计打卡:${items.ljdk}\n累计奖励:${items.ljjl}\n最近奖励:${items.zjjl}\n当前打卡等级:${items.currenDkLevel}`);
|
||||
message += `最近打卡:${items.zjdk}\n本月打卡:${items.bydk}\n连续打卡:${items.lxdk}\n累计打卡:${items.ljdk}\n累计奖励:${items.ljjl}\n最近奖励:${items.zjjl}\n当前打卡等级:${items.currenDkLevel}\n`;
|
||||
} catch (e) {
|
||||
console.error('获取统计信息时发生异常:', e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取个人信息
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getPoints() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/home.php?mod=space&uid=${uid}&do=profile&from=space`, 'get', headers);
|
||||
const $ = cheerio.load(data);
|
||||
const ulElement = $('.pf_l');
|
||||
const item = {};
|
||||
ulElement.find('li').each((index, element) => {
|
||||
const label = $(element).find('em').text().trim();
|
||||
const value = $(element).text().replace(label, '').trim();
|
||||
switch (label) {
|
||||
case '积分':
|
||||
item.points = parseInt(value);
|
||||
break;
|
||||
case '牛值':
|
||||
item.bullValue = parseInt(value);
|
||||
break;
|
||||
case '飞牛币':
|
||||
item.flyingBullCoins = parseInt(value);
|
||||
break;
|
||||
case '登陆天数':
|
||||
item.loginDays = parseInt(value);
|
||||
break;
|
||||
}
|
||||
});
|
||||
console.log(`当前积分:${item.points}\n当前牛值:${item.bullValue}\n当前飞牛币:${item.flyingBullCoins}\n当前登录天数:${item.loginDays}`);
|
||||
message += `当前积分:${item.points}\n当前牛值:${item.bullValue}\n当前飞牛币:${item.flyingBullCoins}\n当前登录天数:${item.loginDays}\n\n`;
|
||||
} catch (e) {
|
||||
console.error('获取个人信息时发生异常:', e);
|
||||
}
|
||||
}
|
||||
|
||||
async function follow() {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/home.php?mod=spacecp&ac=follow&op=add&hash=${formHash}&fuid=6441&infloat=yes&handlekey=followmod&inajax=1&ajaxtarget=fwin_content_followmod`, 'get', headers);
|
||||
}
|
||||
361
脚本库/web版/账密/香蕉视频/2025-04-28_sudojia_bananaVideo_1a8fb322.js
Normal file
361
脚本库/web版/账密/香蕉视频/2025-04-28_sudojia_bananaVideo_1a8fb322.js
Normal file
@@ -0,0 +1,361 @@
|
||||
// # Source: https://github.com/sudojia/AutoTaskScript/blob/script/src/client/sudojia_bananaVideo.js
|
||||
// # Raw: https://raw.githubusercontent.com/sudojia/AutoTaskScript/script/src/client/sudojia_bananaVideo.js
|
||||
// # Repo: sudojia/AutoTaskScript
|
||||
// # Path: src/client/sudojia_bananaVideo.js
|
||||
// # UploadedAt: 2025-04-28T19:26:13+08:00
|
||||
// # SHA256: 1a8fb3222c27ae2783be5e0562b3110bdb4f4d984f503c7f8b3c48d7ef588dfc
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/**
|
||||
* 香蕉视频 APP
|
||||
*
|
||||
* 扫码下载:https://pic.rmb.bdstatic.com/bjh/240914/dc8411e749492d270032b5278c5abd321993.png
|
||||
* 开发不易,走个邀请码呗,感谢!!!
|
||||
* 邀请码:IOWDUC
|
||||
* 每日签到及任务获得金币, 金币可提现或在棋牌处单车变摩托, 10 金币 = 1元, 保底每日 6 金币
|
||||
* 手机号#密码
|
||||
* export BANANA_ACCOUNT = '18888888888#123456'
|
||||
* 多账号用 & 或换行
|
||||
*
|
||||
* @author Telegram@sudojia
|
||||
* @site https://blog.imzjw.cn
|
||||
* @date 2024/09/14
|
||||
*
|
||||
* const $ = new Env('香蕉视频')
|
||||
* cron: 10 1 * * *
|
||||
*/
|
||||
const initScript = require('../utils/initScript')
|
||||
const {$, notify, sudojia, checkUpdate} = initScript('香蕉视频');
|
||||
const bananaList = process.env.BANANA_ACCOUNT ? process.env.BANANA_ACCOUNT.split(/[\n&]/) : [];
|
||||
// 消息推送
|
||||
let message = '';
|
||||
// 接口地址
|
||||
const baseUrl = 'https://mgcrjh.ipajx0.cc'
|
||||
// 收藏列表数组
|
||||
let favoriteList = [];
|
||||
// 请求头
|
||||
const headers = {
|
||||
"x-system": "Android",
|
||||
"x-channel": "xj1",
|
||||
"x-version": "5.0.5",
|
||||
'User-Agent': sudojia.getRandomUserAgent('H5'),
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7"
|
||||
};
|
||||
|
||||
!(async () => {
|
||||
await checkUpdate($.name, bananaList);
|
||||
console.log(`\n已随机分配 User-Agent\n\n${headers['user-agent'] || headers['User-Agent']}`);
|
||||
for (let i = 0; i < bananaList.length; i++) {
|
||||
const index = i + 1;
|
||||
const [phone, pwd] = bananaList[i].split('#');
|
||||
console.log(`\n*****第[${index}]个${$.name}账号*****`);
|
||||
message += `📣====${$.name}账号[${index}]====📣\n`;
|
||||
await main(phone, pwd);
|
||||
await $.wait(sudojia.getRandomWait(2000, 2500));
|
||||
}
|
||||
if (message) {
|
||||
await notify.sendNotify(`「${$.name}」`, `${message}`);
|
||||
}
|
||||
})().catch((e) => $.logErr(e)).finally(() => $.done());
|
||||
|
||||
async function main(phone, pwd) {
|
||||
// 登录
|
||||
await login(phone, pwd);
|
||||
await $.wait(sudojia.getRandomWait(1500, 2000));
|
||||
|
||||
// 获取用户信息
|
||||
await getUserInfo();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2000));
|
||||
|
||||
// 签到
|
||||
await sign();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2000));
|
||||
|
||||
// 添加收藏
|
||||
await addFavorite();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2000));
|
||||
|
||||
// 获取收藏列表并删除收藏
|
||||
await getFavoriteList();
|
||||
await $.wait(sudojia.getRandomWait(800, 1200));
|
||||
await removeFavorite();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2000));
|
||||
|
||||
// 点击广告任务
|
||||
await adViewClick();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2000));
|
||||
|
||||
// 下载长视频任务
|
||||
await downLoadVideoTask();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2000));
|
||||
|
||||
// 观看影片任务
|
||||
await watchVideo();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2000));
|
||||
|
||||
// 保存二维码任务
|
||||
await qrcodeSave();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2000));
|
||||
|
||||
// 发布评论任务
|
||||
await postComment();
|
||||
await $.wait(sudojia.getRandomWait(1500, 2000));
|
||||
|
||||
// 获取金币
|
||||
await getPoints();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async function login(phone, pwd) {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/login`, 'post', headers, `logintype=0&mobiprefix=86&mobi=${phone}&password=${pwd}`);
|
||||
if (0 !== data.retcode) {
|
||||
return console.error(data.errmsg);
|
||||
}
|
||||
headers['X-Cookie-Auth'] = data.data.xxx_api_auth;
|
||||
console.log(`登录成功~`);
|
||||
} catch (e) {
|
||||
console.error(`获取用户信息时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getUserInfo() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/ucp/index`, 'get', headers);
|
||||
if (0 !== data.retcode) {
|
||||
return console.error(data.errmsg);
|
||||
}
|
||||
console.log(`昵称:${data.data.user.username}`);
|
||||
message += `昵称:${data.data.user.username}\n`;
|
||||
} catch (e) {
|
||||
console.error(`获取用户信息时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function sign() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/ucp/task/sign`, 'post', headers);
|
||||
if (0 !== data.retcode) {
|
||||
message += `${data.errmsg}\n`;
|
||||
return console.error(data.errmsg);
|
||||
}
|
||||
console.log(`签到成功,金币+${data.data.taskdone}`);
|
||||
message += `签到成功\n`;
|
||||
} catch (e) {
|
||||
console.error(`签到时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频收藏
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function addFavorite() {
|
||||
// 每次收藏的最大尝试次数
|
||||
const maxAttempts = 5;
|
||||
for (let i = 0; i < 5; i++) {
|
||||
let attempt = 0;
|
||||
while (attempt < maxAttempts) {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/favorite/add`, 'post', headers, `vodid=${sudojia.getRandomWait(1, 66000)}`);
|
||||
if (data.retcode === 0) {
|
||||
console.log(`第 ${i + 1} 次收藏视频成功!`);
|
||||
await $.wait(sudojia.getRandomWait(1500, 2300));
|
||||
break;
|
||||
} else if (data.retcode === -1) {
|
||||
console.log(`第 ${i + 1} 次收藏视频失败(已收藏),重新尝试...`);
|
||||
attempt++;
|
||||
await $.wait(sudojia.getRandomWait(1500, 2300));
|
||||
} else {
|
||||
console.error(`第 ${i + 1} 次收藏视频失败,错误代码:${data.retcode},错误信息:${data.errmsg}`);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`收藏视频时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
if (attempt === maxAttempts) {
|
||||
console.error(`收藏视频达到最大尝试次数,收藏任务未成功`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收藏列表
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getFavoriteList() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/favorite/listing`, 'get', headers);
|
||||
if (0 !== data.retcode) {
|
||||
return console.error(`获取收藏列表失败:${data.errmsg}`);
|
||||
}
|
||||
for (const item of data.data.rows) {
|
||||
favoriteList.push(item.vodid);
|
||||
}
|
||||
console.log(`已获取收藏列表,开始删除收藏...`);
|
||||
} catch (e) {
|
||||
console.error(`获取收藏列表时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除收藏列表
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function removeFavorite() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/favorite/remove`, 'post', headers, `vodids=${favoriteList}`);
|
||||
if (0 !== data.retcode) {
|
||||
return console.error(`删除收藏视频失败:${data.errmsg}`);
|
||||
}
|
||||
console.log(`${data.errmsg}`);
|
||||
} catch (e) {
|
||||
console.error(`删除收藏视频时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 点击广告任务
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function adViewClick() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/ucp/task/adviewClick`, 'get', headers);
|
||||
if (0 !== data.retcode) {
|
||||
return console.error(`点击广告失败:${data.errmsg}`);
|
||||
}
|
||||
console.log(`点击广告成功,金币+${data.data.taskdone}`);
|
||||
} catch (e) {
|
||||
console.error(`点击广告时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 长视频下载任务
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function downLoadVideoTask() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/vod/reqdown/${sudojia.getRandomWait(1, 66000)}`, 'get', headers);
|
||||
if (0 !== data.retcode) {
|
||||
if (3 === data.retcode) {
|
||||
await $.wait(sudojia.getRandomWait(800, 1200));
|
||||
return await downLoadVideoTask();
|
||||
}
|
||||
console.error(`下载长视频失败:${data.errmsg}`);
|
||||
return;
|
||||
}
|
||||
if (!data.data.taskdone) {
|
||||
return console.error(`下载长视频任务已完成`);
|
||||
}
|
||||
console.log(`下载长视频任务成功,金币+${data.data.taskdone}`);
|
||||
} catch (e) {
|
||||
console.error(`下载长视频任务时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 观看影片任务
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function watchVideo() {
|
||||
try {
|
||||
let watched = 0;
|
||||
while (watched < 10) {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/v2/vod/reqplay/${sudojia.getRandomWait(1, 66000)}`, 'get', headers);
|
||||
if (0 !== data.retcode) {
|
||||
console.error(`观看影片任务失败:${data.errmsg}`);
|
||||
await $.wait(sudojia.getRandomWait(800, 1200));
|
||||
continue;
|
||||
}
|
||||
watched++;
|
||||
console.log(`已观看影片数量:${watched}`);
|
||||
await $.wait(sudojia.getRandomWait(1500, 2300));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`观看影片时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存二维码任务
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function qrcodeSave() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/ucp/task/qrcodeSave`, 'get', headers);
|
||||
if (0 !== data.retcode) {
|
||||
return console.error(`保存二维码任务失败:${data.errmsg}`);
|
||||
}
|
||||
console.log(`保存二维码任务成功,金币+${data.data.taskdone}`);
|
||||
} catch (e) {
|
||||
console.error(`保存二维码任务时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布评论任务
|
||||
*
|
||||
* @returns {Promise<*|undefined>}
|
||||
*/
|
||||
async function postComment() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/comment/post`, 'post', headers, `vodid=${sudojia.getRandomWait(1, 66000)}&content=好`);
|
||||
if (0 !== data.retcode) {
|
||||
if (3 === data.retcode) {
|
||||
await $.wait(sudojia.getRandomWait(800, 1200));
|
||||
return await postComment();
|
||||
}
|
||||
console.error(`发布评论失败:${data.errmsg}`);
|
||||
return
|
||||
}
|
||||
console.log(data.errmsg);
|
||||
} catch (e) {
|
||||
console.error(`发布评论时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取金币
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function getPoints() {
|
||||
try {
|
||||
const data = await sudojia.sendRequest(`${baseUrl}/ucp/index`, 'get', headers);
|
||||
if (0 !== data.retcode) {
|
||||
return console.error(data.errmsg);
|
||||
}
|
||||
console.log(`当前金币:${data.data.user.goldcoin}`);
|
||||
message += `当前金币:${data.data.user.goldcoin}`;
|
||||
} catch (e) {
|
||||
console.error(`获取金币时发生异常:${e}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user