Compare commits

..

16 Commits
1.0.6 ... 1.1.8

Author SHA1 Message Date
ikun
6ec83c4196 fix:意外 2024-09-05 21:27:36 +08:00
ikun
a7ce46aa52 fix:兼容问题 2024-09-05 20:54:34 +08:00
ikun
b4ea1edb53 chore: 优化代码工整性 2024-09-01 14:00:20 +08:00
ikun
f555f0273d rm: 搜索游戏自动获取App ID 2024-08-29 17:22:04 +08:00
ikun
3ba8b67f0e fix: bug 2024-08-27 09:48:20 +08:00
ikun
73c92e550e feat: 加入搜索游戏名入库功能
Co-Authored-By: Tibbar <49330075+tibbar213@users.noreply.github.com>
2024-08-26 19:06:05 +08:00
ikun
a2fa038324 feat&&fix: bug!bug!bug! 2024-08-22 22:40:50 +08:00
ikun
ea3aedbab3 fix: 史 2024-08-22 21:48:04 +08:00
ikun
51ccc579f4 feat:配置文件修改 2024-08-22 14:10:30 +08:00
ikun
17e654a68e feat:没什么用懒得发Release 2024-08-21 17:27:50 +08:00
ikun
c4f4fb9e92 feat: 增加一个清单库 2024-08-16 15:11:31 +08:00
ikun
e38af1675c fix: 修改QQ群链接 2024-08-15 19:53:41 +08:00
ikun
50194cf7de 更新 main.py 2024-08-14 19:00:27 +08:00
ikun
7063f2f5dc rm: 移除jsdelivr的CDN服务 2024-08-13 10:25:28 +08:00
ikun
2c6b3bebe1 fix: Github API请求数量为0时不返回错误
史中史代码,看不懂与我无关
2024-08-12 19:18:56 +08:00
ikun
5c74940702 feat: 加了几个加速镜像 2024-08-12 15:08:54 +08:00
13 changed files with 328 additions and 253 deletions

1
.gitignore vendored
View File

@@ -168,3 +168,4 @@ cython_debug/
*.bat
*.xml
*.exe
*.dll

0
common/__init__.py Normal file
View File

36
common/config.py Normal file
View File

@@ -0,0 +1,36 @@
import ujson as json
import aiofiles
from . import log
import os
import sys
import asyncio
log = log.log
# 生成配置文件
async def gen_config_file():
default_config ={
"Github_Personal_Token": "",
"Custom_Steam_Path": "",
"QA1": "温馨提示Github_Personal_Token可在Github设置的最底下开发者选项找到详情看教程",
"教程": "https://lyvx-my.sharepoint.com/:w:/g/personal/ikun_ikunshare_com/EWqIqyCElLNLo_CKfLbqix0BWU_O03HLzEHQKHdJYrUz-Q?e=79MZjw"
}
async with aiofiles.open("./config.json", mode="w", encoding="utf-8") as f:
await f.write(json.dumps(default_config, indent=2, ensure_ascii=False,
escape_forward_slashes=False))
await f.close()
log.info(' 🖱️ 程序可能为第一次启动,请填写配置文件后重新启动程序')
# 加载配置文件
async def load_config():
if not os.path.exists('./config.json'):
await gen_config_file()
os.system('pause')
sys.exit()
else:
async with aiofiles.open("./config.json", mode="r", encoding="utf-8") as f:
config = json.loads(await f.read())
return config
config = asyncio.run(load_config())

23
common/dkey_merge.py Normal file
View File

@@ -0,0 +1,23 @@
import asyncio
import aiofiles
import vdf
from .log import log
lock = asyncio.Lock()
async def depotkey_merge(config_path, depots_config):
if not config_path.exists():
async with lock:
log.error(' 👋 Steam默认配置不存在可能是没有登录账号')
return
async with aiofiles.open(config_path, encoding='utf-8') as f:
config = vdf.load(f)
software = config['InstallConfigStore']['Software']
valve = software.get('Valve') or software.get('valve')
steam = valve.get('Steam') or valve.get('steam')
if 'depots' not in steam:
steam['depots'] = {}
steam['depots'].update(depots_config['depots'])
async with aiofiles.open(config_path, mode='w', encoding='utf-8') as f:
vdf.dump(config, f, pretty=True)
return True

17
common/getsteampath.py Normal file
View File

