Files

453 lines
21 KiB
Python
Raw Permalink Normal View History

2022-12-18 14:03:34 +08:00
# encoding:utf-8
2026-01-30 09:53:46 +08:00
import copy
2022-12-13 01:50:43 +08:00
import json
2023-04-04 14:02:14 +08:00
import logging
2022-12-13 01:50:43 +08:00
import os
2023-04-04 00:59:21 +08:00
import pickle
2022-12-13 01:50:43 +08:00
2023-04-17 01:00:08 +08:00
from common.log import logger
# 将所有可用的配置项写在字典里, 请使用小写字母
# 此处的配置值无实际意义程序不会读取此处的配置仅用于提示格式请将配置加入到config.json中
2023-03-27 14:40:19 +08:00
available_setting = {
# openai api配置
"open_ai_api_key": "", # openai api key
# openai apibase当use_azure_chatgpt为true时需要设置对应的api base
"open_ai_api_base": "https://api.openai.com/v1",
"claude_api_base": "https://api.anthropic.com/v1", # claude api base
"gemini_api_base": "https://generativelanguage.googleapis.com", # gemini api base
2023-03-27 14:40:19 +08:00
"proxy": "", # openai使用的代理
# chatgpt模型 当use_azure_chatgpt为true时其名称为Azure上model deployment名称
2024-07-19 11:04:45 +08:00
"model": "gpt-3.5-turbo", # 可选择: gpt-4o, pt-4o-mini, gpt-4-turbo, claude-3-sonnet, wenxin, moonshot, qwen-turbo, xunfei, glm-4, minimax, gemini等模型全部可选模型详见common/const.py文件
"bot_type": "", # 可选配置使用兼容openai格式的三方服务时候需填"chatGPT"。bot具体名称详见common/const.py文件列出的bot_type如不填根据model名称判断
2023-03-27 14:40:19 +08:00
"use_azure_chatgpt": False, # 是否使用azure的chatgpt
2023-04-17 01:00:08 +08:00
"azure_deployment_id": "", # azure 模型部署名称
"azure_api_version": "", # azure api版本
2023-03-27 14:40:19 +08:00
# Bot触发配置
"single_chat_prefix": ["bot", "@bot"], # 私聊时文本需要包含该前缀才能触发机器人回复
"single_chat_reply_prefix": "[bot] ", # 私聊时自动回复的前缀,用于区分真人
2023-08-30 20:49:00 +08:00
"single_chat_reply_suffix": "", # 私聊时自动回复的后缀,\n 可以换行
"group_chat_prefix": ["@bot"], # 群聊时包含该前缀则会触发机器人回复
"no_need_at": False, # 群聊回复时是否不需要艾特
2023-03-27 14:40:19 +08:00
"group_chat_reply_prefix": "", # 群聊时自动回复的前缀
"group_chat_reply_suffix": "", # 群聊时自动回复的后缀,\n 可以换行
2023-03-27 14:40:19 +08:00
"group_chat_keyword": [], # 群聊时包含该关键词则会触发机器人回复
"group_at_off": False, # 是否关闭群聊时@bot的触发
"group_name_white_list": ["ChatGPT测试群", "ChatGPT测试群2"], # 开启自动回复的群名称列表
"group_name_keyword_white_list": [], # 开启自动回复的群名称关键词列表
"group_chat_in_one_session": ["ChatGPT测试群"], # 支持会话上下文共享的群名称
2026-03-12 17:08:09 +08:00
"group_shared_session": False, # 群聊是否共享会话上下文所有成员共享。False时每个用户在群内有独立会话
2023-11-27 14:38:45 +08:00
"nick_name_black_list": [], # 用户昵称黑名单
2024-06-12 19:14:09 +08:00
"group_welcome_msg": "", # 配置新人进群固定欢迎语,不配置则使用随机风格欢迎
2023-04-03 23:58:19 +08:00
"trigger_by_self": False, # 是否允许机器人触发
"text_to_image": "dall-e-2", # 图片生成模型,可选 dall-e-2, dall-e-3
# Azure OpenAI dall-e-3 配置
"dalle3_image_style": "vivid", # 图片生成dalle3的风格可选有 vivid, natural
"dalle3_image_quality": "hd", # 图片生成dalle3的质量可选有 standard, hd
# Azure OpenAI DALL-E API 配置, 当use_azure_chatgpt为true时,用于将文字回复的资源和Dall-E的资源分开.
"azure_openai_dalle_api_base": "", # [可选] azure openai 用于回复图片的资源 endpoint默认使用 open_ai_api_base
"azure_openai_dalle_api_key": "", # [可选] azure openai 用于回复图片的资源 key默认使用 open_ai_api_key
"azure_openai_dalle_deployment_id":"", # [可选] azure openai 用于回复图片的资源 deployment id默认使用 text_to_image
"image_proxy": True, # 是否需要图片代理国内访问LinkAI时需要
2023-03-27 14:40:19 +08:00
"image_create_prefix": ["", "", ""], # 开启图片回复的前缀
2023-04-17 01:00:08 +08:00
"concurrency_in_session": 1, # 同一会话最多有多少条消息在处理中大于1可能乱序
"image_create_size": "256x256", # 图片大小,可选有 256x256, 512x512, 1024x1024 (dall-e-3默认为1024x1024)
2024-06-12 19:14:09 +08:00
"group_chat_exit_group": False,
2023-03-27 14:40:19 +08:00
# chatgpt会话参数
"expires_in_seconds": 3600, # 无操作会话的过期时间
# 人格描述
"character_desc": "你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。",
2023-03-27 14:40:19 +08:00
"conversation_max_tokens": 1000, # 支持上下文记忆的最多字符数
# chatgpt限流配置
"rate_limit_chatgpt": 20, # chatgpt的调用频率限制
"rate_limit_dalle": 50, # openai dalle的调用频率限制
# chatgpt api参数 参考https://platform.openai.com/docs/api-reference/chat/create
2023-03-25 18:08:37 +08:00
"temperature": 0.9,
"top_p": 1,
"frequency_penalty": 0,
"presence_penalty": 0,
"request_timeout": 180, # chatgpt请求超时时间openai接口默认设置为600对于难问题一般需要较长时间
2023-04-17 01:00:08 +08:00
"timeout": 120, # chatgpt重试超时时间在这个时间内将会自动重试
2023-07-25 09:52:47 +08:00
# Baidu 文心一言参数
2023-08-25 16:06:55 +08:00
"baidu_wenxin_model": "eb-instant", # 默认使用ERNIE-Bot-turbo模型
"baidu_wenxin_api_key": "", # Baidu api key
"baidu_wenxin_secret_key": "", # Baidu secret key
2024-08-16 14:58:17 +08:00
"baidu_wenxin_prompt_enabled": False, # Enable prompt if you are using ernie character model
2023-08-25 16:06:55 +08:00
# 讯飞星火API
"xunfei_app_id": "", # 讯飞应用ID
"xunfei_api_key": "", # 讯飞 API key
"xunfei_api_secret": "", # 讯飞 API secret
"xunfei_domain": "", # 讯飞模型对应的domain参数Spark4.0 Ultra为 4.0Ultra,其他模型详见: https://www.xfyun.cn/doc/spark/Web.html
"xunfei_spark_url": "", # 讯飞模型对应的请求地址Spark4.0 Ultra为 wss://spark-api.xf-yun.com/v4.0/chat其他模型参考详见: https://www.xfyun.cn/doc/spark/Web.html
2023-09-01 11:32:58 +08:00
# claude 配置
"claude_api_cookie": "",
"claude_uuid": "",
2024-03-12 10:39:51 +08:00
# claude api key
2024-06-12 19:14:09 +08:00
"claude_api_key": "",
# 通义千问API, 获取方式查看文档 https://help.aliyun.com/document_detail/2587494.html
2023-12-08 14:12:21 +08:00
"qwen_access_key_id": "",
"qwen_access_key_secret": "",
"qwen_agent_key": "",
"qwen_app_id": "",
"qwen_node_id": "", # 流程编排模型用到的id如果没有用到qwen_node_id请务必保持为空字符串
2024-06-05 00:44:08 +08:00
# 阿里灵积(通义新版sdk)模型api key
"dashscope_api_key": "",
2023-12-15 10:19:48 +08:00
# Google Gemini Api Key
"gemini_api_key": "",
2023-09-01 11:32:58 +08:00
# wework的通用配置
"wework_smart": True, # 配置wework是否使用已登录的企业微信False为多开
2023-03-27 14:40:19 +08:00
# 语音设置
"speech_recognition": True, # 是否开启语音识别
2023-03-27 14:40:19 +08:00
"group_speech_recognition": False, # 是否开启群组语音识别
"voice_reply_voice": False, # 是否使用语音回复语音需要设置对应语音合成引擎的api key
2023-04-01 22:27:11 +08:00
"always_reply_voice": False, # 是否一直使用语音回复
2024-07-19 15:46:19 +08:00
"voice_to_text": "openai", # 语音识别引擎支持openai,baidu,google,azure,xunfei,ali
"text_to_voice": "openai", # 语音合成引擎支持openai,baidu,google,azure,xunfei,ali,pytts(offline),elevenlabs,edge(online)
2023-11-10 10:48:52 +08:00
"text_to_voice_model": "tts-1",
"tts_voice_id": "alloy",
2023-04-01 16:36:27 +08:00
# baidu 语音api配置 使用百度语音识别和语音合成时需要
2023-03-27 14:40:19 +08:00
"baidu_app_id": "",
"baidu_api_key": "",
"baidu_secret_key": "",
# 1536普通话(支持简单的英文识别) 1737英语 1637粤语 1837四川话 1936普通话远场
2024-05-21 22:32:35 +08:00
"baidu_dev_pid": 1536,
2023-04-01 16:36:27 +08:00
# azure 语音api配置 使用azure语音识别和语音合成时需要
"azure_voice_api_key": "",
"azure_voice_region": "japaneast",
2023-08-19 11:20:47 +08:00
# elevenlabs 语音api配置
2024-06-12 19:14:09 +08:00
"xi_api_key": "", # 获取ap的方法可以参考https://docs.elevenlabs.io/api-reference/quick-start/authentication
"xi_voice_id": "", # ElevenLabs提供了9种英式、美式等英语发音id分别是“Adam/Antoni/Arnold/Bella/Domi/Elli/Josh/Rachel/Sam”
2023-03-27 14:40:19 +08:00
# 服务时间限制目前支持itchat
"chat_time_module": False, # 是否开启服务时间限制
"chat_start_time": "00:00", # 服务开始时间
"chat_stop_time": "24:00", # 服务结束时间
2023-04-23 03:51:09 +08:00
# 翻译api
"translate": "baidu", # 翻译api支持baidu
# baidu翻译api的配置
"baidu_translate_app_id": "", # 百度翻译api的appid
"baidu_translate_app_key": "", # 百度翻译api的秘钥
2023-03-25 18:08:37 +08:00
# itchat的配置
2023-03-27 14:40:19 +08:00
"hot_reload": False, # 是否开启热重载
# wechaty的配置
2023-03-27 14:40:19 +08:00
"wechaty_puppet_service_token": "", # wechaty的token
2023-03-30 01:01:00 +08:00
# wechatmp的配置
2023-04-17 01:00:08 +08:00
"wechatmp_token": "", # 微信公众平台的Token
"wechatmp_port": 8080, # 微信公众平台的端口,需要端口转发到80或443
"wechatmp_app_id": "", # 微信公众平台的appID
"wechatmp_app_secret": "", # 微信公众平台的appsecret
"wechatmp_aes_key": "", # 微信公众平台的EncodingAESKey加密模式需要
# wechatcom的通用配置
"wechatcom_corp_id": "", # 企业微信公司的corpID
# wechatcomapp的配置
"wechatcomapp_token": "", # 企业微信app的token
"wechatcomapp_port": 9898, # 企业微信app的服务端口,不需要端口转发
"wechatcomapp_secret": "", # 企业微信app的secret
"wechatcomapp_agent_id": "", # 企业微信app的agent_id
"wechatcomapp_aes_key": "", # 企业微信app的aes_key
# 飞书配置
"feishu_port": 80, # 飞书bot监听端口
2023-11-23 22:05:10 +08:00
"feishu_app_id": "", # 飞书机器人应用APP Id
"feishu_app_secret": "", # 飞书机器人APP secret
"feishu_token": "", # 飞书 verification token
"feishu_bot_name": "", # 飞书机器人的名字
2026-01-31 12:32:41 +08:00
"feishu_event_mode": "websocket", # 飞书事件接收模式: webhook(HTTP服务器) 或 websocket(长连接)
# 钉钉配置
"dingtalk_client_id": "", # 钉钉机器人Client ID
2024-06-04 11:23:45 +08:00
"dingtalk_client_secret": "", # 钉钉机器人Client Secret
"dingtalk_card_enabled": False,
2023-03-25 18:08:37 +08:00
# chatgpt指令自定义触发词
2023-04-17 01:00:08 +08:00
"clear_memory_commands": ["#清除记忆"], # 重置会话指令,必须以#开头
2023-03-30 16:06:57 +08:00
# channel配置
2026-02-26 18:34:08 +08:00
"channel_type": "", # 通道类型,支持多渠道同时运行。单个: "feishu",多个: "feishu, dingtalk" 或 ["feishu", "dingtalk"]。可选值: web,feishu,dingtalk,wechatmp,wechatmp_service,wechatcom_app
"web_console": True, # 是否自动启动Web控制台默认启动。设为False可禁用
"subscribe_msg": "", # 订阅消息, 支持: wechatmp, wechatmp_service, wechatcom_app
2023-04-04 14:02:14 +08:00
"debug": False, # 是否开启debug模式开启后会打印更多日志
2023-04-17 01:24:39 +08:00
"appdata_dir": "", # 数据目录
2023-04-05 05:37:06 +08:00
# 插件配置
"plugin_trigger_prefix": "$", # 规范插件提供聊天相关指令的前缀,建议不要和管理员指令前缀"#"冲突
2023-07-28 16:33:41 +08:00
# 是否使用全局插件配置
"use_global_plugin_config": False,
2024-06-12 19:14:09 +08:00
"max_media_send_count": 3, # 单次最大发送媒体资源的个数
"media_send_interval": 1, # 发送图片的事件间隔,单位秒
2024-02-05 12:15:28 +08:00
# 智谱AI 平台配置
"zhipu_ai_api_key": "",
"zhipu_ai_api_base": "https://open.bigmodel.cn/api/paas/v4",
"moonshot_api_key": "",
"moonshot_base_url": "https://api.moonshot.cn/v1",
2026-02-15 00:02:50 +08:00
# 豆包(火山方舟) 平台配置
"ark_api_key": "",
"ark_base_url": "https://ark.cn-beijing.volces.com/api/v3",
2025-03-11 11:12:57 +08:00
#魔搭社区 平台配置
"modelscope_api_key": "",
"modelscope_base_url": "https://api-inference.modelscope.cn/v1/chat/completions",
# LinkAI平台配置
2023-06-08 23:57:59 +08:00
"use_linkai": False,
2023-05-29 15:52:26 +08:00
"linkai_api_key": "",
2023-08-22 11:09:01 +08:00
"linkai_app_code": "",
2024-05-03 14:10:07 +08:00
"linkai_api_base": "https://api.link-ai.tech", # linkAI服务地址
2026-02-23 15:06:31 +08:00
"cloud_host": "client.link-ai.tech",
2026-03-11 19:42:37 +08:00
"cloud_deployment_id": "",
2026-02-03 00:43:42 +08:00
"minimax_api_key": "",
2024-06-12 19:14:09 +08:00
"Minimax_group_id": "",
"Minimax_base_url": "",
2024-11-26 14:09:20 +08:00
"web_port": 9899,
2026-02-02 11:58:19 +08:00
"agent": True, # 是否开启Agent模式
2026-02-01 12:31:58 +08:00
"agent_workspace": "~/cow", # agent工作空间路径用于存储skills、memory等
"agent_max_context_tokens": 50000, # Agent模式下最大上下文tokens
2026-02-02 12:03:16 +08:00
"agent_max_context_turns": 30, # Agent模式下最大上下文记忆轮次
"agent_max_steps": 15, # Agent模式下单次运行最大决策步数
2023-03-25 18:08:37 +08:00
}
2023-03-27 14:40:19 +08:00
2023-03-25 18:08:37 +08:00
class Config(dict):
def __init__(self, d=None):
super().__init__()
if d is None:
d = {}
for k, v in d.items():
self[k] = v
2023-04-04 00:59:21 +08:00
# user_datas: 用户数据key为用户名value为用户数据也是dict
self.user_datas = {}
2023-03-25 18:08:37 +08:00
def __getitem__(self, key):
2026-01-31 12:32:41 +08:00
# 跳过以下划线开头的注释字段
if not key.startswith("_") and key not in available_setting:
logger.warning("[Config] key '{}' not in available_setting, may not take effect".format(key))
2023-03-25 18:08:37 +08:00
return super().__getitem__(key)
def __setitem__(self, key, value):
2026-01-31 12:32:41 +08:00
# 跳过以下划线开头的注释字段
if not key.startswith("_") and key not in available_setting:
logger.warning("[Config] key '{}' not in available_setting, may not take effect".format(key))
2023-03-25 18:08:37 +08:00
return super().__setitem__(key, value)
def get(self, key, default=None):
2026-01-31 12:50:21 +08:00
# 跳过以下划线开头的注释字段
if key.startswith("_"):
return super().get(key, default)
# 如果key不在available_setting中直接返回default
if key not in available_setting:
return super().get(key, default)
2023-03-27 14:40:19 +08:00
try:
2023-03-25 18:08:37 +08:00
return self[key]
except KeyError as e:
return default
except Exception as e:
raise e
2023-03-27 14:40:19 +08:00
2023-04-04 00:59:21 +08:00
# Make sure to return a dictionary to ensure atomic
def get_user_data(self, user) -> dict:
if self.user_datas.get(user) is None:
self.user_datas[user] = {}
return self.user_datas[user]
def load_user_datas(self):
try:
2023-04-17 01:24:39 +08:00
with open(os.path.join(get_appdata_dir(), "user_datas.pkl"), "rb") as f:
2023-04-04 00:59:21 +08:00
self.user_datas = pickle.load(f)
2026-02-02 12:18:57 +08:00
logger.debug("[Config] User datas loaded.")
2023-04-04 00:59:21 +08:00
except FileNotFoundError as e:
2026-02-07 11:17:58 +08:00
logger.debug("[Config] User datas file not found, ignore.")
2023-04-04 00:59:21 +08:00
except Exception as e:
2026-02-07 11:17:58 +08:00
logger.warning("[Config] User datas error: {}".format(e))
2023-04-04 00:59:21 +08:00
self.user_datas = {}
def save_user_datas(self):
try:
2023-04-17 01:24:39 +08:00
with open(os.path.join(get_appdata_dir(), "user_datas.pkl"), "wb") as f:
2023-04-04 00:59:21 +08:00
pickle.dump(self.user_datas, f)
logger.info("[Config] User datas saved.")
except Exception as e:
logger.info("[Config] User datas error: {}".format(e))
2023-03-27 14:40:19 +08:00
2023-04-17 01:00:08 +08:00
2023-03-25 18:08:37 +08:00
config = Config()
2022-12-13 01:50:43 +08:00
2023-03-27 14:40:19 +08:00
2024-05-13 19:53:33 +08:00
def drag_sensitive(config):
2024-06-04 12:50:59 +08:00
try:
if isinstance(config, str):
conf_dict: dict = json.loads(config)
conf_dict_copy = copy.deepcopy(conf_dict)
for key in conf_dict_copy:
if "key" in key or "secret" in key:
if isinstance(conf_dict_copy[key], str):
2024-06-04 12:50:59 +08:00
conf_dict_copy[key] = conf_dict_copy[key][0:3] + "*" * 5 + conf_dict_copy[key][-3:]
return json.dumps(conf_dict_copy, indent=4)
2024-05-13 19:53:33 +08:00
2024-06-04 12:50:59 +08:00
elif isinstance(config, dict):
config_copy = copy.deepcopy(config)
for key in config:
if "key" in key or "secret" in key:
if isinstance(config_copy[key], str):
2024-06-04 12:50:59 +08:00
config_copy[key] = config_copy[key][0:3] + "*" * 5 + config_copy[key][-3:]
return config_copy
except Exception as e:
logger.exception(e)
return config
2024-05-13 19:53:33 +08:00
return config
2022-12-13 01:50:43 +08:00
def load_config():
global config
2026-02-02 12:18:57 +08:00
# 打印 ASCII Logo
logger.info(" ____ _ _ ")
logger.info(" / ___|_____ __ / \\ __ _ ___ _ __ | |_ ")
logger.info("| | / _ \\ \\ /\\ / // _ \\ / _` |/ _ \\ '_ \\| __|")
logger.info("| |__| (_) \\ V V // ___ \\ (_| | __/ | | | |_ ")
logger.info(" \\____\\___/ \\_/\\_//_/ \\_\\__, |\\___|_| |_|\\__|")
logger.info(" |___/ ")
2026-02-02 12:25:47 +08:00
logger.info("")
config_path = "./config.json"
2022-12-19 01:25:34 +08:00
if not os.path.exists(config_path):
2023-04-17 01:00:08 +08:00
logger.info("配置文件不存在将使用config-template.json模板")
2023-03-25 10:02:19 +08:00
config_path = "./config-template.json"
2022-12-19 01:25:34 +08:00
config_str = read_file(config_path)
2024-06-04 12:50:59 +08:00
logger.debug("[INIT] config str: {}".format(drag_sensitive(config_str)))
2023-03-26 02:00:35 +08:00
2022-12-19 01:25:34 +08:00
# 将json字符串反序列化为dict类型
2023-03-25 18:08:37 +08:00
config = Config(json.loads(config_str))
2023-03-25 10:02:19 +08:00
# override config with environment variables.
# Some online deployment platforms (e.g. Railway) deploy project from github directly. So you shouldn't put your secrets like api key in a config file, instead use environment variables to override the default config.
for name, value in os.environ.items():
name = name.lower()
2026-01-31 12:32:41 +08:00
# 跳过以下划线开头的注释字段
if name.startswith("_"):
continue
2023-03-25 18:08:37 +08:00
if name in available_setting:
2023-04-22 12:01:29 +08:00
logger.info("[INIT] override config by environ args: {}={}".format(name, value))
try:
config[name] = eval(value)
except Exception:
if value == "false":
config[name] = False
elif value == "true":
config[name] = True
else:
config[name] = value
2023-03-25 10:02:19 +08:00
2023-04-04 15:59:56 +08:00
if config.get("debug", False):
2023-04-04 14:02:14 +08:00
logger.setLevel(logging.DEBUG)
2023-04-17 01:00:08 +08:00
logger.debug("[INIT] set log level to DEBUG")
2023-04-04 14:02:14 +08:00
2024-06-04 12:50:59 +08:00
logger.info("[INIT] load config: {}".format(drag_sensitive(config)))
2022-12-19 01:25:34 +08:00
2026-02-02 12:18:57 +08:00
# 打印系统初始化信息
logger.info("[INIT] ========================================")
logger.info("[INIT] System Initialization")
logger.info("[INIT] ========================================")
logger.info("[INIT] Channel: {}".format(config.get("channel_type", "unknown")))
logger.info("[INIT] Model: {}".format(config.get("model", "unknown")))
# Agent模式信息
if config.get("agent", False):
workspace = config.get("agent_workspace", "~/cow")
logger.info("[INIT] Mode: Agent (workspace: {})".format(workspace))
else:
2026-02-02 12:25:47 +08:00
logger.info("[INIT] Mode: Chat (在config.json中设置 \"agent\":true 可启用Agent模式)")
2026-02-02 12:18:57 +08:00
logger.info("[INIT] Debug: {}".format(config.get("debug", False)))
logger.info("[INIT] ========================================")
2026-03-09 11:37:45 +08:00
# Sync selected config values to environment variables so that
# subprocesses (e.g. shell skill scripts) can access them directly.
# Existing env vars are NOT overwritten (env takes precedence).
_CONFIG_TO_ENV = {
"open_ai_api_key": "OPENAI_API_KEY",
"open_ai_api_base": "OPENAI_API_BASE",
"linkai_api_key": "LINKAI_API_KEY",
"linkai_api_base": "LINKAI_API_BASE",
"claude_api_key": "CLAUDE_API_KEY",
"claude_api_base": "CLAUDE_API_BASE",
"gemini_api_key": "GEMINI_API_KEY",
"gemini_api_base": "GEMINI_API_BASE",
"minimax_api_key": "MINIMAX_API_KEY",
"minimax_api_base": "MINIMAX_API_BASE",
"zhipu_ai_api_key": "ZHIPU_AI_API_KEY",
"zhipu_ai_api_base": "ZHIPU_AI_API_BASE",
"moonshot_api_key": "MOONSHOT_API_KEY",
"moonshot_api_base": "MOONSHOT_API_BASE",
"ark_api_key": "ARK_API_KEY",
"ark_api_base": "ARK_API_BASE",
}
injected = 0
for conf_key, env_key in _CONFIG_TO_ENV.items():
if env_key not in os.environ:
val = config.get(conf_key, "")
if val:
os.environ[env_key] = str(val)
injected += 1
if injected:
logger.info("[INIT] Synced {} config values to environment variables".format(injected))
2023-04-04 00:59:21 +08:00
config.load_user_datas()
2022-12-13 01:50:43 +08:00
2023-04-17 01:00:08 +08:00
2022-12-13 01:50:43 +08:00
def get_root():
2023-03-27 14:40:19 +08:00
return os.path.dirname(os.path.abspath(__file__))
2022-12-13 01:50:43 +08:00
def read_file(path):
2023-04-17 01:00:08 +08:00
with open(path, mode="r", encoding="utf-8") as f:
2022-12-13 01:50:43 +08:00
return f.read()
def conf():
return config
2023-04-17 01:24:39 +08:00
def get_appdata_dir():
data_path = os.path.join(get_root(), conf().get("appdata_dir", ""))
if not os.path.exists(data_path):
logger.info("[INIT] data path not exists, create it: {}".format(data_path))
os.makedirs(data_path)
2023-04-17 01:24:39 +08:00
return data_path
def subscribe_msg():
trigger_prefix = conf().get("single_chat_prefix", [""])[0]
msg = conf().get("subscribe_msg", "")
return msg.format(trigger_prefix=trigger_prefix)
# global plugin config
plugin_config = {}
def write_plugin_config(pconf: dict):
"""
写入插件全局配置
:param pconf: 全量插件配置
"""
global plugin_config
for k in pconf:
plugin_config[k.lower()] = pconf[k]
def remove_plugin_config(name: str):
"""
移除待重新加载的插件全局配置
:param name: 待重载的插件名
"""
global plugin_config
plugin_config.pop(name.lower(), None)
def pconf(plugin_name: str) -> dict:
"""
根据插件名称获取配置
:param plugin_name: 插件名称
:return: 该插件的配置项
"""
return plugin_config.get(plugin_name.lower())
2023-07-28 12:40:06 +08:00
# 全局配置,用于存放全局生效的状态
2024-06-12 19:14:09 +08:00
global_config = {"admin_users": []}