Skip to content

Commit

Permalink
Merge pull request #79 from Cassius0924/feat-discord-message-forwarding
Browse files Browse the repository at this point in the history
  • Loading branch information
Cassius0924 authored Mar 4, 2024
2 parents 705fc11 + 4fc0eec commit 379a3b9
Show file tree
Hide file tree
Showing 13 changed files with 242 additions and 68 deletions.
35 changes: 17 additions & 18 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
default_language_version:
python: python3.8

python: python3.8
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.14
hooks:
- id: ruff
- id: ruff-format
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
name: isort (python)
- repo: https://github.com/PyCQA/bandit
rev: 1.7.7
hooks:
- id: bandit
args: ['-c', 'pyproject.toml']

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.14
hooks:
- id: ruff
- id: ruff-format
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
name: isort (python)
- repo: https://github.com/PyCQA/bandit
rev: 1.7.7
hooks:
- id: bandit
args: ['-c', 'pyproject.toml']
additional_dependencies: ["bandit[toml]"]
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ python3 -m wechatter

## 支持的命令

- [x] GPT 问答,基于 [Copilot-GPT4-Service](https://github.com/aaamoon/copilot-gpt4-service)(不支持定时任务)
- [x] GPT 问答(不支持定时任务)
- [x] Bilibili 热搜
- [x] 知乎热搜
- [x] 微博热搜
Expand Down Expand Up @@ -115,6 +115,7 @@ python3 -m wechatter
![official_account_reminder_show](docs/images/official_account_reminder_show.png)

- [x] **定时任务**:大部分命令均支持定时任务。需进行[配置](#%EF%B8%8F-task-cron-配置)
- [x] **Discord 消息转发**:基于 Discord Webhook,将微信消息转发到 Discord 频道。需进行[配置](#%EF%B8%8F-discord-message-forwarding-配置)

## 支持的游戏

Expand Down Expand Up @@ -169,12 +170,12 @@ python3 -m wechatter
| `command_prefix` | 机器人命令前缀 | 默认为 `/` ,可以设置为`>>``!` 等任意字符 |
| `need_mentioned` | 群聊中的命令是否需要@机器人 | 默认为 `True` |

### ⚙️ Copilot GPT4 配置
### ⚙️ LLM 配置

| 配置项 | 解释 | 备注 |
| --- | --- | --- |
| `cp_gpt4_base_api` | CopilotGPT4 服务的 BaseAPI | 默认为 `http://localhost:8080` |
| `cp_token` | GitHub Copilot 的 Token |`ghu_` 开头的字符串 |
| `openai_base_api` | OpenAI 服务的 BaseAPI | 默认为 `https://api.openai.com` |
| `openai_token` | OpenAI Token(Key) |`sk_` 开头的字符串密钥 |

### ⚙️ GitHub Webhook 配置

Expand All @@ -190,7 +191,7 @@ python3 -m wechatter
| 配置项 | 子项 | 解释 | 备注 |
| --- | --- | --- | --- |
| `message_forwarding_enabled` | | 功能开关,是否开启消息转发 | 默认为 `False` |
| `message_forwarding_rule_list` | | 消息规则列表,每个规则包含三个字段`from_list``to_person_list``to_group_list` | |
| `message_forwarding_rule_list` | | 消息规则列表,每个规则包含四个字段`from_list``from_list_exclude``to_person_list``to_group_list` | |
| | `from_list` | 消息转发来源列表,即消息发送者 | 可以填多个用户名称或群名称,若要转发所有消息则使用 `["%ALL"]` |
| | `from_list_exclude` | 消息转发来源排除列表,不转发此列表的用户和群 | 只在 `from_list``["%ALL"]` 时生效 |
| | `to_person_list` | 消息转发目标用户列表,即消息接收用户 | 可以填多个用户名称或为空列表 |
Expand Down Expand Up @@ -223,6 +224,17 @@ python3 -m wechatter

关于命令名称可选值请参阅[自定义命令关键词配置详细](docs/custom_command_key_config_detail.md)

### ⚙️ Discord Message Forwarding 配置

| 配置项 | 解释 | 备注 |
| --- | --- | --- |
| `discord_message_forwarding_enabled` | 功能开关,是否开启 Discord 消息转发 | 默认为 `False` |
| `discord_message_forwarding_rule_list` | 消息规则列表,每个规则包含三个字段:`from_list``to_discord_webhook_url``to_discord_webhook_name` | |
| | `from_list` | 消息转发来源列表,即消息发送者 | 可以填多个用户名称或群名称,若要转发所有消息则使用 `["%ALL"]` |
| | `from_list_exclude` | 消息转发来源排除列表,不转发此列表的用户和群 | 只在 `from_list``["%ALL"]` 时生效 |
| | `discord_webhook_url` | 消息转发目标 Discord Webhook URL | |


## 日志文件

日志文件存放在项目根目录下的 `logs/` 文件夹中。
Expand Down
Empty file removed atest.py
Empty file.
16 changes: 12 additions & 4 deletions config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ command_prefix: /
need_mentioned: False


# Copilot GPT4
cp_gpt4_base_api: http://localhost:999
cp_token: ghu_your_token
# LLM
openai_base_api: https://api.openai.com
openai_token: sk_your_openai_token


# GitHub Webhook
Expand Down Expand Up @@ -83,4 +83,12 @@ custom_command_key_dict:
gpt4: [ ">" ]
bili-hot: [ "bh" ]
play: [ "p" ]
weather: [ "w", "温度" ]
weather: [ "w", "温度" ]


# Discord Message Forwarding:Discord 消息转发
discord_message_forwarding_enabled: True
discord_message_forwarding_rule_list:
- from_list: [ "%ALL" ]
from_list_exclude: [ "" ]
webhook_url: "your_discord_webhook_url"
12 changes: 5 additions & 7 deletions wechatter/commands/_commands/copilot_gpt4.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from loguru import logger

import wechatter.utils.path_manager as pm
from wechatter.commands.handlers import command
from wechatter.config import config
from wechatter.database import (
Expand All @@ -16,9 +15,9 @@
from wechatter.sender import sender
from wechatter.utils import post_request_json
from wechatter.utils.time import get_current_date, get_current_time, get_current_week
from wechatter.utils.url_joiner import join_urls

DEFAULT_TOPIC = "(对话进行中*)"
# DEFAULT_MODEL = "gpt-4"
# TODO: 初始化对话,Prompt选择
DEFAULT_CONVERSATION = [
{
Expand Down Expand Up @@ -197,9 +196,8 @@ def _gptx_continue(model: str, to: SendTo, message: str = "") -> None:


class CopilotGPT4:
api = f"{config['cp_gpt4_base_api']}/v1/chat/completions"
bearer_token = "Bearer " + config["cp_token"]
save_path = pm.get_abs_path("data/copilot_gpt4/chats/")
chat_api = join_urls(config["openai_base_api"], "v1/chat/completions")
token = "Bearer " + config["openai_token"]

@staticmethod
def create_chat(person: Person, model: str) -> GptChatInfo:
Expand Down Expand Up @@ -428,15 +426,15 @@ def _chat(chat_info: GptChatInfo, message: str, message_obj, is_save: bool) -> s
newconv = [{"role": "user", "content": message}]
# 发送请求
headers = {
"Authorization": CopilotGPT4.bearer_token,
"Authorization": CopilotGPT4.token,
"Content-Type": "application/json",
}
json = {
"model": chat_info.model,
"messages": DEFAULT_CONVERSATION + chat_info.get_conversation() + newconv,
}
r_json = post_request_json(
url=CopilotGPT4.api, headers=headers, json=json, timeout=60
url=CopilotGPT4.chat_api, headers=headers, json=json, timeout=60
)

# 判断是否有 error 或 code 字段
Expand Down
4 changes: 4 additions & 0 deletions wechatter/config/parsers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from .discord_message_forwarding_rule_list_parser import (
parse_discord_message_forwarding_rule_list,
)
from .message_forwarding_rule_list_parser import parse_message_forwarding_rule_list
from .official_account_reminder_rule_list_parser import (
parse_official_account_reminder_rule_list,
Expand All @@ -8,4 +11,5 @@
"parse_task_cron_list",
"parse_message_forwarding_rule_list",
"parse_official_account_reminder_rule_list",
"parse_discord_message_forwarding_rule_list",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import Dict, List, Tuple


def parse_discord_message_forwarding_rule_list(rule_list: List) -> Tuple[Dict, Dict]:
"""
解析消息转发规则列表
:param rule_list: 消息转发规则列表
:return: 转发规则元组,第一个元素为全局转发规则,第二个元素为特定转发规则
"""
all_message_rule = {
"is_none": True,
"from_list_exclude": [],
"webhook_url": "",
}
specific_message_rules = {}
for rule in rule_list:
if "%ALL" in rule["from_list"]:
all_message_rule["is_none"] = False
all_message_rule["from_list_exclude"].extend(
rule.get("from_list_exclude", [])
)
all_message_rule["webhook_url"] = rule["webhook_url"]
else:
for from_name in rule["from_list"]:
if from_name not in specific_message_rules:
specific_message_rules[from_name] = {
"webhook_url": [],
}
specific_message_rules[from_name]["webhook_url"] = rule["webhook_url"]
return all_message_rule, specific_message_rules
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ def parse_message_forwarding_rule_list(rule_list: List) -> Tuple[Dict, Dict]:
:return: 转发规则元组,第一个元素为全局转发规则,第二个元素为特定转发规则
"""
all_message_rule = {
"is_none": True,
"from_list_exclude": [],
"to_group_list": [],
"to_person_list": [],
}
specific_message_rules = {}
for rule in rule_list:
if "%ALL" in rule["from_list"]:
all_message_rule["is_none"] = False
all_message_rule["from_list_exclude"].extend(
rule.get("from_list_exclude", [])
)
Expand Down
19 changes: 15 additions & 4 deletions wechatter/config/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"bot_name",
"command_prefix",
"need_mentioned",
"cp_gpt4_base_api",
"cp_token",
"openai_base_api",
"openai_token",
"github_webhook_enabled",
"github_webhook_api_path",
"message_forwarding_enabled",
Expand All @@ -18,6 +18,8 @@
"official_account_reminder_rule_list",
"all_task_cron_enabled",
"task_cron_list",
"discord_message_forwarding_enabled",
"discord_message_forwarding_rule_list",
]


Expand Down Expand Up @@ -45,10 +47,10 @@ def validate_config(config):
# raise ValueError(error_msg)

# 定时任务配置
task_cron_ess_fields = ["task", "cron", "commands"]
ess_fields = ["task", "cron", "commands"]
for i, task_cron in enumerate(config["task_cron_list"]):
# task_cron_list 字段验证
for field in task_cron_ess_fields:
for field in ess_fields:
if field not in task_cron:
error_msg = f"配置参数错误:task_cron_list[{i}] 缺少必要字段 {field}"
logger.critical(error_msg)
Expand All @@ -73,4 +75,13 @@ def validate_config(config):
logger.critical(error_msg)
raise ValueError(error_msg)

# Discord 消息转发配置
ess_fields = ["from_list", "webhook_url"]
for i, rule in enumerate(config["discord_message_forwarding_rule_list"]):
for field in ess_fields:
if field not in rule:
error_msg = f"配置参数错误:discord_message_forwarding_rule_list[{i}] 缺少必要字段 {field}"
logger.critical(error_msg)
raise ValueError(error_msg)

logger.info("配置文件验证通过!")
Loading

0 comments on commit 379a3b9

Please sign in to comment.