@@ -0,0 +1,17 @@
import winreg
from pathlib import Path
from common import config
config = config.config
# 通过注册表获取Steam安装路径
def get_steam_path():
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Valve\Steam')
steam_path = Path(winreg.QueryValueEx(key, 'SteamPath')[0])
custom_steam_path = config["Custom_Steam_Path"]
if not custom_steam_path == '':
return Path(custom_steam_path)
else:
return steam_path
steam_path = get_steam_path()

33
common/glunlock.py Normal file
View File

@@ -0,0 +1,33 @@
from common import getsteampath
steam_path = getsteampath.steam_path
# 增加GreenLuma解锁相关文件
async def greenluma_add(depot_id_list):
app_list_path = steam_path / 'AppList'
if app_list_path.exists() and app_list_path.is_file():
app_list_path.unlink(missing_ok=True)
if not app_list_path.is_dir():
app_list_path.mkdir(parents=True, exist_ok=True)
depot_dict = {}
for i in app_list_path.iterdir():
if i.stem.isdecimal() and i.suffix == '.txt':
with i.open('r', encoding='utf-8') as f:
app_id_ = f.read().strip()
depot_dict[int(i.stem)] = None
if app_id_.isdecimal():
depot_dict[int(i.stem)] = int(app_id_)
for depot_id in depot_id_list:
if int(depot_id) not in depot_dict.values():
index = max(depot_dict.keys()) + 1 if depot_dict.keys() else 0
if index != 0:
for i in range(max(depot_dict.keys())):
if i not in depot_dict.keys():
index = i
break
with (app_list_path / f'{index}.txt').open('w', encoding='utf-8') as f:
f.write(str(depot_id))
depot_dict[index] = int(depot_id)
return True
glunlock = greenluma_add

23
common/log.py Normal file
View File

@@ -0,0 +1,23 @@
import colorlog
import logging
# 初始化日志记录器
def init_log():
logger = logging.getLogger('Onekey')
logger.setLevel(logging.DEBUG)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.DEBUG)
fmt_string = '%(log_color)s[%(name)s][%(levelname)s]%(message)s'
log_colors = {
'INFO': 'cyan',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'purple'
}
fmt = colorlog.ColoredFormatter(fmt_string, log_colors=log_colors)
stream_handler.setFormatter(fmt)
logger.addHandler(stream_handler)
return logger
log = init_log()

28
common/manifestdown.py Normal file
View File

@@ -0,0 +1,28 @@
from aiohttp import ClientError
from .log import log
# 下载清单
async def get(sha, path, repo, session):
url_list = [
# f'https://gh.api.99988866.xyz/https://raw.githubusercontent.com/{repo}/{sha}/{path}',
f'https://cdn.jsdmirror.com/gh/{repo}@{sha}/{path}',
f'https://jsd.onmicrosoft.cn/gh/{repo}@{sha}/{path}',
f'https://mirror.ghproxy.com/https://raw.githubusercontent.com/{repo}/{sha}/{path}',
f'https://raw.githubusercontent.com/{repo}/{sha}/{path}',
f'https://gh.jiasu.in/https://raw.githubusercontent.com/{repo}/{sha}/{path}'
]
retry = 3
while retry:
for url in url_list:
try:
async with session.get(url, ssl=False) as r:
if r.status == 200:
return await r.read()
else:
log.error(f' 🔄 获取失败: {path} - 状态码: {r.status}')
except ClientError:
log.error(f' 🔄 获取失败: {path} - 连接错误')
retry -= 1
log.warning(f' 🔄 重试剩余次数: {retry} - {path}')
log.error(f' 🔄 超过最大重试次数: {path}')
raise Exception(f' 🔄 无法下载: {path}')

22
common/migration.py Normal file
View File

@@ -0,0 +1,22 @@
import os
from common import log, getsteampath
from pathlib import Path
# 设置文件目录
log = log.log
steam_path = getsteampath.steam_path
directory = Path(steam_path / "config" / "stplug-in")
# 遍历目录中的所有文件
def migrate():
for filename in os.listdir(directory):
if filename.startswith("Onekey_unlock_"):
new_filename = filename[len("Onekey_unlock_"):]
old_file = os.path.join(directory, filename)
new_file = os.path.join(directory, new_filename)
os.rename(old_file, new_file)
log.info(f'Renamed: {filename} -> {new_filename}')
migrate = migrate

8
common/stack_error.py Normal file
View File

