diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..b5c713a
Binary files /dev/null and b/.DS_Store differ
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/config-generator.iml b/.idea/config-generator.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/.idea/config-generator.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..c04eacf
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..d56657a
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..68dd44c
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/__init__.py b/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/config.py b/config.py
new file mode 100644
index 0000000..8fef616
--- /dev/null
+++ b/config.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+# coding:utf-8
+import enum
+import os
+import sys
+import time
+
+curr_dir = os.path.split(os.path.abspath(__file__))[0]
+sys.path.append(os.path.join(curr_dir, 'firebase_tools'))
+sys.path.append(os.path.join(curr_dir, 'google_drive'))
+sys.path.append(os.path.join(curr_dir, 'ipm'))
+
+import ipm.wechat_alert as wechat
+import ipm.clear_cdn as clear_cdn
+
+from notification_helper import NotificationHelper
+from firebase_tools.firebase_helper import FirebaseHelperInstance, FirebaseHelper
+from google_drive.google_sheet import GoogleSheetHelper
+
+firebase_helper = FirebaseHelperInstance()
+sheet_helper = GoogleSheetHelper()
+time_start = time.time()
+
+def calc_step_time(step:str):
+ global time_start
+ time_end = time.time()
+ print(f'{step}步骤完成|耗时: {(time_end - time_start):.0f}秒')
+ time_start = time.time()
+
+class env(enum.Enum):
+ debug = 'debug' # 调试环境
+ release = 'release' # 发布环境
+
+class platform(enum.Enum):
+ No = 'None'
+ Android = 'Android'
+ iOS = 'iOS'
+ All = 'All'
+
+def get_platform_list(platform_param):
+ if platform_param == platform.All.value:
+ return [platform.Android.value, platform.iOS.value]
+ elif platform_param == platform.Android.value or platform_param == platform.iOS.value:
+ return [platform_param]
+ return None
+
+# region 项目定义
+class project(enum.Enum):
+ dof = 'dof'
+ d2 = 'd2'
+ find_out = 'find_out'
+ find_master = 'find_master'
+ find_it = 'find_it'
+
+# endregion
+
+# region firebase接口
+def get_firebase_instance(project_id) -> FirebaseHelper:
+ if project_id == project.dof.value:
+ return firebase_helper.get_firebase_dof()
+ elif project_id == project.d2.value:
+ return firebase_helper.get_firebase_d2()
+ elif project_id == project.find_out.value:
+ return firebase_helper.get_firebase_find_out()
+ elif project_id == project.find_master.value:
+ return firebase_helper.get_firebase_find_master()
+ elif project_id == project.find_it.value:
+ return firebase_helper.get_firebase_find_it()
+ else:
+ return None
+# endregion
+
+# region 企业微信通知接口
+HOOK_URL = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4d38d2a3-4fd7-41c3-a3b1-10af3ba639b4'
+notification = NotificationHelper(HOOK_URL)
+def wechat_alert():
+ wechat.wechat_alert(notification.get_msg(), notification.get_hook_url(), notification.get_people_list())
+def wechat_alert_message(message: str):
+ wechat.wechat_alert(message, notification.get_hook_url())
+def wechat_alert_exception(e: Exception):
+ wechat.wechat_alert(str(e), notification.get_hook_url(), "15036516116")
+# endregion
+
+def get_project_cdn(project_id):
+ if project_id == project.dof.value:
+ return 'https://cdn3-dof.fungame.cloud'
+ elif project_id == project.d2.value:
+ return 'https://cdn3-dof.fungame.cloud'
+ elif project_id == project.find_out.value:
+ return 'https://cdn3-find-out.fungame.cloud'
+ elif project_id == project.find_master.value:
+ return 'https://cdn3-find-master.fungame.cloud'
+ elif project_id == project.find_it.value:
+ return 'https://cdn3-find-it.fungame.cloud'
+ else:
+ return None
\ No newline at end of file
diff --git a/config_generator.py b/config_generator.py
new file mode 100644
index 0000000..e283bf0
--- /dev/null
+++ b/config_generator.py
@@ -0,0 +1,391 @@
+#!/usr/bin/env python
+# coding:utf-8
+import json
+import os
+import sys
+
+import config
+import utils
+
+class CDNConfig:
+ enable = False
+ dir = ''
+ filename = ''
+ version = ''
+
+ def __init__(self, enable: bool, dir: str, filename: str, version: str):
+ self.enable = enable
+ self.dir = dir
+ self.filename = filename
+ self.version = version
+
+class RemoteConfig:
+ enable = False
+ key = ''
+ group = ''
+ condition = ''
+
+ def __init__(self, enable, key, group, condition):
+ self.enable = enable
+ self.key = key
+ self.group = group
+ self.condition = condition
+
+class ConfigGenerator:
+ google_sheet_file_name = None
+ sheet_table_name = None
+ project = None
+ platform = None
+ env = None
+ cdn_config = None
+ remote_config = None
+ sheet_helper = None
+ firebase_helper = None
+
+ field_dict = {} # 字段名称字典
+ field_type_dict = {} # 字段类型字典
+
+ # region 配置生成器初始化
+ def __init__(self, google_sheet_file_name, sheet_table_name, project, platform, env):
+ self.sheet_helper = config.sheet_helper
+ self.google_sheet_file_name = google_sheet_file_name
+ self.sheet_table_name = sheet_table_name
+ self.project = project
+ self.platform = platform.lower()
+ self.env = env
+ self.init_notification_param()
+ self.init_config_generator_param()
+
+ def init_notification_param(self):
+ config.notification.append_msg(f'生成配置文件[文件名: {self.google_sheet_file_name}, 表名: {self.sheet_table_name}]')
+ config.notification.append_msg(f'配置构建参数[项目: {self.project}, 平台: {self.platform}, 环境: {self.env}]')
+
+ def init_config_generator_param(self):
+ sheet = self.sheet_helper.get_sheet_table(self.google_sheet_file_name, self.sheet_table_name)
+ if sheet is None:
+ config.wechat_alert_exception(f'获取表格失败[文件名: {self.google_sheet_file_name}, 表名: {self.sheet_table_name}]')
+ sheet_all_row_datas = sheet.get_all_values(major_dimension='ROWS')
+ for i, row_values in enumerate(sheet_all_row_datas):
+ if i == 0:
+ self.parse_cdn_config(row_values)
+ elif i == 1:
+ self.parse_remote_config(row_values)
+ elif i == 3:
+ self.parse_field(row_values, self.field_dict)
+ elif i == 4:
+ self.parse_field_type(row_values, self.field_type_dict)
+ else:
+ break
+
+ def parse_cdn_config(self, row_values):
+ enable_index = -1
+ enable_value = None
+ dir_index = -1
+ dir_value = None
+ filename_index = -1
+ filename_value = None
+ version_index = -1
+ version_value = None
+
+ for i, cell_value in enumerate(row_values):
+ if cell_value == 'enable':
+ enable_index = i + 1
+ elif cell_value == '目录':
+ dir_index = i + 1
+ elif cell_value == '文件名':
+ filename_index = i + 1
+ elif cell_value == '版本':
+ version_index = i + 1
+
+ for i, cell_value in enumerate(row_values):
+ if i == enable_index:
+ if str(cell_value).lower() == 'true':
+ enable_value = True
+ elif i == dir_index:
+ dir_value = cell_value
+ elif i == filename_index:
+ filename_value = cell_value
+ elif i == version_index:
+ version_value = cell_value
+ self.cdn_config = CDNConfig(enable_value, dir_value, filename_value, version_value)
+
+ def parse_remote_config(self, row_values):
+ pass
+ enable_index = -1
+ enable_value = False
+ key_index = -1
+ key_value = None
+ group_index = -1
+ group_value = None
+ condition_index = -1
+ condition_value = None
+ for i, cell_value in enumerate(row_values):
+ if cell_value == 'enable':
+ enable_index = i + 1
+ if cell_value == 'key':
+ key_index = i + 1
+ elif cell_value == 'group':
+ group_index = i + 1
+ elif cell_value == 'condition':
+ condition_index = i + 1
+ for i, cell_value in enumerate(row_values):
+ if i == enable_index:
+ if str(cell_value).lower() == 'true':
+ enable_value = True
+ elif i == key_index:
+ remote_key = cell_value
+ if '#platform#' in remote_key:
+ remote_key = remote_key.replace('#platform#', self.platform)
+ key_value = remote_key
+ elif i == group_index:
+ group_value = cell_value
+ elif i == condition_index:
+ condition_value = cell_value
+ self.remote_config = RemoteConfig(enable_value, key_value, group_value, condition_value)
+
+ def parse_field(self, row_values, field_dict):
+ for i, field_name in enumerate(row_values):
+ if i == 0:
+ continue
+ if field_name != '':
+ field_dict[i] = field_name
+ print(str(field_dict))
+
+ def parse_field_type(self, row_values, field_type_dict):
+ for i, field_type in enumerate(row_values):
+ if i == 0:
+ continue
+ if field_type != '':
+ field_type_dict[i] = field_type
+ print(str(field_type_dict))
+ # endregion
+
+ def gen_config_json(self):
+ sheet = self.sheet_helper.get_sheet_table(self.google_sheet_file_name, self.sheet_table_name)
+ sheet_all_row_datas = sheet.get_all_values(major_dimension='ROWS')
+ config_json = {'datas': []}
+ error_lines = []
+ data_row_index = -1
+ for i, row_values in enumerate(sheet_all_row_datas):
+ if data_row_index == -1:
+ if 'data' not in str(row_values[0]).lower():
+ continue
+ else:
+ data_row_index = i
+
+ if self.is_row_env_valid(row_values) is False:
+ continue
+
+ item_data, error = self.parse_row_data(i + 1, row_values, self.field_dict, self.field_type_dict)
+ if error != '':
+ error_lines.append(error)
+ elif len(item_data) == 0:
+ continue
+ else:
+ config_json['datas'].append(item_data)
+
+ if len(error_lines) > 0:
+ config.notification.append_msg(str(error_lines))
+ return
+
+ _json = json.dumps(config_json)
+ filename = self.get_config_filename()
+ local_file_path = self.get_local_config_file_path()
+ utils.write_json_file(local_file_path, _json)
+ config.notification.append_msg(f"{filename} 关卡配置生成成功!当前总关卡数:{len(config_json['datas'])}")
+ config.wechat_alert(f'{filename} json:{_json}')
+ print(f"{filename} json: {_json}")
+ return _json
+
+ # region 行数据解析
+ def is_row_env_valid(self, row_values):
+ if self.env == config.env.debug.value:
+ return True
+ if row_values[1] == 'TRUE':
+ return True
+ return False
+
+ def parse_row_data(self, row, row_values, field_dict, field_type_dict):
+ item_data = {}
+ error = ''
+ for i, value in enumerate(row_values):
+ if i not in field_dict or i not in field_type_dict:
+ continue
+
+ field = field_dict[i]
+ field_type = field_type_dict[i]
+ isvalid, check_error = self.check_field_type_valid(field_type, value)
+ if isvalid:
+ item_data[field] = self.get_type_value(field_type, value)
+ else:
+ error += f'|{check_error}'
+ if error != '':
+ error = f"第{row}行->id:{item_data['id']}关卡配置错误: {error}"
+ return item_data, error
+
+ def check_field_type_valid(self, field_type, value):
+ if value is None:
+ return False, f'值为空'
+
+ if field_type == '': # 默认值
+ return True, ''
+
+ try:
+ if field_type == 'int':
+ int(value)
+ elif field_type == 'float' or field_type == 'double':
+ float(value)
+ elif field_type == 'bool':
+ if value.lower() not in ['true', 'false']:
+ return False, f'布尔值格式错误: {value}'
+ elif field_type == 'string':
+ # 字符串类型不需要特殊验证
+ pass
+ elif field_type.startswith('List<'):
+ inner_type = field_type[5:-1] # 提取 List 中的 type
+ if value == '':
+ return True, '' # 空列表是有效的
+
+ items = value.split('#')
+ for item in items:
+ if item == '':
+ continue
+ valid, error = self.check_field_type_valid(inner_type, item)
+ if not valid:
+ return False, f'列表元素 {item} {error}'
+ else:
+ return False, f'未知类型: {field_type}'
+
+ return True, ''
+ except ValueError:
+ return False, f'类型转换错误: 无法将 {value} 转换为 {field_type}'
+ except Exception as e:
+ return False, f'验证错误: {str(e)}'
+
+ def get_type_value(self, field_type, value):
+ if value is None:
+ return None
+
+ if field_type == 'int':
+ if value == '':
+ return 0
+ return int(value)
+ elif field_type == 'float' or field_type == 'double':
+ if value == '':
+ return 0.0
+ return float(value)
+ elif field_type == 'bool':
+ if value == '':
+ return False
+ return value.lower() == 'true'
+ elif field_type == 'string':
+ return value
+ elif field_type.startswith('List<'):
+ if value == '':
+ return []
+ inner_type = field_type[5:-1]
+ items = value.split('#')
+ result = []
+ for item in items:
+ if item == '':
+ continue
+ result.append(self.get_type_value(inner_type, item))
+ return result
+ else:
+ # 未知类型,返回原始值
+ return value
+ # endregion
+
+ def upload_cdn(self):
+ if self.cdn_config is None:
+ config.notification.append_msg('cdn配置为空,不上传cdn')
+ return
+
+ if self.cdn_config.enable is False:
+ config.notification.append_msg('cdn配置未开启, 不上传cdn')
+ return
+
+ filename = self.get_config_filename()
+ local_file_path = self.get_local_config_file_path()
+ if not os.path.exists(local_file_path):
+ return
+ storage_level_db_path = f"{self.cdn_config.dir}/{filename}"
+ generation = config.get_firebase_instance(self.project).upload_file(local_file_path, storage_level_db_path)
+ config.notification.append_msg(f"{filename}配置上传到cdn路径:{storage_level_db_path}成功")
+ cdn_url = f'{config.get_project_cdn(self.project)}/{storage_level_db_path}?generation={generation}'
+ config.notification.append_msg(f"配置最新下载链接url:{cdn_url}")
+ return generation
+
+ def update_remote_config(self, generation=None):
+ if self.remote_config is None:
+ config.notification.append_msg('remote配置为空,不更新RemoteConfig')
+ return
+
+ if self.remote_config.enable is False:
+ config.notification.append_msg('remote配置未开启,不更新RemoteConfig')
+ return
+
+ filename = self.get_config_filename()
+ storage_level_db_path = f"{self.cdn_config.dir}/{filename}"
+ cdn = config.get_project_cdn(self.project)
+ if generation is None:
+ generation = self.firebase_helper.get_file_generation(storage_level_db_path)
+ level_db_cdn_url = f'{cdn}/{storage_level_db_path}' if generation is None else f'{cdn}/{storage_level_db_path}?generation={generation}'
+ key = self.remote_config.key
+ group = None if self.remote_config.group == '' else self.remote_config.group
+ condition = None if self.remote_config.condition == '' else self.remote_config.condition
+ if self.project is not None:
+ config.get_firebase_instance(self.project).update_remote_config_json_value(group, condition, key, self.env, level_db_cdn_url, True)
+ config.notification.append_msg(f"[group:{group}, condition:{condition}, key:{key} env:{self.env}] 云控更新成功")
+
+ def get_local_config_file_path(self):
+ local_file_path = f'temp_config/{self.get_config_filename()}'
+ return local_file_path
+
+ def get_config_filename(self):
+ cdn_filename = self.cdn_config.filename
+ if '#platform#' in cdn_filename:
+ if self.platform == config.platform.All.value or self.platform == config.platform.No.value:
+ cdn_filename = cdn_filename.replace('#platform#', '')
+ else:
+ cdn_filename = cdn_filename.replace('#platform#', self.platform)
+ cdn_filename += f'-{self.env}.json'
+ return cdn_filename
+
+project_id = None
+platform = None
+env = None
+google_sheet_file_name = None
+sheet_table_name = None
+param_enable_upload_cdn = None
+param_enable_upload_remote_config = None
+
+if len(sys.argv) > 1:
+ project_id = sys.argv[1]
+if len(sys.argv) > 2:
+ platform = sys.argv[2]
+if len(sys.argv) > 3:
+ env = sys.argv[3]
+if len(sys.argv) > 4:
+ google_sheet_file_name = sys.argv[4]
+if len(sys.argv) > 5:
+ sheet_table_name = sys.argv[5]
+if len(sys.argv) > 6:
+ param_enable_upload_cdn = sys.argv[6]
+if len(sys.argv) > 7:
+ param_enable_upload_remote_config = sys.argv[7]
+
+if __name__ == "__main__":
+ if project_id is None or platform is None or env is None or google_sheet_file_name is None or sheet_table_name is None:
+ config.notification.append_msg(f'参数错误[project_id:{project_id}, platform:{platform}, env:{env}, '
+ f'google_sheet_file_name:{google_sheet_file_name}, sheet_table_name:{sheet_table_name}]')
+ exit(1)
+
+ config_generator = ConfigGenerator(google_sheet_file_name, sheet_table_name, project_id, platform, env)
+ config_json = config_generator.gen_config_json()
+ generation = None
+ if str(param_enable_upload_cdn).lower() is 'true':
+ generation = config_generator.upload_cdn()
+ if str(param_enable_upload_remote_config).lower() is 'true':
+ config_generator.update_remote_config(generation)
+
diff --git a/firebase_tools/__init__.py b/firebase_tools/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/firebase_tools/dof2-b9070.json b/firebase_tools/dof2-b9070.json
new file mode 100644
index 0000000..71f7637
--- /dev/null
+++ b/firebase_tools/dof2-b9070.json
@@ -0,0 +1,12 @@
+{
+ "type": "service_account",
+ "project_id": "dof2-b9070",
+ "private_key_id": "80b51c5076c03aa4dba9ad1c9c1a8ee50e31517b",
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDDXEwSyb+/YLj1\nxa9OQz4Gex5JBnolvGQC+V8FcWFGq1V2VFSWNjUPA1EZy9TR3FqgdrxNYFUk7M1r\n4cdImbrobRhQFmPU/s/ejjG8jFtqEXBiiSRy1UXVHEY+GUBTuvivcZsV9Sz2HE3e\nRepm0Uuzzi92wujdqcEWNoIvtsUR3AIdfFTSHDyfal+rLjlGUwNZ+1PQ3JXA1CMZ\nw/Cvtt4SY26qDwYF83op5BiavTVbdO/FKrHvx4gCS3C8m4nWkU3d4V7frvvf1zOE\nZrgmYQFW8ftVEOWhg9hY/RnLwgvhBXpcx1HZ956hlWNcGliH2WxYd07jjCecWH2i\nLPaK6PdFAgMBAAECggEARgqKybekdBBQ7+jSu8v26mrsxkC4vVvIPZq7ex+VwTj/\nWH/OndZMepf1VTrTj/QhV+OKCnHNxQHTemjFwp0/OkKW02vbmgtLap7vbQqjYalj\n8if6NeOJ+Gh9NJloCzz/GSOxdxNibdBjCJxneDp0mkADm2AxDfvlGrorPcEY8Zgf\nUqfsHf4LBE+tYL0LqZXQ7LivE0K3M2UUcGkemthg3cs2fit8DCJS4ASG6KtWinOu\nEEmnQmdK9oKHAEcVylPnIEk9ssISZsvTeA2nGiEvo8WDcs0Z0qpdKSnkmob6k9UG\nEK+BGORaaNvYCRf/wP7cEBNjb5yWhStXCzYNkAZqxwKBgQDtbye6j6mI+UzFWEdh\nT+jR84Glub0ykuq3QW7CSQm8AiWVQk0uvO6CaKy533K3WAtV9QRtwOalk3vUPbv6\nyd1hXQT5H3pKNZkzshFLDoZkFix9KshcqC46ToH2q7uKp59Sf6sXqlOJKynMyfm9\nHItG5ICYOk+s8EPaLFOI1YMHzwKBgQDSou5vWBnAvx47kaBf0Fo/Z9z/cLM5sGap\n8rFxJUyybc8eJ9GX1eQMN73Asw/4u/FZkzn0GjyigHHtsGWK0VlRzL9qkmvM5itB\nsKqEKo1wuuZk4RxBZRCFiYkGlfy901pmn5sazxZ/NZ+eme2Qh4iZP5BII8e61Nol\nJVUbu2FAqwKBgQCgUhnlYvP6xTsNVdp83tQ6T84O9SfHamSKcOg0z9R+2oQ+EJLF\nKFV0QPHAYBy5p/2fgN4IreQPkVJfsX+oi32sLH8bKCIO0bosqeP7ZkdgdYh8y9KW\nngj43eHriXIM4bo2nnYMeLoHONn0qbyz8P4qVEhwgY8jGuj1/FA7aNAdCQKBgDko\nbXtZdOOQ+StBATv+1f6OuLG4a2okLDfB29TQQlfI5INSWtXQ/Okz1xILhTICDiQ4\nh2luFTYjlMbjLyrUVGCWJvtMcGRRsTtKLXtf8LG+hfap/3jfa/RQthZLbSI10Do4\n5WYI/BnY+0+WhZjKro6naQeqbfCNAgVCdC3qUyGxAoGBAM0eyfhmbhXWa0WmYUTb\nHCssWth+Ho3JsaKtFURv4ge7y8Zo1jvAZD/zxNIqnpwgQt0qBHN62LWW62tZjfZG\n9zbTx+F+oBXAs/6bLgmUtq5uIjaZmdxlMAP0XB47vIh05Vk0aRP25ZJbVvdDeH2X\n650CYdAWqcq6HfemrobXoI21\n-----END PRIVATE KEY-----\n",
+ "client_email": "firebase-adminsdk-u80vp@dof2-b9070.iam.gserviceaccount.com",
+ "client_id": "115792727331856285564",
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ "token_uri": "https://oauth2.googleapis.com/token",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-u80vp%40dof2-b9070.iam.gserviceaccount.com"
+}
diff --git a/firebase_tools/find-differences-65e47.json b/firebase_tools/find-differences-65e47.json
new file mode 100644
index 0000000..c7ee05b
--- /dev/null
+++ b/firebase_tools/find-differences-65e47.json
@@ -0,0 +1,13 @@
+{
+ "type": "service_account",
+ "project_id": "find-differences-65e47",
+ "private_key_id": "f8b22c8131e1028b5babd8e370aec172acbb652c",
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCuL3v95XnhHq0l\nJ7nIStzXv++FZE2x65TXCyYII8hZhyga07kz2RQuQ2lsd9jRD/1MbHBLXd7wimQH\nnsYb0NHTw3WdAXYmW3As3QVqjJMTm3KsFC7ZXd35er7z3Pt7WbYtNXZmoATT61su\nqL9wXYhwD8L2n3Mp2Tiq7E0vSBzFodJHd+rxhFiKeJpKpmo45jojztM4lfiseYYJ\nEYQPF+RjdjWwhFWlh3mdRALogcSuUkvfEvhv9rxv2i826+NiSZTvH+qtSpOpbHyy\nraaA+23Qsznta7QqixuQ0CmpS6cPf+Jfx53RP4s7Lm28Qkz5ev0GK6GkFhg1VfIh\n5mqm6Fr1AgMBAAECggEAS6y8kTd3xoq1zZ0fNTn1DVTJYmoL6T8AyJaC3Oly2xaB\noXoXjcODZYALFsFQtK9eLCw2cz/ioh11zOu5hQ8pgfd6qw4d/xcdupgBiONu6IdS\nABm6qtwBmqgturPonBQDNkvyVy6xOkKXuEM+/LneE1V9rfjjJyzE1llYRTDusxtc\n9UZAK3jHYeam7JMa+0TA1J08WXIdub9agKiF23as6UdSoBZlCOp+ubbdqUXXqDZl\nD9BUmUfFx0X+Mj8TNS6nZ0TVsi0BoWeSbtzVOC3Ff1vBAv7rqGe1RiVy6ExrmPXW\nFjmPVhPqr6/3lexDCF4MlOem8SH9EPkgMcmPnMvNFwKBgQDoXCPOrL5KdsHsXZiI\n6nhBsR6eYdOapQiO8VvlcgoGYRQ7o18/fNXqiK3xXxY2hcPmmr5H+pDDrZXPbltc\nIgxvRCc/oX8qUXUEwGJ2hhJtb8WutaZitSWjWtBX3pQxlJ9oX11CS5OcpgqdjkuP\nm4ZWNhqVFh2p0mEU4eBo92KiPwKBgQC/6C4GRRRulzey/9vhQg9moGO/A1L4WqT9\neekNn2Q93Tqw3UV7AnsjiR1tNrAuRaIR+KBfeFAHQIyx0P7tJSZalfq7X7Yj5Zxz\n6PeueetBtP9J+v7ultOb/OrGeET+ZeRkS+YxGvHRUeu6gwxb+nj5fJPMqTkiU4/c\nYhtGqGuNywKBgCMCDtsKp7jsX5dPGrY2LVwoZWaTcqAwETQIJUJShjQj2DqMCMO1\n+TzWzu44103rpXJPCjAqDjmNI68W/2jIMHtrF0a8/D3R/AF1QuB8nrYiSvRhpenl\nRQBxpEY44Lb/n2zIQXLFlD3bvmmykKvYUMsYZ7TimiGF8t6EkZz++LtdAoGAWfL7\nz5iFcSiTxOTELRsHmPTIi/mE5D+oYd7Ia8gv9gdBwTCVpoiNKyTTlCM0BRxCUOYW\nVWlRKXUJ/TaWppTpG0B9G2JLPxwabwHdRfyDVnL9zbFF2JL9cHnlmU06GXusx44D\nwTR977zUHsHaAyqtlVLc++q9iudb4NJjMoUylG0CgYEAwJD2bLlkIxOEeWt6HZxO\n6Hr3ysmhrwyayyGswDrXY7xss8Himla3Q7AlqQYzQH5iwNoL4tPZ+4nXAtxwZZvX\nuQRUSTIrGzC516H7JnI3m5UPd3X7IPVMP6Ui1BgacaE8FB7PbGYttqlJtEfNeBFx\n//4YAJQpbpsaXKyPeFh4aqA=\n-----END PRIVATE KEY-----\n",
+ "client_email": "firebase-adminsdk-3n2xs@find-differences-65e47.iam.gserviceaccount.com",
+ "client_id": "109381139516717789089",
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ "token_uri": "https://oauth2.googleapis.com/token",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-3n2xs%40find-differences-65e47.iam.gserviceaccount.com",
+ "universe_domain": "googleapis.com"
+}
\ No newline at end of file
diff --git a/firebase_tools/find-it-a08e5.json b/firebase_tools/find-it-a08e5.json
new file mode 100644
index 0000000..aa489dd
--- /dev/null
+++ b/firebase_tools/find-it-a08e5.json
@@ -0,0 +1,13 @@
+{
+ "type": "service_account",
+ "project_id": "find-it-a08e5",
+ "private_key_id": "f833603c7dd7dea5fb4cd13361a3a57a4e12dac2",
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVHLiNmwrOinYx\noTlgGFtYzZKYNNZhmkayEY++jqTHHOrJkZgbtKgCk69ZS/6ocU6Rsh3YUgGK8Duf\n8j2+yHVWFXooi9/IZ5/HraVzaJobZIfLagcCOXlVaxa8JC+VuehFEqpydF+I2PII\ng9LUYqEQUyvuWb6tUMxxUYOiV5AaxCLmAKR7yRkPPnqVroDqDONFLSDo9gf+doE6\n9Eh4PSWwHrzyk8sc8nxC9J14455bU3iYACLrtzN7dfAsONV1nhWbmYjyRhJpNfB6\noWiKUrQ+2yPtX7NPSSVAB55mlSnd/52GA7f4apGS0z4QAre7GihW3rk+eFhSr+P2\nD9/UXIYxAgMBAAECggEADiTFVNSU34dN99ZA5hFHwrmGAKcFEV45UekbdqSl5/cR\n2AXbJ/+R5PXjPdRu1sQKWF4PYAN1ScDO3DsqAObx7qAnRtidpgHGl2x9Xg7zp1zB\nLG1hgLLKzDH6xMrMA65ebXMjL8xsaLspOQpyrBjNorU6Zau8HWmO3/hueZBBJp19\nuKLdeUYlmurDAhgD2wu1nai4/fB+nw9CyF1NsA7fRgY7Ie4uoz75fJGRhofLK2Bv\nQ7mXwhtjNISznM5wuA6QuyXSuUP8RL7/5YRpO7kP1z89apcPmV1K/HLkx5uhs3WY\nlPG99VDO0H3ju1SN/sjX0CGeLQQvRDk1uWhiv9z3JwKBgQD40CXZ/r3qPuk/+Y8h\nZu9A6geiMRUwmbXtSCuMgnHmCYcZUPZrSFu4sUyJy670zpQ5WcGacWuV5Aw8c9jW\nc4/YDO9eL+9EXy7e2mNORt03bFDYMFcaAQnUiqdPPYYvhr/4A4HZnyMoKfAQMNe2\n6oabyAHlZK4iyD9UdT6iOgsIlwKBgQDbRJURZ0Jl7hBPt/15Z+PxyrDNKmLTAWhy\nxl8F+zwWi4SH3t3gwvvlhvD3VLluxU2GvtOXHxZcWofMw3dre3YqYv1H+gF9NuP7\nQljWqHDViBxAn9d4pOvONSIVZE27JvBN7X2qffX5l7JI9m3gGXsPBFEF9bnUhRXG\ntFcpSEm4dwKBgAHwpYromJR9/xWXnY0WH2FzMbILDe4+FJQQDv7eeYLgqiQBZJp7\nivOKtl0QsIGKJs+3qnHI1pzplUrXYGZzqjh2CVvDperzjwr/yuxuUwU+m/bDkbpL\nLcdxeVJ92VD/jPmjFV0cB4sloJCPwO7VL02BproiKdVtmEjRTTa4myNrAoGBAJuE\nykIcviBzuMgCFNtOT4OIotvx60QD5KQ7hNxGNHk9HZQNA8xOH8HNcw3J3vftIy6m\nHIc8OmzonRcjsIjgeZBYw5KQhQvdqdflWANwVw9sybUgagCc4M9SKkmH6gYK+Tgc\ncRxC2PrdmEtd1dKz3+9nvVv/zH0qo6Za9NNH/VnDAoGALLLI/pSJHlo0JLYdfVF1\nNQ69x1EF/iQR0LGjVLEdA/Lh+0KWG/cj/9+dxwKS3BSpySRxrhyW+P3ORozPF+JW\nHtZQALaxgESt8pTecnvhTpgFikSXhqKh5C9kz9ih12NgYi+lEbRKWAbSf5ny70CE\n76K1MnGyieVknBW8oYShnRE=\n-----END PRIVATE KEY-----\n",
+ "client_email": "pipelineupdate@find-it-a08e5.iam.gserviceaccount.com",
+ "client_id": "103397347800378546383",
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ "token_uri": "https://oauth2.googleapis.com/token",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/pipelineupdate%40find-it-a08e5.iam.gserviceaccount.com",
+ "universe_domain": "googleapis.com"
+}
diff --git a/firebase_tools/find-master-387702.json b/firebase_tools/find-master-387702.json
new file mode 100644
index 0000000..c91194f
--- /dev/null
+++ b/firebase_tools/find-master-387702.json
@@ -0,0 +1,13 @@
+{
+ "type": "service_account",
+ "project_id": "infra-387702",
+ "private_key_id": "1c49457f4057330ab45796ae4068b7e743a71ea2",
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3wcxP3hxoMe4s\nvAQUhfzp4lcykjF3WUR46CD+FYzfP4R7hTxg/0sgckzCmz0Oru1KkaxsrzVVLzSe\ntVzJ3vmiEBpE4D/0/KEjMBS5scM4f4EpS9OhGNGQLxaSurg6m125ZpYZREw2f/Sm\nrhlXwZdk8BElOX7o9PkC5sUH563/Ot0HOo6mqxVKNfTVo59CtNii82FmGe6+oen0\ntYyXsLw0sc+I4C7q4z8QFRP1p1xX6jtjaGjO5xo/PooBHBhii5GEdapPwfDFNhNY\ndpQI/ojDcCTFD7uQR+MU5LHL7YXJZxv6nzSMxgmbc8gbbbSaxe2BgBBjZ4aszgjE\n6ra8/hB5AgMBAAECggEAEsrlsJnWJSRNF8NbNfedfdRdZ1E68JofJe/UdvPAglDi\nRUkjG4bkWaNC3Sin6gVjBGwpOnzBKy7ullgVLxqIBGZZ72cRN2ZyOtFnHzYSMWgd\nzxm/gRNTFEgyimtA3dKHl2dJzLf2xOCZZkX6FsbYSzT/heNvSpcKE91Cs3wix+4i\naOUmYB44/Uxklv0PoxeSm0VfRiTVxW71plqk1qAx0YUKinpPgn+T8jDe5o0woRmP\nVoxVY2Sw0Top7k0Lt46qRj6ZHwGTZWPS4A8ZnkHIOCmkXNqEWCYaXQ/0Z49Pn8+K\n0IDX35DuLORtd2B4GGQ3AlobDZMkwN63PNmkOPHwUQKBgQDhe5O7O4Pc3cdSzBMv\n4fe5mXCDCixsYDVzPxYI65RG05zNvG1tCeWG++hW8eiEQiSNPUCP2zhMumZykcdg\nWOcR2zijICxcT+Y2jADWDYfIcZC6EMRRC7Dw6CueIxHScAwSEq5EODJ7EF+fIu+3\nSfF4t9cuFHhwdJYnKfYOIYkZcQKBgQDQoIcoAtyVG9R7BAZeQD2i7pCt5eZXX9oa\n8UrPBExgdYRm0euwdGmZb5GuOL4xUBM1tIlt/IvBV63CnR+ULrwdWXtPkl6FKsUd\n+CRhDbOC8li0lENF3POz/bOouei0MIEImJk2oeuJFo4Ps8ueNHZ2CTyCFlIhGZnf\nTS9VY/UjiQKBgHolZXvx25bUFVwG7QXtVTMXqdlys2nqHEpYDGm8pFBR5gmVX3nH\n+KzM3anr1dd/tSlF2ymSycbW2xSJYAYTYulLZj0H+r/vEHjQEsvh/IJa8tm4p4B3\n4tw+CRLbUJY82G0Z7YlLIB2GWyZr2Ivj5IlOnaR6tlvE7Go+0uoIxKohAoGBALMv\n/YYHFzBWq+RQq6uOH6JupwNFf9ax9CHJ90fhWDxNE0BAst9mzUBFDGoIQIsYTLeG\n7bby/5I7XXnW/EWI8nd+4KOSgu57srwv4gcd/n3M6xWGdlVuFj8U+5dCvjTtqBYb\nAxVic2vWXIPuGEg0pT5yZm8Q/s+BLqEVqT79UJKJAoGAFushetOSBZftrIe10/R8\nCaq8QJw4/OhCblqFqveb1WgvRDOvoax1X6yptY7WNIJ0kTjVIOcr2GqfldA3eNyS\nWkX9NzrX+kFHvpYAY+1RBo5P/wO8AzKEAukctQ2qseXs7mE8EircwSMGfjq8hp4I\nPZ79rr7R6YwUrodNqhs9n/Q=\n-----END PRIVATE KEY-----\n",
+ "client_email": "find-master-remoteconfig@infra-387702.iam.gserviceaccount.com",
+ "client_id": "106603798019848556340",
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ "token_uri": "https://oauth2.googleapis.com/token",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/find-master-remoteconfig%40infra-387702.iam.gserviceaccount.com",
+ "universe_domain": "googleapis.com"
+}
diff --git a/firebase_tools/firebase_helper.py b/firebase_tools/firebase_helper.py
new file mode 100644
index 0000000..2205afc
--- /dev/null
+++ b/firebase_tools/firebase_helper.py
@@ -0,0 +1,445 @@
+#!/usr/bin/env python
+# coding:utf-8
+import io
+import json
+import os
+import sys
+import google.cloud.storage
+import requests
+
+curr_dir = os.path.split(os.path.abspath(__file__))[0]
+print(curr_dir)
+sys.path.append(os.path.join(curr_dir, "../"))
+
+import utils as utils
+import firebase_admin
+from firebase_admin import credentials, db
+from firebase_admin import storage, firestore
+from oauth2client.service_account import ServiceAccountCredentials
+
+DOF_GOOGLE_SERVER_FILE = os.path.join(curr_dir, "find-differences-65e47.json")
+D2_GOOGLE_SERVER_FILE = os.path.join(curr_dir, "dof2-b9070.json")
+FindOut_GOOGLE_SERVER_FILE = os.path.join(curr_dir, "dof2-b9070.json")
+FindMaster_GOOGLE_SERVER_FILE = os.path.join(curr_dir, "find-master-387702.json")
+FindIt_GOOGLE_SERVER_FILE = os.path.join(curr_dir, "find-it-a08e5.json")
+
+DOF_PROJECT_ID = "find-differences-65e47"
+D2_PROJECT_ID = "dof2-b9070"
+FindOut_PROJECT_ID = "dof2-b9070"
+FindMaster_PROJECT_ID = "find-master-88ffb"
+FindIt_PROJECT_ID = "find-it-a08e5"
+
+BASE_URL = "https://firebaseremoteconfig.googleapis.com"
+
+def get_remote_config_file(project_id):
+ return os.path.join(curr_dir, f"remote_config_{project_id}.json")
+
+def get_remote_config_url(project_id):
+ return f"{BASE_URL}/v1/projects/{project_id}/remoteConfig"
+
+class Singleton:
+ _instances = {}
+
+ def __new__(cls, *args, **kwargs):
+ if cls not in cls._instances:
+ cls._instances[cls] = super().__new__(cls)
+ return cls._instances[cls]
+
+class FirebaseHelperInstance(Singleton):
+ def __init__(self):
+ print("初始化")
+ self.firebase_dof = None
+ self.firebase_d2 = None
+ self.firebase_find_out = None
+ self.firebase_find_master = None
+ self.firebase_find_it = None
+
+ def get_firebase_dof(self):
+ if self.firebase_dof is None:
+ self.firebase_dof = FirebaseHelper(DOF_PROJECT_ID, DOF_GOOGLE_SERVER_FILE)
+ return self.firebase_dof
+
+ def get_firebase_d2(self):
+ if self.firebase_d2 is None:
+ self.firebase_d2 = FirebaseHelper(D2_PROJECT_ID, D2_GOOGLE_SERVER_FILE)
+ return self.firebase_d2
+
+ def get_firebase_find_out(self):
+ if self.firebase_find_out is None:
+ self.firebase_find_out = FirebaseHelper(FindOut_PROJECT_ID, FindOut_GOOGLE_SERVER_FILE)
+ return self.firebase_find_out
+
+ def get_firebase_find_master(self):
+ if self.firebase_find_master is None:
+ self.firebase_find_master = FirebaseHelper(FindMaster_PROJECT_ID, FindMaster_GOOGLE_SERVER_FILE)
+ return self.firebase_find_master
+
+ def get_firebase_find_it(self):
+ if self.firebase_find_it is None:
+ self.firebase_find_it = FirebaseHelper(FindIt_PROJECT_ID, FindIt_GOOGLE_SERVER_FILE)
+ return self.firebase_find_it
+
+
+class FirebaseHelper:
+ def __init__(self, project_id, google_service_file):
+ print(f'init--{project_id}')
+ self.firebase_app = None
+ self.storage_instance = None
+ self.config = {}
+ self.config["project_id"] = project_id
+ self.GOOGLE_SERVER_FILE = google_service_file
+ self.REMOTE_CONFIG_FILE = get_remote_config_file(project_id)
+ self.REMOTE_CONFIG_URL = get_remote_config_url(project_id)
+ self.init()
+
+ def init(self):
+ self.init_firebase(self.config["project_id"])
+ self.init_storage(self.config["project_id"])
+
+ def init_firebase(self, project_id):
+ storage_bucket = "gs://" + project_id + ".appspot.com"
+ databaseURL = "https://" + project_id + ".firebaseio.com/"
+ cred = credentials.Certificate(self.GOOGLE_SERVER_FILE)
+ self.firebase_app = firebase_admin.initialize_app(cred, {
+ "databaseURL": databaseURL,
+ "storageBucket": storage_bucket
+ }, name=project_id)
+
+ self.refFirestore = firestore.client(app=self.firebase_app)
+ print("初始 firebase 成功")
+
+ def init_storage(self, project_id):
+ bucket = project_id + ".appspot.com"
+ if self.firebase_app:
+ self.storage_instance = storage.bucket(name=bucket, app=self.firebase_app)
+ print("初始 storage 成功")
+
+ def get_files(self, prefix=""):
+ print("prefix = " + prefix)
+ blobs = self.storage_instance.list_blobs(prefix=prefix)
+ return blobs
+
+ def get_files_match(self, prefix, match_glob):
+ blobs = self.storage_instance.list_blobs(prefix=prefix, match_glob=match_glob)
+ return blobs
+
+ def get_files_all_versions(self, prefix=""):
+ print("prefix = " + prefix)
+ blobs = self.storage_instance.list_blobs(prefix=prefix, versions=True)
+ return blobs
+
+ def get_file(self, storage_file, generation=None):
+ blob = self.storage_instance.get_blob(storage_file, generation=generation)
+ return blob
+
+ def get_file_generation(self, storage_file):
+ blob = self.storage_instance.get_blob(storage_file)
+ if blob is None:
+ return None
+ else:
+ return blob.generation
+
+ # 上传单个文件(会比较hash和md5码)
+ def upload_single_bundle(self, local_file, storage_file, blob_dic, ext_meta={}, try_count=0):
+ try_count = try_count + 1
+ if try_count > 3:
+ return False
+ try:
+ blob = None
+ if storage_file in blob_dic:
+ blob = blob_dic[storage_file]
+
+ is_same = False
+ if blob is not None:
+ local_hash = utils.calc_hash(local_file)
+ local_md5 = utils.calc_md5(local_file)
+
+ storage_hash = ""
+ if blob.metadata is not None and 'hash' in blob.metadata:
+ storage_hash = blob.metadata['hash']
+
+ storage_md5 = ""
+ if blob.metadata is not None and 'md5' in blob.metadata:
+ storage_md5 = blob.metadata['md5']
+
+ is_same = storage_hash == local_hash and storage_md5 == local_md5
+
+ if not is_same:
+ print(f"{local_file} 上传中..")
+ self.upload_file(local_file, storage_file, ext_meta)
+ else:
+ print(f"{local_file} hash和md5码和storage文件一致,不重复上传..")
+ return True
+ except Exception as e:
+ print(local_file + " 上传失败,尝试重试,错误信息:" + repr(e))
+ self.upload_single_bundle(local_file, storage_file, blob_dic, ext_meta, try_count)
+
+ def upload_thumbnail_image(self, local_file, storage_file, ext_meta={}, try_count=0):
+ try_count = try_count + 1
+ if try_count > 3:
+ return False
+ try:
+ self.upload_file(local_file, storage_file, ext_meta)
+ return True
+ except Exception as e:
+ print(local_file + " 上传失败,尝试重试,错误信息:" + repr(e))
+ self.upload_thumbnail_image(local_file, storage_file, ext_meta, try_count)
+
+ def upload_file(self, local_file, storage_file, ext_meta={}):
+ try:
+ upload_blob = self.storage_instance.blob(storage_file)
+ meta = {
+ 'hash': utils.calc_hash(local_file),
+ 'md5': utils.calc_md5(local_file),
+ }
+
+ meta.update(ext_meta)
+ upload_blob.metadata = meta
+ if local_file.endswith(".json"):
+ utils.gzip_file(local_file)
+ upload_blob.content_encoding = "gzip"
+ upload_blob.upload_from_filename(local_file + '.gz')
+ os.unlink(local_file + '.gz')
+ else:
+ upload_blob.upload_from_filename(local_file)
+ blob = self.storage_instance.get_blob(storage_file)
+ print(local_file + " 上传成功 generation = {}".format(blob.generation))
+ return blob.generation
+ except Exception as e:
+ raise Exception(e)
+
+ def update_metadata(self, storage_file, ext_meta={}):
+ try:
+ blob = self.storage_instance.get_blob(storage_file)
+ if blob is not None:
+ meta = blob.metadata
+ meta.update(ext_meta)
+ blob.metadata = meta
+ blob.patch()
+ print(storage_file + " 更新metadata成功")
+ else:
+ print(storage_file + " 文件不存在")
+ except Exception as e:
+ raise Exception(e)
+
+ # region RemoteConfig更新
+
+ def get_access_token(self):
+ file_value = ""
+ with open(self.GOOGLE_SERVER_FILE, "r") as f:
+ file_value = json.load(f)
+
+ credentials = ServiceAccountCredentials.from_json_keyfile_dict(file_value, [
+ "https://www.googleapis.com/auth/firebase.remoteconfig"])
+ access_token_info = credentials.get_access_token()
+ return access_token_info.access_token
+
+ def get_remote_value(self):
+ """
+ 获取RemoteConfig配置,并写入到remote_config.json中
+ :return: ETag
+ """
+ try:
+ headers = {
+ "Authorization": "Bearer " + self.get_access_token()
+ }
+ resp = requests.get(self.REMOTE_CONFIG_URL, headers=headers)
+
+ if resp.status_code == 200:
+ with io.open(self.REMOTE_CONFIG_FILE, "wb") as f:
+ f.write(resp.text.encode("utf-8"))
+
+ print("remote config 写入完成: remote_config.json")
+ print("ETag from server: {}".format(resp.headers["ETag"]))
+ return resp.headers["ETag"]
+ else:
+ print("remote_config.json上传失败")
+ print(resp.text)
+ return None
+ except Exception as e:
+ print("获取 RemoteConfig值失败 " + repr(e))
+ raise Exception("Fail")
+
+ def upload_remote_config_value(self, etag):
+ """
+ 上传 remote_config.json 文件至firebase后台
+ :param: etag
+ """
+ try:
+ with open(self.REMOTE_CONFIG_FILE, "r", encoding="utf-8") as f:
+ content = f.read()
+ print("开始上传 remote config:>" + content + "<")
+ headers = {
+ "Authorization": "Bearer " + self.get_access_token(),
+ "Content-Type": "application/json; UTF-8",
+ "If-Match": etag
+ }
+ resp = requests.put(self.REMOTE_CONFIG_URL, data=content.encode("utf-8"), headers=headers)
+ if resp.status_code == 200:
+ print("推送成功")
+ print("ETag from server: {}".format(resp.headers["ETag"]))
+ return True
+ else:
+ print("推送失败")
+ print(resp.text)
+ return False
+ except Exception as e:
+ print("更新 RemoteConfig值失败 " + repr(e))
+ return False
+
+ def check_or_create_string_field(self, json_dict, keys, value):
+ arr = keys.split("/")
+ field = json_dict
+ index = 0
+ for item in arr:
+ if index == len(arr) - 1:
+ print("item = " + item)
+ field[item] = value
+ print(field[item])
+ else:
+ field = field[item]
+
+ index = index + 1
+
+ def check_or_create_json_value(self, json_dict, keys, value):
+ arr = keys.split("/")
+ field = json_dict
+ index = 0
+ for item in arr:
+ if index == len(arr) - 1:
+ print("item = " + item)
+ field[item] = json.dumps(value)
+ print(field[item])
+ else:
+ field = field[item]
+
+ index = index + 1
+
+ def check_or_create_json_field_value(self, json_dict, keys, sub_key, sub_value):
+ arr = keys.split("/")
+ field = json_dict
+ index = 0
+ for item in arr:
+ if index == len(arr) - 1:
+ print("item = " + item)
+ value = json.loads(field[item])
+ value[sub_key] = sub_value
+ field[item] = json.dumps(value)
+ print(field[item])
+ else:
+ field = field[item]
+
+ index = index + 1
+
+ def update_remote_config_json_value(self, group, condition, remote_key, value, is_upload=False):
+ try:
+ etag = None
+ if is_upload or not os.path.exists(self.REMOTE_CONFIG_FILE):
+ etag = self.get_remote_value()
+
+ remote_content = ""
+ with open(self.REMOTE_CONFIG_FILE, "r") as f:
+ remote_content = f.read()
+
+ if remote_content != None and remote_content != "":
+ remote_content_json = json.loads(remote_content)
+ keys = ""
+ if group is not None and group != "":
+ keys = f"parameterGroups/{group}/parameters/"
+ else:
+ keys = f"parameters/"
+
+ if condition is not None and condition != "":
+ keys = keys + f"{remote_key}/conditionalValues/{condition}/value"
+ else:
+ keys = keys + f"{remote_key}/defaultValue/value"
+
+ self.check_or_create_json_value(remote_content_json, keys, value)
+
+ print("\n\n")
+ print(remote_content_json)
+ print("\n\n")
+ # 将online_json写入到remote_config.json文件
+ utils.write_json(self.REMOTE_CONFIG_FILE, remote_content_json)
+ if is_upload:
+ self.upload_remote_config_value(etag)
+ except Exception as e:
+ print(e)
+ raise Exception(f"[remote_config group:{group}, condition:{condition}, remote_key:{remote_key}] 更新失败")
+
+ def update_remote_config_json_field_value(self, group, condition, remote_key, json_field_key, value, is_upload=False):
+ try:
+ etag = None
+ if is_upload or not os.path.exists(self.REMOTE_CONFIG_FILE):
+ etag = self.get_remote_value()
+
+ remote_content = ""
+ with open(self.REMOTE_CONFIG_FILE, "r") as f:
+ remote_content = f.read()
+
+ if remote_content != None and remote_content != "":
+ remote_content_json = json.loads(remote_content)
+ keys = ""
+ if group is not None and group != "":
+ keys = f"parameterGroups/{group}/parameters/"
+ else:
+ keys = f"parameters/"
+
+ if condition is not None and condition != "":
+ keys = keys + f"{remote_key}/conditionalValues/{condition}/value"
+ else:
+ keys = keys + f"{remote_key}/defaultValue/value"
+
+ self.check_or_create_json_field_value(remote_content_json, keys, json_field_key, value)
+
+ # 将online_json写入到remote_config.json文件
+ utils.write_json(self.REMOTE_CONFIG_FILE, remote_content_json)
+ if is_upload:
+ self.upload_remote_config_value(etag)
+ except Exception as e:
+ print(e)
+ raise Exception(f"[remote_config group:{group}, condition:{condition}, remote_key:{remote_key}, json_field_key:{json_field_key}] 更新失败")
+
+ def update_remote_config_string_value(self, group, condition, remote_key, value, is_upload=False):
+ try:
+ etag = None
+ if is_upload or not os.path.exists(self.REMOTE_CONFIG_FILE):
+ etag = self.get_remote_value()
+
+ remote_content = ""
+ with open(self.REMOTE_CONFIG_FILE, "r") as f:
+ remote_content = f.read()
+
+ if remote_content != None and remote_content != "":
+ remote_content_json = json.loads(remote_content)
+ keys = ""
+ if group is not None and group != "":
+ keys = f"parameterGroups/{group}/parameters/"
+ else:
+ keys = f"parameters/"
+
+ if condition is not None and condition != "":
+ keys = keys + f"{remote_key}/conditionalValues/{condition}/value"
+ else:
+ keys = keys + f"{remote_key}/defaultValue/value"
+
+ self.check_or_create_string_field(remote_content_json, keys, value)
+
+ print("\n\n")
+ print(remote_content_json)
+ print("\n\n")
+ # 将online_json写入到remote_config.json文件
+ utils.write_json(self.REMOTE_CONFIG_FILE, remote_content_json)
+ if is_upload:
+ self.upload_remote_config_value(etag)
+ except Exception as e:
+ print(e)
+ raise Exception(f"[remote_config group:{group}, condition:{condition}, remote_key:{remote_key}] 更新失败")
+
+ def GetInfor(self, targetFile: str) -> google.cloud.storage.bucket.Bucket:
+
+ blob = self.storage_instance.get_blob(targetFile)
+ return blob
+
+ def GetGeneration(self, targetFile: str) -> str:
+ return str(self.GetInfor(targetFile).generation)
diff --git a/firebase_tools/remote_config_dof2-b9070.json b/firebase_tools/remote_config_dof2-b9070.json
new file mode 100644
index 0000000..169a881
--- /dev/null
+++ b/firebase_tools/remote_config_dof2-b9070.json
@@ -0,0 +1 @@
+{"conditions": [{"name": "ios", "expression": "device.os == 'ios'", "tagColor": "BLUE"}, {"name": "android_high_rating_countries", "expression": "device.os == 'android' && device.country in ['IN', 'DE', 'IT', 'JP', 'RU', 'GB']", "tagColor": "PURPLE"}, {"name": "android_low_rating_countries", "expression": "device.os == 'android' && device.country in ['BR', 'FR', 'TW']", "tagColor": "DEEP_ORANGE"}, {"name": "android_high_rating_countries_t1", "expression": "device.os == 'android' && device.country in ['US']", "tagColor": "DEEP_ORANGE"}, {"name": "US", "expression": "device.country in ['US']", "tagColor": "ORANGE"}, {"name": "JP", "expression": "device.country in ['JP']", "tagColor": "DEEP_ORANGE"}, {"name": "DE", "expression": "device.country in ['DE']", "tagColor": "PINK"}, {"name": "GB", "expression": "device.country in ['GB']", "tagColor": "PURPLE"}, {"name": "CA", "expression": "device.country in ['CA']", "tagColor": "INDIGO"}, {"name": "FR", "expression": "device.country in ['FR']", "tagColor": "BLUE"}, {"name": "TW", "expression": "device.country in ['TW']", "tagColor": "TEAL"}, {"name": "BR", "expression": "device.country in ['BR']", "tagColor": "GREEN"}, {"name": "IT", "expression": "device.country in ['IT']", "tagColor": "LIME"}, {"name": "ES", "expression": "device.country in ['ES']", "tagColor": "ORANGE"}, {"name": "RU", "expression": "device.country in ['RU']", "tagColor": "PINK"}, {"name": "IN", "expression": "device.country in ['IN']", "tagColor": "GREEN"}, {"name": "android", "expression": "device.os == 'android'", "tagColor": "GREEN"}, {"name": "ios_review_version", "expression": "app.id == '1:172777672378:ios:7edca11b54334430963c83' && app.version.==(['1.2.1'])", "tagColor": "DEEP_ORANGE"}, {"name": "TxCDN-Rollout-Non-US", "expression": "device.country in ['IN', 'JP', 'BR', 'FR', 'DE', 'CA', 'TW', 'GB', 'HK', 'KR', 'AT', 'AU', 'BE', 'MM', 'IT', 'NL', 'PR', 'ES']", "tagColor": "BLUE"}, {"name": "TxCDN-Rollout-US", "expression": "device.country in ['US']", "tagColor": "LIME"}, {"name": "Android_US", "expression": "device.os == 'android' && device.country in ['US']", "tagColor": "BROWN"}, {"name": "hint", "expression": "app.audiences.inAtLeastOne(['hint_5'])", "tagColor": "INDIGO"}, {"name": "hour", "expression": "app.audiences.inAtLeastOne(['hourglasses_5'])", "tagColor": "ORANGE"}, {"name": "ads", "expression": "app.audiences.inAtLeastOne(['iap_noads'])", "tagColor": "PURPLE"}, {"name": "sub", "expression": "app.audiences.inAtLeastOne(['iap_sub5'])", "tagColor": "DEEP_ORANGE"}, {"name": "subnew", "expression": "app.audiences.inAtLeastOne(['iap_subnew14'])", "tagColor": "LIME"}, {"name": "KR", "expression": "device.country in ['KR']", "tagColor": "BLUE"}, {"name": "cdn3", "expression": "percent('bcgqwx6l7b2s') between 90 and 100", "tagColor": "ORANGE"}, {"name": "ios_promo_code", "expression": "device.os == 'ios' && app.id == '1:172777672378:ios:60060e48d53df048963c83' && app.version.<=(['3.39.0'])", "tagColor": "BROWN"}, {"name": "FO-Android", "expression": "app.id == '1:172777672378:android:2cbb65ac9c92b468963c83'", "tagColor": "INDIGO"}, {"name": "FO-IOS", "expression": "app.id == '1:172777672378:ios:60060e48d53df048963c83'", "tagColor": "ORANGE"}, {"name": "D2-IOS", "expression": "app.id == '1:172777672378:ios:7edca11b54334430963c83'", "tagColor": "TEAL"}, {"name": "D2-Android", "expression": "app.id == '1:172777672378:android:7b3e2a2c4427c0cc963c83'", "tagColor": "BROWN"}, {"name": "test_ios_promo_code", "expression": "device.os == 'ios' && app.id == '1:172777672378:ios:60060e48d53df048963c83' && app.version.<=(['3.13.0'])", "tagColor": "BROWN"}, {"name": "france", "expression": "device.country in ['FR']", "tagColor": "GREEN"}, {"name": "Mexico", "expression": "device.country in ['MX']", "tagColor": "BROWN"}, {"name": "United Kingdom", "expression": "device.country in ['GB']", "tagColor": "PURPLE"}, {"name": "Brazil", "expression": "device.country in ['BR']", "tagColor": "LIME"}, {"name": "china", "expression": "device.language in ['zh-Hans', 'zh']", "tagColor": "INDIGO"}, {"name": "chinese", "expression": "device.language in ['zh-Hans', 'zh-Hant', 'zh-TW', 'zh']", "tagColor": "ORANGE"}, {"name": "NewGVE_Android", "expression": "app.id == '1:172777672378:android:7b3e2a2c4427c0cc963c83' && app.version.>(['2.26.0'])", "tagColor": "TEAL"}, {"name": "NewGVE_iOS", "expression": "app.id == '1:172777672378:ios:7edca11b54334430963c83' && app.version.>(['2.26.0'])", "tagColor": "BLUE"}, {"name": "uk", "expression": "device.country in ['GB']", "tagColor": "INDIGO"}, {"name": "brazil", "expression": "device.country in ['BR']", "tagColor": "PINK"}, {"name": "chn", "expression": "device.language in ['zh-Hans']", "tagColor": "ORANGE"}, {"name": "simplified Chinese", "expression": "device.language in ['zh-Hans']", "tagColor": "INDIGO"}, {"name": "Android v2.29.1", "expression": "app.id == '1:172777672378:android:7b3e2a2c4427c0cc963c83' && app.version.>=(['2.29.1'])", "tagColor": "PURPLE"}, {"name": "iOS v2.29.1", "expression": "app.id == '1:172777672378:ios:7edca11b54334430963c83' && app.version.>=(['2.29.1'])", "tagColor": "INDIGO"}, {"name": "less_android_V3.2.0", "expression": "app.id == '1:172777672378:android:7b3e2a2c4427c0cc963c83' && app.version.<=(['3.1.0'])", "tagColor": "BLUE"}, {"name": "less_ios_V3.2.0", "expression": "app.id == '1:172777672378:ios:7edca11b54334430963c83' && app.version.<=(['3.1.0'])", "tagColor": "DEEP_ORANGE"}, {"name": "open_by_country_Android", "expression": "device.os == 'android' && device.country in ['JP', 'BR', 'GB', 'CA', 'AU']", "tagColor": "BLUE"}, {"name": "close_by_country_Android", "expression": "device.os == 'android' && device.country in ['KR']", "tagColor": "DEEP_ORANGE"}, {"name": "country", "expression": "device.country in ['CN']", "tagColor": "ORANGE"}, {"name": "close_by_country_IOS", "expression": "device.country in ['JP', 'BR', 'KR', 'GB', 'CA', 'AU'] && device.os == 'ios'", "tagColor": "TEAL"}, {"name": "3340ABtest", "expression": "device.country in ['SS']", "tagColor": "PURPLE"}, {"name": "200level", "expression": "app.userProperty['b_level'] > 200", "tagColor": "GREEN"}, {"name": "AR", "expression": "device.country in ['AR']", "tagColor": "ORANGE"}, {"name": "IDN", "expression": "device.country in ['ID']", "tagColor": "GREEN"}], "parameters": {"special_chest_coins": {"defaultValue": {"value": "20"}, "description": "\u7279\u6b8a\u5173\u5361\u7ed3\u7b97\u5956\u52b1\u7684\u91d1\u5e01\u6570\u91cf", "valueType": "STRING"}, "keywords_config": {"defaultValue": {"value": "{ \"enable\": true,\"btad\":false,\"betterAd\":0 }"}, "conditionalValues": {"FO-Android": {"value": "{ \"enable\": true,\"btad\":false,\"betterAd\":0 }"}, "FO-IOS": {"value": "{ \"enable\": true,\"btad\":false,\"betterAd\":0 }"}, "D2-IOS": {"value": "{ \"enable\": true,\"btad\":false }"}, "D2-Android": {"value": "{ \"enable\": true,\"btad\":false }"}}, "description": "\u6e38\u620fkeywords\u5f00\u5173", "valueType": "STRING"}, "chest_config_v2120": {"defaultValue": {"value": "{\"isShowCountdown\":false,\"chestArr\":[{\"star\":10,\"coin\":4,\"allMul\":[5,4,3,2],\"debris\":6,\"countdown\":1800},{\"star\":10,\"coin\":5,\"allMul\":[5,4,3,2],\"debris\":7,\"countdown\":1800},{\"star\":10,\"coin\":6,\"allMul\":[5,4,3,2],\"debris\":8,\"countdown\":1800}]}"}, "description": "2.12.0\u7248\u672c\u5b9d\u7bb1\u914d\u7f6e(\u5b9d\u7bb1\u4e2a\u6570\u4e0d\u80fd\u4fee\u6539\uff0c\u53ea\u80fd\u4fee\u6539\u5956\u52b1\u53c2\u6570)\uff0c2.25.0\u6dfb\u52a0\u5b9d\u7bb1\u5012\u8ba1\u65f6\uff08\u7b2c1\u4e2a\u5b9d\u7bb1\u65e0\u5012\u8ba1\u65f6\uff09", "valueType": "JSON"}, "thumbnail_quality_config": {"defaultValue": {"value": "{\"isReplaceMainThumbnail\":false,\"isReplaceSpecialThumbnail\":true,\"isReplaceAtlasThumbnail\":true,\"mainQuality\":\"0.3\",\"specialQuality\":\"0.5\",\"atlasQuality\":\"0.5\"}"}, "description": "\u5173\u5361\u7f29\u7565\u56fe\u7684\u54c1\u8d28\u76f8\u5173\u914d\u7f6e\uff0c\u53c2\u6570\u4e3a\u8be5\u6a21\u5f0f\u662f\u5426\u66ff\u6362\u54c1\u8d28\uff0c\u4ee5\u53ca\u8be5\u6a21\u5f0f\u66ff\u6362\u4e3a\u591a\u5c11\u54c1\u8d28(\u53ea\u80fd\u4e3a0.1\uff0c0.3\uff0c0.5\uff0c0.7\u8fd9\u56db\u79cd\uff0c\u8d8a\u5927\u8d8a\u6e05\u6670)", "valueType": "JSON"}, "hard_level_config": {"defaultValue": {"value": "{\"open_level_num\":99999,\"level_multiple_base\":10}"}, "conditionalValues": {"china": {"value": "{\"open_level_num\":15,\"level_multiple_base\":5}"}}, "description": "hard_level\u73a9\u6cd5\uff0copen_level_num:\u5f00\u542f\u529f\u80fd\u7684\u5173\u5361\u6570,level_multiple_base:\u5173\u5361\u57fa\u7840\u500d\u6570\uff0c\u5173\u5361\u4e0b\u6807\u4e3a\u8be5\u6570\u5b57\u500d\u6570\u5c31\u662fhard level", "valueType": "JSON"}, "to_next_map_config": {"defaultValue": {"value": "{\"is_show_animation_half_page\":true,\"pass_level_def_reward_coin_count\":12,\"pass_whereis_level_def_reward_coin_count\":12,\"pass_challenge_level_def_reward_coin_count\":12}"}, "description": "\u4e3b\u9875\u52a8\u753b\u6d41\u7a0b\u63a7\u5236", "valueType": "JSON"}, "event_res_url_head": {"defaultValue": {"value": "https://cdn2.dof.fungame.studio"}, "description": "\u6d3b\u52a8\u5173\u5361\u8d44\u6e90\u5934\u5730\u5740", "valueType": "STRING"}, "standalone_gve_asset_manifest": {"defaultValue": {"value": "{\"Gve_Map\": \"4c6c6cf3ed712f26c8cf3075977a62f1\", \"Gve_Data\": \"cc013a45809afa48086a4a5d6b971a0e\", \"Gve_score\": \"9f935a3def779ba8ea514c123d45287f\", \"Robot_Data\": \"77dc5c68bb928fc6a1c67204126fe789\", \"Gve_comconfig\": \"ef06239b2a38185d787d0c9d8de22082\"}"}, "valueType": "JSON"}, "unload_texture_cd": {"defaultValue": {"value": "300"}, "description": "\u6e38\u620f\u5185\uff0c\u6253\u5f00\u4e3b\u754c\u9762\u65f6\u4f1a\u53bb\u5378\u8f7d\u7f13\u5b58texture\u7684\u8d44\u6e90\uff0c\u8fd9\u4e2a\u53c2\u6570\u662f\u5378\u8f7d\u8d44\u6e90\u7684cd\u65f6\u95f4\u3002\u5355\u4f4d\u79d2", "valueType": "STRING"}, "eventVersionsTime": {"defaultValue": {"value": "2023.03.16"}, "description": "\u7528\u4e8e\u5237\u65b0firestore\u7684event_list\u6d3b\u52a8\u5217\u8868\u6587\u4ef6", "valueType": "STRING"}, "main_banner_config": {"defaultValue": {"value": "{\"IsShowMainBanner\":true,\"ShowBannerLevel\":5,\"AutoPopNum\":2,\"FirstAutoPopLevelNum\":20,\"AutoPopIntervalLevelNum\":20}"}, "description": "\u4e3b\u9875banner\u663e\u793a\u7684\u4e00\u4e9b\u6761\u4ef6,IsShowMainBanner:\u662f\u5426\u663e\u793a\u81ea\u5df1\u505a\u7684banner\uff0cShowBannerLevel\uff1a\u9700\u8981\u901a\u8fc7\u591a\u5c11\u5173\u624d\u663e\u793a\uff0cAutoPopNum\uff1a\u5173\u5361\u7ed3\u7b97\u64ad\u653e\u5dee\u8bc4\u7136\u540e\u5f39\u51fa\u53bb\u5e7f\u544a\u5f39\u7a97\u7684\u6b21\u6570 FirstAutoPopLevelNum\uff1a\u9996\u6b21\u81ea\u52a8\u5f39\u51fa\u53bb\u5e7f\u544a\u5f39\u7a97\u7684\u5173\u5361\u6570\uff0cAutoPopIntervalLevelNum\uff1a\u540e\u7eed\u5f39\u51fa\u53bb\u5e7f\u544a\u5f39\u7a97\u9700\u8981\u7684\u5173\u5361\u95f4\u9694\u6570", "valueType": "JSON"}, "gameplay_control_config": {"defaultValue": {"value": "{\"isOpenDC\":true,\"dcFrontLevel\":20,\"isOpenEvent\":true,\"eventFrontLevel\":20,\"isOpenGVE\":false,\"gveFrontLevel\":30,\"isOpenTrophy\":true,\"trophyFrontLevel\":10,\"isOpenRank\":true,\"rankFrontLevel\":10,\"isOpenDCGuide\":false,\"isOpenEventGuide\":true,\"carRaceOpen\":false,\"isOpenStarShowDown\":true,\"starShowDownFrontLevel\":20,\"levelLife\":5}"}, "description": "\u63a7\u5236\u4e3b\u9875\u73a9\u6cd5\u6309\u94ae\u662f\u5426\u5f00\u542f\uff0c\u4ee5\u53ca\u5f00\u542f\u6240\u9700\u8981\u7684\u524d\u7f6e\u5173\u5361\uff0c2.16.0\u7248\u672c\u5f00\u59cb\u4f7f\u7528\uff0c2.25\u7248\u672c\u65b0\u589eisOpenDCGuide\uff0cisOpenEventGuide\u63a7\u5236\u5f39\u7a97\u662f\u5426\u53ef\u4ee5\u663e\u793a,levelLife:\u5173\u5361\u5185\u751f\u547d\u503c\uff0c\u5c0f\u4e8e\u7b49\u4e8e0\u5c31\u662f\u4e0d\u5f00\u542f", "valueType": "JSON"}, "atlas_config": {"defaultValue": {"value": "{\"debug_url\": \"https://cdn3-dof.fungame.cloud/d2/level_config_new/atlas/atlas_debug.json?generation=1701857684255208&alt=media\", \"release_url\": \"https://cdn3-dof.fungame.cloud/d2/level_config_new/atlas/atlas_release.json?generation=1702030193387573&alt=media\"}"}, "description": "\u56fe\u96c6\u5173\u5361\u914d\u7f6e", "valueType": "JSON"}, "advanced_map_premium_coin_remote_config": {"defaultValue": {"value": " { \"premium_map_default_coin\": 5000, \"premium_unlock\": 0, \"default_product\": { \"map_id\": \"default\", \"name\": \"iapc_premiummap_499\", \"android_id\": \"fo.a.iapc.premiummap.499\", \"ios_id\": \"fo.i.iapc.premiummap.499\", \"price\": 4.99 }, \"products\": [], \"discount_coin_products\": [ { \"map_id\": \"nycxmas23\", \"discount_rate\": 80, \"start_time\": \"20231222T090500\", \"end_time\": \"20231229T090000\" } ], \"default_coin_map_list\": { \"mystery\": \"5000\", \"paris\": \"5000\", \"tokyo2\": \"5000\", \"rome\": \"5000\", \"greek\": \"5000\", \"la\": \"5000\", \"cyberpunk\": \"5000\", \"vineyard\": \"5000\", \"galactic\": \"5000\", \"skull\": \"5000\", \"goblin\": \"5000\", \"nycxmas23\": \"5000\", \"fantasia\": \"5000\", \"bluehole\": \"5000\", \"treehome\": \"5000\", \"superbowl\": \"5000\", \"abandoned\": \"5000\", \"cavern\": \"5000\", \"dragon\": \"5000\", \"fruity\": \"5000\", \"core\": \"5000\", \"dessert\": \"5000\", \"toycity\": \"5000\", \"polar\": \"5000\", \"shadow\": \"5000\", \"olympus\": \"5000\", \"tribalafrica\": \"5000\", \"slumber\": \"5000\" }, \"not_auto_discount_map_list\": [ \"mystery\", \"treehome\" ], \"discount_map_list\": [ { \"map_id\": \"mystery\", \"discount\": 40, \"start_time\": \"20240429T090500\", \"end_time\": \"20240513T090000\" }, { \"map_id\": \"treehome\", \"discount\": 40, \"start_time\": \"20240510T090500\", \"end_time\": \"20240524T090000\" } ], \"auto_discount_time\": 168, \"auto_discount\": 40, \"premium_iap_free\": [] }"}, "description": "\u9ad8\u7ea7\u8d27\u5e01\u8d2d\u4e70\u9ad8\u7ea7\u5730\u56fe\u914d\u7f6e", "valueType": "JSON"}, "coop_gve": {"defaultValue": {"value": "{\"open_level\":30,\"combo_time\":8}"}, "description": "gve\u914d\u7f6e\uff0copen_level\u57282.16.0\u540e\u505c\u6b62\u4f7f\u7528", "valueType": "JSON"}, "ad_impression": {"defaultValue": {"value": "{\"enable\":true}"}, "description": "D2 ARO\u4e70\u91cf\u914d\u7f6e", "valueType": "JSON"}, "unlock_special_debris_config": {"defaultValue": {"value": "{\"allIntervalAndDebris\":[{\"leftInterval\":1,\"debrisCount\":12},{\"leftInterval\":21,\"debrisCount\":15}]}"}, "description": "\u7279\u6b8a\u5173\u5361\u89e3\u9501\u5173\u5361\u6240\u9700\u7684\u94a5\u5319\u6570\u91cf\u7684\u914d\u7f6e\uff1a\u5de6\u533a\u95f4\uff08\u542b\uff09+\u6570\u91cf\u914d\u7f6e", "valueType": "JSON"}, "is_show_chest_on_the_main_view": {"defaultValue": {"value": "true"}, "description": "\u662f\u5426\u4f7f\u7528\u5728\u4e3b\u9875\u663e\u793a\u7ed3\u7b97\u5b9d\u7bb1\u7684\u6a21\u5f0f\uff0cV2.22.0\u5f00\u59cb\uff0c\u4e3afalse\u5c31\u8fd8\u662f\u4f7f\u7528\u7ed3\u7b97\u9875\u663e\u793a\u5956\u52b1\u5b9d\u7bb1", "valueType": "BOOLEAN"}, "level_star_score": {"defaultValue": {"value": "{\"diff5Scores\":[30,60,90],\"diff6Scores\":[40,80,130],\"diff7Scores\":[45,100,180],\"diff8Scores\":[55,120,200],\"diff9Scores\":[60,140,230],\"diff10Scores\":[70,160,260],\"diff15Scores\":[105,210,410],\"diff20Scores\":[140,280,560],\"comboDuration\":8,\"diffFindScore\":10,\"hpScore\":0,\"timeScore\":0,\"timeConvert\":30}"}, "description": "\u5173\u5361\u8bc4\u661f\u7cfb\u7edf\u914d\u7f6e", "valueType": "JSON"}, "ad_config": {"defaultValue": {"value": "{\"isShowLevelStarInterstitial\":false}"}, "description": "isShowLevelStarInterstitial :\u5173\u5361\u5f00\u59cb\u662f\u5426\u5141\u8bb8\u53ef\u4ee5\u663e\u793a\u63d2\u5c4f\u5e7f\u544a", "valueType": "JSON"}, "cdn_config": {"defaultValue": {"value": "{\"main\":\"https://cdn3-dof.fungame.cloud/\",\"fallback\":\"https://cdn2.dof.fungame.studio/\",\"replace\":[\"https://cdn.dof.fungame.studio/\",\"https://cdn1.dof.fungame.studio/\",\"https://cdn2.dof.fungame.studio/\",\"https://cdn3-dof.fungame.cloud/\",\"https://firebasestorage.googleapis.com/v0/b/find-differences-65e47.appspot.com/o/\"]}"}, "description": "cdn\u914d\u7f6e", "valueType": "JSON"}, "hint_offset_time": {"defaultValue": {"value": "15"}, "description": "\u5173\u5361hint\u95f4\u9694\u65f6\u95f4", "valueType": "NUMBER"}, "fo_test": {"defaultValue": {"value": "{\"value\":2}"}, "description": "test", "valueType": "JSON"}, "fo_new_icon": {"defaultValue": {"value": "true"}, "description": "ios\u4f7f\u7528\u65b0icon", "valueType": "BOOLEAN"}, "taich_config": {"defaultValue": {"value": "{\"enable\":true,\"value\":0.2}"}, "description": "D2\u592a\u678102\u914d\u7f6e", "valueType": "JSON"}, "evets_resource_contorl": {"defaultValue": {"value": "[{\"eventName\":\"women_2022\",\"resourceVersionTime\":\"4\",\"configVersionTime\":\"4\"},{\"eventName\":\"easter_2022\",\"resourceVersionTime\":\"4\",\"configVersionTime\":\"5\"},{\"eventName\":\"mother_2022\",\"resourceVersionTime\":\"2\",\"configVersionTime\":\"2\"},{\"eventName\":\"ocean_2022\",\"resourceVersionTime\":\"1\",\"configVersionTime\":\"1\"},{\"eventName\":\"build_2022\",\"resourceVersionTime\":\"1\",\"configVersionTime\":\"1\"},{\"eventName\":\"scenery_2022\",\"resourceVersionTime\":\"4\",\"configVersionTime\":\"4\"},{\"eventName\":\"halloween_2022\",\"resourceVersionTime\":\"1\",\"configVersionTime\":\"1\"}]"}, "description": "configVersionTime \u91cd\u65b0\u62c9\u53d6\u5bf9\u5e94\u6d3b\u52a8\u7684firestore\u8d44\u6e90\uff0cresourceVersionTime\u91cd\u65b0\u62c9\u53d6storage\u8d44\u6e90", "valueType": "JSON"}, "ui_interstitial_time": {"defaultValue": {"value": "9999"}, "description": "\u73a9\u5bb6\u505c\u7559\u5728UI\u754c\u9762\u89e6\u53d1\u63d2\u5c4f\u5e7f\u544a\u673a\u5236\u7684\u65f6\u95f4cd", "valueType": "STRING"}, "medal_rank_config": {"defaultValue": {"value": "{\"OneCycleStageRewards\":[{\"dayOfWeek\":1,\"oneCycle\":4,\"rewardsArr\":[{\"stage\":4,\"coin\":2},{\"stage\":6,\"coin\":2},{\"stage\":8,\"coin\":3},{\"stage\":10,\"coin\":3},{\"stage\":14,\"coin\":4},{\"stage\":18,\"coin\":4},{\"stage\":20,\"coin\":5}]},{\"dayOfWeek\":5,\"oneCycle\":3,\"rewardsArr\":[{\"stage\":4,\"coin\":2},{\"stage\":6,\"coin\":2},{\"stage\":8,\"coin\":3},{\"stage\":10,\"coin\":3},{\"stage\":14,\"coin\":4},{\"stage\":18,\"coin\":4},{\"stage\":20,\"coin\":5}]}],\"MaxAwardRanking\":10,\"AllAwardArr\":[{\"ranking\":1,\"reward\":{\"coin\":100,\"hint\":3}},{\"ranking\":2,\"reward\":{\"coin\":70,\"hint\":2}},{\"ranking\":3,\"reward\":{\"coin\":40,\"hint\":1}},{\"ranking\":4,\"reward\":{\"coin\":20,\"hint\":0}},{\"ranking\":11,\"reward\":{\"coin\":0,\"hint\":0}}],\"RobotArr\":[{\"leastNum\":0,\"weight\":10,\"addStarNumInterval\":{\"left\":20,\"right\":30},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":5}},{\"leastNum\":0,\"weight\":100,\"addStarNumInterval\":{\"left\":15,\"right\":24},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":5}},{\"leastNum\":1,\"weight\":500,\"addStarNumInterval\":{\"left\":10,\"right\":18},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":5}},{\"leastNum\":3,\"weight\":2000,\"addStarNumInterval\":{\"left\":6,\"right\":12},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":5}},{\"leastNum\":10,\"weight\":6000,\"addStarNumInterval\":{\"left\":3,\"right\":7},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":5}},{\"leastNum\":10,\"weight\":5000,\"addStarNumInterval\":{\"left\":1,\"right\":3},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":10}}]}"}, "conditionalValues": {"200level": {"value": "{\"OneCycleStageRewards\":[{\"dayOfWeek\":1,\"oneCycle\":4,\"rewardsArr\":[{\"stage\":4,\"coin\":2},{\"stage\":6,\"coin\":2},{\"stage\":8,\"coin\":3},{\"stage\":10,\"coin\":3},{\"stage\":14,\"coin\":4},{\"stage\":18,\"coin\":4},{\"stage\":20,\"coin\":5}]},{\"dayOfWeek\":5,\"oneCycle\":3,\"rewardsArr\":[{\"stage\":4,\"coin\":2},{\"stage\":6,\"coin\":2},{\"stage\":8,\"coin\":3},{\"stage\":10,\"coin\":3},{\"stage\":14,\"coin\":4},{\"stage\":18,\"coin\":4},{\"stage\":20,\"coin\":5}]}],\"MaxAwardRanking\":10,\"AllAwardArr\":[{\"ranking\":1,\"reward\":{\"coin\":100,\"hint\":3}},{\"ranking\":2,\"reward\":{\"coin\":70,\"hint\":2}},{\"ranking\":3,\"reward\":{\"coin\":40,\"hint\":1}},{\"ranking\":4,\"reward\":{\"coin\":20,\"hint\":0}},{\"ranking\":11,\"reward\":{\"coin\":0,\"hint\":0}}],\"RobotArr\":[{\"leastNum\":1,\"weight\":10,\"addStarNumInterval\":{\"left\":20,\"right\":30},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":5}},{\"leastNum\":1,\"weight\":100,\"addStarNumInterval\":{\"left\":15,\"right\":24},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":5}},{\"leastNum\":1,\"weight\":500,\"addStarNumInterval\":{\"left\":10,\"right\":18},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":5}},{\"leastNum\":5,\"weight\":2000,\"addStarNumInterval\":{\"left\":6,\"right\":12},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":5}},{\"leastNum\":10,\"weight\":6000,\"addStarNumInterval\":{\"left\":3,\"right\":7},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":5}},{\"leastNum\":10,\"weight\":5000,\"addStarNumInterval\":{\"left\":1,\"right\":3},\"addStarInterval\":{\"left\":1,\"right\":1},\"startStarInterval\":{\"left\":1,\"right\":10}}]}"}}, "description": "v3.11.0\u540e\u5f00\u59cb\u4f7f\u7528\uff0c\u5956\u724c\u6392\u884c\u699c\u76f8\u5173\u4e91\u63a7.oneCycle:\u4e00\u4e2a\u5468\u671f\u591a\u5c11\u5929\uff0cMaxAwardRanking:\u6700\u5927\u5956\u52b1\u7684\u6392\u540d\uff0cAllAwardArr\uff1a\u7ed3\u7b97\u7684\u5956\u52b1\u533a\u95f4\u53ca\u91d1\u5e01\uff0cRobotArr\u673a\u5668\u4eba\u7684\u76f8\u5173\u914d\u7f6e\uff0cleastNum\u8be5\u7c7b\u578b\u673a\u5668\u4eba\u7684\u6700\u5c11\u6570\u91cf\uff0cweight\u8be5\u7c7b\u578b\u673a\u5668\u4eba\u6743\u91cd\uff0caddStarNumInterval\u6bcf\u5929\u589e\u52a0\u661f\u661f\u6b21\u6570\u7684\u533a\u95f4\uff0caddStarInterval\uff0c\u6bcf\u6b21\u589e\u52a0\u661f\u661f\u6570\u91cf\u7684\u533a\u95f4\uff0cstartStarInterval\u661f\u661f\u521d\u59cb\u503c\u7684\u533a\u95f4,rewardsArr :\u9636\u6bb5\u5956\u52b1\u7684\u914d\u7f6e", "valueType": "JSON"}, "level_show_share": {"defaultValue": {"value": "30"}, "description": "\u5173\u5361\u591a\u5c11\u5173\u663e\u793ashare\u5206\u4eab\u6309\u94ae", "valueType": "NUMBER"}, "chest_config": {"defaultValue": {"value": "{\"chestArr\":[{\"levelCount\":5,\"baseCoins\":5,\"allMul\":[5,4,3,2]},{\"levelCount\":5,\"baseCoins\":5,\"allMul\":[5,4,3,2]},{\"levelCount\":5,\"baseCoins\":5,\"allMul\":[5,4,3,2]},{\"levelCount\":5,\"baseCoins\":5,\"allMul\":[5,4,3,2]}]}"}, "description": "2.12.0\u7248\u672c\u4e4b\u524d\u8001\u7248\u672c\u5b9d\u7bb1\u7684\u914d\u7f6e\u6570\u636e", "valueType": "JSON"}, "star_showdown_config": {"defaultValue": {"value": "{\"oneCycle\":3,\"MaxAwardRanking\":10,\"AllAwardArr\":[{\"ranking\":1,\"coin\":100},{\"ranking\":2,\"coin\":70},{\"ranking\":3,\"coin\":40},{\"ranking\":4,\"coin\":20},{\"ranking\":11,\"coin\":0}],\"RobotArr\":[{\"leastNum\":0,\"weight\":10,\"addStarNumInterval\":{\"left\":20,\"right\":30},\"addStarInterval\":{\"left\":3,\"right\":3},\"startStarInterval\":{\"left\":1,\"right\":15}},{\"leastNum\":0,\"weight\":100,\"addStarNumInterval\":{\"left\":15,\"right\":25},\"addStarInterval\":{\"left\":2,\"right\":3},\"startStarInterval\":{\"left\":1,\"right\":15}},{\"leastNum\":1,\"weight\":500,\"addStarNumInterval\":{\"left\":12,\"right\":20},\"addStarInterval\":{\"left\":2,\"right\":3},\"startStarInterval\":{\"left\":1,\"right\":15}},{\"leastNum\":3,\"weight\":2000,\"addStarNumInterval\":{\"left\":6,\"right\":12},\"addStarInterval\":{\"left\":1,\"right\":3},\"startStarInterval\":{\"left\":1,\"right\":15}},{\"leastNum\":10,\"weight\":6000,\"addStarNumInterval\":{\"left\":3,\"right\":7},\"addStarInterval\":{\"left\":1,\"right\":3},\"startStarInterval\":{\"left\":1,\"right\":15}},{\"leastNum\":10,\"weight\":5000,\"addStarNumInterval\":{\"left\":1,\"right\":3},\"addStarInterval\":{\"left\":1,\"right\":2},\"startStarInterval\":{\"left\":1,\"right\":30}}]}"}, "conditionalValues": {"200level": {"value": "{\"oneCycle\":3,\"MaxAwardRanking\":10,\"AllAwardArr\":[{\"ranking\":1,\"coin\":100},{\"ranking\":2,\"coin\":70},{\"ranking\":3,\"coin\":40},{\"ranking\":4,\"coin\":20},{\"ranking\":11,\"coin\":0}],\"RobotArr\":[{\"leastNum\":1,\"weight\":10,\"addStarNumInterval\":{\"left\":20,\"right\":30},\"addStarInterval\":{\"left\":3,\"right\":3},\"startStarInterval\":{\"left\":1,\"right\":15}},{\"leastNum\":1,\"weight\":100,\"addStarNumInterval\":{\"left\":15,\"right\":25},\"addStarInterval\":{\"left\":2,\"right\":3},\"startStarInterval\":{\"left\":1,\"right\":15}},{\"leastNum\":1,\"weight\":500,\"addStarNumInterval\":{\"left\":12,\"right\":20},\"addStarInterval\":{\"left\":2,\"right\":3},\"startStarInterval\":{\"left\":1,\"right\":15}},{\"leastNum\":5,\"weight\":2000,\"addStarNumInterval\":{\"left\":6,\"right\":12},\"addStarInterval\":{\"left\":1,\"right\":3},\"startStarInterval\":{\"left\":1,\"right\":15}},{\"leastNum\":10,\"weight\":6000,\"addStarNumInterval\":{\"left\":3,\"right\":7},\"addStarInterval\":{\"left\":1,\"right\":3},\"startStarInterval\":{\"left\":1,\"right\":15}},{\"leastNum\":10,\"weight\":5000,\"addStarNumInterval\":{\"left\":1,\"right\":3},\"addStarInterval\":{\"left\":1,\"right\":2},\"startStarInterval\":{\"left\":1,\"right\":30}}]}"}}, "description": "\u661f\u661f\u5468\u699c\u673a\u5668\u4eba\u4e91\u63a7\uff0coneCycle:\u4e00\u4e2a\u5468\u671f\u591a\u5c11\u5929\uff0cMaxAwardRanking:\u6700\u5927\u5956\u52b1\u7684\u6392\u540d\uff0cAllAwardArr\uff1a\u7ed3\u7b97\u7684\u5956\u52b1\u533a\u95f4\u53ca\u91d1\u5e01\uff0cRobotArr\u673a\u5668\u4eba\u7684\u76f8\u5173\u914d\u7f6e\uff0cleastNum\u8be5\u7c7b\u578b\u673a\u5668\u4eba\u7684\u6700\u5c11\u6570\u91cf\uff0cweight\u8be5\u7c7b\u578b\u673a\u5668\u4eba\u6743\u91cd\uff0caddStarNumInterval\u6bcf\u5929\u589e\u52a0\u661f\u661f\u6b21\u6570\u7684\u533a\u95f4\uff0caddStarInterval\uff0c\u6bcf\u6b21\u589e\u52a0\u661f\u661f\u6570\u91cf\u7684\u533a\u95f4\uff0cstartStarInterval\u661f\u661f\u521d\u59cb\u503c\u7684\u533a\u95f4", "valueType": "JSON"}, "DailyChallengeUpDate": {"defaultValue": {"value": "V3.3"}, "description": "\u6bcf\u65e5\u6311\u6218\u66f4\u65b0", "valueType": "STRING"}, "postcard_test": {"defaultValue": {"value": "2"}, "valueType": "STRING"}, "level_score_remote_config": {"defaultValue": {"value": "{\"oneDiffTime\":15,\"minErrorNum\":3,\"isShowLevelTime\":false,\"isShowGuideRule\":false,\"starRuleArr\":[{\"type\":0,\"value\":0},{\"type\":1,\"value\":15},{\"type\":3,\"value\":1}]}"}, "description": "\u5173\u5361\u4e09\u661f\u4e91\u63a7\uff0coneDiffTime\uff1a\u627e\u5230\u4e00\u4e2a\u4e0d\u540c\u70b9\u7684\u65f6\u95f4\uff0cminErrorNum\uff1a\u9519\u8bef\u4e0d\u8d85\u8fc7\u6b21\u6570\u3002isShowLevelTime\uff1a\u662f\u5426\u663e\u793a\u5173\u5361\u5185\u8ba1\u65f6\u3002isShowGuideRule\uff1a\u662f\u5426\u663e\u793a\u5f15\u5bfc\u9875\u89c4\u5219\u3002 \u89c4\u5219\u6570\u7ec4\u6309\u7c7b\u578b\u533a\u5206/// 0,\u89c4\u5219\u662f\u662f\u5426\u901a\u5173 /// 1,\u89c4\u5219\u662f\u662f\u65f6\u95f4\u9650\u5236\u591a\u5c11\u79d2\uff0c\u586b\u6574\u6570 /// 2,\u89c4\u5219\u662f\u70b9\u9519\u6b21\u6570\u5c11\u4e8e\u591a\u5c11\u6b21\uff0c\u586b\u6574\u6570 /// 3,\u89c4\u5219\u662fcombo\u7684\u767e\u5206\u6bd4", "valueType": "JSON"}, "gig_bag_remote_config": {"defaultValue": {"value": "{\"gift_package_switch\":true,\"gig_bags\":[{\"code\":\"iapc_giftpack_099\",\"magnifier_count\":1,\"hourglasses_count\":1,\"battery_count\":1,\"compass_count\":1,\"discounts\":60,\"level\":1},{\"code\":\"iapc_giftpack_499\",\"magnifier_count\":3,\"hourglasses_count\":3,\"battery_count\":3,\"compass_count\":3,\"discounts\":60,\"level\":2},{\"code\":\"iapc_giftpack_999\",\"magnifier_count\":6,\"hourglasses_count\":6,\"battery_count\":6,\"compass_count\":6,\"discounts\":60,\"level\":3},{\"code\":\"iapc_giftpack_1999\",\"magnifier_count\":12,\"hourglasses_count\":12,\"battery_count\":12,\"compass_count\":12,\"discounts\":60,\"level\":4},{\"code\":\"iapc_giftpack_4999\",\"magnifier_count\":30,\"hourglasses_count\":30,\"battery_count\":30,\"compass_count\":30,\"discounts\":60,\"level\":5},{\"code\":\"iapc_giftpack_9999\",\"magnifier_count\":60,\"hourglasses_count\":60,\"battery_count\":60,\"compass_count\":60,\"discounts\":60,\"level\":6}],\"refresh_time\":48,\"open_function_level\":0,\"pop_circulate_lim\":3,\"recover_time\":14,\"gift_pop_first\":155,\"gift_pop_circulate\":155,\"gift_pop_circulate_match\":75}"}, "description": "\u793c\u5305\u4e91\u63a7", "valueType": "JSON"}}, "version": {"versionNumber": "5597", "updateTime": "2025-03-04T07:03:54.168414Z", "updateUser": {"email": "firebase-adminsdk-u80vp@dof2-b9070.iam.gserviceaccount.com"}, "updateOrigin": "REST_API", "updateType": "INCREMENTAL_UPDATE"}, "parameterGroups": {"postcard": {"parameters": {"postcard_event": {"defaultValue": {"value": "[{\"assetConfig\": {\"name\": \"spring_2023\", \"a_g\": \"1681464536289278\", \"i_g\": \"1681464543524931\"}, \"startData\": \"20230417T090000\", \"endData\": \"20230501T090000\"}, {\"assetConfig\": {\"name\": \"mother_2023\", \"a_g\": \"1682567146539133\", \"i_g\": \"1682567148889932\"}, \"startData\": \"20230501T090500\", \"endData\": \"20230515T090000\"}, {\"assetConfig\": {\"name\": \"cat_2023\", \"a_g\": \"1683868847123744\", \"i_g\": \"1683868858588831\"}, \"startData\": \"20230515T090500\", \"endData\": \"20230601T090000\"}, {\"assetConfig\": {\"name\": \"amusement_2023\", \"a_g\": \"1685432523833622\", \"i_g\": \"1685432530640822\"}, \"startData\": \"20230601T090500\", \"endData\": \"20230616T090000\"}, {\"assetConfig\": {\"name\": \"father_2023\", \"a_g\": \"1686800454479668\", \"i_g\": \"1686800457296030\"}, \"startData\": \"20230616T090500\", \"endData\": \"20230630T090000\"}, {\"assetConfig\": {\"name\": \"chocolate_2023\", \"a_g\": \"1687770977179972\", \"i_g\": \"1687770978913511\"}, \"startData\": \"20230630T090500\", \"endData\": \"20230717T090000\"}, {\"assetConfig\": {\"name\": \"cosmos_20230717\", \"a_g\": \"1689152653855730\", \"i_g\": \"1689152699696012\"}, \"startData\": \"20230717T090500\", \"endData\": \"20230801T090000\"}, {\"assetConfig\": {\"name\": \"dog_20230801\", \"a_g\": \"1716344678510377\", \"i_g\": \"1716344681037088\"}, \"startData\": \"20230801T090500\", \"endData\": \"20230817T090000\"}, {\"assetConfig\": {\"name\": \"campus_20230817\", \"a_g\": \"1716344781440056\", \"i_g\": \"1716344792274525\"}, \"startData\": \"20230817T090500\", \"endData\": \"20230901T090000\"}, {\"assetConfig\": {\"name\": \"tomato_20230901\", \"a_g\": \"1716344896701279\", \"i_g\": \"1716344902559355\"}, \"startData\": \"20230901T090500\", \"endData\": \"20230915T090000\"}, {\"assetConfig\": {\"name\": \"undersea_20230915\", \"a_g\": \"1716344991895340\", \"i_g\": \"1716344996942957\"}, \"startData\": \"20230915T090500\", \"endData\": \"20231002T090000\"}, {\"assetConfig\": {\"name\": \"balloon_20231002\", \"a_g\": \"1716345097599429\", \"i_g\": \"1716345106791794\"}, \"startData\": \"20231002T090500\", \"endData\": \"20231016T090000\"}, {\"assetConfig\": {\"name\": \"halloween_20231016\", \"a_g\": \"1716345298209452\", \"i_g\": \"1716345306419007\"}, \"startData\": \"20231016T090500\", \"endData\": \"20231101T090000\"}, {\"assetConfig\": {\"name\": \"snowy_20231101\", \"a_g\": \"1716345408171634\", \"i_g\": \"1716345419950680\"}, \"startData\": \"20231101T090500\", \"endData\": \"20231116T090000\"}, {\"assetConfig\": {\"name\": \"thanksgiving_20231116\", \"a_g\": \"1716346771611981\", \"i_g\": \"1716346779871495\"}, \"startData\": \"20231116T090500\", \"endData\": \"20231201T090000\"}, {\"assetConfig\": {\"name\": \"cartoon_20231201\", \"a_g\": \"1716280629551288\", \"i_g\": \"1716280631380169\"}, \"startData\": \"20231201T090500\", \"endData\": \"20231215T090000\"}, {\"assetConfig\": {\"name\": \"christmas_20231215\", \"a_g\": \"1716280882292625\", \"i_g\": \"1716280884076546\"}, \"startData\": \"20231215T090500\", \"endData\": \"20231229T090000\"}, {\"assetConfig\": {\"name\": \"newyear24_1229\", \"a_g\": \"1716280963563936\", \"i_g\": \"1716280965361998\"}, \"startData\": \"20231229T090500\", \"endData\": \"20240115T090000\"}, {\"assetConfig\": {\"name\": \"teatime24_0115\", \"a_g\": \"1716281050130859\", \"i_g\": \"1716281051691039\"}, \"startData\": \"20240115T090500\", \"endData\": \"20240130T090000\"}, {\"assetConfig\": {\"name\": \"valentine24_0130\", \"a_g\": \"1716281129693131\", \"i_g\": \"1716281131334524\"}, \"startData\": \"20240130T090500\", \"endData\": \"20240215T090000\"}, {\"assetConfig\": {\"name\": \"vintage24_0215\", \"a_g\": \"1716281214652830\", \"i_g\": \"1716281216462648\"}, \"startData\": \"20240215T090500\", \"endData\": \"20240229T090000\"}, {\"assetConfig\": {\"name\": \"womensday24_0229\", \"a_g\": \"1716281295454713\", \"i_g\": \"1716281297163488\"}, \"startData\": \"20240229T090500\", \"endData\": \"20240315T090000\"}, {\"assetConfig\": {\"name\": \"stpatrick24_0315\", \"a_g\": \"1716281382500210\", \"i_g\": \"1716281384569285\"}, \"startData\": \"20240315T090500\", \"endData\": \"20240329T090000\"}, {\"assetConfig\": {\"name\": \"easter24_0329\", \"a_g\": \"1716281471545662\", \"i_g\": \"1716281473019180\"}, \"startData\": \"20240329T090500\", \"endData\": \"20240415T090000\"}, {\"assetConfig\": {\"name\": \"yarnart24_0415\", \"a_g\": \"1716347311401783\", \"i_g\": \"1716347313257476\"}, \"startData\": \"20240415T090500\", \"endData\": \"20240430T090000\"}, {\"assetConfig\": {\"name\": \"mothersday24_0430\", \"a_g\": \"1714037447784436\", \"i_g\": \"1714037449944919\"}, \"startData\": \"20240430T090500\", \"endData\": \"20240515T090000\"}, {\"assetConfig\": {\"name\": \"gardening24_0515\", \"a_g\": \"1715761139647770\", \"i_g\": \"1715761141497838\"}, \"startData\": \"20240515T090500\", \"endData\": \"20240531T090000\"}, {\"assetConfig\": {\"name\": \"mybaby24_0531\", \"a_g\": \"1716977691985556\", \"i_g\": \"1716977693857905\"}, \"startData\": \"20240531T090500\", \"endData\": \"20240617T090000\"}, {\"assetConfig\": {\"name\": \"mermaid24_0617\", \"a_g\": \"1718362232485229\", \"i_g\": \"1718362238542421\"}, \"startData\": \"20240617T090500\", \"endData\": \"20240703T090000\"}, {\"assetConfig\": {\"name\": \"travel24_0703\", \"a_g\": \"1719397691324669\", \"i_g\": \"1719397694907457\"}, \"startData\": \"20240703T090500\", \"endData\": \"20240718T090000\"}, {\"assetConfig\": {\"name\": \"animal24_0718\", \"a_g\": \"1721549436855947\", \"i_g\": \"1721549453064911\"}, \"startData\": \"20240718T090500\", \"endData\": \"20240802T090000\"}, {\"assetConfig\": {\"name\": \"fireworks24_0802\", \"a_g\": \"1722496046072771\", \"i_g\": \"1722496048222318\"}, \"startData\": \"20240802T090500\", \"endData\": \"20240818T090000\"}, {\"assetConfig\": {\"name\": \"summer24_0818\", \"a_g\": \"1723716537899751\", \"i_g\": \"1723716540038985\"}, \"startData\": \"20240818T090500\", \"endData\": \"20240902T090000\"}, {\"assetConfig\": {\"name\": \"fruit24_0902\", \"a_g\": \"1725011816056544\", \"i_g\": \"1725011818259928\"}, \"startData\": \"20240902T090500\", \"endData\": \"20240917T090000\"}, {\"assetConfig\": {\"name\": \"museum24_0917\", \"a_g\": \"1726134614660423\", \"i_g\": \"1726134616759142\"}, \"startData\": \"20240917T090500\", \"endData\": \"20241002T090000\"}, {\"assetConfig\": {\"name\": \"autumn24_1002\", \"a_g\": \"1727146321354587\", \"i_g\": \"1727146323601510\"}, \"startData\": \"20241002T090500\", \"endData\": \"20241017T090000\"}, {\"assetConfig\": {\"name\": \"halloween24_1017\", \"a_g\": \"1727146346486907\", \"i_g\": \"1727146349437234\"}, \"startData\": \"20241017T090500\", \"endData\": \"20241102T090000\"}, {\"assetConfig\": {\"name\": \"casual24_1102\", \"a_g\": \"1727146369590636\", \"i_g\": \"1727146371801678\"}, \"startData\": \"20241102T090500\", \"endData\": \"20241118T090000\"}, {\"assetConfig\": {\"name\": \"thanksgiving24_1118\", \"a_g\": \"1727146395025588\", \"i_g\": \"1727146397402264\"}, \"startData\": \"20241118T090500\", \"endData\": \"20241202T090000\"}, {\"assetConfig\": {\"name\": \"winter24_1202\", \"a_g\": \"1727146422144275\", \"i_g\": \"1727146424311165\"}, \"startData\": \"20241202T090500\", \"endData\": \"20241217T090000\"}, {\"assetConfig\": {\"name\": \"christmas24_1217\", \"a_g\": \"1727146448170861\", \"i_g\": \"1727146450325820\"}, \"startData\": \"20241217T090500\", \"endData\": \"20250101T090000\"}, {\"assetConfig\": {\"name\": \"newyear25\", \"a_g\": \"1735092972198040\", \"i_g\": \"1735092974405429\"}, \"startData\": \"20250101T090500\", \"endData\": \"20250119T235959\"}, {\"assetConfig\": {\"name\": \"lunanewyear25\", \"a_g\": \"1735093018395811\", \"i_g\": \"1735093020716343\"}, \"startData\": \"20250120T000000\", \"endData\": \"20250202T235959\"}, {\"assetConfig\": {\"name\": \"valentine25\", \"a_g\": \"1735093042560669\", \"i_g\": \"1735093044788407\"}, \"startData\": \"20250203T000000\", \"endData\": \"20250216T235959\"}, {\"assetConfig\": {\"name\": \"magical25\", \"a_g\": \"1735093065823708\", \"i_g\": \"1735093068031694\"}, \"startData\": \"20250217T000000\", \"endData\": \"20250302T235959\"}, {\"assetConfig\": {\"name\": \"womensday25\", \"a_g\": \"1739353607612095\", \"i_g\": \"1739353609724385\"}, \"startData\": \"20250303T000000\", \"endData\": \"20250316T235959\"}, {\"assetConfig\": {\"name\": \"picnic25\", \"a_g\": \"1739353632336778\", \"i_g\": \"1739353634441158\"}, \"startData\": \"20250317T000000\", \"endData\": \"20250330T235959\"}, {\"assetConfig\": {\"name\": \"easter25\", \"a_g\": \"1739353656600738\", \"i_g\": \"1739353658700032\"}, \"startData\": \"20250331T000000\", \"endData\": \"20250413T235959\"}, {\"assetConfig\": {\"name\": \"worldart25\", \"a_g\": \"1739353679331632\", \"i_g\": \"1739353681454299\"}, \"startData\": \"20250414T000000\", \"endData\": \"20250427T235959\"}]"}, "valueType": "JSON"}, "postcard_event_test": {"defaultValue": {"value": "[{\"assetConfig\": {\"name\": \"spring_2023\", \"a_g\": \"1681464536289278\", \"i_g\": \"1681464543524931\"}, \"startData\": \"20230417T090000\", \"endData\": \"20230501T090000\"}, {\"assetConfig\": {\"name\": \"mother_2023\", \"a_g\": \"1682567146539133\", \"i_g\": \"1682567148889932\"}, \"startData\": \"20230501T090500\", \"endData\": \"20230515T090000\"}, {\"assetConfig\": {\"name\": \"cat_2023\", \"a_g\": \"1683868847123744\", \"i_g\": \"1683868858588831\"}, \"startData\": \"20230515T090500\", \"endData\": \"20230601T090000\"}, {\"assetConfig\": {\"name\": \"amusement_2023\", \"a_g\": \"1685432523833622\", \"i_g\": \"1685432530640822\"}, \"startData\": \"20230601T090500\", \"endData\": \"20230616T090000\"}, {\"assetConfig\": {\"name\": \"father_2023\", \"a_g\": \"1686800454479668\", \"i_g\": \"1686800457296030\"}, \"startData\": \"20230616T090500\", \"endData\": \"20230630T090000\"}, {\"assetConfig\": {\"name\": \"chocolate_2023\", \"a_g\": \"1687770977179972\", \"i_g\": \"1687770978913511\"}, \"startData\": \"20230630T090500\", \"endData\": \"20230717T090000\"}, {\"assetConfig\": {\"name\": \"cosmos_20230717\", \"a_g\": \"1689152653855730\", \"i_g\": \"1689152699696012\"}, \"startData\": \"20230717T090500\", \"endData\": \"20230801T090000\"}, {\"assetConfig\": {\"name\": \"dog_20230801\", \"a_g\": \"1716344678510377\", \"i_g\": \"1716344681037088\"}, \"startData\": \"20230801T090500\", \"endData\": \"20230817T090000\"}, {\"assetConfig\": {\"name\": \"campus_20230817\", \"a_g\": \"1716344781440056\", \"i_g\": \"1716344792274525\"}, \"startData\": \"20230817T090500\", \"endData\": \"20230901T090000\"}, {\"assetConfig\": {\"name\": \"tomato_20230901\", \"a_g\": \"1716344896701279\", \"i_g\": \"1716344902559355\"}, \"startData\": \"20230901T090500\", \"endData\": \"20230915T090000\"}, {\"assetConfig\": {\"name\": \"undersea_20230915\", \"a_g\": \"1716344991895340\", \"i_g\": \"1716344996942957\"}, \"startData\": \"20230915T090500\", \"endData\": \"20231002T090000\"}, {\"assetConfig\": {\"name\": \"balloon_20231002\", \"a_g\": \"1716345097599429\", \"i_g\": \"1716345106791794\"}, \"startData\": \"20231002T090500\", \"endData\": \"20231016T090000\"}, {\"assetConfig\": {\"name\": \"halloween_20231016\", \"a_g\": \"1716345298209452\", \"i_g\": \"1716345306419007\"}, \"startData\": \"20231016T090500\", \"endData\": \"20231101T090000\"}, {\"assetConfig\": {\"name\": \"snowy_20231101\", \"a_g\": \"1716345408171634\", \"i_g\": \"1716345419950680\"}, \"startData\": \"20231101T090500\", \"endData\": \"20231116T090000\"}, {\"assetConfig\": {\"name\": \"thanksgiving_20231116\", \"a_g\": \"1716346771611981\", \"i_g\": \"1716346779871495\"}, \"startData\": \"20231116T090500\", \"endData\": \"20231201T090000\"}, {\"assetConfig\": {\"name\": \"cartoon_20231201\", \"a_g\": \"1716280629551288\", \"i_g\": \"1716280631380169\"}, \"startData\": \"20231201T090500\", \"endData\": \"20231215T090000\"}, {\"assetConfig\": {\"name\": \"christmas_20231215\", \"a_g\": \"1716280882292625\", \"i_g\": \"1716280884076546\"}, \"startData\": \"20231215T090500\", \"endData\": \"20231229T090000\"}, {\"assetConfig\": {\"name\": \"newyear24_1229\", \"a_g\": \"1716280963563936\", \"i_g\": \"1716280965361998\"}, \"startData\": \"20231229T090500\", \"endData\": \"20240115T090000\"}, {\"assetConfig\": {\"name\": \"teatime24_0115\", \"a_g\": \"1716281050130859\", \"i_g\": \"1716281051691039\"}, \"startData\": \"20240115T090500\", \"endData\": \"20240130T090000\"}, {\"assetConfig\": {\"name\": \"valentine24_0130\", \"a_g\": \"1716281129693131\", \"i_g\": \"1716281131334524\"}, \"startData\": \"20240130T090500\", \"endData\": \"20240215T090000\"}, {\"assetConfig\": {\"name\": \"vintage24_0215\", \"a_g\": \"1716281214652830\", \"i_g\": \"1716281216462648\"}, \"startData\": \"20240215T090500\", \"endData\": \"20240229T090000\"}, {\"assetConfig\": {\"name\": \"womensday24_0229\", \"a_g\": \"1716281295454713\", \"i_g\": \"1716281297163488\"}, \"startData\": \"20240229T090500\", \"endData\": \"20240315T090000\"}, {\"assetConfig\": {\"name\": \"stpatrick24_0315\", \"a_g\": \"1716281382500210\", \"i_g\": \"1716281384569285\"}, \"startData\": \"20240315T090500\", \"endData\": \"20240329T090000\"}, {\"assetConfig\": {\"name\": \"easter24_0329\", \"a_g\": \"1716281471545662\", \"i_g\": \"1716281473019180\"}, \"startData\": \"20240329T090500\", \"endData\": \"20240415T090000\"}, {\"assetConfig\": {\"name\": \"yarnart24_0415\", \"a_g\": \"1716347311401783\", \"i_g\": \"1716347313257476\"}, \"startData\": \"20240415T090500\", \"endData\": \"20240430T090000\"}, {\"assetConfig\": {\"name\": \"mothersday24_0430\", \"a_g\": \"1714037447784436\", \"i_g\": \"1714037449944919\"}, \"startData\": \"20240430T090500\", \"endData\": \"20240515T090000\"}, {\"assetConfig\": {\"name\": \"gardening24_0515\", \"a_g\": \"1715761139647770\", \"i_g\": \"1715761141497838\"}, \"startData\": \"20240515T090500\", \"endData\": \"20240531T090000\"}, {\"assetConfig\": {\"name\": \"mybaby24_0531\", \"a_g\": \"1716977691985556\", \"i_g\": \"1716977693857905\"}, \"startData\": \"20240531T090500\", \"endData\": \"20240617T090000\"}, {\"assetConfig\": {\"name\": \"mermaid24_0617\", \"a_g\": \"1718362232485229\", \"i_g\": \"1718362238542421\"}, \"startData\": \"20240617T090500\", \"endData\": \"20240703T090000\"}, {\"assetConfig\": {\"name\": \"travel24_0703\", \"a_g\": \"1719397691324669\", \"i_g\": \"1719397694907457\"}, \"startData\": \"20240703T090500\", \"endData\": \"20240718T090000\"}, {\"assetConfig\": {\"name\": \"animal24_0718\", \"a_g\": \"1721549436855947\", \"i_g\": \"1721549453064911\"}, \"startData\": \"20240718T090500\", \"endData\": \"20240802T090000\"}, {\"assetConfig\": {\"name\": \"fireworks24_0802\", \"a_g\": \"1722496046072771\", \"i_g\": \"1722496048222318\"}, \"startData\": \"20240802T090500\", \"endData\": \"20240818T090000\"}, {\"assetConfig\": {\"name\": \"summer24_0818\", \"a_g\": \"1723716537899751\", \"i_g\": \"1723716540038985\"}, \"startData\": \"20240818T090500\", \"endData\": \"20240902T090000\"}, {\"assetConfig\": {\"name\": \"fruit24_0902\", \"a_g\": \"1725011816056544\", \"i_g\": \"1725011818259928\"}, \"startData\": \"20240902T090500\", \"endData\": \"20240917T090000\"}, {\"assetConfig\": {\"name\": \"museum24_0917\", \"a_g\": \"1726134614660423\", \"i_g\": \"1726134616759142\"}, \"startData\": \"20240917T090500\", \"endData\": \"20241002T090000\"}, {\"assetConfig\": {\"name\": \"autumn24_1002\", \"a_g\": \"1727146321354587\", \"i_g\": \"1727146323601510\"}, \"startData\": \"20241002T090500\", \"endData\": \"20241017T090000\"}, {\"assetConfig\": {\"name\": \"halloween24_1017\", \"a_g\": \"1727146346486907\", \"i_g\": \"1727146349437234\"}, \"startData\": \"20241017T090500\", \"endData\": \"20241102T090000\"}, {\"assetConfig\": {\"name\": \"casual24_1102\", \"a_g\": \"1727146369590636\", \"i_g\": \"1727146371801678\"}, \"startData\": \"20241102T090500\", \"endData\": \"20241118T090000\"}, {\"assetConfig\": {\"name\": \"thanksgiving24_1118\", \"a_g\": \"1727146395025588\", \"i_g\": \"1727146397402264\"}, \"startData\": \"20241118T090500\", \"endData\": \"20241202T090000\"}, {\"assetConfig\": {\"name\": \"winter24_1202\", \"a_g\": \"1727146422144275\", \"i_g\": \"1727146424311165\"}, \"startData\": \"20241202T090500\", \"endData\": \"20241217T090000\"}, {\"assetConfig\": {\"name\": \"christmas24_1217\", \"a_g\": \"1727146448170861\", \"i_g\": \"1727146450325820\"}, \"startData\": \"20241217T090500\", \"endData\": \"20250101T090000\"}, {\"assetConfig\": {\"name\": \"newyear25\", \"a_g\": \"1735092972198040\", \"i_g\": \"1735092974405429\"}, \"startData\": \"20250101T090500\", \"endData\": \"20250119T235959\"}, {\"assetConfig\": {\"name\": \"lunanewyear25\", \"a_g\": \"1735093018395811\", \"i_g\": \"1735093020716343\"}, \"startData\": \"20250120T000000\", \"endData\": \"20250202T235959\"}, {\"assetConfig\": {\"name\": \"valentine25\", \"a_g\": \"1735093042560669\", \"i_g\": \"1735093044788407\"}, \"startData\": \"20250203T000000\", \"endData\": \"20250216T235959\"}, {\"assetConfig\": {\"name\": \"magical25\", \"a_g\": \"1735093065823708\", \"i_g\": \"1735093068031694\"}, \"startData\": \"20250217T000000\", \"endData\": \"20250302T235959\"}, {\"assetConfig\": {\"name\": \"womensday25\", \"a_g\": \"1739353607612095\", \"i_g\": \"1739353609724385\"}, \"startData\": \"20250303T000000\", \"endData\": \"20250316T235959\"}, {\"assetConfig\": {\"name\": \"picnic25\", \"a_g\": \"1739353632336778\", \"i_g\": \"1739353634441158\"}, \"startData\": \"20250317T000000\", \"endData\": \"20250330T235959\"}, {\"assetConfig\": {\"name\": \"easter25\", \"a_g\": \"1739353656600738\", \"i_g\": \"1739353658700032\"}, \"startData\": \"20250331T000000\", \"endData\": \"20250413T235959\"}, {\"assetConfig\": {\"name\": \"worldart25\", \"a_g\": \"1739353679331632\", \"i_g\": \"1739353681454299\"}, \"startData\": \"20250414T000000\", \"endData\": \"20250427T235959\"}]"}, "valueType": "JSON"}, "add_time": {"defaultValue": {"value": "0"}, "description": "\u6839\u636e\u70b9\u51fb\u9519\u8bef\u6b21\u6570\uff0c\u6bcf\u6b21\u591a\u51cf\u5c11\u7684\u65f6\u95f4", "valueType": "STRING"}, "base_time": {"defaultValue": {"value": "10"}, "conditionalValues": {"ios": {"value": "10"}}, "description": "\u6bcf\u6b21\u70b9\u51fb\u9519\u8bef\u8981\u51cf\u5c11\u7684\u65f6\u95f4", "valueType": "STRING"}, "event_add_time": {"defaultValue": {"value": "60"}, "description": "\u6d3b\u52a8\u5173\u5361\uff0c\u5931\u8d25\u540e\u9700\u8981\u52a0\u7684\u65f6\u95f4", "valueType": "STRING"}, "event_start_count_down_time": {"defaultValue": {"value": "180"}, "conditionalValues": {"ios": {"value": "180"}}, "description": "\u6d3b\u52a8\u5173\u5361\u5185\u7684\u7684\u5f00\u59cb\u8ba1\u65f6\u65f6\u95f4", "valueType": "NUMBER"}, "event_level_difficulty": {"defaultValue": {"value": "{\"_1_point_low\":5,\"_1_point_hight\":6,\"_2_point_low\":7,\"_2_point_hight\":8,\"_3_point_low\":9,\"_3_point_hight\":10,\"_4_point_low\":-1,\"_4_point_hight\":-1,\"_5_point_low\":-1,\"_5_point_hight\":-1,\"_1_time_low\":0,\"_1_time_hight\":30,\"_2_time_low\":31,\"_2_time_hight\":60,\"_3_time_low\":31,\"_3_time_hight\":60,\"_4_time_low\":91,\"_4_time_hight\":120,\"_5_time_low\":121,\"_5_time_hight\":65536}"}, "description": "\u6d3b\u52a8\u96be\u5ea6\u914d\u7f6e", "valueType": "JSON"}, "event_is_open_time_mod": {"defaultValue": {"value": "true"}, "description": "\u63a7\u5236\u6d3b\u52a8\u7684\u8ba1\u65f6\u6a21\u5f0f\u662f\u5426\u6253\u5f00", "valueType": "BOOLEAN"}, "postcard_remote_config": {"defaultValue": {"value": "{\"postcard_arr\":[{\"unlcok_debris\":1,\"level_count\":25,\"size\":5,\"PostcardChest\":[{\"chest_level\":0,\"all_index\":[0],\"coins\":2},{\"chest_level\":0,\"all_index\":[6],\"coins\":2},{\"chest_level\":1,\"all_index\":[12],\"coins\":3},{\"chest_level\":0,\"all_index\":[18],\"coins\":2},{\"chest_level\":0,\"all_index\":[24],\"coins\":2}]},{\"unlcok_debris\":2,\"level_count\":36,\"size\":6,\"PostcardChest\":[{\"chest_level\":1,\"all_index\":[0],\"coins\":3},{\"chest_level\":1,\"all_index\":[7],\"coins\":3},{\"chest_level\":2,\"all_index\":[14],\"coins\":4},{\"chest_level\":1,\"all_index\":[21],\"coins\":3},{\"chest_level\":1,\"all_index\":[28],\"coins\":3},{\"chest_level\":1,\"all_index\":[35],\"coins\":3}]},{\"unlcok_debris\":3,\"level_count\":49,\"size\":7,\"PostcardChest\":[{\"chest_level\":2,\"all_index\":[0],\"coins\":4},{\"chest_level\":2,\"all_index\":[8],\"coins\":4},{\"chest_level\":2,\"all_index\":[16],\"coins\":4},{\"chest_level\":2,\"all_index\":[24],\"coins\":5},{\"chest_level\":2,\"all_index\":[32],\"coins\":4},{\"chest_level\":2,\"all_index\":[40],\"coins\":4},{\"chest_level\":2,\"all_index\":[48],\"coins\":4}]}],\"is_use_main_level\":true,\"main_level_get_debris_num\":1}"}, "description": "is_use_main_level :\u662f\u5426\u4f7f\u7528\u4e3b\u7ebf\u5173\u5361\uff0cmain_level_get_debris_num\u901a\u5173\u4e3b\u7ebf\u5173\u5361\u540e\u83b7\u5f97\u591a\u5c11\u788e\u7247\uff0c \"unlcok_debris\": \u8fd9\u5f20\u660e\u4fe1\u7247\u7684\u683c\u5b50\u9700\u8981\u591a\u5c11\u788e\u7247, \"level_count\": \u8fd9\u5f20\u540d\u7247\u6709\u591a\u5c11\u5173\u5361, \"size\": \u8fd9\u5f20\u660e\u4fe1\u7247\u7684\u884c\u548c\u5217, \"PostcardChest\": chest_level,\u5b9d\u7bb1\u7b49\u7ea7\uff0call_index\u8fd9\u4e2a\u7b49\u7ea7\u7684\u5b9d\u7bb1\u6240\u5728\u683c\u5b50\u7684\u4e0b\u6807\uff0ccoins\uff0c\u8fd9\u79cd\u5b9d\u7bb1\u7684\u91d1\u5e01\uff08\u5b9d\u7bb1\u76f8\u51730\u8d77\u8ba1\u6570\uff09", "valueType": "JSON"}}}, "Level": {"parameters": {"float_unlockmode_pass_value": {"defaultValue": {"value": "1.0"}, "description": "\u89e3\u9501\u4e0b\u4e2a\u5927\u5173\u5361\u901a\u8fc7\u5c0f\u5173\u5361\u6bd4\u4f8b\u6570\u503c", "valueType": "NUMBER"}, "level_end_success_num": {"defaultValue": {"value": "50"}, "description": "\u524d\u591a\u5c11\u5173\u4e0a\u62a5\u5173\u5361\u5b8c\u6210\u4e8b\u4ef6", "valueType": "NUMBER"}, "game_stages_config_debug_url": {"defaultValue": {"value": "https://cdn2.dof.fungame.studio/d2/level_config/debug/GameStagesConfig.json"}, "description": "\u6e38\u620fStage debug\u914d\u7f6eurl", "valueType": "STRING"}, "game_stages_config_url": {"defaultValue": {"value": "https://cdn2.dof.fungame.studio/d2/level_config/release/GameStagesConfig.json"}, "description": "\u6e38\u620fStage\u914d\u7f6eurl", "valueType": "STRING"}, "int_unlockmode_passall_value": {"defaultValue": {"value": "3"}, "description": "\u901a\u8fc7\u6240\u6709\u5173\u5361\u624d\u80fd\u89e3\u9501\u4e0b\u4e2a\u5927\u5173\u5361\u7684\u5927\u5173\u5361\u6570\u503c", "valueType": "NUMBER"}, "find_sound": {"defaultValue": {"value": "A"}, "description": "A-\u5355\u97f3\u9636 B-\u591a\u97f3\u9636", "valueType": "STRING"}, "BG_black": {"defaultValue": {"value": "0.5"}, "description": "\u5173\u5361\u9ed1\u8272\u80cc\u666f(\uff080\u52301\uff09\u5e94\u7528\u5185\u9ed8\u8ba41) \u6570\u5b57\u8868\u793a\u9ed1\u8272\u7684\u7a0b\u5ea6\uff0c\u8d8a\u9760\u8fd10\u8d8a\u9ed1", "valueType": "NUMBER"}, "game_stages_config_url_v170": {"defaultValue": {"value": "https://cdn2.dof.fungame.studio/d2/level_config/release/GameStagesConfig.json"}, "description": "\u6e38\u620f\u4e3b\u9898\u914d\u7f6e", "valueType": "STRING"}, "last_diff_petal_add_time": {"defaultValue": {"value": "30"}, "description": "\u9650\u65f6\u5173\u5361\u6700\u540e\u4e00\u4e2a\u70b9\u4f7f\u7528hint\u589e\u52a0\u591a\u5c11\u79d2", "valueType": "STRING"}, "is_show_level_end_rank_text": {"defaultValue": {"value": "true"}, "description": "\u662f\u5426\u663e\u793a\u7ed3\u7b97\u754c\u9762\u7684\u6392\u884c\u699c\u4fe1\u606f\u7684\u6587\u6848", "valueType": "BOOLEAN"}, "special_config_debug_url": {"defaultValue": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/special_level_debug/special_level_config.json?generation=1713518263318822&alt=media"}, "conditionalValues": {"JP": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/special_level_debug/special_level_config_JP.json?generation=1713518273790152&alt=media"}, "KR": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/special_level_debug/special_level_config_KR.json?generation=1713518284988591&alt=media"}}, "description": "\u7279\u6b8a\u5173\u5361\u7684debug\u914d\u7f6eURL", "valueType": "STRING"}, "special_config_release_url": {"defaultValue": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/special_level_release/special_level_config.json?generation=1712892947591773&alt=media"}, "conditionalValues": {"JP": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/special_level_release/special_level_config_JP.json?generation=1712892953200115&alt=media"}, "KR": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/special_level_release/special_level_config_KR.json?generation=1712892957023055&alt=media"}}, "description": "\u7279\u6b8a\u5173\u5361\u7684release\u914d\u7f6e\u7684URL", "valueType": "STRING"}, "new_game_stages_config_debug_url": {"defaultValue": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/debug/GameStagesConfig.json?generation=1737455877567478&alt=media"}, "conditionalValues": {"less_android_V3.2.0": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/debug/GameStagesConfig.json?generation=1729242641660613&alt=media"}, "less_ios_V3.2.0": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/debug/GameStagesConfig.json?generation=1729242641660613&alt=media"}}, "description": "\u6700\u65b0\u7684debug\u7248\u672c\u7684\u56fd\u5bb6\u914d\u7f6e\u7684URL", "valueType": "STRING"}, "new_game_stages_config_url": {"defaultValue": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/release/GameStagesConfig.json?generation=1737457400475695&alt=media"}, "conditionalValues": {"less_android_V3.2.0": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/release/GameStagesConfig.json?generation=1727233397802957&alt=media"}, "less_ios_V3.2.0": {"value": "https://cdn3-dof.fungame.cloud/d2/level_config_new/release/GameStagesConfig.json?generation=1727233397802957&alt=media"}}, "description": "\u6700\u65b0\u7684\u53d1\u5e03\u7248\u672c\u7684\u6ca1\u6709\u7279\u6b8a\u5173\u5361\u7684\u56fd\u5bb6\u914d\u7f6eURL", "valueType": "STRING"}, "stage_level_default_unlock_count": {"defaultValue": {"value": "20"}, "description": "\u6bcf\u4e2a\u56fd\u5bb6\u521d\u59cb\u89e3\u9501\u7684\u5173\u5361\u6570\u91cf\u7684\u6700\u5927\u503c", "valueType": "STRING"}, "level_default_cache_count": {"defaultValue": {"value": "12"}, "description": "\u4e3b\u7ebf\u5173\u5361\u7f13\u5b58\u6570\u91cf", "valueType": "STRING"}, "special_level_config": {"defaultValue": {"value": "{\"debug\": \"https://cdn3-dof.fungame.cloud/d2/level_config_new/special_level_debug/special_level_config_v3.2.0.json?generation=1733396110485469\", \"release\": \"https://cdn3-dof.fungame.cloud/d2/level_config_new/special_level_release/special_level_config_v3.2.0.json?generation=1733396133887772\"}"}, "description": "\u7279\u6b8a\u5173\u5361\u914d\u7f6e\uff0c\u4e0d\u533a\u5206\u56fd\u5bb6\uff0c\u57283.2.0\u7248\u672c\u4e4b\u540e\uff0c\u53ef\u4ee5\u652f\u630110\u4e2a\u70b9\u4ee5\u4e0a\u5173\u5361", "valueType": "JSON"}, "special_level_config_3_10_0": {"defaultValue": {"value": "{\"debug\": \"https://cdn3-dof.fungame.cloud/d2/level_config_new/special_level_debug/special_level_config_v3.10.0.json?generation=1737110917603542\", \"release\": \"https://cdn3-dof.fungame.cloud/d2/level_config_new/special_level_release/special_level_config_v3.10.0.json?generation=1737110983457149\"}"}, "description": "3.10.0\u4e4b\u540e\u7684\u7279\u6b8a\u5173\u5361\u914d\u7f6e\u3002\u4f7f\u7528ig,ag\u6765\u8282\u7701json\u7684\u7a7a\u95f4", "valueType": "JSON"}}}, "rate_config": {"description": "d2\u8bc4\u5206\u5f39\u7a97\u76f8\u5173\u7684\u53c2\u6570", "parameters": {"app_rater": {"defaultValue": {"value": "{\"gap_days\":1,\"last_pop_gap_days\":7,\"finish_games\":4}"}, "description": "\u6e38\u620f\u8bc4\u5206\u914d\u7f6e", "valueType": "JSON"}, "rate_json_config": {"defaultValue": {"value": "{\n \"ratePlayedLevelCount\": 30,\n \t\"rateA\": 1,\n \t\"rateB\": 2,\n \"numberOfBufferLevels\": 0\n}"}, "description": "d2\u8bc4\u5206\u76f8\u5173\u7684\u914d\u7f6e\uff0cratePlayedLevelCount:\u901a\u5173\u6570\u5c11\u4e8e\u8be5\u6570\u503c\u4e3arateA\u7c7b\u7528\u6237\uff0c\u591a\u4e8e\u4e3arateB\u7c7b\u7528\u6237 rateA,rateB:\u8fde\u7eedn\u6b21\u8bc4\u4e94\u661f\u624d\u5f39\u8c37\u6b4c\u5546\u5e97\u8bc4\u5206\u5f39\u7a97 numberOfBufferLevels: \u89e6\u53d1\u9700\u8981\u5f39\u8c37\u6b4c\u8bc4\u5206\u5f39\u7a97\u6761\u4ef6\u540e\u518d\u901a\u591a\u5c11\u5173\u624d\u771f\u6b63\u5f39\u51fa\u5f39\u7a97", "valueType": "STRING"}}}, "gameguide": {"description": "\u6e38\u620f\u73a9\u6cd5\u5f15\u5bfc", "parameters": {"dc_guide_update_time_config": {"defaultValue": {"value": "20220407T210013"}, "description": "\u6bcf\u65e5\u6311\u6218\u5f15\u5bfc\u66f4\u65b0\u65f6\u95f4", "valueType": "STRING"}, "latest_version": {"defaultValue": {"value": "1.5.1"}, "conditionalValues": {"ios": {"value": "1.6.2"}, "android": {"value": "1.6.1"}}, "description": "\u76ee\u524d\u6700\u65b0\u7684\u9879\u76ee\u7248\u672c\u53f7", "valueType": "STRING"}, "update_guide_frequency": {"defaultValue": {"value": "10"}, "description": "\u66f4\u65b0\u5f39\u7a97\u6bcf\u5929\u5f39\u51fa\u7684\u9891\u7387\u6216\u8005\u6b21\u6570\uff0c\u5927\u4e8e\u7b49\u4e8e10\u5c31\u662f\u4e0d\u9650\u6b21\u6570", "valueType": "STRING"}, "dc_guide_cdn_head": {"defaultValue": {"value": "https://cdn2.dof.fungame.studio"}, "description": "\u6bcf\u65e5\u6311\u6218\u5f15\u5bfc\u5f39\u7a97\u7684CDN\u5934\u90e8", "valueType": "STRING"}}}, "Control Event And DailyChallenge": {"description": "\u63a7\u5236\u6d3b\u52a8\u548c\u6bcf\u65e5\u6311\u6218\u8fd8\u6709\u5173\u5361\u5f39\u7a97\u7684\u4e00\u4e9b\u914d\u7f6e", "parameters": {"is_show_dailychallenge_entrance": {"defaultValue": {"value": "true"}, "description": "\u6bcf\u65e5\u6311\u6218\u6311\u6218\u5165\u53e3\u7684\u663e\u793a\u63a7\u5236,2.16.0\u540e\u505c\u6b62\u4f7f\u7528", "valueType": "BOOLEAN"}, "how_many_levels_show_daily_challenge": {"defaultValue": {"value": "20"}, "description": "\u7b2c\u591a\u5c11\u5173\u6253\u5f00\u6bcf\u65e5\u6311\u6218\u73a9\u6cd5\uff0c2.16.0\u540e\u505c\u6b62\u4f7f\u7528", "valueType": "NUMBER"}, "how_many_levels_show_event": {"defaultValue": {"value": "20"}, "description": "\u7b2c\u591a\u5c11\u5173\u6253\u5f00\u6d3b\u52a8\u73a9\u6cd5\uff0c2.16.0\u540e\u505c\u6b62\u4f7f\u7528", "valueType": "NUMBER"}, "do_not_show_next_btn_before_N_levels": {"defaultValue": {"value": "30"}, "description": "\u5728\u591a\u5c11\u5173\u4e4b\u524d\u7ed3\u7b97\u754c\u9762\u53ea\u663e\u793anext\u6309\u94ae\u4e0d\u663e\u793ahome\uff0c\u76ee\u524d\u6ca1\u7528", "valueType": "NUMBER"}, "do_not_show_special_btn_before_N_levels": {"defaultValue": {"value": "30"}, "description": "\u5728\u591a\u5c11\u5173\u4e4b\u524d\u4e0d\u663e\u793aspecial\u6309\u94ae,\u76ee\u524d\u6ca1\u7528\uff0c\u5f88\u4e45\u6ca1\u7528\u8fc7\u4e86", "valueType": "NUMBER"}, "daily_challenge_add_time": {"defaultValue": {"useInAppDefault": true}, "description": "\u6bcf\u65e5\u6311\u6218\u5728\u5931\u8d25\u540e\u52a0\u7684\u65f6\u95f4", "valueType": "STRING"}, "how_many_levels_show_rank": {"defaultValue": {"value": "10"}, "description": "\u591a\u5c11\u5173\u5f00\u59cb\u663e\u793a\u6392\u884c\u699c\uff0c2.16.0\u540e\u505c\u6b62\u4f7f\u7528", "valueType": "STRING"}}}, "d2": {"description": "d2\u9879\u76ee\u4e91\u63a7\u914d\u7f6e", "parameters": {"dc_config": {"defaultValue": {"value": "{\"chest\":[\"5#5#1\",\"12#7#2\",\"20#10#3\"],\"day_level_num\":1,\"enable_coin_unlock\":false,\"unlock_coin\":10,\"enable_ad_unlock\":false}"}, "description": "d2\u6bcf\u65e5\u6311\u6218\u914d\u7f6e\u3010chest:7#5#1\uff0c7:\u8868\u793a\u5b8c\u6210\u51e0\u5929\u53ef\u4ee5\u9886\u5956\uff0c5:\u91d1\u5e01\u5956\u52b1\u6570\u76ee\uff0c1:\u5b9d\u7bb1\u663e\u793a\u7b49\u7ea7 day_level_num\uff1a\u6bcf\u65e5\u6311\u6218\u6bcf\u5929\u5173\u5361\u6570\u76ee[1,3] enable_coin_unlock\uff1a\u662f\u5426\u5f00\u542f\u91d1\u5e01\u89e3\u9501 unlock_coin\uff1a\u89e3\u9501\u91d1\u5e01\u6570\u91cf enable_ad_unlock\uff1a\u662f\u5426\u5f00\u542f\u5e7f\u544a\u89e3\u9501\u3011", "valueType": "JSON"}, "difference_15_library": {"defaultValue": {"value": "{\"debug\": \"https://cdn3-dof.fungame.cloud/difference-picture-library/15_difference_library_debug.json?generation=1737025273112937\", \"release\": \"https://cdn3-dof.fungame.cloud/difference-picture-library/15_difference_library_release.json?generation=1740784239701293\"}"}, "description": "15\u4e2a\u4e0d\u540c\u70b9\u56fe\u5e93", "valueType": "JSON"}, "difference_20_library": {"defaultValue": {"value": "{\"debug\": \"https://cdn3-dof.fungame.cloud/difference-picture-library/20_difference_library_debug.json?generation=1732499136336086\", \"release\": \"https://cdn3-dof.fungame.cloud/difference-picture-library/20_difference_library_release.json?generation=1732672224580952\"}"}, "description": "20\u4e2a\u4e0d\u540c\u70b9\u56fe\u5e93", "valueType": "JSON"}, "library_ignore": {"defaultValue": {"value": "{\"url\": \"https://cdn3-dof.fungame.cloud/difference-picture-library/library_ignore.json?generation=1740462214007805\"}"}, "description": "\u56fe\u5e93\u5ffd\u7565\u914d\u7f6eurl", "valueType": "JSON"}, "hard_level_select": {"defaultValue": {"value": "{\"stage\":2,\"select_groups\":[{\"param\":[\"5#0#0.6\",\"10#0#0.9\"]},{\"param\":[\"6#0#0.6\",\"9#0#0.9\"]},{\"param\":[\"7#0#0.6\",\"8#0#0.9\"]}]}"}, "description": "\u56f0\u96be\u5173\u5361\u6311\u9009\u914d\u7f6e{stage:\u56f0\u96be\u5173\u5361\u6709\u51e0\u4e2a\u9636\u6bb5\uff1bselect_groups:\u9636\u6bb5\u6311\u9009\u914d\u7f6e\u7ec4\uff0c\u4f1a\u5728\u6240\u6709\u7ec4\u968f\u673a\u4e00\u7ec4\u4f5c\u4e3a\u6311\u9009\u89c4\u5219\uff1bparam:stage\u914d\u7f6e\u4e86\u51e0\u4e2a\u9636\u6bb5\uff0cparam\u6570\u7ec4\u5c31\u8981\u914d\u7f6e\u51e0\u4e2a\u5b57\u7b26\u4e32\uff1b\u6bcf\u4e2aparam\u6570\u7ec4\u5b57\u7b26\u4e32\u542b\u4e49(5#0.1#0.3\uff0c5\u4ee3\u88685\u4e2a\u4e0d\u540c\u70b9\u56fe\uff0c0.1\uff0c0.3\u4ee3\u8868\u4ece\u4e2d\u4f4d\u6570\u6392\u5e8f\u524d10%-30%\u8303\u56f4\u9009\u53d6\u5173\u5361) }", "valueType": "JSON"}, "main_normal_replace_config": {"defaultValue": {"value": "{\"debug\": \"https://cdn3-dof.fungame.cloud/d2/main_replace_config/main_normal_replace_config-1.0.0-debug.json?generation=1733472587314914\", \"release\": \"https://cdn3-dof.fungame.cloud/d2/main_replace_config/main_normal_replace_config-1.0.0-release.json?generation=1733472620264165\"}"}, "description": "\u4e3b\u7ebf\u666e\u901a\u5173\u5361\u66ff\u6362\u914d\u7f6e", "valueType": "JSON"}}}, "AD Setting": {"description": "\u5e7f\u544a\u914d\u7f6e", "parameters": {"int_ad_cancel_delay_seconds": {"defaultValue": {"value": "5"}, "description": "\u5e7f\u544a\u53d6\u6d88\u663e\u793a\u5ef6\u8fdf\u65f6\u95f4\uff08\u5355\u4f4d\u79d2\uff09", "valueType": "NUMBER"}, "int_level_interstitial": {"defaultValue": {"value": "10"}, "description": "\u591a\u5c11\u5173\u5f00\u542f\u5173\u5361\u63d2\u5c4f\u5e7f\u544a", "valueType": "NUMBER"}, "int_interstitial_cold_seconds": {"defaultValue": {"value": "60"}, "description": "\u63d2\u5c4f\u51b7\u5374\u65f6\u95f4(s)", "valueType": "NUMBER"}}}, "FindOut": {"description": "FindOut\u9879\u76ee\u914d\u7f6eRemoteConfig\u53c2\u6570", "parameters": {"fo_interstitial_cold_seconds": {"defaultValue": {"value": "90"}, "description": "FindOut\u63d2\u5c4f\u51b7\u5374\u65f6\u95f4(s)", "valueType": "STRING"}, "fo_level_configuration_debug_url": {"defaultValue": {"value": "https://cdn1.find-out.fungame.studio/level_config/debug/all_config/AllTypesConfigs.json"}, "description": "FindOut\u5173\u5361\u7684\u6d4b\u8bd5\u914d\u7f6e", "valueType": "STRING"}, "fo_level_configuration_time_stamp": {"defaultValue": {"value": "20221107T182822"}, "description": "FindOut\u5173\u5361\u914d\u7f6e\u66f4\u65b0\u7684\u65f6\u95f4\u6233", "valueType": "STRING"}, "fo_level_configuration_url": {"defaultValue": {"value": "https://cdn1.find-out.fungame.studio/level_config/release/all_config/AllTypesConfigs.json"}, "description": "FindOut\u5173\u5361\u914d\u7f6e\u7684URL", "valueType": "STRING"}, "max_lives": {"defaultValue": {"useInAppDefault": true}, "description": "\u6700\u5927\u751f\u547d\u503c(\u63d2\u5c4f)", "valueType": "NUMBER"}, "fo_chest_ad_mul": {"defaultValue": {"value": "3"}, "description": "findout\u9879\u76ee\u7ed3\u7b97\u9875\u9762\u5e7f\u544a\u500d\u6570", "valueType": "NUMBER"}, "fo_inter_config": {"defaultValue": {"value": "{\"new_user_time\":600,\"no_find_delay\":0,\"inter_cold\":90,\"delay_count\":0,\"enable_remove_banner\":true,\"enable_click_error\":true}"}, "description": "new_user_time: \u65b0\u624b\u4fdd\u62a4\u65f6\u95f4(s), no_find_delay: \u6ca1\u6709\u627e\u5230\u5ef6\u65f6\u65f6\u95f4(s), inter_cold: \u63d2\u5c4f\u51b7\u5374\u65f6\u95f4(s)\uff0cdelay_count\u5ef6\u65f6\u6b21\u6570,banner\u53bb\u5e7f\u544a\u53bbbanner, \u542f\u7528\u70b9\u51fb\u9519\u8bef\u7684\u65f6\u5019\u624d\u64ad\u653e\u5e7f\u544a enable_click_error;", "valueType": "JSON"}, "fo_cdn_config": {"defaultValue": {"value": "{\"main\":\"https://cdn3-find-out.fungame.cloud/\",\"fallback\":\"https://cdn2.find-out.fungame.studio/\",\"replace\":[\"https://cdn1.find-out.fungame.studio/\",\"https://cdn2.find-out.fungame.studio/\",\"https://cdn3-find-out.fungame.cloud/\",\"https://firebasestorage.googleapis.com/v0/b/dof2-b9070.appspot.com/o/\"]}"}, "description": "find out cdn\u914d\u7f6e", "valueType": "JSON"}, "resources_update_time": {"defaultValue": {"value": "20221010T000000"}, "description": "\u65f6\u95f4\u6233\u53d1\u751f\u53d8\u5316\u65f6\u56de\u53bbfirestore\u7684\u6240\u6709\u5173\u5361\u7684\u65f6\u95f4\u6233\uff0c\u7528\u4e8e\u66f4\u65b0\u66ff\u6362\u8d44\u6e90", "valueType": "STRING"}, "challenge_resources_update_time": {"defaultValue": {"value": "6"}, "description": "\u6311\u6218\u8d44\u6e90\u66f4\u65b0\u65f6\u95f4", "valueType": "STRING"}, "hourglass_add_time": {"defaultValue": {"value": "30"}, "description": "\u6c99\u6f0f\u6dfb\u52a0\u7684\u65f6\u95f4", "valueType": "NUMBER"}, "fo_quality_config": {"defaultValue": {"value": "{\"memory_low\":3000,\"memory_medium\":6000,\"low_view_max\":12,\"normal_view_max\":16}"}, "description": "\u9ad8\u4f4e\u7aef\u624b\u673a\u914d\u7f6e", "valueType": "JSON"}, "fo_no_ad_popup": {"defaultValue": {"value": "{\"enable\":true,\"inter_num\":0}"}, "description": "\u53bb\u5e7f\u544a\u5f39\u7a97\u914d\u7f6e", "valueType": "JSON"}, "fo_chest_config": {"defaultValue": {"value": "{\"open_level\":1,\"close_level\":1000,\"duration\":24,\"cold_time\":24,\"duration_day\":1,\"cold_time_day\":1,\"button_show_delay_ms\":1200,\"chest_rewards\":\"30,10|50,15|70,15|100,20|100,20\"}"}, "description": "\u5b9d\u7bb1\u914d\u7f6e", "valueType": "JSON"}, "fo_types_map_config": {"defaultValue": {"value": "{\"main\": \"level_config/findit.release.json?generation=1689055221984416\", \"main_debug\": \"level_config/findit.debug.json?generation=1688975521843667\", \"match\": \"level_config/match.release.json?generation=1689055276328248\", \"match_debug\": \"level_config/match.debug.json?generation=1689058115054232\", \"challenge\": \"level_config/challenge.release.json?generation=1688725676331333\", \"challenge_debug\": \"level_config/challenge.debug.json?generation=1689068487450441\", \"events\": \"level_config/events.release.json?generation=1687838381543643\", \"events_debug\": \"level_config/events.debug.json?generation=1686816195944059\", \"coin\": \"level_config/coin.release.json?generation=1689055545606767\", \"coin_debug\": \"level_config/coin.debug.json?generation=1689059121901048\", \"where_is\": \"level_config/where_is.release.json?generation=1689044569208338\", \"where_is_debug\": \"level_config/where_is.debug.json?generation=1689067977832360\"}"}, "description": "\u6240\u6709\u73a9\u6cd5\u5730\u56feurl\u914d\u7f6e", "valueType": "JSON"}, "fo_game_rate": {"defaultValue": {"value": "{\"treasures_no\":25,\"finish_games\":1,\"last_pop_gap_days\":3,\"finish_treasures_no\":25,\"app_review_treasures_no\":0,\"continue_rate5_nums\":2}"}, "description": "\u6e38\u620f\u8bc4\u5206\u914d\u7f6e(treasures_no\u65b0\u7528\u6237\u627e\u5230\u591a\u5c11\u5b9d\u85cf\u663e\u793a\u8bc4\u5206\uff0cfinish_games\u5b8c\u6210\u591a\u5c11\u5730\u56fe\u624d\u53ef\u4ee5\u663e\u793a\u8bc4\u5206\uff0clast_pop_gap_days\u8bc4\u5206\u65f6\u95f4\u95f4\u9694\uff0cfinish_treasures_no\u73a9\u8fc7\u4e00\u5b9a\u5173\u540e\u8fdb\u5730\u56fe\u627e\u591a\u5c11\u5b9d\u85cf\u663e\u793a\u8bc4\u5206\uff0capp_review_treasures_no\u8bc4\u5206\u540e\u518d\u627e\u591a\u5c11\u5b9d\u85cf\u663e\u793a\u7cfb\u7edf\u8bc4\u5206\uff0ccontinue_rate5_nums\u6848\u5b50m\u503c)", "valueType": "JSON"}, "events_config": {"defaultValue": {"value": "{\"events_highest_reward\":2,\n \"events_two_chest_rewards\":4,\n \"number_of_events_gold_coins\":\"5_10_30\",\n \"number_of_events_levels\":3,\n \"new_number_of_events_levels\":5,\n \t\"number_of_levels_required_to_unlock_the_events\":1,\n \t\"events_interstitial_cd\":45,\n \t\"level_treasures_number\":\"5_10_10\"\n}"}, "description": "events\u529f\u80fd\u7684\u6240\u6709\u4e91\u63a7,\u8001\u7248\u672c\u4e0d\u597d\u7528\uff0c\u820d\u5f03\u4f7f\u7528", "valueType": "STRING"}, "fo_ad_impression": {"defaultValue": {"value": "{\"enable\":true}"}, "conditionalValues": {"android": {"value": "{\"enable\":true}"}}, "description": "\u5e7f\u544aARO\u914d\u7f6e", "valueType": "JSON"}, "fo_item_store": {"defaultValue": {"value": "{\"subscription\":\"\",\"is_order_by_last_select\":false,\"hints\":[\"iapc_hint_099\",\"iapc_hint_499\",\"iapc_hint_999\"],\"hourglasses\":[\"iapc_hourglasses_099\",\"iapc_hourglasses_499\",\"iapc_hourglasses_999\"]}"}, "conditionalValues": {"hint": {"value": "{\"subscription\":\"\",\"is_order_by_last_select\":false,\"hints\":[\"iapc_hint_499\",\"iapc_hint_999\",\"iapc_hint_1999\"],\"hourglasses\":[\"iapc_hourglasses_499\",\"iapc_hourglasses_999\",\"iapc_hourglasses_1999\"]}"}, "hour": {"value": "{\"subscription\":\"\",\"is_order_by_last_select\":false,\"hints\":[\"iapc_hint_499\",\"iapc_hint_999\",\"iapc_hint_1999\"],\"hourglasses\":[\"iapc_hourglasses_499\",\"iapc_hourglasses_999\",\"iapc_hourglasses_1999\"]}"}, "ads": {"value": "{\"subscription\":\"\",\"is_order_by_last_select\":false,\"hints\":[\"iapc_hint_499\",\"iapc_hint_999\",\"iapc_hint_1999\"],\"hourglasses\":[\"iapc_hourglasses_499\",\"iapc_hourglasses_999\",\"iapc_hourglasses_1999\"]}"}, "sub": {"value": "{\"subscription\":\"\",\"is_order_by_last_select\":false,\"hints\":[\"iapc_hint_499\",\"iapc_hint_999\",\"iapc_hint_1999\"],\"hourglasses\":[\"iapc_hourglasses_499\",\"iapc_hourglasses_999\",\"iapc_hourglasses_1999\"]}"}, "subnew": {"value": "{\"subscription\":\"\",\"is_order_by_last_select\":false,\"hints\":[\"iapc_hint_499\",\"iapc_hint_999\",\"iapc_hint_1999\"],\"hourglasses\":[\"iapc_hourglasses_499\",\"iapc_hourglasses_999\",\"iapc_hourglasses_1999\"]}"}}, "description": "2.3.0\u7248\u672c\u5546\u54c1\u9762\u677f\u914d\u7f6e", "valueType": "JSON"}, "new_events_popup_windows_is_open": {"defaultValue": {"value": "true"}, "description": "\u6d3b\u52a8\u5f39\u7a97", "valueType": "BOOLEAN"}, "new_map_popup_windows_is_open": {"defaultValue": {"value": "true"}, "description": "\u65b0\u5730\u56fe\u89e3\u9501\u5f39\u7a97", "valueType": "BOOLEAN"}, "fo_taich_config": {"defaultValue": {"value": "{\"enable\":true,\"value\":0.2}"}, "description": "\u592a\u6781\u914d\u7f6e", "valueType": "JSON"}, "fo_subscription_config": {"defaultValue": {"value": "{\"default_select_sub_prod\":\"iap_subscription_1499\",\"no_ad_default_select_prod\":\"iap_noads_999\",\"pop_window_sub_prod\":\"iap_subscription_1499\",\"is_main_jump_subscription\":true,\"is_show_sub_pop_window\":true,\"discount\":80,\"exchage_cost\":80,\"daily_bonus\":100,\"popup_prod_list\":[\"iap_subscription_1499\",\"iap_subscription_499\",\"iap_subscription_9999\",\"iap_noads_999\"]}"}, "description": "\u8ba2\u9605\u529f\u80fd\u914d\u7f6e", "valueType": "JSON"}, "coin_config": {"defaultValue": {"value": "{\"findit_pass_count\":\"1\",\"match_pass_count\":\"1\",\"once_coin_show_count\":\"170\",\"many_coin_show_count\":\"10\",\"one_coin_value\":\"1\",\"many_coin_value\":\"3\",\"coin_level_time\":\"90\"}"}, "description": "\u91d1\u5e01\u5173\u5361\u7684\u76f8\u5173\u914d\u7f6e", "valueType": "JSON"}, "fo_types_level_config": {"defaultValue": {"value": "{\"main\": \"level_config/main.release.json?generation=1701161449406855\", \"main_debug\": \"level_config/main.debug.json?generation=1701402648277815\", \"match\": \"level_config/match_v310.release.json?generation=1701161450909351\", \"match_debug\": \"level_config/match_v310.debug.json?generation=1701402649227291\", \"coin\": \"level_config/coin.release.json?generation=1701161451647771\", \"coin_debug\": \"level_config/coin.debug.json?generation=1701402649978474\", \"normal\": \"level_config/normal.release.json?generation=1702348213431517\", \"normal_debug\": \"level_config/normal.debug.json?generation=1702281518784198\", \"premium\": \"level_config/premium.release.json?generation=1702436261371430\", \"premium_debug\": \"level_config/premium.debug.json?generation=1702022397866947\", \"challenge\": \"level_config/challenge.release.json?generation=1700814175150160\", \"challenge_debug\": \"level_config/challenge.debug.json?generation=1701249993058089\", \"events\": \"level_config/events.release.json?generation=1689749837023366\", \"events_debug\": \"level_config/events.debug.json?generation=1689749115568934\", \"where_is\": \"level_config/where_is.release.json?generation=1695200972348820\", \"where_is_debug\": \"level_config/where_is.debug.json?generation=1695200682277564\"}"}, "description": "3.1.0\u7248\u672c\u66f4\u6362\u65b0\u624b\u5730\u56fe\u540e\u65b0\u5730\u5730\u56fe\u914d\u7f6e", "valueType": "JSON"}, "new_events_config": {"defaultValue": {"value": "{\"events_highest_reward\":5,\"events_two_chest_rewards\":7,\"number_of_events_gold_coins\":\"15_20_30\",\"number_of_events_levels\":5,\"number_of_levels_required_to_unlock_the_events\":1,\"events_interstitial_cd\":45,\"level_treasures_number\":\"5_5_10_10_10\"}"}, "description": "\u65b0\u7684events\u73a9\u6cd5\u6240\u6709\u7684\u4e91\u63a7", "valueType": "JSON"}, "where_is_remote_config": {"defaultValue": {"value": "{\"event_open\":1,\"unlock_level\":1,\"duration\":7,\"delight_card\":[10,10,10],\"i_ad_time\":45}"}, "description": "where_is\u73a9\u6cd5\u7684\u76f8\u5173\u4e91\u63a7", "valueType": "JSON"}, "challenge_popup_config": {"defaultValue": {"value": "{\"is_open\":\"false\",\"show_count\":\"2\"}"}, "conditionalValues": {"chn": {"value": "{\"is_open\":\"false\",\"show_count\":\"2\"}"}}, "description": "\u6311\u6218\u6a21\u5f0f\u5f39\u7a97\u4e91\u63a7", "valueType": "JSON"}, "facebook_community": {"defaultValue": {"value": "{\"level_limite\":\"2\",\"gap_days\":\"5\",\"max_times\":\"10\",\"coin_gift\":\"100\",\"cut_time\":\"1000\"}"}, "description": "Facebook\u793e\u533a\u4e91\u63a7", "valueType": "JSON"}, "radar_config": {"defaultValue": {"value": "{\"pay\":{\"function_open\":true,\"have_hint_open\":true,\"interval_time\":120,\"max_times\":99,\"level_range_min\":1,\"level_range_max\":100,\"select_model\":[\"Find_It\"],\"duration_time\":100,\"radar_time\":45,\"close_times\":2,\"add_time\":0,\"guide_times\":5,\"add_duration_time\":45},\"free\":{\"function_open\":true,\"have_hint_open\":true,\"interval_time\":60,\"max_times\":99,\"level_range_min\":1,\"level_range_max\":100,\"select_model\":[\"Find_It\"],\"duration_time\":100,\"radar_time\":45,\"close_times\":2,\"add_time\":0,\"guide_times\":5,\"add_duration_time\":45}}"}, "description": "\u96f7\u8fbe\u914d\u7f6e", "valueType": "JSON"}, "fo_item_store_show_style": {"defaultValue": {"value": "1"}, "description": "\u9053\u5177\u5feb\u6377\u8d2d\u4e70\u754c\u9762\u663e\u793a\u6837\u5f0f", "valueType": "NUMBER"}, "fo_item_store_v2": {"defaultValue": {"value": "{\"payer_consumption\":4.99,\"duration\":14,\"hints\":[\"iapc_hint_099\",\"iapc_hint_499\",\"iapc_hint_999\"],\"payer_hints\":[\"iapc_hint_499\",\"iapc_hint_999\",\"iapc_hint_1999\"],\"hourglasses\":[\"iapc_hourglasses_099\",\"iapc_hourglasses_499\",\"iapc_hourglasses_999\"],\"payer_hourglasses\":[\"iapc_hourglasses_499\",\"iapc_hourglasses_999\",\"iapc_hourglasses_1999\"],\"battery\":[\"iapc_battery_099\",\"iapc_battery_499\",\"iapc_battery_999\"],\"payer_battery\":[\"iapc_battery_499\",\"iapc_battery_999\",\"iapc_battery_1999\"],\"compassList\":[\"iapc_compass_099\",\"iapc_compass_499\",\"iapc_compass_999\"],\"plyer_compassList\":[\"iapc_compass_499\",\"iapc_compass_999\",\"iapc_compass_1999\"],\"subscription\":\"iap_noads_999\",\"is_order_by_last_select\":false}"}, "conditionalValues": {"simplified Chinese": {"value": "{ \"payer_consumption\": 4.99, \"duration\": 14, \"hints\": [ \"iapc_hint_499\", \"iapc_hint_999\", \"iapc_hint_1999\" ], \"payer_hints\": [ \"iapc_hint_499\", \"iapc_hint_999\", \"iapc_hint_1999\" ], \"hourglasses\": [ \"iapc_hourglasses_499\", \"iapc_hourglasses_999\", \"iapc_hourglasses_1999\" ], \"payer_hourglasses\": [ \"iapc_hourglasses_499\", \"iapc_hourglasses_999\", \"iapc_hourglasses_1999\" ], \"battery\": [ \"iapc_battery_499\", \"iapc_battery_999\", \"iapc_battery_1999\" ], \"payer_battery\": [ \"iapc_battery_499\", \"iapc_battery_999\", \"iapc_battery_1999\" ], \"compassList\": [ \"iapc_compass_499\", \"iapc_compass_999\", \"iapc_compass_1999\" ], \"plyer_compassList\": [ \"iapc_compass_499\", \"iapc_compass_999\", \"iapc_compass_1999\" ], \"subscription\": \"iap_noads_999\", \"is_order_by_last_select\": false }"}}, "description": "\u9053\u5177\u5feb\u6377\u5f39\u7a97\u7b2c\u4e8c\u7248\u914d\u7f6e(payer_consumption\uff1a\u6d88\u8d39\u91d1\u989d\u4e0b\u9650\uff0cduration\uff1a\u6d88\u8d39\u671f\u9650\uff08\u5929\uff09)", "valueType": "JSON"}, "advanced_map_remote_config": {"defaultValue": {"value": "{\"premium_map_default_coin\": 5000, \"premium_unlock\": 0, \"default_product\": {\"map_id\": \"default\", \"name\": \"iapc_premiummap_499\", \"android_id\": \"fo.a.iapc.premiummap.499\", \"ios_id\": \"fo.i.iapc.premiummap.499\", \"price\": 4.99}, \"products\": [], \"discount_coin_products\": [{\"map_id\": \"nycxmas23\", \"discount_rate\": 80, \"start_time\": \"20231222T090500\", \"end_time\": \"20231229T090000\"}], \"default_coin_map_list\": {\"mystery\": \"5000\", \"paris\": \"5000\", \"tokyo2\": \"5000\", \"rome\": \"5000\", \"greek\": \"5000\", \"la\": \"5000\", \"cyberpunk\": \"5000\", \"vineyard\": \"5000\", \"galactic\": \"5000\", \"skull\": \"5000\", \"goblin\": \"5000\", \"nycxmas23\": \"5000\", \"fantasia\": \"5000\", \"bluehole\": \"5000\", \"treehome\": \"5000\", \"superbowl\": \"5000\", \"abandoned\": \"5000\", \"cavern\": \"5000\", \"dragon\": \"5000\", \"fruity\": \"5000\", \"core\": \"5000\", \"dessert\": \"5000\", \"toycity\": \"5000\", \"polar\": \"5000\", \"shadow\": \"5000\", \"olympus\": \"5000\", \"tribalafrica\": \"5000\", \"slumber\": \"5000\"}, \"not_auto_discount_map_list\": [\"mystery\", \"treehome\"], \"discount_map_list\": [{\"map_id\": \"mystery\", \"discount\": 40, \"start_time\": \"20240429T090500\", \"end_time\": \"20240513T090000\"}, {\"map_id\": \"treehome\", \"discount\": 40, \"start_time\": \"20240510T090500\", \"end_time\": \"20240524T090000\"}], \"auto_discount_time\": 168, \"auto_discount\": 40, \"premium_iap_free\": []}"}, "description": "\u9ad8\u7ea7\u5730\u56fe\u914d\u7f6e", "valueType": "JSON"}, "be_common_remote_config": {"defaultValue": {"value": "{\"main_decrease\":{\"decrease_pass_treasure\":0,\"force_count\":1,\"start_decrease\":1,\"end_decrease\":5}}"}, "description": "\u901a\u7528\u7684remote config decrease_pass_treasure - \u5b9d\u85cf\u51cf\u5c11\u7684\u6570\u91cf force_count - \u524d\u51e0\u6b21\u901a\u5173\u624d\u6709\u6548 start_decrease - \u5f00\u59cb\u5173\u5361 end_decrease - \u7ed3\u675f\u5173\u5361", "valueType": "JSON"}, "fo_chest_config_v2": {"defaultValue": {"value": "{\"function_is_open\":true,\"collect_treasure_num\":0,\"open_level\":1,\"close_level\":1000,\"duration_day\":1,\"cold_time_day\":0,\"button_show_delay_ms\":1200,\"chest_rewards\":\"20,12|30,12|40,12|50,14|30,12|30,12|60,14|80,14|100,30|100,30\"}"}, "description": "\u5b9d\u7bb1\u914d\u7f6e\u7b2c\u4e8c\u7248", "valueType": "JSON"}, "fo_types_level_config_v3100": {"defaultValue": {"value": "{\"normal\": \"level_config/normal_v3100.release.json?generation=1741071828390643\", \"normal_debug\": \"level_config/normal_v3100.debug.json?generation=1741070220776079\", \"premium\": \"level_config/premium_v3100.release.json?generation=1739159050835242\", \"premium_debug\": \"level_config/premium_v3100.debug.json?generation=1739005232056284\", \"challenge\": \"level_config/challenge_v3100.release.json?generation=1735808542290619\", \"challenge_debug\": \"level_config/challenge_v3100.debug.json?generation=1726827232149645\", \"events\": \"level_config/events.release.json?generation=1689749837023366\", \"events_debug\": \"level_config/events.debug.json?generation=1740999373884352\", \"where_is\": \"level_config/where_is.release.json?generation=1695200972348820\", \"where_is_debug\": \"level_config/where_is.debug.json?generation=1695200682277564\"}"}, "description": "v3.10.0\u7248\u672c\u5f00\u59cb\u5173\u5361\u914d\u7f6e\u4e91\u63a7\u53c2\u6570", "valueType": "JSON"}, "enable_ios_promo_code": {"defaultValue": {"value": "false"}, "conditionalValues": {"ios_promo_code": {"value": "true"}}, "description": "ios\u5141\u8bb8\u6253\u5f00\u5151\u6362\u7801", "valueType": "BOOLEAN"}, "vitality_remote_config": {"defaultValue": {"value": "{\"main_switch_Interstitial_ad\":false,\"interstitial_ad_tips\":false,\"loading_time\":1000,\"vitality_max\":90,\"vitality_damping\":1,\"insert_vitality_count\":90,\"pass_level_add_vitality_count\":0,\"main_add_vitality_count\":0,\"match_add_vitality_count\":0,\"watch_video_count\":7,\"video_grade\":[180,190,200,210,220],\"show_remove_ad_commodity\":false,\"vitality_quiver\":[],\"show_countdow\":false,\"show_get_vitality_effect\":false,\"vitality_damping_float\":1,\"open_level_def_vitality\":90,\"show_icon\":false,\"show_vitality_insufficient_view\":false,\"show_vitality_info\":false,\"incentive_video_reset_vitality\":false,\"incentive_video_reset_vitality_count\":90}"}, "conditionalValues": {"chn": {"value": "{\"main_switch_Interstitial_ad\":false,\"interstitial_ad_tips\":false,\"loading_time\":1000,\"vitality_max\":90,\"vitality_damping\":1,\"insert_vitality_count\":90,\"pass_level_add_vitality_count\":0,\"main_add_vitality_count\":0,\"match_add_vitality_count\":0,\"watch_video_count\":7,\"video_grade\":[180,190,200,210,220],\"show_remove_ad_commodity\":false,\"vitality_quiver\":[],\"show_countdow\":false,\"show_get_vitality_effect\":false,\"vitality_damping_float\":1,\"open_level_def_vitality\":90,\"show_icon\":false,\"show_vitality_insufficient_view\":false,\"show_vitality_info\":false,\"incentive_video_reset_vitality\":false,\"incentive_video_reset_vitality_count\":90}"}}, "description": "\u6d3b\u529b\u7cfb\u7edf", "valueType": "JSON"}, "test_enable_ios_promo_code": {"defaultValue": {"value": "false"}, "conditionalValues": {"test_ios_promo_code": {"value": "true"}}, "description": "ios\u5141\u8bb8\u6253\u5f00\u5151\u6362\u7801", "valueType": "BOOLEAN"}, "new_radar_config": {"defaultValue": {"value": "{\"radar_open_type\":2,\"open_level\":1,\"find_count\":0,\"open_magnifiers_guide\":true,\"open_new_radar_guide\":true,\"magnifiers_guide_unlock_find_count\":5,\"new_radar_guide_unlock_find_count\":35,\"free_battery_count\":0,\"scan_time\":300,\"reduce_time\":30,\"speedup_count\":6,\"inner_r\":2,\"circle_r\":3,\"pradar_r\":4.13,\"popup_count\":0,\"find_count_show_tip\":2,\"find_effect_time\":2,\"radar_level_datas\":[{\"find_count\":40,\"time\":600},{\"find_count\":50,\"time\":300},{\"find_count\":50,\"time\":180},{\"find_count\":50,\"time\":120},{\"find_count\":50,\"time\":60}],\"radar_level_datas_new\":[{\"find_count\":0,\"time\":600},{\"find_count\":40,\"time\":420},{\"find_count\":50,\"time\":300},{\"find_count\":50,\"time\":180},{\"find_count\":50,\"time\":120},{\"find_count\":50,\"time\":60}],\"pop_window_show_count\":0}"}, "conditionalValues": {"United Kingdom": {"value": "{\"radar_open_type\":2,\"open_magnifiers_guide\":true,\"open_new_radar_guide\":true,\"magnifiers_guide_unlock_find_count\":5,\"new_radar_guide_unlock_find_count\":35,\"free_battery_count\":0,\"scan_time\":300,\"reduce_time\":60,\"speedup_count\":3,\"inner_r\":2,\"circle_r\":3,\"pradar_r\":4.13,\"popup_count\":0,\"find_count_show_tip\":2,\"find_effect_time\":2,\"radar_level_datas\":[{\"find_count\":40,\"time\":600},{\"find_count\":50,\"time\":300},{\"find_count\":50,\"time\":180},{\"find_count\":50,\"time\":120},{\"find_count\":50,\"time\":60}],\"radar_level_datas_new\":[{\"find_count\":0,\"time\":600},{\"find_count\":40,\"time\":420},{\"find_count\":50,\"time\":300},{\"find_count\":50,\"time\":180},{\"find_count\":50,\"time\":120},{\"find_count\":50,\"time\":60}],\"pop_window_show_count\":0}"}, "Brazil": {"value": "{\"radar_open_type\":2,\"open_magnifiers_guide\":true,\"open_new_radar_guide\":true,\"magnifiers_guide_unlock_find_count\":5,\"new_radar_guide_unlock_find_count\":35,\"free_battery_count\":0,\"scan_time\":300,\"reduce_time\":60,\"speedup_count\":3,\"inner_r\":2,\"circle_r\":3,\"pradar_r\":4.13,\"popup_count\":0,\"find_count_show_tip\":2,\"find_effect_time\":2,\"radar_level_datas\":[{\"find_count\":40,\"time\":600},{\"find_count\":50,\"time\":300},{\"find_count\":50,\"time\":180},{\"find_count\":50,\"time\":120},{\"find_count\":50,\"time\":60}],\"radar_level_datas_new\":[{\"find_count\":0,\"time\":600},{\"find_count\":40,\"time\":420},{\"find_count\":50,\"time\":300},{\"find_count\":50,\"time\":180},{\"find_count\":50,\"time\":120},{\"find_count\":50,\"time\":60}],\"pop_window_show_count\":0}"}}, "description": "\u65b0\u96f7\u8fbe\u914d\u7f6e", "valueType": "JSON"}, "fo_game_rate_show_style": {"defaultValue": {"value": "{\"show_style\":0}"}, "description": "\u8bc4\u5206\u663e\u793a\u6837\u5f0f\u914d\u7f6e\uff0c 1:\u663e\u793a\u4f18\u5316\u6837\u5f0f", "valueType": "JSON"}, "fo_subscription_view_show_style": {"defaultValue": {"value": "{\"show_style\":0}"}, "description": "\u8ba2\u9605\u754c\u9762\u663e\u793a\u6837\u5f0f\u914d\u7f6e\uff081\uff1a\u663e\u793a\u5f39\u7a97\u6837\u5f0f\uff09", "valueType": "JSON"}, "property_hint_animation_config": {"defaultValue": {"value": "{\"open_function\":false,\"need_time\":30,\"animation_time\":5,\"animation_interval\":10,\"show_level_number\":true}"}, "conditionalValues": {"open_by_country_Android": {"value": "{\"open_function\":true,\"need_time\":30,\"animation_time\":5,\"animation_interval\":10,\"show_level_number\":true}"}, "close_by_country_Android": {"value": "{\"open_function\":false,\"need_time\":30,\"animation_time\":5,\"animation_interval\":10,\"show_level_number\":true}"}, "close_by_country_IOS": {"value": "{ \"open_function\": false, \"need_time\": 30, \"animation_time\": 5, \"animation_interval\": 10, \"show_level_number\": true }"}}, "description": "\u9053\u5177\u63d0\u793a\u52a8\u753b\u7684\u4e91\u63a7", "valueType": "JSON"}, "fo_compass_config": {"defaultValue": {"value": "{\"enable\":true,\"compass_guide_unlock_level\":1,\"duration_time\":15,\"is_open_compass\":true,\"is_open_compass_guide\":true,\"compass_guide_unlock_find_count\":69,\"gift_compass_count\":1,\"green_circle_use_times\":1,\"free_compass_count\":1}"}, "conditionalValues": {"chn": {"value": "{\"enable\":true,\"compass_guide_unlock_level\":1,\"duration_time\":15,\"is_open_compass\":true,\"is_open_compass_guide\":true,\"compass_guide_unlock_find_count\":21,\"gift_compass_count\":1,\"green_circle_use_times\":1,\"free_compass_count\":1}"}}, "description": "\u6307\u5357\u9488\u9053\u5177", "valueType": "JSON"}, "level_quest_config": {"defaultValue": {"value": "{\"function_open\":false,\"function_open_level_num_start\":2,\"is_repetition\":false,\"find_count\":22,\"quest_level_datas\":[{\"quest_time\":120,\"quest_award_coin\":1},{\"quest_time\":120,\"quest_award_coin\":2},{\"quest_time\":120,\"quest_award_coin\":4},{\"quest_time\":120,\"quest_award_coin\":6},{\"quest_time\":120,\"quest_award_coin\":8},{\"quest_time\":120,\"quest_award_coin\":10}],\"text_delay_time\":2}"}, "conditionalValues": {"uk": {"value": "{\"function_open\":true,\"function_open_level_num_start\":2,\"is_repetition\":false,\"find_count\":22,\"quest_level_datas\":[{\"quest_time\":120,\"quest_award_coin\":1},{\"quest_time\":120,\"quest_award_coin\":2},{\"quest_time\":120,\"quest_award_coin\":4},{\"quest_time\":120,\"quest_award_coin\":6},{\"quest_time\":120,\"quest_award_coin\":8},{\"quest_time\":120,\"quest_award_coin\":10}],\"text_delay_time\":2}"}, "brazil": {"value": "{\"function_open\":true,\"function_open_level_num_start\":2,\"is_repetition\":false,\"find_count\":22,\"quest_level_datas\":[{\"quest_time\":120,\"quest_award_coin\":1},{\"quest_time\":120,\"quest_award_coin\":2},{\"quest_time\":120,\"quest_award_coin\":4},{\"quest_time\":120,\"quest_award_coin\":6},{\"quest_time\":120,\"quest_award_coin\":8},{\"quest_time\":120,\"quest_award_coin\":10}],\"text_delay_time\":2}"}, "chn": {"value": "{\"function_open\":true,\"function_open_level_num_start\":2,\"is_repetition\":false,\"find_count\":22,\"quest_level_datas\":[{\"quest_time\":120,\"quest_award_coin\":1},{\"quest_time\":120,\"quest_award_coin\":2},{\"quest_time\":120,\"quest_award_coin\":4},{\"quest_time\":120,\"quest_award_coin\":6},{\"quest_time\":120,\"quest_award_coin\":8},{\"quest_time\":120,\"quest_award_coin\":10}],\"text_delay_time\":2}"}}, "description": "\u5c0f\u76ee\u6807\u914d\u7f6e", "valueType": "JSON"}, "match_optimize_remote_config": {"defaultValue": {"value": "{\"hold_num_match\":3,\"pass_level_show_effect_switch\":true,\"pass_level_show_effect_level\":5,\"is_show_animation_half_page\":true}"}, "description": "match\u7684\u914d\u7f6e", "valueType": "JSON"}, "banner_load_setting_remote_config": {"defaultValue": {"value": "{\"function_open\":false,\"time_out\":30}"}, "valueType": "JSON"}, "fo_area_tip_config": {"defaultValue": {"value": "{\"enable\":true,\"is_open_area_tip\":true,\"is_open_area_tip_guide\":true,\"area_tip_guide_unlock_find_count\":95}"}, "description": "\u533a\u57df\u63d0\u793atip \u914d\u7f6e", "valueType": "JSON"}, "continuous_Task_remote_Config": {"defaultValue": {"value": "{\"function_open\":true,\"open_level\":1,\"tasks_count\":[10],\"complete_tasks_coin\":[5],\"special_task_add_coin\":1,\"time_count_down\":false,\"time_count\":120,\"function_open_find_count\":22,\"click_error\":true,\"is_show_emoji_count\":5}"}, "description": "\u8fde\u7eed\u4efb\u52a1", "valueType": "JSON"}, "combo_config": {"defaultValue": {"value": "{\"open_function\":true}"}, "description": "combo\u52a8\u753b", "valueType": "JSON"}, "choose_level_config": {"defaultValue": {"value": "{\"function_open\":true,\"choose_level_limit\":3,\"choose_gold_unlock_price\":100,\"choose_gold_refresh_price\":[100,200,400,800],\"choose_level_pre_download_thum_count\":6,\"choose_level_pre_download_map_count\":1}"}, "description": "\u9009\u5173\u914d\u7f6e", "valueType": "JSON"}, "magnifiers_config": {"defaultValue": {"value": "{\"open_level\":1,\"function_open_find_count\":5,\"open_magnifiers_guide\":true}"}, "valueType": "JSON"}, "rank_remote_config": {"defaultValue": {"value": "{\"enable\":true,\"unlock_level\":2,\"robot_count\":199,\"rank2_level\":20,\"robot_configs\":[{\"num\":1,\"minimum_quantity\":0,\"weight\":10,\"day_points_up_left\":25,\"day_points_up_right\":25,\"points_up_left\":11,\"points_up_right\":15,\"beginning_points_left\":10,\"beginning_points_right\":50},{\"num\":2,\"minimum_quantity\":0,\"weight\":100,\"day_points_up_left\":20,\"day_points_up_right\":20,\"points_up_left\":9,\"points_up_right\":13,\"beginning_points_left\":10,\"beginning_points_right\":70},{\"num\":3,\"minimum_quantity\":3,\"weight\":500,\"day_points_up_left\":16,\"day_points_up_right\":16,\"points_up_left\":4,\"points_up_right\":14,\"beginning_points_left\":15,\"beginning_points_right\":90},{\"num\":4,\"minimum_quantity\":7,\"weight\":2000,\"day_points_up_left\":9,\"day_points_up_right\":9,\"points_up_left\":3,\"points_up_right\":13,\"beginning_points_left\":20,\"beginning_points_right\":110},{\"num\":5,\"minimum_quantity\":50,\"weight\":6000,\"day_points_up_left\":5,\"day_points_up_right\":5,\"points_up_left\":5,\"points_up_right\":15,\"beginning_points_left\":25,\"beginning_points_right\":130},{\"num\":6,\"minimum_quantity\":139,\"weight\":5000,\"day_points_up_left\":2,\"day_points_up_right\":2,\"points_up_left\":5,\"points_up_right\":21,\"beginning_points_left\":30,\"beginning_points_right\":150}],\"robot_configs_rank2\":[{\"num\":1,\"minimum_quantity\":1,\"weight\":10,\"day_points_up_left\":25,\"day_points_up_right\":25,\"points_up_left\":11,\"points_up_right\":15,\"beginning_points_left\":10,\"beginning_points_right\":50},{\"num\":2,\"minimum_quantity\":2,\"weight\":100,\"day_points_up_left\":20,\"day_points_up_right\":20,\"points_up_left\":9,\"points_up_right\":13,\"beginning_points_left\":10,\"beginning_points_right\":70},{\"num\":3,\"minimum_quantity\":7,\"weight\":500,\"day_points_up_left\":16,\"day_points_up_right\":16,\"points_up_left\":4,\"points_up_right\":14,\"beginning_points_left\":15,\"beginning_points_right\":90},{\"num\":4,\"minimum_quantity\":30,\"weight\":2000,\"day_points_up_left\":9,\"day_points_up_right\":9,\"points_up_left\":3,\"points_up_right\":13,\"beginning_points_left\":20,\"beginning_points_right\":110},{\"num\":5,\"minimum_quantity\":60,\"weight\":6000,\"day_points_up_left\":5,\"day_points_up_right\":5,\"points_up_left\":5,\"points_up_right\":15,\"beginning_points_left\":25,\"beginning_points_right\":130},{\"num\":6,\"minimum_quantity\":99,\"weight\":5000,\"day_points_up_left\":2,\"day_points_up_right\":2,\"points_up_left\":5,\"points_up_right\":21,\"beginning_points_left\":30,\"beginning_points_right\":150}],\"first_award\":[{\"type\":0,\"count\":100},{\"type\":1,\"count\":1},{\"type\":2,\"count\":1}],\"second_award\":[{\"type\":0,\"count\":100}],\"third_award\":[{\"type\":0,\"count\":50}],\"other_award\":[{\"type\":0,\"count\":30}],\"other_end_ranking\":10}"}, "conditionalValues": {"chn": {"value": "{\"enable\":true,\"unlock_level\":2,\"robot_count\":199,\"rank2_level\":20,\"robot_configs\":[{\"num\":1,\"minimum_quantity\":0,\"weight\":10,\"day_points_up_left\":25,\"day_points_up_right\":25,\"points_up_left\":7,\"points_up_right\":11,\"beginning_points_left\":10,\"beginning_points_right\":50},{\"num\":2,\"minimum_quantity\":0,\"weight\":100,\"day_points_up_left\":20,\"day_points_up_right\":20,\"points_up_left\":6,\"points_up_right\":10,\"beginning_points_left\":10,\"beginning_points_right\":70},{\"num\":3,\"minimum_quantity\":3,\"weight\":500,\"day_points_up_left\":16,\"day_points_up_right\":16,\"points_up_left\":3,\"points_up_right\":9,\"beginning_points_left\":15,\"beginning_points_right\":90},{\"num\":4,\"minimum_quantity\":7,\"weight\":2000,\"day_points_up_left\":9,\"day_points_up_right\":9,\"points_up_left\":3,\"points_up_right\":13,\"beginning_points_left\":20,\"beginning_points_right\":110},{\"num\":5,\"minimum_quantity\":50,\"weight\":6000,\"day_points_up_left\":5,\"day_points_up_right\":5,\"points_up_left\":5,\"points_up_right\":15,\"beginning_points_left\":25,\"beginning_points_right\":130},{\"num\":6,\"minimum_quantity\":139,\"weight\":5000,\"day_points_up_left\":2,\"day_points_up_right\":2,\"points_up_left\":5,\"points_up_right\":21,\"beginning_points_left\":30,\"beginning_points_right\":150}],\"robot_configs_rank2\":[{\"num\":1,\"minimum_quantity\":1,\"weight\":10,\"day_points_up_left\":25,\"day_points_up_right\":25,\"points_up_left\":7,\"points_up_right\":11,\"beginning_points_left\":10,\"beginning_points_right\":50},{\"num\":2,\"minimum_quantity\":2,\"weight\":100,\"day_points_up_left\":20,\"day_points_up_right\":20,\"points_up_left\":6,\"points_up_right\":10,\"beginning_points_left\":10,\"beginning_points_right\":70},{\"num\":3,\"minimum_quantity\":7,\"weight\":500,\"day_points_up_left\":16,\"day_points_up_right\":16,\"points_up_left\":3,\"points_up_right\":9,\"beginning_points_left\":15,\"beginning_points_right\":90},{\"num\":4,\"minimum_quantity\":30,\"weight\":2000,\"day_points_up_left\":9,\"day_points_up_right\":9,\"points_up_left\":3,\"points_up_right\":13,\"beginning_points_left\":20,\"beginning_points_right\":110},{\"num\":5,\"minimum_quantity\":60,\"weight\":6000,\"day_points_up_left\":5,\"day_points_up_right\":5,\"points_up_left\":5,\"points_up_right\":15,\"beginning_points_left\":25,\"beginning_points_right\":130},{\"num\":6,\"minimum_quantity\":99,\"weight\":5000,\"day_points_up_left\":2,\"day_points_up_right\":2,\"points_up_left\":5,\"points_up_right\":21,\"beginning_points_left\":30,\"beginning_points_right\":150}],\"first_award\":[{\"type\":0,\"count\":100},{\"type\":1,\"count\":1},{\"type\":2,\"count\":1}],\"second_award\":[{\"type\":0,\"count\":100}],\"third_award\":[{\"type\":0,\"count\":50}],\"other_award\":[{\"type\":0,\"count\":30}],\"other_end_ranking\":10}"}}, "description": "\u5468\u699c", "valueType": "JSON"}, "fo_profile_asset_config": {"defaultValue": {"value": "{\"android_debug\": \"https://cdn3-find-out.fungame.cloud/features/profile/Android/profile-debug.bundle?generation=1741073466419955\", \"android_release\": \"\", \"ios_debug\": \"https://cdn3-find-out.fungame.cloud/features/profile/iOS/profile-debug.bundle?generation=1741073467073258\", \"ios_release\": \"\"}"}, "description": "\u4e2a\u4eba\u8d44\u6599\u8d44\u6e90\u5305\u914d\u7f6e", "valueType": "JSON"}}}, "d2-gve": {"description": "D2\u9879\u76eeGVE\u6a21\u5757\u4e91\u63a7\u914d\u7f6e", "parameters": {"standalone_gve_play_cfg": {"defaultValue": {"value": "{\"ai_balance\":10,\"smart_level\":2,\"smart_cd\":{\"min\":2,\"max\":9},\"idiot_cd\":{\"min\":1,\"max\":30},\"smart_item_cd\":12,\"item_price\":[{\"itemId\":1001,\"price\":10},{\"itemId\":1002,\"price\":6},{\"itemId\":1003,\"price\":3}]}"}, "description": "\u5355\u673a\u7248gve\u73a9\u6cd5\u53c2\u6570\u63a7\u5236", "valueType": "JSON"}}}}}
\ No newline at end of file
diff --git a/google_drive/__init__.py b/google_drive/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/google_drive/google_sheet.py b/google_drive/google_sheet.py
new file mode 100644
index 0000000..25d7959
--- /dev/null
+++ b/google_drive/google_sheet.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+# coding:utf-8
+import gspread
+from gspread import Worksheet
+from oauth2client.service_account import ServiceAccountCredentials
+
+GoogleDrive = {
+ "type": "service_account",
+ "project_id": "quickstart-1616645350080",
+ "private_key_id": "c27137e7a9bcb56debff4266d7f5e0b75d84e514",
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQClKVOarC1QskWD\nHxoS/S/Gah0oge71Fd4jDLOAU7cqOWY5/gPzHysBKCoA+Hrq/LE/SzzwFnqfoZTJ\n7RsokQB07iRyipjv6cm1tfZvguA95LVEAgAcpbsIYa/3gDeZ1QvP6ntTlUMCUdza\nP4l/hl3U9ZNqLAa3axKGxeJug6845BgG3fe1gF12ukyqHecUO9Ys5lUB5HsGv32c\nsIezTPFnNRmXyTSPTC4ufeU8tUhF6D+B5/jnSk+Lt7qjHzVBhyHnx7Aa1hYI2KoX\nn5Pp2hD8vaJR6FxMN1S3YP1DQnsjavU/p/wkG0cca/MkVjDc4Wst+00KDmDQb/sY\ndCBw/5RNAgMBAAECggEADFPC0TMTqMe9h3VdUViDZdhKt9jG2JUawNv0U9orvCOP\nnTl32wATCiGQzQS+y+YzZol7kWHkIiEBxXaEhekYsyGJJ+FvW8zDyOO9coI+sW/u\nFZbeokS+ang8FYmE3N75ZDnYnZrw5u3sQX/nh9SkET6JE64YjD0aI2QGq//5JpJF\nBOWFcmRq+oC4b2MmxjbYYfASz9SioyGPmDM9pnj0qAsooh8lbNYG2ot+SXUmQ5G7\n9jcAXAQA/qhboPEWWZr2bRSHum1s7Tnp0nuVR6gPQ48THCyp+ozyZ51ggg7a+KIY\nqWK59VdzZHKadrMqrANDkZyFk8g4WEYOFbcoroOEsQKBgQDOKIVig9m66BoD8l/u\nuEVnPLueOabKdsavwOcTRhIAOmXYiA0Tjntt2UgFMO+yi4LZujRnB0SHv/j6+UPV\nM6+AOdMUOThto9HhWB2CWg+F1U4eYD064GPllC3uiL/hNAy5OdNrtseR6tlQAG+f\nbARm1GqFk9vVHVyTlpWAULfPxQKBgQDNF3EwUkoPV0wALMKX6V4NjYQx6CsjbN7V\ndbBKBgt+OEEt/yE9L9dwuf2mN7YA37zZUFNfeZUnTNAH2EsmInI6wlewvUK7b9eZ\n3FmZcFHV4hlqE8A2vJwk0U42nJuC9dP5bTL8ZFst9qtRdFwlnrZ3rZXzVEtmBKVt\npIDLAZMy6QKBgQCUx/ejZmZ/FjyYNpZ3UPN9kv4QLakqmte/RWc+qKYbFgokX+OY\nBo8bcuEgJfYHE9omSdTBuiQCGFCWx8flmPyCfLjR8o2/yqeQiqgZR+fF/W/4ShpG\nYGSX7f3MFVLtM0QvdQUYynty2ltk+juUgT8X+xq5NkFDp4IFXXqddSOCxQKBgBa4\nLhXIR+QDK6wpSTVC6ORfdPGCYqT9/oFvFCRfHw7QdIf/51K75gXa1LqBGWxnXKhG\nObYt5dQAslrsHwcOcdEIjmZJ0QaqkRu+ST6yLp6e+WnC3lwx8KozdZKfLqsHSIAt\nFKTZCTDCTqArX7nbJyOC20WlZOTcRucqfgn/FqthAoGAe7aZTcUxLbtltXki9nym\nOWQ5WTbwSJukzG8BWtG6vuvJf+tyUvEcMXw5cnrem58FrDUqt1NAS+jso1d+aB9n\n+DulSAgaec/8kYcAnx2EnDQlXceB94FOsjfKD/j2T7ONteieGLYleliXVdhWu/ay\nTIljZsJu1Lnnq49cS0TLgIU=\n-----END PRIVATE KEY-----\n",
+ "client_email": "google-sheet@quickstart-1616645350080.iam.gserviceaccount.com",
+ "client_id": "105134275998904574352",
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ "token_uri": "https://oauth2.googleapis.com/token",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/google-sheet%40quickstart-1616645350080.iam.gserviceaccount.com"
+}
+
+google_drive_auth_scope = [
+ 'https://www.googleapis.com/auth/drive',
+ 'https://www.googleapis.com/auth/drive.file'
+]
+
+def singleton(cls):
+ _instance = {}
+
+ def inner():
+ if cls not in _instance:
+ _instance[cls] = cls()
+ return _instance[cls]
+ return inner
+
+@singleton
+class GoogleSheetHelper:
+ def __init__(self):
+ cred = ServiceAccountCredentials.from_json_keyfile_dict(GoogleDrive, google_drive_auth_scope)
+ self.googleDriveClient = gspread.authorize(cred)
+ self.sheet_dict = {}
+
+ def open_sheet_file(self, sheet_file_name):
+ if sheet_file_name in self.sheet_dict:
+ return self.sheet_dict[sheet_file_name]
+ else:
+ spread_sheet = self.googleDriveClient.open(sheet_file_name)
+ self.sheet_dict[sheet_file_name] = spread_sheet
+ return spread_sheet
+
+ def get_sheet_table(self, sheet_file_name, sheet_table_name) -> Worksheet:
+ try:
+ spread_sheet = self.open_sheet_file(sheet_file_name)
+ return spread_sheet.worksheet(sheet_table_name)
+ except Exception as e:
+ print(e)
+ return None
+
+ def get_or_create_sheet_table(self, sheet_file_name, sheet_table_name, row_count=1, col_count=1) -> Worksheet:
+ spread_sheet = self.open_sheet_file(sheet_file_name)
+ try:
+ return spread_sheet.worksheet(sheet_table_name), False
+ except:
+ return spread_sheet.add_worksheet(sheet_table_name, row_count, col_count), True
+
+ def get_sheet_row(self, sheet: Worksheet, row):
+ if sheet is None:
+ print('传入参数sheet异常 sheet is None')
+ return
+ if row < 0:
+ print(f'传入参数row异常 row={row}')
+ return
+ return sheet.row_values(row)
+
+ def sheet_append_row(self, sheet: Worksheet, value):
+ if sheet is None:
+ print('传入参数sheet is None')
+ return
+ sheet.append_row(value, value_input_option='USER_ENTERED')
+
+ def sheet_update_cells_value(self, sheet: Worksheet, cell_range, values):
+ if sheet is None:
+ print('传入参数sheet is None')
+ return
+ for i, cell in enumerate(cell_range):
+ cell.value = values[i]
+ sheet.update_cells(cell_range)
+
+ def sheet_update_cell_value(self, sheet: Worksheet, row, col, value):
+ if sheet is None:
+ print('传入参数sheet is None')
+ return
+ sheet.update_cell(row, col, value)
+
+
+if __name__ == '__main__':
+ pass
+
diff --git a/ipm/__init__.py b/ipm/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ipm/clear_cdn.py b/ipm/clear_cdn.py
new file mode 100644
index 0000000..666fa77
--- /dev/null
+++ b/ipm/clear_cdn.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+# coding:utf-8
+
+import requests
+import json
+import urllib3
+
+class clear_cdn_util:
+ def __init__(self, x_app_id):
+ self.url = "https://saas.castbox.fm/tool/api/v1/operate/batch/clearCdn"
+ self.x_app_id = x_app_id
+ self.domain_list = []
+ self.clear_file_list = []
+
+ # domain:cdn3-find-master.fungame.cloud
+ def appendDomain(self, domain):
+ self.domain_list.append(domain)
+
+ # storage path:/xx/xx
+ def appendClearFile(self, path):
+ self.clear_file_list.append(path)
+
+ def clearCDN(self):
+ try:
+ if self.x_app_id == "":
+ print("clearCDN failed!!! x_app_id is None")
+ return
+
+ if len(self.domain_list) == 0:
+ print("clearCDN failed!!! domain_list len is 0")
+ return
+
+ if len(self.clear_file_list) == 0:
+ print("clearCDN failed!!! clear_file_list len is 0")
+ return
+
+ params = {
+ "domainList": self.domain_list,
+ "pathSuffixList": self.clear_file_list
+ }
+ data = json.dumps(params)
+ print(data)
+ urllib3.disable_warnings()
+ r = requests.post(self.url,
+ headers={"X-APP-ID": self.x_app_id, "Content-Type": "application/json"},
+ data=data,
+ verify=False
+ )
+
+ print(r.status_code)
+ print(str(r))
+ if r.status_code == 200:
+ print(f"{str(self.clear_file_list)} clearCDN OK!!! ")
+ except Exception as e:
+ print("clearCDN failed!!! error: " + repr(e))
+
diff --git a/ipm/wechat_alert.py b/ipm/wechat_alert.py
new file mode 100644
index 0000000..0aca433
--- /dev/null
+++ b/ipm/wechat_alert.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+# coding=utf-8
+
+import requests
+import json
+
+
+def wechat_alert(message, hook_url, at_people_list=[]):
+ pass
+ webhook = hook_url
+ header = {
+ "Content-Type": "application/json",
+ "Charset": "UTF-8"
+ }
+
+ print(message)
+ msg = {
+ "msgtype": "text",
+ "text": {
+ "content": message,
+ "mentioned_mobile_list": at_people_list,
+ },
+ }
+ message_json = json.dumps(msg)
+ info = requests.post(url=webhook, data=message_json, headers=header)
+ print(info.text)
+
+
+if __name__ == "__main__":
+ wechat_alert("测试机器人消息发送")
\ No newline at end of file
diff --git a/notification_helper.py b/notification_helper.py
new file mode 100644
index 0000000..d70d241
--- /dev/null
+++ b/notification_helper.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+# coding:utf-8
+
+class NotificationHelper:
+ def __init__(self, hook_url):
+ self.message = '########################################\n'
+ self.hook_url = hook_url
+ self.at_people_list = []
+
+ def append_at_people(self, people):
+ if people not in self.at_people_list:
+ self.at_people_list.append(people)
+
+ def get_people_list(self):
+ return self.at_people_list
+
+ def clear_msg(self):
+ self.message = '########################################\n'
+
+ def append_msg(self, msg):
+ print(msg)
+ self.message += msg + '\n'
+
+ def append_end_msg(self):
+ self.message += '########################################\n'
+
+ def get_msg(self):
+ return self.message
+
+ def get_hook_url(self):
+ return self.hook_url
diff --git a/utils.py b/utils.py
new file mode 100644
index 0000000..2d175bc
--- /dev/null
+++ b/utils.py
@@ -0,0 +1,254 @@
+#!/usr/bin/env python
+# coding:utf-8
+import glob
+import hashlib
+import json
+import os
+import sys
+import gzip
+import shutil
+import subprocess
+import zipfile
+
+curr_dir = os.path.split(os.path.abspath(__file__))[0]
+
+def write_json_file(filename, json):
+ """
+ 将JSON内容写入指定文件
+ :param filename: 文件路径
+ :param json: 要写入的JSON内容
+ :return: 无
+ """
+ # 确保文件所在目录存在
+ directory = os.path.dirname(filename)
+ if directory and not os.path.exists(directory):
+ os.makedirs(directory)
+
+ with open(filename, "w") as f:
+ f.write(json)
+ f.close()
+
+def write_json_file(folder, filename, json):
+ if not os.path.exists(folder):
+ os.mkdir(folder)
+ f = open(folder + '/' + filename, "w")
+ f.write(json)
+ f.close()
+
+
+def gzip_file(_in_file):
+ with open(_in_file, 'rb') as f_in:
+ with gzip.open(_in_file + '.gz', 'wb') as f_out:
+ shutil.copyfileobj(f_in, f_out)
+
+
+def zip_dir(dir_path, out_fullname):
+ """
+ 压缩指定文件夹
+ :param dir_path: 目标文件夹路径
+ :param out_fullname: 压缩文件报错路径+xxxx.zip
+ :return: 无
+ """
+ zip = zipfile.ZipFile(out_fullname, "w", zipfile.ZIP_DEFLATED)
+ for path, dirnames, filenames in os.walk(dir_path):
+ # 去掉目标跟路径,只对目标文件夹下边的文件及文件夹进行压缩
+ fpath = path.replace(dir_path, '')
+ for filename in filenames:
+ zip.write(os.path.join(path, filename), os.path.join(fpath, filename))
+ zip.close()
+
+
+def unzip_dir(zip_src, dst_dir):
+ """
+ 解压文件到指定文件夹
+ :param zip_src: zip文件
+ :param dst_dir: 解压目录
+ :return: 无
+ """
+ r = zipfile.is_zipfile(zip_src)
+ if r:
+ fz = zipfile.ZipFile(zip_src, 'r')
+ for file in fz.namelist():
+ fz.extract(file, dst_dir)
+ else:
+ print('%s This is not zip' % zip_src)
+
+
+def zip_file(file_path, out_fullname):
+ """
+ 压缩指定文件
+ :param file_path: 目标文件路径
+ :param out_fullname: 压缩文件保存路径+xxxx.zip
+ :return: 无
+ """
+ file_zip = zipfile.ZipFile(out_fullname, 'w')
+ file_zip.write(file_path, compress_type=zipfile.ZIP_DEFLATED)
+ file_zip.close()
+
+
+def unzip_file(zip_file_path, sp_path=""):
+ """
+ 解压文件
+ :param zip_file_path: zip文件路径
+ :param sp_path: 指定目录
+ :return: 无
+ """
+ file_zip = zipfile.ZipFile(zip_file_path)
+ sp_path = sp_path if sp_path != "" else "{}/../".format(os.path.splitext(zip_file_path)[0])
+ # 解压
+ file_zip.extractall(path=sp_path)
+
+
+def get_file_last_line(f_name):
+ """
+ :param f_name: f_name为所读xx.txt文件
+ :return: 文件最后一行
+ """
+ print(f_name)
+ with open(f_name, 'r') as f: # 打开文件
+ first_line = f.readline() # 读第一行
+ off = -50 # 设置偏移量
+ while True:
+ f.seek(off, 2) # seek(off, 2)表示文件指针:从文件末尾(2)开始向前50个字符(-50)
+ lines = f.readlines() # 读取文件指针范围内所有行
+ if len(lines) >= 2: # 判断是否最后至少有两行,这样保证了最后一行是完整的
+ last_line = lines[-1] # 取最后一行
+ break
+ # 如果off为50时得到的readlines只有一行内容,那么不能保证最后一行是完整的
+ # 所以off翻倍重新运行,直到readlines不止一行
+ off *= 2
+
+ print('文件' + f_name + '第一行为:' + first_line)
+ print('文件' + f_name + '最后一行为:' + last_line)
+ return last_line
+
+
+def open_json(path):
+ dic = {}
+ with open(path, 'r') as f:
+ dic = json.load(f)
+
+ return dic
+
+
+def write_json(path, content):
+ with open(path, 'w') as f:
+ json.dump(content, f)
+
+
+def calc_hash(filepath):
+ """
+ 根据文件内容,生成hash值
+ :param filepath: 文件路径
+ :return: hash code
+ """
+ with open(filepath, 'rb') as f:
+ sha1obj = hashlib.sha1()
+ sha1obj.update(f.read())
+ hash_code = sha1obj.hexdigest()
+ return hash_code
+
+
+def calc_md5(filepath):
+ """
+ 根据文件内容,生成md5码
+ :param filepath: 文件路径
+ :return: md5 code
+ """
+ with open(filepath, 'rb') as f:
+ md5obj = hashlib.md5(f.read())
+ md5_code = md5obj.hexdigest()
+ return md5_code
+
+
+def delete_files_with_extension(folder_path, extension):
+ """
+ 删除指定文件夹内指定后缀的文件
+ :param folder_path: 文件夹路径
+ :param extension: 后缀名称
+ :return: 无
+ """
+ # 获取指定文件夹内指定后缀的文件列表
+ files = glob.glob(os.path.join(folder_path, f"*.{extension}"))
+ # 遍历文件列表并删除文件
+ for file_path in files:
+ os.remove(file_path)
+
+
+def run_cmd(str_cmd, log_path=""):
+ if len(log_path) > 1:
+ logfile = open(log_path, "a")
+ logfile.writelines("-----------------------------")
+ logfile.writelines(str(str_cmd))
+
+ process = subprocess.Popen(
+ str_cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ print(str_cmd)
+ lines_out = process.stdout.readlines()
+ for line in lines_out:
+ print(line)
+ if len(log_path) > 1:
+ logfile.writelines(str(line))
+
+ lines_error = process.stderr.readlines()
+ if len(log_path) > 1 and len(lines_error) > 0:
+ logfile.writelines("has error:\n\n")
+ for line in lines_error:
+ print(line)
+ if len(log_path) > 1:
+ logfile.writelines(str(line))
+
+ print("end: " + str_cmd)
+ if len(log_path) > 0:
+ logfile.writelines("end: " + str_cmd)
+ logfile.close()
+
+ return lines_out, lines_error
+
+
+def mkdirs(dir_path: str):
+ if not os.path.exists(dir_path):
+ os.makedirs(dir_path)
+
+
+def clear_dirs(dir_path: str):
+ if os.path.exists(dir_path):
+ shutil.rmtree(dir_path)
+ os.makedirs(dir_path)
+
+
+def copy_dir(src_dir, dst_dir):
+ if not os.path.exists(src_dir):
+ return
+ if not os.path.exists(dst_dir):
+ os.makedirs(dst_dir)
+ for item in os.listdir(src_dir):
+ src_item = os.path.join(src_dir, item)
+ dst_item = os.path.join(dst_dir, item)
+ if os.path.isdir(src_item):
+ copy_dir(src_item, dst_item)
+ else:
+ shutil.copyfile(src_item, dst_item)
+
+
+def copy_file(src_thum_file, dst_thum_file):
+ if not os.path.exists(src_thum_file):
+ return
+ shutil.copyfile(src_thum_file, dst_thum_file)
+
+
+def get_bundle_file_path(bundle_dir_path):
+ """
+ 在指定目录中查找.bundle后缀文件,返回文件路径,不遍历子目录
+ :param bundle_dir_path: 目标文件夹路径
+ :return: .bundle文件路径,如果没找到则返回None
+ """
+ if not os.path.exists(bundle_dir_path):
+ return None
+
+ for file in os.listdir(bundle_dir_path):
+ file_path = os.path.join(bundle_dir_path, file)
+ if os.path.isfile(file_path) and file.endswith('.bundle'):
+ return file_path
+
+ return None
\ No newline at end of file