This commit is contained in:
parent
c9ae81b358
commit
329b0b7812
1
.python-version
Normal file
1
.python-version
Normal file
|
@ -0,0 +1 @@
|
|||
3.11
|
|
@ -1,6 +1,19 @@
|
|||
# 使用前请阅读文档:https://bili33.top/posts/MHYY-AutoCheckin-Manual-Gen2/
|
||||
# 有问题请前往Github开启issue:https://github.com/GamerNoTitle/MHYY/issues
|
||||
|
||||
notifications:
|
||||
# Server酱
|
||||
serverchan:
|
||||
key: ""
|
||||
# 钉钉机器人
|
||||
# 安全关键词需要包含 `MHYY`,否则会被钉钉机器人拒绝
|
||||
dingtalk:
|
||||
webhook_url: "https://oapi.dingtalk.com/robot/send?access_token=2b350a189512e1484d54e8b588c163f787ec9c2798725490f92f63d42b1e2b17"
|
||||
# Telegram机器人
|
||||
telegram:
|
||||
bot_token: "6689586847:AAH0lg1uuXiZMsou9WNYif7qqrbCSdZWWj0"
|
||||
chat_id: "1762053255"
|
||||
|
||||
######## 以下为账号配置项,可以多账号,详情请参考文档 ########
|
||||
accounts:
|
||||
# 第一个账号
|
||||
|
|
485
main.py
485
main.py
|
@ -8,6 +8,7 @@ import time
|
|||
import yaml
|
||||
import logging
|
||||
|
||||
# --- Logging Setup ---
|
||||
if os.environ.get("MHYY_LOGLEVEL", "").upper() == "DEBUG":
|
||||
loglevel = logging.DEBUG
|
||||
elif os.environ.get("MHYY_LOGLEVEL", "").upper() == "WARNING":
|
||||
|
@ -17,7 +18,6 @@ elif os.environ.get("MHYY_LOGLEVEL", "").upper() == "ERROR":
|
|||
else:
|
||||
loglevel = logging.INFO
|
||||
|
||||
# 设置日志配置
|
||||
logging.basicConfig(
|
||||
level=loglevel,
|
||||
format="%(asctime)s [%(levelname)s]: %(message)s",
|
||||
|
@ -27,42 +27,163 @@ logging.basicConfig(
|
|||
logger = logging.getLogger()
|
||||
|
||||
|
||||
# --- Config Reading Function ---
|
||||
def ReadConf(variable_name, default_value=None):
|
||||
# Try to get the variable from the environment
|
||||
"""
|
||||
Reads YAML configuration from environment variable or config.yml.
|
||||
Assumes the variable_name contains the full YAML content.
|
||||
"""
|
||||
env_value = os.environ.get(variable_name)
|
||||
|
||||
if env_value:
|
||||
config_data = yaml.load(env_value, Loader=yaml.FullLoader)
|
||||
return config_data
|
||||
try:
|
||||
# Attempt to load from environment variable (assuming it's YAML)
|
||||
config_data = yaml.load(env_value, Loader=yaml.FullLoader)
|
||||
logger.debug("Configuration loaded from environment variable.")
|
||||
return config_data
|
||||
except yaml.YAMLError as e:
|
||||
logger.error(
|
||||
f"Failed to parse YAML from environment variable '{variable_name}': {e}"
|
||||
)
|
||||
return default_value # Return default or None if env parsing fails
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"An unexpected error occurred reading environment variable '{variable_name}': {e}"
|
||||
)
|
||||
return default_value
|
||||
|
||||
# If not found in environment, try to read from config.yml
|
||||
# If not found or failed in environment, try to read from config.yml
|
||||
try:
|
||||
with open("config.yml", "r", encoding="utf-8") as config_file:
|
||||
config_data = yaml.load(config_file, Loader=yaml.FullLoader)
|
||||
logger.debug("Configuration loaded from config.yml file.")
|
||||
return config_data
|
||||
except FileNotFoundError:
|
||||
logger.warning("config.yml not found.")
|
||||
return default_value
|
||||
except yaml.YAMLError as e:
|
||||
logger.error(f"Failed to parse YAML from config.yml: {e}")
|
||||
return default_value
|
||||
except Exception as e:
|
||||
logger.error(f"An unexpected error occurred reading config.yml: {e}")
|
||||
return default_value
|
||||
|
||||
|
||||
# --- Sentry Setup ---
|
||||
sentry_sdk.init(
|
||||
"https://425d7b4536f94c9fa540fe34dd6609a2@o361988.ingest.sentry.io/6352584",
|
||||
traces_sample_rate=1.0,
|
||||
)
|
||||
|
||||
conf = ReadConf("MHYY_CONFIG")["accounts"]
|
||||
# --- Load Configuration ---
|
||||
full_config = ReadConf("MHYY_CONFIG", {}) # Read the entire config
|
||||
accounts_conf = full_config.get("accounts")
|
||||
notification_settings = full_config.get(
|
||||
"notifications", {}
|
||||
) # Get notification settings, default to empty dict
|
||||
|
||||
if not conf:
|
||||
logger.error("请正确配置环境变量或者config.yml后再运行本脚本!")
|
||||
if not accounts_conf:
|
||||
logger.error(
|
||||
"请正确配置环境变量 MHYY_CONFIG 或者 config.yml 并包含 'accounts' 部分后再运行本脚本!"
|
||||
)
|
||||
os._exit(0)
|
||||
logger.info(f"检测到 {len(conf)} 个账号,正在进行任务……")
|
||||
logger.info(f"检测到 {len(accounts_conf)} 个账号,正在进行任务……")
|
||||
|
||||
|
||||
# Options
|
||||
sct_status = os.environ.get("sct") # https://sct.ftqq.com/
|
||||
sct_key = os.environ.get("sct_key")
|
||||
sct_url = f"https://sctapi.ftqq.com/{sct_key}.send?title=MHYY-AutoCheckin 自动推送"
|
||||
def send_notifications(message: str, settings: dict):
|
||||
"""Sends message to configured notification services."""
|
||||
if not message or not settings:
|
||||
logger.debug("No message to send or no notification settings configured.")
|
||||
return
|
||||
|
||||
sct_msg = ""
|
||||
logger.info("Attempting to send notifications...")
|
||||
|
||||
# ServerChan (SCT)
|
||||
sct_conf = settings.get("serverchan", {})
|
||||
sct_key = sct_conf.get("key")
|
||||
if sct_key:
|
||||
sct_url = f"https://sctapi.ftqq.com/{sct_key}.send"
|
||||
try:
|
||||
payload = {"title": "MHYY-AutoCheckin 状态推送", "desp": message}
|
||||
response = httpx.get(sct_url, params=payload, timeout=10)
|
||||
response.raise_for_status()
|
||||
logger.info("ServerChan notification sent successfully.")
|
||||
except httpx.HTTPStatusError as e:
|
||||
logger.error(
|
||||
f"ServerChan HTTP error occurred: {e.response.status_code} - {e.response.text}"
|
||||
)
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"An error occurred while requesting ServerChan: {e}")
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"An unexpected error occurred sending ServerChan notification: {e}"
|
||||
)
|
||||
else:
|
||||
logger.debug("ServerChan not configured.")
|
||||
|
||||
# DingTalk
|
||||
dingtalk_conf = settings.get("dingtalk", {})
|
||||
dingtalk_webhook_url = dingtalk_conf.get("webhook_url")
|
||||
if dingtalk_webhook_url:
|
||||
try:
|
||||
payload = {"msgtype": "text", "text": {"content": message}}
|
||||
response = httpx.post(dingtalk_webhook_url, json=payload, timeout=10)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
if result.get("errcode") == 0:
|
||||
logger.info("DingTalk notification sent successfully.")
|
||||
else:
|
||||
logger.error(
|
||||
f"DingTalk error: {result.get('errcode')} - {result.get('errmsg')}"
|
||||
)
|
||||
except httpx.HTTPStatusError as e:
|
||||
logger.error(
|
||||
f"DingTalk HTTP error occurred: {e.response.status_code} - {e.response.text}"
|
||||
)
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"An error occurred while requesting DingTalk: {e}")
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"An unexpected error occurred sending DingTalk notification: {e}"
|
||||
)
|
||||
else:
|
||||
logger.debug("DingTalk not configured.")
|
||||
|
||||
telegram_conf = settings.get("telegram", {})
|
||||
telegram_bot_token = telegram_conf.get("bot_token")
|
||||
telegram_chat_id = telegram_conf.get("chat_id")
|
||||
if telegram_bot_token and telegram_chat_id:
|
||||
telegram_url = f"https://api.telegram.org/bot{telegram_bot_token}/sendMessage"
|
||||
try:
|
||||
# Telegram text message parameters
|
||||
params = {
|
||||
"chat_id": telegram_chat_id,
|
||||
"text": message,
|
||||
# Optional: parse_mode can be 'MarkdownV2', 'HTML', or None
|
||||
# For simplicity, sending as plain text. Be careful with special characters if using Markdown/HTML.
|
||||
# "parse_mode": "HTML"
|
||||
}
|
||||
response = httpx.get(telegram_url, params=params, timeout=10)
|
||||
response.raise_for_status() # Raise an exception for bad status codes
|
||||
result = response.json()
|
||||
if result.get("ok"):
|
||||
logger.info("Telegram notification sent successfully.")
|
||||
else:
|
||||
logger.error(
|
||||
f"Telegram error: {result.get('error_code')} - {result.get('description')}"
|
||||
)
|
||||
except httpx.HTTPStatusError as e:
|
||||
logger.error(
|
||||
f"Telegram HTTP error occurred: {e.response.status_code} - {e.response.text}"
|
||||
)
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"An error occurred while requesting Telegram: {e}")
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"An unexpected error occurred sending Telegram notification: {e}"
|
||||
)
|
||||
else:
|
||||
logger.debug("Telegram not configured.")
|
||||
|
||||
|
||||
class RunError(Exception):
|
||||
|
@ -71,9 +192,13 @@ class RunError(Exception):
|
|||
|
||||
if __name__ == "__main__":
|
||||
if not os.environ.get("MHYY_DEBUG", False):
|
||||
wait_time = random.randint(10, 60) # Random Sleep to Avoid Ban
|
||||
logger.info(f"为了避免同一时间签到人数太多导致被官方怀疑,开始休眠 {wait_time} 秒")
|
||||
wait_time = random.randint(10, 11) # Random Sleep to Avoid Ban
|
||||
logger.info(
|
||||
f"为了避免同一时间签到人数太多导致被官方怀疑,开始休眠 {wait_time} 秒"
|
||||
)
|
||||
time.sleep(wait_time)
|
||||
|
||||
version = "5.0.0" # Default version
|
||||
try:
|
||||
ver_info = httpx.get(
|
||||
"https://hyp-api.mihoyo.com/hyp/hyp-connect/api/getGameBranches?game_ids[]=1Z8W5NHUQb&launcher_id=jGHBHlcOq1",
|
||||
|
@ -83,10 +208,11 @@ if __name__ == "__main__":
|
|||
version = json.loads(ver_info)["data"]["game_branches"][0]["main"]["tag"]
|
||||
logger.info(f"从官方API获取到云·原神最新版本号:{version}")
|
||||
except Exception as e:
|
||||
version = "5.0.0"
|
||||
logger.warning(f"获取版本号失败,使用默认版本:{version}")
|
||||
logger.warning(f"获取版本号失败,使用默认版本:{version}. Error: {e}")
|
||||
|
||||
for config in accounts_conf:
|
||||
notification_msg = "【MHYY】签到状态推送\n\n" # Message container for the current account
|
||||
|
||||
for config in conf:
|
||||
# 各种API的URL
|
||||
NotificationURL = "https://api-cloudgame.mihoyo.com/hk4e_cg_cn/gamer/api/listNotifications?status=NotificationStatusUnread&type=NotificationTypePopup&is_sort=true"
|
||||
WalletURL = "https://api-cloudgame.mihoyo.com/hk4e_cg_cn/wallet/wallet/get"
|
||||
|
@ -94,129 +220,212 @@ if __name__ == "__main__":
|
|||
"https://api-cloudgame.mihoyo.com/hk4e_cg_cn/gamer/api/getAnnouncementInfo"
|
||||
)
|
||||
|
||||
if config == "":
|
||||
# Verify config
|
||||
raise RunError(
|
||||
f"请在Settings->Secrets->Actions页面中新建名为config的变量,并将你的配置填入后再运行!"
|
||||
)
|
||||
else:
|
||||
token = config["token"]
|
||||
client_type = config["type"]
|
||||
sysver = config["sysver"]
|
||||
deviceid = config["deviceid"]
|
||||
devicename = config["devicename"]
|
||||
devicemodel = config["devicemodel"]
|
||||
appid = config["appid"]
|
||||
headers = {
|
||||
"x-rpc-combo_token": token,
|
||||
"x-rpc-client_type": str(client_type),
|
||||
"x-rpc-app_version": str(version),
|
||||
"x-rpc-sys_version": str(sysver),
|
||||
"x-rpc-channel": "cyydmihoyo",
|
||||
"x-rpc-device_id": deviceid,
|
||||
"x-rpc-device_name": devicename,
|
||||
"x-rpc-device_model": devicemodel,
|
||||
"x-rpc-vendor_id": "1",
|
||||
"x-rpc-cg_game_biz": "hk4e_cn",
|
||||
"x-rpc-op_biz": "clgm_cn",
|
||||
"x-rpc-language": "zh-cn",
|
||||
"Host": "api-cloudgame.mihoyo.com",
|
||||
"Connection": "Keep-Alive",
|
||||
"Accept-Encoding": "gzip",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0",
|
||||
}
|
||||
bbsid = re.findall(r"oi=[0-9]+", token)[0].replace("oi=", "")
|
||||
region = config.get("region", "cn")
|
||||
if region == "os":
|
||||
headers["x-rpc-channel"] = "mihoyo"
|
||||
headers["x-rpc-cg_game_biz"] = "hk4e_global"
|
||||
headers["x-rpc-op_biz"] = "clgm_global"
|
||||
headers["x-rpc-cg_game_id"] = "9000254"
|
||||
headers["x-rpc-app_id"] = "600493"
|
||||
headers["User-Agent"] = "okhttp/4.10.0"
|
||||
headers["Host"] = "sg-cg-api.hoyoverse.com"
|
||||
NotificationURL = "https://sg-cg-api.hoyoverse.com/hk4e_global/cg/gamer/api/listNotifications?status=NotificationStatusUnread&type=NotificationTypePopup&is_sort=true"
|
||||
WalletURL = (
|
||||
"https://sg-cg-api.hoyoverse.com/hk4e_global/cg/wallet/wallet/get"
|
||||
)
|
||||
AnnouncementURL = "https://sg-cg-api.hoyoverse.com/hk4e_global/cg/gamer/api/getAnnouncementInfo"
|
||||
# Validate account config entry
|
||||
if not isinstance(config, dict) or "token" not in config:
|
||||
error_msg = f"跳过无效的账号配置条目: {config}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += error_msg + "\n"
|
||||
send_notifications(
|
||||
notification_msg, notification_settings
|
||||
) # Notify about invalid config
|
||||
continue # Skip this entry
|
||||
|
||||
logger.info(
|
||||
f"正在进行第 {conf.index(config) + 1} 个账号,服务器为{'CN' if region != 'os' else 'GLOBAL'}……"
|
||||
)
|
||||
try:
|
||||
wallet = httpx.get(WalletURL, headers=headers, timeout=60, verify=False)
|
||||
logger.debug(wallet.text)
|
||||
if json.loads(wallet.text) == {
|
||||
"data": None,
|
||||
"message": "登录已失效,请重新登录",
|
||||
"retcode": -100,
|
||||
}:
|
||||
logger.error(f"当前登录已过期,请重新登陆!返回为:{wallet.text}")
|
||||
sct_msg += f"当前登录已过期,请重新登陆!返回为:{wallet.text}"
|
||||
else:
|
||||
logger.info(
|
||||
f"你当前拥有免费时长 {json.loads(wallet.text)['data']['free_time']['free_time']} 分钟,畅玩卡状态为 {json.loads(wallet.text)['data']['play_card']['short_msg']},拥有原点 {json.loads(wallet.text)['data']['coin']['coin_num']} 点({int(json.loads(wallet.text)['data']['coin']['coin_num'])/10}分钟)"
|
||||
token = config["token"]
|
||||
client_type = config.get("type", 5)
|
||||
sysver = config.get("sysver", "14.0")
|
||||
deviceid = config["deviceid"]
|
||||
devicename = config.get("devicename", "iPhone 13")
|
||||
devicemodel = config.get("devicemodel", "iPhone13,3")
|
||||
appid = config.get("appid", "1953439978")
|
||||
|
||||
# Construct headers
|
||||
headers = {
|
||||
"x-rpc-combo_token": token,
|
||||
"x-rpc-client_type": str(client_type),
|
||||
"x-rpc-app_version": str(version),
|
||||
"x-rpc-sys_version": str(sysver),
|
||||
"x-rpc-channel": "cyydmihoyo",
|
||||
"x-rpc-device_id": deviceid,
|
||||
"x-rpc-device_name": devicename,
|
||||
"x-rpc-device_model": devicemodel,
|
||||
"x-rpc-vendor_id": "1",
|
||||
"x-rpc-cg_game_biz": "hk4e_cn",
|
||||
"x-rpc-op_biz": "clgm_cn",
|
||||
"x-rpc-language": "zh-cn",
|
||||
"Host": "api-cloudgame.mihoyo.com",
|
||||
"Connection": "Keep-Alive",
|
||||
"Accept-Encoding": "gzip",
|
||||
"User-Agent": f"Mozilla/5.0 (iPhone; CPU iPhone OS {sysver} like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
|
||||
}
|
||||
|
||||
bbsid_match = re.search(r"oi=(\d+)", token)
|
||||
bbsid = bbsid_match.group(1) if bbsid_match else "N/A"
|
||||
|
||||
region = config.get("region", "cn")
|
||||
if region == "os":
|
||||
headers["x-rpc-channel"] = "mihoyo"
|
||||
headers["x-rpc-cg_game_biz"] = "hk4e_global"
|
||||
headers["x-rpc-op_biz"] = "clgm_global"
|
||||
headers["x-rpc-cg_game_id"] = "9000254"
|
||||
headers["x-rpc-app_id"] = "600493"
|
||||
headers["User-Agent"] = "okhttp/4.10.0"
|
||||
headers["Host"] = "sg-cg-api.hoyoverse.com"
|
||||
NotificationURL = "https://sg-cg-api.hoyoverse.com/hk4e_global/cg/gamer/api/listNotifications?status=NotificationStatusUnread&type=NotificationTypePopup&is_sort=true"
|
||||
WalletURL = (
|
||||
"https://sg-cg-api.hoyoverse.com/hk4e_global/cg/wallet/wallet/get"
|
||||
)
|
||||
sct_msg += f"你当前拥有免费时长 {json.loads(wallet.text)['data']['free_time']['free_time']} 分钟,畅玩卡状态为 {json.loads(wallet.text)['data']['play_card']['short_msg']},拥有原点 {json.loads(wallet.text)['data']['coin']['coin_num']} 点({int(json.loads(wallet.text)['data']['coin']['coin_num'])/10}分钟)"
|
||||
announcement = httpx.get(
|
||||
AnnouncementURL, headers=headers, timeout=60, verify=False
|
||||
AnnouncementURL = "https://sg-cg-api.hoyoverse.com/hk4e_global/cg/gamer/api/getAnnouncementInfo"
|
||||
|
||||
logger.info(
|
||||
f"--- 正在进行第 {accounts_conf.index(config) + 1} 个账号 (BBSID: {bbsid}),服务器为{'CN' if region != 'os' else 'GLOBAL'} ---"
|
||||
)
|
||||
notification_msg += (
|
||||
f"☁️ 云原神签到结果 ({'CN' if region != 'os' else 'GLOBAL'}):\n"
|
||||
)
|
||||
notification_msg += (
|
||||
f"账号 {accounts_conf.index(config) + 1} (BBSID: {bbsid})\n\n"
|
||||
)
|
||||
|
||||
try:
|
||||
wallet_res = httpx.get(
|
||||
WalletURL, headers=headers, timeout=30, verify=False
|
||||
)
|
||||
logger.debug(f'获取到公告列表:{json.loads(announcement.text)["data"]}')
|
||||
res = httpx.get(
|
||||
NotificationURL, headers=headers, timeout=60, verify=False
|
||||
)
|
||||
success, Signed = False, False
|
||||
logger.debug(res.text)
|
||||
try:
|
||||
if list(json.loads(res.text)["data"]["list"]) == []:
|
||||
success = True
|
||||
Signed = True
|
||||
Over = False
|
||||
elif (
|
||||
json.loads(json.loads(res.text)["data"]["list"][-1]["msg"])[
|
||||
"msg"
|
||||
]
|
||||
== "每日登录奖励"
|
||||
):
|
||||
success = True
|
||||
Signed = False
|
||||
Over = False
|
||||
elif (
|
||||
json.loads(json.loads(res.text)["data"]["list"][-1]["msg"])[
|
||||
"over_num"
|
||||
]
|
||||
> 0
|
||||
):
|
||||
success = True
|
||||
Signed = False
|
||||
Over = True
|
||||
else:
|
||||
success = False
|
||||
except IndexError:
|
||||
success = False
|
||||
if success:
|
||||
if Signed:
|
||||
logger.info(f"获取签到情况成功!今天是否已经签到过了呢?")
|
||||
sct_msg += f"获取签到情况成功!今天是否已经签到过了呢?"
|
||||
logger.debug(f"完整返回体为:{res.text}")
|
||||
elif not Signed and Over:
|
||||
logger.info(
|
||||
f'获取签到情况成功!当前免费时长已经达到上限!签到情况为{json.loads(res.text)["data"]["list"][0]["msg"]}'
|
||||
)
|
||||
sct_msg += f"获取签到情况成功!当前免费时长已经达到上限!签到情况为{json.loads(res.text)['data']['list'][0]['msg']}"
|
||||
else:
|
||||
logger.info(f"已经签到过了!")
|
||||
sct_msg += f"已经签到过了!"
|
||||
wallet_res.raise_for_status()
|
||||
wallet_data = wallet_res.json()
|
||||
logger.debug(f"Wallet response: {wallet_data}")
|
||||
|
||||
if wallet_data.get("retcode") == -100:
|
||||
error_msg = f"当前登录已过期,请重新登陆!返回为:{wallet_data.get('message', 'Unknown error')}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += error_msg + "\n"
|
||||
elif wallet_data.get("retcode") == 0 and wallet_data.get("data"):
|
||||
free_time = wallet_data["data"]["free_time"]["free_time"]
|
||||
play_card_msg = wallet_data["data"]["play_card"]["short_msg"]
|
||||
coin_num = wallet_data["data"]["coin"]["coin_num"]
|
||||
coin_minutes = int(coin_num) / 10 if coin_num is not None else 0
|
||||
wallet_status = f"✅ 钱包:免费时长 {free_time} 分钟,畅玩卡状态为 {play_card_msg},拥有原点 {coin_num} 点 ({coin_minutes:.0f}分钟)\n"
|
||||
logger.info(wallet_status.strip())
|
||||
notification_msg += wallet_status
|
||||
else:
|
||||
logger.info(f"当前没有签到!请稍后再试!")
|
||||
sct_msg += f"当前没有签到!请稍后再试!"
|
||||
if sct_key:
|
||||
httpx.get(sct_url, params={"desp": sct_msg})
|
||||
error_msg = f"获取钱包信息失败: {wallet_data.get('retcode')} - {wallet_data.get('message', 'Unknown error')}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += error_msg + "\n"
|
||||
|
||||
except httpx.HTTPStatusError as e:
|
||||
error_msg = f"获取钱包信息HTTP错误: {e.response.status_code} - {e.response.text}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += error_msg + "\n"
|
||||
except httpx.RequestError as e:
|
||||
error_msg = f"请求钱包信息失败: {e}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += error_msg + "\n"
|
||||
except Exception as e:
|
||||
error_msg = f"解析钱包信息出错: {e}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += error_msg + "\n"
|
||||
|
||||
# --- Check Sign-in Status ---
|
||||
try:
|
||||
announcement_res = httpx.get(
|
||||
AnnouncementURL, headers=headers, timeout=30, verify=False
|
||||
)
|
||||
announcement_res.raise_for_status()
|
||||
# logger.debug(f'Announcement response: {announcement_res.text}') # Too verbose usually
|
||||
|
||||
notification_res = httpx.get(
|
||||
NotificationURL, headers=headers, timeout=30, verify=False
|
||||
)
|
||||
notification_res.raise_for_status()
|
||||
notification_data = notification_res.json()
|
||||
logger.debug(f"Notification response: {notification_data}")
|
||||
|
||||
sign_in_status = "❓ 未知签到状态" # Default status
|
||||
|
||||
if notification_data.get("retcode") == 0 and notification_data.get(
|
||||
"data"
|
||||
):
|
||||
notification_list = notification_data["data"].get("list", [])
|
||||
|
||||
if not notification_list:
|
||||
sign_in_status = "✅ 今天似乎已经签到过了!(通知列表为空)"
|
||||
logger.info(sign_in_status)
|
||||
notification_msg += sign_in_status + "\n"
|
||||
else:
|
||||
# Look for a notification indicating sign-in reward or limit reached
|
||||
# The logic here was a bit fragile, let's try to be more robust
|
||||
# Look for specific message patterns if possible, or just check the presence of notifications
|
||||
|
||||
last_notification_msg = notification_list[0].get(
|
||||
"msg"
|
||||
) # Assume the first one is the latest? Or the last one? Original code used [-1]... let's stick to that for now.
|
||||
if len(notification_list) > 0:
|
||||
last_notification_msg = notification_list[-1].get("msg")
|
||||
|
||||
try:
|
||||
# Attempt to parse the 'msg' field which is often a JSON string itself
|
||||
msg_payload = json.loads(last_notification_msg)
|
||||
logger.debug(
|
||||
f"Parsed last notification msg payload: {msg_payload}"
|
||||
)
|
||||
|
||||
if msg_payload.get("msg") == "每日登录奖励":
|
||||
sign_in_status = f"✅ 获取签到情况成功!{msg_payload.get('msg')}:获得 {msg_payload.get('free_time')} 分钟"
|
||||
logger.info(sign_in_status)
|
||||
notification_msg += sign_in_status + "\n"
|
||||
elif msg_payload.get("over_num", 0) > 0:
|
||||
sign_in_status = f"✅ 获取签到情况成功!免费时长已达上限,未能获得 {msg_payload.get('free_time')} 分钟 (超出 {msg_payload.get('over_num')} 分钟)"
|
||||
logger.info(sign_in_status)
|
||||
notification_msg += sign_in_status + "\n"
|
||||
else:
|
||||
# Catch-all for other notification types or unexpected payloads
|
||||
sign_in_status = f"❓ 获取到其他通知,可能已经签到或状态未知: {last_notification_msg}"
|
||||
logger.info(sign_in_status)
|
||||
notification_msg += sign_in_status + "\n"
|
||||
|
||||
except json.JSONDecodeError:
|
||||
# 'msg' is not a JSON string
|
||||
sign_in_status = f"❓ 获取到非标准通知,可能已经签到或状态未知: {last_notification_msg}"
|
||||
logger.info(sign_in_status)
|
||||
notification_msg += sign_in_status + "\n"
|
||||
except Exception as e:
|
||||
# Other errors during parsing msg
|
||||
sign_in_status = f"❌ 解析通知详情时出错: {e}. Raw msg: {last_notification_msg}"
|
||||
logger.error(sign_in_status)
|
||||
notification_msg += sign_in_status + "\n"
|
||||
|
||||
elif notification_data.get("retcode") != 0:
|
||||
error_msg = f"获取通知列表失败: {notification_data.get('retcode')} - {notification_data.get('message', 'Unknown error')}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += error_msg + "\n"
|
||||
|
||||
except httpx.HTTPStatusError as e:
|
||||
error_msg = f"获取通知列表HTTP错误: {e.response.status_code} - {e.response.text}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += error_msg + "\n"
|
||||
except httpx.RequestError as e:
|
||||
error_msg = f"请求通知列表失败: {e}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += error_msg + "\n"
|
||||
except Exception as e:
|
||||
error_msg = f"检查签到状态时出错: {e}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += error_msg + "\n"
|
||||
|
||||
except KeyError as e:
|
||||
# This catches missing required keys in account config
|
||||
error_msg = f"账号配置缺少必需的键: {e}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += f"❌ 账号配置错误: {error_msg}\n"
|
||||
except Exception as e:
|
||||
logger.error(f"执行过程中出错:{str(e)}")
|
||||
sct_msg += f"执行过程中出错:{str(e)}"
|
||||
if sct_key:
|
||||
httpx.get(sct_url, params={"desp": sct_msg})
|
||||
raise RunError(str(e))
|
||||
# Catch any other unexpected errors during account processing
|
||||
error_msg = f"处理账号时发生未知错误: {e}"
|
||||
logger.error(error_msg)
|
||||
notification_msg += f"❌ 账号处理错误: {error_msg}\n"
|
||||
|
||||
if accounts_conf.index(config) < len(accounts_conf) - 1:
|
||||
notification_msg += "\n---\n\n"
|
||||
|
||||
send_notifications(notification_msg, notification_settings)
|
||||
|
||||
logger.info("所有任务已经执行完毕!")
|
||||
|
|
11
pyproject.toml
Normal file
11
pyproject.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[project]
|
||||
name = "mhyy"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
"httpx>=0.28.1",
|
||||
"pyyaml>=6.0.2",
|
||||
"sentry-sdk>=2.32.0",
|
||||
]
|
164
uv.lock
Normal file
164
uv.lock
Normal file
|
@ -0,0 +1,164 @@
|
|||
version = 1
|
||||
revision = 2
|
||||
requires-python = ">=3.11"
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "idna" },
|
||||
{ name = "sniffio" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload_time = "2025-03-17T00:02:54.77Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload_time = "2025-03-17T00:02:52.713Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2025.6.15"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload_time = "2025-06-15T02:45:51.329Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload_time = "2025-06-15T02:45:49.977Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload_time = "2025-04-24T03:35:25.427Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload_time = "2025-04-24T03:35:24.344Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload_time = "2025-04-24T22:06:22.219Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload_time = "2025-04-24T22:06:20.566Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpx"
|
||||
version = "0.28.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
{ name = "certifi" },
|
||||
{ name = "httpcore" },
|
||||
{ name = "idna" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload_time = "2024-12-06T15:37:23.222Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload_time = "2024-12-06T15:37:21.509Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload_time = "2024-09-15T18:07:39.745Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload_time = "2024-09-15T18:07:37.964Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mhyy"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "httpx" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "sentry-sdk" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "httpx", specifier = ">=0.28.1" },
|
||||
{ name = "pyyaml", specifier = ">=6.0.2" },
|
||||
{ name = "sentry-sdk", specifier = ">=2.32.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload_time = "2024-08-06T20:33:50.674Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload_time = "2024-08-06T20:32:03.408Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload_time = "2024-08-06T20:32:04.926Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload_time = "2024-08-06T20:32:06.459Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload_time = "2024-08-06T20:32:08.338Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload_time = "2024-08-06T20:32:14.124Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload_time = "2024-08-06T20:32:16.17Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload_time = "2024-08-06T20:32:18.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload_time = "2024-08-06T20:32:19.889Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload_time = "2024-08-06T20:32:21.273Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload_time = "2024-08-06T20:32:25.131Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload_time = "2024-08-06T20:32:26.511Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload_time = "2024-08-06T20:32:28.363Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload_time = "2024-08-06T20:32:30.058Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload_time = "2024-08-06T20:32:31.881Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload_time = "2024-08-06T20:32:37.083Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload_time = "2024-08-06T20:32:38.898Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload_time = "2024-08-06T20:32:40.241Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload_time = "2024-08-06T20:32:41.93Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload_time = "2024-08-06T20:32:43.4Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload_time = "2024-08-06T20:32:44.801Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload_time = "2024-08-06T20:32:46.432Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload_time = "2024-08-06T20:32:51.188Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload_time = "2024-08-06T20:32:53.019Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload_time = "2024-08-06T20:32:54.708Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload_time = "2024-08-06T20:32:56.985Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload_time = "2024-08-06T20:33:03.001Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload_time = "2024-08-06T20:33:04.33Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-sdk"
|
||||
version = "2.32.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/10/59/eb90c45cb836cf8bec973bba10230ddad1c55e2b2e9ffa9d7d7368948358/sentry_sdk-2.32.0.tar.gz", hash = "sha256:9016c75d9316b0f6921ac14c8cd4fb938f26002430ac5be9945ab280f78bec6b", size = 334932, upload_time = "2025-06-27T08:10:02.89Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/01/a1/fc4856bd02d2097324fb7ce05b3021fb850f864b83ca765f6e37e92ff8ca/sentry_sdk-2.32.0-py2.py3-none-any.whl", hash = "sha256:6cf51521b099562d7ce3606da928c473643abe99b00ce4cb5626ea735f4ec345", size = 356122, upload_time = "2025-06-27T08:10:01.424Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sniffio"
|
||||
version = "1.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload_time = "2024-02-25T23:20:04.057Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload_time = "2024-02-25T23:20:01.196Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload_time = "2025-06-02T14:52:11.399Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload_time = "2025-06-02T14:52:10.026Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload_time = "2025-06-18T14:07:41.644Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload_time = "2025-06-18T14:07:40.39Z" },
|
||||
]
|
Loading…
Reference in New Issue
Block a user