@@ -0,0 +1,8 @@
import traceback
# 错误堆栈处理
def stack_error(exception):
stack_trace = traceback.format_exception(type(exception), exception, exception.__traceback__)
return ''.join(stack_trace)
stack_error = stack_error

29
common/stunlock.py Normal file
View File

@@ -0,0 +1,29 @@
from common import log, getsteampath
import asyncio
import aiofiles
import os
import subprocess
lock = asyncio.Lock()
log = log.log
steam_path = getsteampath.steam_path
# 增加SteamTools解锁相关文件
async def stool_add(depot_data, app_id):
lua_filename = f"{app_id}.lua"
lua_filepath = steam_path / "config" / "stplug-in" / lua_filename
async with lock:
log.info(f' ✅ SteamTools解锁文件生成: {lua_filepath}')
async with aiofiles.open(lua_filepath, mode="w", encoding="utf-8") as lua_file:
await lua_file.write(f'addappid({app_id}, 1, "None")\n')
for depot_id, depot_key in depot_data:
await lua_file.write(f'addappid({depot_id}, 1, "{depot_key}")\n')
luapacka_path = steam_path / "config" / "stplug-in" / "luapacka.exe"
subprocess.run([str(luapacka_path), str(lua_filepath)])
os.remove(lua_filepath)
return True
stunlock = stool_add

357
main.py
View File

