瀏覽代碼

feat: support Discord now

JustSong 2 年之前
父節點
當前提交
cfdc4ce357
共有 6 個文件被更改,包括 88 次插入2 次删除
  1. 1 1
      README.md
  2. 54 0
      channel/discord.go
  3. 3 0
      channel/main.go
  4. 1 0
      controller/user.go
  5. 2 1
      model/user.go
  6. 27 0
      web/src/components/PushSetting.js

+ 1 - 1
README.md

@@ -50,7 +50,7 @@ _✨ 搭建专属于你的消息推送服务,支持多种消息推送方式,
    + Bark App,
    + WebSocket 客户端([官方客户端](https://github.com/songquanpeng/personal-assistant),[接入文档](./docs/API.md#websocket-客户端)),
    + Telegram 机器人,
-   + Discord 群机器人(WIP)
+   + Discord 群机器人,
 2. 多种用户登录注册方式:
    + 邮箱登录注册以及通过邮箱进行密码重置。
    + [GitHub 开放授权](https://github.com/settings/applications/new)。

+ 54 - 0
channel/discord.go

@@ -0,0 +1,54 @@
+package channel
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"message-pusher/model"
+	"net/http"
+)
+
+type discordMessageRequest struct {
+	Content string `json:"content"`
+}
+
+type discordMessageResponse struct {
+	Code    int    `json:"code"`
+	Message string `json:"message"`
+}
+
+func SendDiscordMessage(message *model.Message, user *model.User) error {
+	if user.DiscordWebhookURL == "" {
+		return errors.New("未配置 Discord 群机器人消息推送方式")
+	}
+	if message.Content == "" {
+		message.Content = message.Description
+	}
+	messageRequest := discordMessageRequest{
+		Content: message.Content,
+	}
+
+	jsonData, err := json.Marshal(messageRequest)
+	if err != nil {
+		return err
+	}
+	resp, err := http.Post(user.DiscordWebhookURL, "application/json", bytes.NewBuffer(jsonData))
+	if err != nil {
+		return err
+	}
+	if resp.StatusCode == http.StatusNoContent {
+		return nil
+	}
+	var res discordMessageResponse
+	err = json.NewDecoder(resp.Body).Decode(&res)
+	if err != nil {
+		return err
+	}
+	if res.Code != 0 {
+		return errors.New(res.Message)
+	}
+	if resp.StatusCode == http.StatusBadRequest {
+		return errors.New(resp.Status)
+	}
+	return nil
+}

+ 3 - 0
channel/main.go

@@ -13,6 +13,7 @@ const (
 	TypeLark              = "lark"
 	TypeDing              = "ding"
 	TypeTelegram          = "telegram"
+	TypeDiscord           = "discord"
 	TypeBark              = "bark"
 	TypeClient            = "client"
 	TypeNone              = "none"
@@ -38,6 +39,8 @@ func SendMessage(message *model.Message, user *model.User) error {
 		return SendClientMessage(message, user)
 	case TypeTelegram:
 		return SendTelegramMessage(message, user)
+	case TypeDiscord:
+		return SendDiscordMessage(message, user)
 	case TypeNone:
 		return nil
 	default:

+ 1 - 0
controller/user.go

@@ -425,6 +425,7 @@ func UpdateSelf(c *gin.Context) {
 		ClientSecret:                       user.ClientSecret,
 		TelegramBotToken:                   user.TelegramBotToken,
 		TelegramChatId:                     user.TelegramChatId,
+		DiscordWebhookURL:                  user.DiscordWebhookURL,
 	}
 	channel.TokenStoreUpdateUser(&cleanUser, originUser)
 

+ 2 - 1
model/user.go

@@ -41,6 +41,7 @@ type User struct {
 	ClientSecret                       string `json:"client_secret"`
 	TelegramBotToken                   string `json:"telegram_bot_token"`
 	TelegramChatId                     string `json:"telegram_chat_id"`
+	DiscordWebhookURL                  string `json:"discord_webhook_url"`
 }
 
 func GetMaxUserId() int {
@@ -77,7 +78,7 @@ func GetUserById(id int, selectAll bool) (*User, error) {
 			"channel", "token",
 			"wechat_test_account_id", "wechat_test_account_template_id", "wechat_test_account_open_id",
 			"wechat_corp_account_id", "wechat_corp_account_agent_id", "wechat_corp_account_user_id", "wechat_corp_account_client_type",
-			"corp_webhook_url", "lark_webhook_url", "ding_webhook_url", "bark_server", "telegram_chat_id",
+			"corp_webhook_url", "lark_webhook_url", "ding_webhook_url", "bark_server", "telegram_chat_id", "discord_webhook_url",
 		}).First(&user, "id = ?", id).Error
 	}
 	return &user, err

+ 27 - 0
web/src/components/PushSetting.js

@@ -35,6 +35,7 @@ const PushSetting = () => {
     client_secret: '',
     telegram_bot_token: '',
     telegram_chat_id: '',
+    discord_webhook_url: '',
   });
   let [loading, setLoading] = useState(false);
 
@@ -117,6 +118,9 @@ const PushSetting = () => {
         data.telegram_bot_token = inputs.telegram_bot_token;
         data.telegram_chat_id = inputs.telegram_chat_id;
         break;
+      case 'discord':
+        data.discord_webhook_url = inputs.discord_webhook_url;
+        break;
       default:
         showError(`无效的参数:${which}`);
         return;
@@ -188,6 +192,7 @@ const PushSetting = () => {
                 { key: 'bark', text: 'Bark App', value: 'bark' },
                 { key: 'client', text: 'WebSocket 客户端', value: 'client' },
                 { key: 'telegram', text: 'Telegram 机器人', value: 'telegram' },
+                { key: 'discord', text: 'Discord 群机器人', value: 'discord' },
               ]}
               value={inputs.channel}
               onChange={handleInputChange}
@@ -551,6 +556,28 @@ const PushSetting = () => {
             保存
           </Button>
           <Button onClick={() => test('telegram')}>测试</Button>
+          <Divider />
+          <Header as='h3'>
+            Discord 群机器人设置(discord)
+            <Header.Subheader>
+              通过 Discord 群机器人进行推送,配置流程:选择一个 channel -> 设置
+              -> 整合 -> 创建 Webhook -> 点击复制 Webhook URL
+            </Header.Subheader>
+          </Header>
+          <Form.Group widths={2}>
+            <Form.Input
+              label='Webhook 地址'
+              name='discord_webhook_url'
+              onChange={handleInputChange}
+              autoComplete='off'
+              value={inputs.discord_webhook_url}
+              placeholder='在此填写 Discord 提供的 Webhook 地址'
+            />
+          </Form.Group>
+          <Button onClick={() => submit('discord')} loading={loading}>
+            保存
+          </Button>
+          <Button onClick={() => test('discord')}>测试</Button>
         </Form>
       </Grid.Column>
     </Grid>