def sell_card(targetQQ: str, cards_to_send: List[str]) -> str: cards_to_send = [ name for name in cards_to_send if name != CARD_PLACEHOLDER ] original_cards = [*cards_to_send] # 读取配置信息 load_config("config.toml", "config.toml.local") cfg = config() # 12.30 送卡片次数(re:好像送给别人没有上限?) indexes = list(range(len(cfg.account_configs), 0, -1)) card_info_map = parse_card_group_info_map(zzconfig()) for name in cards_to_send: if name not in card_info_map: return f"{name}不是本期卡片名称,有效的卡片名称为: {list(card_info_map.keys())}" success_send_list = [] for idx in indexes: # 从1开始,第i个 account_config = cfg.account_configs[idx - 1] show_head_line(f"开始处理第{idx}个账户[{account_config.name}]", color("fg_bold_yellow")) djcHelper = DjcHelper(account_config, cfg.common) lr = djcHelper.fetch_pskey() djcHelper.check_skey_expired() djcHelper.get_bind_role_list() remaining_cards = [] for name in cards_to_send: res = djcHelper.send_card_by_name(name, targetQQ) retCode = int(res["13333"]["ret"]) if retCode == 0: success_send_list.append(name) else: remaining_cards.append(name) if len(original_cards) == 1: if retCode == 10017: return "该账号今日已被赠送过四次" cards_to_send = remaining_cards if len(cards_to_send) == 0: break msg = "" if len(success_send_list) != 0: msg += f"\n成功发送以下卡片:{success_send_list}" if len(cards_to_send) != 0: msg += f"\n无法发送以下卡片:{cards_to_send},是否已达到赠送上限或者这个卡卖完了?" if len(success_send_list) != 0: msg += f"\n请使用手机打开集卡页面确认是否到账~ 若到账请按1元每张的价格主动扫码转账哦~(不自觉的坏孩子会被tjjtds哦<_<)" msg += "\n" return msg
def init_venv_and_requirements(venv_path=".venv", requirements_path="requirements.txt", disable_douban=False, enable_proxy=False): if not enable_proxy: logger.info("当前已无视系统代理") bypass_proxy() # 初始化相关路径变量 pyscript_path = os.path.join(venv_path, "Scripts") py_path = os.path.join(pyscript_path, "python") pip_path = os.path.join(pyscript_path, "pip") show_head_line(f"尝试初始化venv环境", color("bold_yellow")) subprocess.call([ "python", "-m", "venv", venv_path, ]) logger.info("尝试更新pip setuptools wheel") douban_op = ["-i", "https://pypi.doubanio.com/simple"] if disable_douban: douban_op = [] subprocess.call([ py_path, "-m", "pip", "install", *douban_op, "--upgrade", "pip", "setuptools", "wheel", ]) logger.info("尝试安装依赖库和pyinstaller") subprocess.call([ pip_path, "install", *douban_op, "-r", requirements_path, "--upgrade", "wheel", "pyinstaller", ]) logger.info("安装pywin32_postinstall") subprocess.call([ py_path, os.path.join(pyscript_path, "pywin32_postinstall.py"), "-install", ])
def clear_github_artifact(dir_all_release, dir_github_action_artifact): old_cwd = os.getcwd() show_head_line("清空旧版本github artifact目录", color("bold_yellow")) if not os.path.isdir(dir_all_release): os.mkdir(dir_all_release) os.chdir(dir_all_release) shutil.rmtree(dir_github_action_artifact, ignore_errors=True) os.mkdir(dir_github_action_artifact) os.chdir(old_cwd)
def show_usage(): show_head_line("从2020-10-26至今小助手使用情况概览", color("fg_bold_yellow")) last_n_days = get_last_n_days(14) extra_time_periods = [*time_periods, *last_n_days] extra_time_periods_desc = [*time_periods_desc, *last_n_days] heads = ["计数对象", *extra_time_periods_desc] colSizes = [20, *[8 for _ in extra_time_periods_desc]] rows = [ [ "本机使用次数", *[ get_count(my_usage_counter_name, period) for period in extra_time_periods ] ], # ["当前版本总计使用数", *[get_count(this_version_global_usage_counter_name, period) for period in extra_time_periods]], # ["所有版本总计使用数", *[get_count(global_usage_counter_name, period) for period in extra_time_periods]], # ["当前版本活跃用户数", *[get_record_count_name_start_with(this_version_user_usage_prefix, period) for period in extra_time_periods]], [ "活跃用户数", *[ get_record_count_name_start_with( user_usage_counter_name_prefix, period) for period in extra_time_periods ], ], # ["DLC用户数", *[get_record_count_name_start_with(auto_updater_usage_counter_name_prefix, period) for period in extra_time_periods]], [ "按月付费用户数", *[ get_record_count_name_start_with( active_monthly_pay_user_usage_counter_name_prefix, period) for period in extra_time_periods ], ], ] logger.info(tableify(heads, colSizes)) for row in rows: logger.info(color("fg_bold_cyan") + tableify(row, colSizes))
prompt = f"如需直接使用默认版本号:{now_version} 请直接按回车\n或手动输入版本号后按回车:" version = input(prompt) or now_version version_reg = r"\d+\.\d+\.\d+" if re.match(version_reg, version) is None: logger.info(f"版本号格式有误,正确的格式类似:1.0.0 ,而不是 {version}") exit(-1) # 最大化窗口 change_console_window_mode_async(disable_min_console=True) version = 'v' + version run_start_time = datetime.now() show_head_line(f"开始发布版本 {version}", color("bold_yellow")) set_title_cmd = f"title 发布 {version}" os.system(set_title_cmd) # 先声明一些需要用到的目录的地址 dir_src = os.path.realpath('.') dir_all_release = os.path.realpath(os.path.join("releases")) release_dir_name = f"DNF蚊子腿小助手_{version}_by风之凌殇" release_7z_name = f'{release_dir_name}.7z' dir_github_action_artifact = "_github_action_artifact" # ---------------构建 # 调用构建脚本 os.chdir(dir_src) build()
from config import load_config, config from djc_helper import DjcHelper from log import color from util import show_head_line if __name__ == '__main__': # 读取配置信息 load_config("config.toml", "config.toml.local") cfg = config() # 12.30 送卡片次数(re:好像送给别人没有上限?) indexes = [4] for idx in indexes: # 从1开始,第i个 account_config = cfg.account_configs[idx - 1] show_head_line("开始处理第{}个账户[{}]".format(idx, account_config.name), color("fg_bold_yellow")) djcHelper = DjcHelper(account_config, cfg.common) djcHelper.check_skey_expired() djcHelper.get_bind_role_list() lr = djcHelper.fetch_pskey() # re: 先填QQ # undone: 然后填写卡片 targetQQ = "XXXXXXXXXXX" cards_to_send = [ ("XXXXXXXXXXX", 1), ("XXXXXXXXXXX", 1), ("XXXXXXXXXXX", 1), ("XXXXXXXXXXX", 1),
def release(): # ---------------准备工作 prompt = f"如需直接使用默认版本号:{now_version} 请直接按回车\n或手动输入版本号后按回车:" version = input(prompt) or now_version version_reg = r"\d+\.\d+\.\d+" if re.match(version_reg, version) is None: logger.info(f"版本号格式有误,正确的格式类似:1.0.0 ,而不是 {version}") pause_and_exit(-1) # 最大化窗口 change_console_window_mode_async(disable_min_console=True) version = "v" + version run_start_time = datetime.now() show_head_line(f"开始发布版本 {version}", color("bold_yellow")) set_title_cmd = f"title 发布 {version}" os.system(set_title_cmd) # 先声明一些需要用到的目录的地址 dir_src = os.path.realpath(".") dir_all_release = os.path.realpath(os.path.join("releases")) release_dir_name = f"DNF蚊子腿小助手_{version}_by风之凌殇" release_7z_name = f"{release_dir_name}.7z" dir_github_action_artifact = "_github_action_artifact" # ---------------构建 # 调用构建脚本 os.chdir(dir_src) build() # ---------------清除一些历史数据 make_sure_dir_exists(dir_all_release) os.chdir(dir_all_release) clear_github_artifact(dir_all_release, dir_github_action_artifact) # ---------------打包 os.chdir(dir_src) package(dir_src, dir_all_release, release_dir_name, release_7z_name, dir_github_action_artifact) # ---------------构建增量补丁 create_patch_for_latest_n_version = 3 # ---------------构建增量包 os.chdir(dir_all_release) show_head_line(f"开始构建增量包,最多包含过去{create_patch_for_latest_n_version}个版本到最新版本的补丁", color("bold_yellow")) create_patch(dir_src, dir_all_release, create_patch_for_latest_n_version, dir_github_action_artifact) # ---------------获取补丁地址(分开方便调试) os.chdir(dir_all_release) patch_file_name = create_patch( dir_src, dir_all_release, create_patch_for_latest_n_version, dir_github_action_artifact, get_final_patch_path_only=True, ) # ---------------标记新版本 show_head_line("提交版本和版本变更说明,并同步到docs目录,用于生成github pages", color("bold_yellow")) os.chdir(dir_src) commit_new_version() # ---------------上传到蓝奏云 show_head_line("开始上传到蓝奏云", color("bold_yellow")) os.chdir(dir_src) with open("upload_cookie.json") as fp: cookie = json.load(fp) os.chdir(dir_all_release) uploader = Uploader() uploader.login(cookie) if uploader.login_ok: logger.info("蓝奏云登录成功,开始上传压缩包") def path_in_src(filepath_relative_to_src: str) -> str: return os.path.realpath(os.path.join(dir_src, filepath_relative_to_src)) realpath = os.path.realpath upload_info_list = [ ( uploader.folder_djc_helper, [ (realpath(release_7z_name), uploader.history_version_prefix), (path_in_src("utils/auto_updater.exe"), ""), (path_in_src("使用教程/使用文档.docx"), ""), (path_in_src("使用教程/视频教程.txt"), ""), (path_in_src("付费指引/付费指引.docx"), ""), (path_in_src("utils/不要下载增量更新文件_这个是给自动更新工具使用的.txt"), ""), (realpath(patch_file_name), uploader.history_patches_prefix), ], ), ( uploader.folder_dnf_calc, [ (realpath(release_7z_name), uploader.history_version_prefix), ], ), ] logger.info(color("bold_green") + "具体上传列表如下:") for upload_folder, upload_list in upload_info_list: logger.info(color("bold_cyan") + f"\t{upload_folder.name}:") for local_filepath, _history_file_prefix in upload_list: logger.info(f"\t\t{local_filepath}") logger.info("\n") for upload_folder, upload_list in upload_info_list: for local_filepath, history_file_prefix in reversed(upload_list): # 逆序遍历,确保同一个网盘目录中,列在前面的最后才上传,从而在网盘显示时显示在最前方 total_try_count = 1 for try_index in range_from_one(total_try_count): upload_ok = uploader.upload_to_lanzouyun( local_filepath, upload_folder, history_file_prefix=history_file_prefix ) if upload_ok: break logger.warning(f"第{try_index}/{total_try_count}次尝试上传{local_filepath}失败,等待一会后重试") if try_index < total_try_count: count_down("上传到网盘", 5 * try_index) else: logger.error("蓝奏云登录失败") # ---------------推送版本到github # 打包完成后git添加标签 os.chdir(dir_src) show_head_line("开始推送到github", color("bold_yellow")) push_github(version) # ---------------结束 logger.info("+" * 40) logger.info(color("bold_yellow") + f"{version} 发布完成,共用时{datetime.now() - run_start_time},请检查上传至蓝奏云流程是否OK") logger.info("+" * 40) os.system("PAUSE")
def build(disable_douban=False): # 初始化相关路径变量 venv_path = ".venv" pyinstaller_path = os.path.join(venv_path, "Scripts", "pyinstaller") # 初始化venv和依赖 init_venv_and_requirements(".venv", disable_douban) show_head_line(f"将使用.venv环境进行编译", color("bold_yellow")) build_configs = [ ("main.py", "DNF蚊子腿小助手.exe", "utils/icons/DNF蚊子腿小助手.ico", ".", ["PyQt5"], []), ("auto_updater.py", "auto_updater.exe", "", "utils", ["PyQt5"], []), ("ark_lottery_special_version.py", "DNF蚊子腿小助手_集卡特别版.exe", "utils/icons/ark_lottery_special_version.ico", ".", ["PyQt5"], []), ("config_ui.py", "DNF蚊子腿小助手配置工具.exe", "utils/icons/config_ui.ico", ".", [], ["--noconsole"]), ] for idx, config in enumerate(build_configs): prefix = f"{idx + 1}/{len(build_configs)}" src_path, exe_name, icon_path, target_dir, exclude_modules, extra_args = config logger.info(color("bold_yellow") + f"{prefix} 开始编译 {exe_name}") cmd_build = [ pyinstaller_path, '--name', exe_name, '-F', src_path, ] if icon_path != "": cmd_build.extend(['--icon', icon_path]) for module in exclude_modules: cmd_build.extend(['--exclude-module', module]) cmd_build.extend(extra_args) logger.info(f"{prefix} 开始编译 {exe_name},命令为:{' '.join(cmd_build)}") subprocess.call(cmd_build) logger.info(f"编译结束,进行善后操作") # 复制二进制 logger.info(f"复制{exe_name}到目标目录{target_dir}") if not os.path.isdir(target_dir): os.mkdir(target_dir) target_path = os.path.join(target_dir, exe_name) shutil.copyfile(os.path.join("dist", exe_name), target_path) # 删除临时文件 logger.info("删除临时文件") for directory in ["build", "dist", "__pycache__"]: shutil.rmtree(directory, ignore_errors=True) os.remove(f"{exe_name}.spec") filesize = os.path.getsize(target_path) logger.info( color("bold_green") + f"{prefix} 编译{exe_name}结束,最终大小为{human_readable_size(filesize)}") logger.info("done")
def package(dir_src, dir_all_release, release_dir_name, release_7z_name, dir_github_action_artifact): old_cwd = os.getcwd() show_head_line(f"开始打包 {release_dir_name} 所需内容", color("bold_yellow")) # 确保发布根目录存在 if not os.path.isdir(dir_all_release): os.mkdir(dir_all_release) # 并清空当前的发布版本目录 dir_current_release = os.path.realpath(os.path.join(dir_all_release, release_dir_name)) shutil.rmtree(dir_current_release, ignore_errors=True) os.mkdir(dir_current_release) logger.info(color("bold_yellow") + f"将部分内容从 {dir_src} 复制到 {dir_current_release} ") # 需要复制的文件与目录 files_to_copy = [] # 基于正则确定初始复制范围 reg_wantted_file = r'.*\.(toml|md|txt|png|jpg|docx|url)$' for file in os.listdir('.'): if not re.search(reg_wantted_file, file, flags=re.IGNORECASE): continue files_to_copy.append(file) # 额外补充一些文件和目录 files_to_copy.extend([ "config.example.toml", "DNF蚊子腿小助手.exe", "DNF蚊子腿小助手配置工具.exe", "DNF蚊子腿小助手配置文件.bat", "使用教程", "付费指引", "相关信息", "utils", ]) # 按顺序复制 files_to_copy = sorted(files_to_copy) # 复制文件与目录过去 for filename in files_to_copy: source = os.path.join(dir_src, filename) destination = os.path.join(dir_current_release, filename) if os.path.isdir(filename): logger.info(f"拷贝目录 {filename}") shutil.copytree(source, destination) else: logger.info(f"拷贝文件 {filename}") shutil.copyfile(source, destination) logger.info(color("bold_yellow") + "移动部分文件的位置和名称") files_to_move = [ ("utils/auto_updater.exe", "utils/auto_updater_latest.exe"), ("CHANGELOG.MD", "相关信息/CHANGELOG.MD"), ("README.MD", "相关信息/README.MD"), ] for src_file, dst_file in files_to_move: src_file = os.path.join(dir_current_release, src_file) dst_file = os.path.join(dir_current_release, dst_file) logger.info(f"移动{src_file}到{dst_file}") shutil.move(src_file, dst_file) logger.info(color("bold_yellow") + "清除一些无需发布的内容") dir_to_filenames_need_remove = { ".": [ *list(path.name for path in pathlib.Path(".").glob('requirements*.txt')), "config.toml.local", *list(path.name for path in pathlib.Path(".").glob('config.toml.github_action*')), ], "utils": [ "logs", ".db", ".cached", ".first_run", ".log.filename", "buy_auto_updater_users.txt", "user_monthly_pay_info.txt", "notices.txt", *list(path.name for path in pathlib.Path("utils").glob('chrome_portable_*')), "upx.exe", ], } for dir_path, filenames in dir_to_filenames_need_remove.items(): for filename in filenames: filepath = os.path.join(dir_current_release, f"{dir_path}/{filename}") if not os.path.exists(filepath): continue if os.path.isdir(filepath): logger.info(f"移除目录 {filepath}") shutil.rmtree(filepath, ignore_errors=True) else: logger.info(f"移除文件 {filepath}") os.remove(filepath) # 压缩打包 os.chdir(dir_all_release) logger.info(color("bold_yellow") + "开始压缩打包") compress_dir_with_bandizip(release_dir_name, release_7z_name, dir_src) # 额外备份一份最新的供github action 使用 shutil.copyfile(release_7z_name, os.path.join(dir_github_action_artifact, 'djc_helper.7z')) os.chdir(old_cwd)
def sell_card(targetQQ: str, cards_to_send: List[str]) -> str: cards_to_send = [name for name in cards_to_send if name != CARD_PLACEHOLDER] original_cards = [*cards_to_send] # 读取配置信息 cfg = config() # 12.30 送卡片次数(re:好像送给别人没有上限?) indexes = list(range(len(cfg.account_configs), 0, -1)) if not is_new_version_ark_lottery(): card_info_map = parse_card_group_info_map(zzconfig()) for name in cards_to_send: if name not in card_info_map: return f"{name}不是本期卡片名称,有效的卡片名称为: {list(card_info_map.keys())}" success_send_list = [] for idx in indexes: # 从1开始,第i个 account_config = cfg.account_configs[idx - 1] show_head_line(f"开始处理第{idx}个账户[{account_config.name}]", color("fg_bold_yellow")) if not account_config.function_switches.get_ark_lottery or not account_config.is_enabled(): continue djcHelper = DjcHelper(account_config, cfg.common) djcHelper.fetch_pskey() djcHelper.check_skey_expired() djcHelper.get_bind_role_list() remaining_cards = [] for name in cards_to_send: send_ok = False if is_new_version_ark_lottery(): send_ok = djcHelper.dnf_ark_lottery_send_card(name, targetQQ) else: res = djcHelper.send_card_by_name(name, targetQQ) retCode = int(res["13333"]["ret"]) if retCode == 0: send_ok = True else: if len(original_cards) == 1: if retCode == 10017: return "该账号今日已被赠送过四次" if send_ok: success_send_list.append(name) else: remaining_cards.append(name) cards_to_send = remaining_cards if len(cards_to_send) == 0: break msg = "" if len(success_send_list) != 0: msg += f"\n成功发送以下卡片:{success_send_list}" if len(cards_to_send) != 0: msg += f"\n无法发送以下卡片:{cards_to_send},是否已达到赠送上限或者这个卡卖完了?" if len(success_send_list) != 0: msg += "\n请使用手机打开集卡页面确认是否到账~ 若到账请按1元每张的价格主动扫码转账哦~(不定期我会核查的,如果买了不付款的话就加入本工具黑名单~)" msg += "\n" return msg
from config import load_config, config from djc_helper import DjcHelper from log import color from util import show_head_line if __name__ == '__main__': # 读取配置信息 load_config("config.toml", "config.toml.local") cfg = config() # 12.30 送卡片次数(re:好像送给别人没有上限?) indexes = [4] for idx in indexes: # 从1开始,第i个 account_config = cfg.account_configs[idx - 1] show_head_line(f"开始处理第{idx}个账户[{account_config.name}]", color("fg_bold_yellow")) djcHelper = DjcHelper(account_config, cfg.common) lr = djcHelper.fetch_pskey() djcHelper.check_skey_expired() djcHelper.get_bind_role_list() # re: 先填QQ undone: 然后填写卡片 targetQQ = "XXXXXXXXXXX" cards_to_send = [ ("XXXXXXXXXXX", 1), ("XXXXXXXXXXX", 1), ("XXXXXXXXXXX", 1), ("XXXXXXXXXXX", 1), ] for name, count in cards_to_send:
def main(): increase_counter(name="run/begin", ga_type=ga.GA_REPORT_TYPE_PAGE_VIEW) prepare_env() # 启动时检查是否需要同步本机数据目录备份的旧版本配置 try_load_old_version_configs_from_user_data_dir() change_title() print_update_message_on_first_run_new_version() logger.warning( f"开始运行DNF蚊子腿小助手,ver={now_version} {ver_time},powered by {author}") logger.warning( color("fg_bold_cyan") + "如果觉得我的小工具对你有所帮助,想要支持一下我的话,可以帮忙宣传一下或打开付费指引/支持一下.png,扫码打赏哦~") # 读取配置信息 load_config("config.toml", "config.toml.local") cfg = config() if len(cfg.account_configs) == 0: raise Exception("未找到有效的账号配置,请检查是否正确配置。ps:多账号版本配置与旧版本不匹配,请重新配置") notify_manual_check_update_on_release_too_long(cfg.common) check_proxy(cfg) try_report_usage_info(cfg) if cfg.common.disable_cmd_quick_edit: disable_quick_edit_mode() show_notices() if cfg.common.allow_only_one_instance: logger.info("当前仅允许单个实例运行,将尝试干掉其他实例~") async_call(kill_other_instance_on_start) else: logger.info("当前允许多个实例同时运行~") init_pool(cfg.get_pool_size()) change_title(multiprocessing_pool_size=cfg.get_pool_size(), enable_super_fast_mode=cfg.common.enable_super_fast_mode) show_multiprocessing_info(cfg) account_names = [] for account_cfg in cfg.account_configs: account_names.append(account_cfg.name) logger.info(f"当前共配置{len(account_names)}个账号,具体如下:{account_names}") clean_dir_to_size(log_directory, cfg.common.max_logs_size * MiB, cfg.common.keep_logs_size * MiB) clean_dir_to_size(f"utils/{log_directory}", cfg.common.max_logs_size * MiB, cfg.common.keep_logs_size * MiB) show_ask_message_box(cfg) check_all_skey_and_pskey(cfg) check_djc_role_binding() # 确保道聚城绑定OK后在活动运行同时进行异步的弹窗提示 check_first_run_async(cfg) # 挪到所有账号都登陆后再尝试自动更新,从而能够判定是否已购买DLC try_auto_update(cfg) # 检查是否有更新,用于提示未购买自动更新的朋友去手动更新~ if cfg.common.check_update_on_start: check_update(cfg) # 查询付费信息供后面使用 show_head_line("查询付费信息") logger.warning("开始查询付费信息,请稍候~") user_buy_info = get_user_buy_info(cfg.get_qq_accounts()) show_buy_info(user_buy_info, cfg, need_show_message_box=False) sas(cfg, "启动时展示账号概览", user_buy_info) # 预先尝试创建和加入固定队伍,从而每周第一次操作的心悦任务也能加到队伍积分中 try_join_xinyue_team(cfg, user_buy_info) # 正式进行流程 run(cfg, user_buy_info) # 尝试领取心悦组队奖励 try_take_xinyue_team_award(cfg, user_buy_info) # # 尝试派赛利亚出去打工 # try_xinyue_sailiyam_start_work(cfg) # 活动开启关闭时调这个开关即可 enable_card_lottery = False if enable_card_lottery: auto_send_cards(cfg) show_extra_infos(cfg) sas(cfg, "运行完毕展示账号概览", user_buy_info) if enable_card_lottery: show_lottery_status("卡片赠送完毕后展示各账号抽卡卡片以及各礼包剩余可领取信息", cfg, need_show_tips=True) show_pay_info(cfg) # 显示小助手的使用概览 if cfg.common._show_usage: show_usage() # 运行结束展示下多进程信息 show_multiprocessing_info(cfg) # 检查是否有更新,用于提示未购买自动更新的朋友去手动更新~ if cfg.common.check_update_on_end: check_update(cfg) # 运行完毕备份配置到本机数据目录 try_save_configs_to_user_data_dir() increase_counter(name="run/end", ga_type=ga.GA_REPORT_TYPE_PAGE_VIEW) show_head_line("运行完毕")
def build(disable_douban=False, enable_proxy=False, use_upx=True): # 初始化相关路径变量 venv_path = ".venv" pyinstaller_path = os.path.join(venv_path, "Scripts", "pyinstaller") # 初始化venv和依赖 init_venv_and_requirements(".venv", "requirements.txt", disable_douban, enable_proxy) show_head_line(f"将使用.venv环境进行编译", color("bold_yellow")) temp_remove_file_dir = os.path.join(".cached", "build_temp_remove_files") site_packages_path = os.path.join(venv_path, "Lib", "site-packages") dep_files_to_remove_during_build = { "PyQt5/Qt5": [ "Translations", ], "PyQt5/Qt5/bin": [ "opengl32sw.dll", "libEGL.dll", "libGLESV2.dll", "Qt5Svg.dll", "Qt5Network.dll", "Qt5Qml.dll", "Qt5QmlModels.dll", "Qt5Quick.dll", "Qt5WebSockets.dll", "d3dcompiler_47.dll", ], "PyQt5/Qt5/plugins": [ "iconengines/qsvgicon.dll", "imageformats/qsvg.dll", "imageformats/qwebp.dll", "platforms/qwebgl.dll", ] } logger.info( color("bold_green") + f"开始编译前先尝试移动这些确定用不到的库文件到临时目录 {temp_remove_file_dir},从而尽可能减少最终编译的大小") for parent_directory, file_or_directory_name_list in dep_files_to_remove_during_build.items( ): for file_or_directory_name in file_or_directory_name_list: path = os.path.join(site_packages_path, parent_directory, file_or_directory_name) backup_path = os.path.join(temp_remove_file_dir, parent_directory, file_or_directory_name) if not os.path.exists(path): logger.warning(f"\t{path} 不存在,将跳过") continue # 将文件移动到备份目录 logger.info(f"\t开始移动 {path}") make_sure_dir_exists(os.path.dirname(backup_path)) shutil.move(path, backup_path) # 实际编译流程 build_configs = [ ("main.py", "DNF蚊子腿小助手.exe", "utils/icons/DNF蚊子腿小助手.ico", ".", ["PyQt5"], []), ("auto_updater.py", "auto_updater.exe", "", "utils", ["PyQt5"], []), ("ark_lottery_special_version.py", "DNF蚊子腿小助手_集卡特别版.exe", "utils/icons/ark_lottery_special_version.ico", ".", ["PyQt5"], []), ("config_ui.py", "DNF蚊子腿小助手配置工具.exe", "utils/icons/config_ui.ico", ".", [], ["--noconsole"]), ] for idx, config in enumerate(build_configs): prefix = f"{idx + 1}/{len(build_configs)}" src_path, exe_name, icon_path, target_dir, exclude_modules, extra_args = config logger.info(color("bold_yellow") + f"{prefix} 开始编译 {exe_name}") cmd_build = [ pyinstaller_path, '--name', exe_name, '-F', src_path, ] if icon_path != "": cmd_build.extend(['--icon', icon_path]) for module in exclude_modules: cmd_build.extend(['--exclude-module', module]) if use_upx: cmd_build.extend(['--upx-dir', "utils"]) cmd_build.extend(extra_args) logger.info(f"{prefix} 开始编译 {exe_name},命令为:{' '.join(cmd_build)}") subprocess.call(cmd_build) logger.info(f"编译结束,进行善后操作") # 复制二进制 logger.info(f"复制{exe_name}到目标目录{target_dir}") if not os.path.isdir(target_dir): os.mkdir(target_dir) target_path = os.path.join(target_dir, exe_name) shutil.copyfile(os.path.join("dist", exe_name), target_path) # 删除临时文件 logger.info("删除临时文件") for directory in ["build", "dist", "__pycache__"]: shutil.rmtree(directory, ignore_errors=True) os.remove(f"{exe_name}.spec") filesize = os.path.getsize(target_path) logger.info( color("bold_green") + f"{prefix} 编译{exe_name}结束,最终大小为{human_readable_size(filesize)}") logger.info(color("bold_green") + f"编译完毕将库文件移动回来 - {site_packages_path}") for parent_directory, file_or_directory_name_list in dep_files_to_remove_during_build.items( ): for file_or_directory_name in file_or_directory_name_list: path = os.path.join(site_packages_path, parent_directory, file_or_directory_name) backup_path = os.path.join(temp_remove_file_dir, parent_directory, file_or_directory_name) if not os.path.exists(backup_path): logger.warning(f"\t备份文件 {backup_path} 不存在,将跳过") continue # 将文件移动到备份目录 logger.info(f"开始还原备份文件/目录 {backup_path}") make_sure_dir_exists(os.path.dirname(path)) shutil.move(backup_path, path) logger.info("done")
def cui(): # 读取配置信息 load_config("config.toml", "config.toml.local") cfg = config() from main_def import check_proxy check_proxy(cfg) # note: 以下内容修改为自己的配置 # 大号的账号序号(从1开始) dahao_indexes = [1] # 三个小号的序号 xiaohao_indexes = [6, 7, 8] # 三个小号的QQ号 xiaohao_qq_list = ["3036079506", "1470237902", "1276170371"] # re: 流程: # 1. send_to_xiaohao设为True,大号发送宝箱链接给三个小号 # 2. 电脑上,大号QQ里点开三个小号对话的宝箱链接,替换Scode到scode_list里面 # 3. send_to_xiaohao设为False,让小号开启各个宝箱 # --------------- 每次只需要按流程修改下面几行 --------------------- send_to_xiaohao = True # send_to_xiaohao = False scode_list = [ "MDJKQ0t5dDJYazlMVmMrc2ZXV0tVT0xsZitZMi9YOXZUUFgxMW1PcnQ2Yz0=", "UFgxa1lQZ3RBZERCMTU0N3dSWmcwZUxsZitZMi9YOXZUUFgxMW1PcnQ2Yz0=", "cXNpZTIrY2dRYk1GL2E4UjlGQzBkdUxsZitZMi9YOXZUUFgxMW1PcnQ2Yz0=", ] if len(xiaohao_qq_list) != scode_list: message_box("配置的小号数目与scode数目不一致,请确保两者一致", "出错了") sys.exit() # --------------- 每次只需要按流程修改上面几行 --------------------- # 登录相应账号 if send_to_xiaohao: indexes = dahao_indexes else: indexes = xiaohao_indexes for idx in indexes: # 从1开始,第i个 account_config = cfg.account_configs[idx - 1] show_head_line(f"预先获取第{idx}个账户[{account_config.name}]的skey", color("fg_bold_yellow")) if not account_config.is_enabled(): logger.warning("账号被禁用,将跳过") continue djcHelper = DjcHelper(account_config, cfg.common) djcHelper.fetch_pskey() djcHelper.check_skey_expired() # 执行对应逻辑 for order_index, account_index in enumerate(indexes): # 从1开始,第i个 account_config = cfg.account_configs[account_index - 1] show_head_line(f"开始处理第{account_index}个账户[{account_config.name}]", color("fg_bold_yellow")) if not account_config.is_enabled(): logger.warning("账号被禁用,将跳过") continue djcHelper = DjcHelper(account_config, cfg.common) djcHelper.fetch_pskey() djcHelper.check_skey_expired() djcHelper.get_bind_role_list() if send_to_xiaohao: logger.info( color("bold_green") + f"发送宝箱链接给小号QQ: {xiaohao_qq_list}") djcHelper.majieluo_send_to_xiaohao(xiaohao_qq_list) msg = ( "1. 请在电脑登录大号QQ,依次点击各个小号的对话框里刚刚发送的宝箱链接,在浏览器中复制其链接中sCode的值到scode_list对应位置\n" "2. 请修改send_to_xiaohao为False后再次运行") message_box(msg, "后续流程") else: scode = scode_list[order_index] logger.info( f"第{order_index + 1}个小号领取刚刚运行后填写的Scode列表中第{order_index + 1}个scode - {scode}" ) res = djcHelper.majieluo_open_box(scode) if res.sOutValue1 == 0: logger.info(color("bold_green") + "领取成功") else: code_to_message = { "1": "无效的赠送链接", "2": "不能打开自己的礼盒~", "3": "该礼盒已经被开启", "4": "好友今天的礼盒已经被全部打开了哦~", "5": "一天只可以打开3次礼盒哦~", "6": "该礼盒已经被开启", "7": "该礼盒已经被开启", } message = "系统繁忙,请稍后再试~" if res.sOutValue1 in code_to_message: message = code_to_message[res.sOutValue1] logger.error(message) time.sleep(1) # 第二次执行完毕提示修改send_to_xiaohao if not send_to_xiaohao: message_box("已领取完毕,请修改send_to_xiaohao为True,方便明天继续从头用", "提示")