@@ -1,63 +1,25 @@
import os
import vdf
import winreg
import argparse
import aiohttp
import aiofiles
import traceback
import subprocess
import colorlog
import logging
import json
import time
import sys
import psutil
import asyncio
from common import log, config, getsteampath, stunlock, glunlock, stack_error, manifestdown, dkey_merge, migration
from aiohttp import ClientSession
from pathlib import Path
# 初始化日志记录器
def init_log():
logger = logging.getLogger('Onekey')
logger.setLevel(logging.DEBUG)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.DEBUG)
fmt_string = '%(log_color)s[%(name)s][%(levelname)s]%(message)s'
log_colors = {
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'purple'
}
fmt = colorlog.ColoredFormatter(fmt_string, log_colors=log_colors)
stream_handler.setFormatter(fmt)
logger.addHandler(stream_handler)
return logger
# 生成配置文件
def gen_config_file():
default_config = {"Github_Persoal_Token": "", "Custom_Steam_Path": ""}
with open('./config.json', 'w', encoding='utf-8') as f:
json.dump(default_config, f)
log.info(' 🖱️ 程序可能为第一次启动,请填写配置文件后重新启动程序')
# 加载配置文件
def load_config():
if not os.path.exists('./config.json'):
gen_config_file()
os.system('pause')
sys.exit()
else:
with open('./config.json', 'r', encoding='utf-8') as f:
config = json.load(f)
return config
log = init_log()
config = load_config()
log = log.log
config = config.config
lock = asyncio.Lock()
steam_path = getsteampath.steam_path
isGreenLuma = any((steam_path / dll).exists() for dll in ['GreenLuma_2024_x86.dll', 'GreenLuma_2024_x64.dll', 'User32.dll'])
isSteamTools = (steam_path / 'config' / 'stplug-in').is_dir()
stunlock = stunlock.stunlock
glunlock = glunlock.glunlock
stack_error = stack_error.stack_error
get = manifestdown.get
depotkey_merge = dkey_merge.depotkey_merge
migration = migration.migrate
print('\033[1;32;40m _____ __ _ _____ _ _ _____ __ __ ' + '\033[0m')
@@ -67,243 +29,136 @@ print('\033[1;32;40m | | | | | |\\ | | __| | |\\ \\ | __| \\ / ' + '\
print('\033[1;32;40m | |_| | | | \\ | | |___ | | \\ \\ | |___ / /' + '\033[0m')
print('\033[1;32;40m \\_____/ |_| \\_| |_____| |_| \\_\\ |_____| /_/' + '\033[0m')
log.info('作者ikun0014')
log.info('本项目基于wxy1343/ManifestAutoUpdate进行修改采用GPL V3许可证')
log.info('版本1.0.6')
log.info('本项目基于wxy1343/ManifestAutoUpdate进行修改采用ACSL许可证')
log.info('版本1.1.7')
log.info('项目仓库https://github.com/ikunshare/Onekey')
log.debug('官网ikunshare.com')
log.warning('倒卖本工具的臭傻逼https://space.bilibili.com/3546655638948756')
log.warning('注意据传Steam新版本对部分解锁工具进行了检测但目前未发现问题如果你被封号可以issue反馈')
log.warning('本项目完全免费如果你在淘宝QQ群内通过购买方式获得赶紧回去骂商家死全家\n交流群组:\n点击链接加入群聊【ikun分享】https://qm.qq.com/q/D9Uiva3RVS\nhttps://t.me/ikunshare_group')
# 通过注册表获取Steam安装路径
def get_steam_path():
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Valve\Steam')
steam_path = Path(winreg.QueryValueEx(key, 'SteamPath')[0])
custom_steam_path = config.get("Custom_Steam_Path", "")
if not custom_steam_path == '':
return Path(custom_steam_path)
else:
return steam_path
steam_path = get_steam_path()
isGreenLuma = any((steam_path / dll).exists() for dll in ['GreenLuma_2024_x86.dll', 'GreenLuma_2024_x64.dll', 'User32.dll'])
isSteamTools = (steam_path / 'config' / 'stplug-in').is_dir()
# 错误堆栈处理
def stack_error(exception):
stack_trace = traceback.format_exception(type(exception), exception, exception.__traceback__)
return ''.join(stack_trace)
# 下载清单
async def get(sha, path):
url_list = [
f'https://gcore.jsdelivr.net/gh/{repo}@{sha}/{path}',
f'https://fastly.jsdelivr.net/gh/{repo}@{sha}/{path}',
f'https://cdn.jsdelivr.net/gh/{repo}@{sha}/{path}',
f'https://raw.dgithub.xyz/{repo}/{sha}/{path}'
]
retry = 3
async with aiohttp.ClientSession() as session:
while retry:
for url in url_list:
try:
async with session.get(url, ssl=False) as r:
if r.status == 200:
return await r.read()
else:
log.error(f' 🔄 获取失败: {path} - 状态码: {r.status}')
except aiohttp.ClientError:
log.error(f' 🔄 获取失败: {path} - 连接错误')
retry -= 1
log.warning(f' 🔄 重试剩余次数: {retry} - {path}')
log.error(f' 🔄 超过最大重试次数: {path}')
raise Exception(f' 🔄 无法下载: {path}')
log.info('官网ikunshare.com')
log.warning('本项目完全开源免费如果你在淘宝QQ群内通过购买方式获得赶紧回去骂商家死全家\n交流群组:\n点击链接加入群聊【𝗶𝗸𝘂𝗻分享】https://qm.qq.com/q/d7sWovfAGI\nhttps://t.me/ikunshare_group')
# 获取清单信息
async def get_manifest(sha, path, steam_path: Path):
async def get_manifest(sha, path, steam_path: Path, repo, session):
collected_depots = []
try:
if path.endswith('.manifest'):
depot_cache_path = steam_path / 'depotcache'
async with lock:
if not depot_cache_path.exists():
depot_cache_path.mkdir(exist_ok=True)
if not depot_cache_path.exists():
depot_cache_path.mkdir(exist_ok=True)
save_path = depot_cache_path / path
if save_path.exists():
async with lock:
log.warning(f'👋已存在清单: {path}')
log.warning(f'👋已存在清单: {path}')
return collected_depots
content = await get(sha, path)
async with lock:
log.info(f' 🔄 清单下载成功: {path}')
content = await get(sha, path, repo, session)
log.info(f' 🔄 清单下载成功: {path}')
async with aiofiles.open(save_path, 'wb') as f:
await f.write(content)
elif path == 'Key.vdf':
content = await get(sha, path)
async with lock:
log.info(f' 🔄 密钥下载成功: {path}')
content = await get(sha, path, repo, session)
log.info(f' 🔄 密钥下载成功: {path}')
depots_config = vdf.loads(content.decode(encoding='utf-8'))
for depot_id, depot_info in depots_config['depots'].items():
collected_depots.append((depot_id, depot_info['DecryptionKey']))
except KeyboardInterrupt:
raise
except Exception as e:
log.error(f'处理失败: {path} - {stack_error(e)}')
traceback.print_exc()
raise
return collected_depots
# 合并DecryptionKey
async def depotkey_merge(config_path, depots_config):
if not config_path.exists():
async with lock:
log.error(' 👋 Steam默认配置不存在可能是没有登录账号')
return
with open(config_path, encoding='utf-8') as f:
config = vdf.load(f)
software = config['InstallConfigStore']['Software']
valve = software.get('Valve') or software.get('valve')
steam = valve.get('Steam') or valve.get('steam')
if 'depots' not in steam:
steam['depots'] = {}
steam['depots'].update(depots_config['depots'])
with open(config_path, 'w', encoding='utf-8') as f:
vdf.dump(config, f, pretty=True)
return True
# 增加SteamTools解锁相关文件
async def stool_add(depot_data, app_id):
lua_filename = f"Onekey_unlock_{app_id}.lua"
lua_filepath = steam_path / "config" / "stplug-in" / lua_filename
async with lock:
log.info(f' ✅ SteamTools解锁文件生成: {lua_filepath}')
with open(lua_filepath, "w", encoding="utf-8") as lua_file:
lua_file.write(f'addappid({app_id}, 1, "None")\n')
for depot_id, depot_key in depot_data:
lua_file.write(f'addappid({depot_id}, 1, "{depot_key}")\n')
luapacka_path = steam_path / "config" / "stplug-in" / "luapacka.exe"
subprocess.run([str(luapacka_path), str(lua_filepath)])
os.remove(lua_filepath)
return True
# 增加GreenLuma解锁相关文件
async def greenluma_add(depot_id_list):
app_list_path = steam_path / 'appcache' / 'appinfo.vdf'
if app_list_path.exists() and app_list_path.is_file():
app_list_path.unlink(missing_ok=True)
if not app_list_path.is_dir():
app_list_path.mkdir(parents=True, exist_ok=True)
depot_dict = {}
for i in app_list_path.iterdir():
if i.stem.isdecimal() and i.suffix == '.txt':
with i.open('r', encoding='utf-8') as f:
app_id_ = f.read().strip()
depot_dict[int(i.stem)] = None
if app_id_.isdecimal():
depot_dict[int(i.stem)] = int(app_id_)
for depot_id in depot_id_list:
if int(depot_id) not in depot_dict.values():
index = max(depot_dict.keys()) + 1 if depot_dict.keys() else 0
if index != 0:
for i in range(max(depot_dict.keys())):
if i not in depot_dict.keys():
index = i
break
with (app_list_path / f'{index}.txt').open('w', encoding='utf-8') as f:
f.write(str(depot_id))
depot_dict[index] = int(depot_id)
return True
# 检测Github Api请求数量
async def check_github_api_limit(headers):
async def check_github_api_rate_limit(headers, session):
url = 'https://api.github.com/rate_limit'
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers, ssl=False) as r:
async with session.get(url, headers=headers, ssl=False) as r:
if not r == None:
r_json = await r.json()
remain_limit = r_json['rate']['remaining']
use_limit = r_json['rate']['used']
reset_time = r_json['rate']['reset']
f_reset_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(reset_time))
log.info(f' 🔄 已用Github请求数{use_limit}')
log.info(f' 🔄 剩余Github请求数{remain_limit}')
if r.status == 429:
log.info(f' 🔄 你的Github Api请求数已超限请尝试增加Persoal Token')
log.info(f' 🔄 请求数重置时间:{f_reset_time}')
return True
else:
log.error('孩子,你怎么做到的?')
os.system('pause')
if r.status == 200:
rate_limit = r_json['rate']
remaining_requests = rate_limit['remaining']
reset_time = rate_limit['reset']
reset_time_formatted = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(reset_time))
log.info(f' 🔄 剩余请求次数: {remaining_requests}')
else:
log.error('Github请求数检查失败')
# 检查进程是否运行
def check_process_running(process_name):
for process in psutil.process_iter(['name']):
if process.info['name'] == process_name:
return True
return False
if remaining_requests == 0:
log.warning(f' ⚠ GitHub API 请求数已用尽,将在 {reset_time_formatted} 重置, 不想等生成一个填配置文件里')
# 主函数
async def main(app_id):
app_id_list = list(filter(str.isdecimal, app_id.strip().split('-')))
app_id = app_id_list[0]
github_token = config.get("Github_Persoal_Token", "")
headers = {'Authorization': f'Bearer {github_token}'} if github_token else None
async with ClientSession() as session:
github_token = config["Github_Personal_Token"]
headers = {'Authorization': f'Bearer {github_token}'} if github_token else None
latest_date = None
selected_repo = None
await check_github_api_limit(headers)
# 检查Github API限额
await check_github_api_rate_limit(headers, session)
url = f'https://api.github.com/repos/{repo}/branches/{app_id}'
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers, ssl=False) as r:
r_json = await r.json()
if 'commit' in r_json:
sha = r_json['commit']['sha']
url = r_json['commit']['commit']['tree']['url']
date = r_json['commit']['commit']['author']['date']
async with session.get(url, headers=headers, ssl=False) as r2:
r2_json = await r2.json()
if 'tree' in r2_json:
collected_depots = []
for i in r2_json['tree']:
result = await get_manifest(sha, i['path'], steam_path)
collected_depots.extend(result)
if collected_depots:
if isSteamTools:
await stool_add(collected_depots, app_id)
log.info(' ✅ 找到SteamTools已添加解锁文件')
if isGreenLuma:
await greenluma_add([app_id])
depot_config = {'depots': {depot_id: {'DecryptionKey': depot_key} for depot_id, depot_key in collected_depots}}
depotkey_merge(steam_path / 'config' / 'config.vdf', depot_config)
if await greenluma_add([int(i) for i in depot_config['depots'] if i.isdecimal()]):
log.info(' ✅ 找到GreenLuma已添加解锁文件')
log.info(f' ✅ 清单最后更新时间:{date}')
log.info(f' ✅ 入库成功: {app_id}')
return True
log.error(f' ⚠ 清单下载或生成.st失败: {app_id}')
return False
for repo in repos:
url = f'https://api.github.com/repos/{repo}/branches/{app_id}'
try:
async with session.get(url, headers=headers, ssl=False) as r:
r_json = await r.json()
if 'commit' in r_json:
date = r_json['commit']['commit']['author']['date']
if latest_date is None or date > latest_date:
latest_date = date
selected_repo = repo
except Exception as e:
log.error(f' ⚠ 获取分支信息失败: {stack_error(e)}')
traceback.print_exc()
if selected_repo:
log.info(f' 🔄 选择清单仓库:{selected_repo}')
url = f'https://api.github.com/repos/{selected_repo}/branches/{app_id}'
async with session.get(url, headers=headers, ssl=False) as r:
r_json = await r.json()
if 'commit' in r_json:
sha = r_json['commit']['sha']
url = r_json['commit']['commit']['tree']['url']
async with session.get(url, headers=headers, ssl=False) as r2:
r2_json = await r2.json()
if 'tree' in r2_json:
collected_depots = []
for i in r2_json['tree']:
result = await get_manifest(sha, i['path'], steam_path, selected_repo, session)
collected_depots.extend(result)
if collected_depots:
if isSteamTools:
await stunlock(collected_depots, app_id)
log.info(' ✅ 找到SteamTools已添加解锁文件')
if isGreenLuma:
await glunlock([app_id])
depot_config = {'depots': {depot_id: {'DecryptionKey': depot_key} for depot_id, depot_key in collected_depots}}
await depotkey_merge(steam_path / 'config' / 'config.vdf', depot_config)
if await glunlock([int(i) for i in depot_config['depots'] if i.isdecimal()]):
log.info(' ✅ 找到GreenLuma已添加解锁文件')
log.info(f' ✅ 清单最后更新时间:{date}')
log.info(f' ✅ 入库成功: {app_id}')
os.system('pause')
return True
log.error(f' ⚠ 清单下载或生成失败: {app_id}')
os.system('pause')
return False
parser = argparse.ArgumentParser()
parser.add_argument('-a', '--app-id')
args = parser.parse_args()
repo = 'ManifestHub/ManifestHub'
repos = [
'ManifestHub/ManifestHub',
'ikun0014/ManifestHub',
'Auiowu/ManifestAutoUpdate',
'tymolu233/ManifestAutoUpdate'
]
if __name__ == '__main__':
try:
log.debug('App ID可以在SteamDB或Steam商店链接页面查看')
asyncio.run(main(args.app_id or input('需要入库的App ID: ')))
migration()
log.info('App ID可以在SteamDB或Steam商店链接页面查看')
app_id = input("请输入游戏AppID").strip()
asyncio.run(main(app_id))
except KeyboardInterrupt:
exit()
except Exception as e:
log.error(f' ⚠ 发生错误: {stack_error(e)}')
traceback.print_exc()
if not args.app_id:
os.system('pause')
traceback.print_exc()

View File

@@ -1,5 +1,5 @@
aiofiles==24.1.0
aiohttp==3.9.5
colorlog==6.8.2
psutil==6.0.0
ujson==5.10.0
vdf==3.4
nuitka==2.4.8