This is an automated email from the ASF dual-hosted git repository.

linkinstar pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-answer-plugins.git

commit b1e443772503752a64d810d3c452b9b6d62e2cbc
Author: Anan <[email protected]>
AuthorDate: Fri Oct 11 01:59:39 2024 +0000

    Fix readme and integrate notification
---
 user-center-slack/README.md           |  42 ++++++++++----
 user-center-slack/client.go           |   7 +--
 user-center-slack/config.go           |   3 +-
 user-center-slack/go.mod              |   7 ---
 user-center-slack/go.sum              |   6 +-
 user-center-slack/i18n/en_US.yaml     |   5 --
 user-center-slack/i18n/translation.go |  24 +++++++-
 user-center-slack/i18n/zh_CN.yaml     |  41 ++++++--------
 user-center-slack/notification.go     | 102 +++++++++++++++++-----------------
 user-center-slack/schema.go           |  33 +++++++++++
 user-center-slack/user_config.go      |  44 ++++++++++++++-
 11 files changed, 201 insertions(+), 113 deletions(-)

diff --git a/user-center-slack/README.md b/user-center-slack/README.md
index 753eec9..a15e890 100644
--- a/user-center-slack/README.md
+++ b/user-center-slack/README.md
@@ -1,20 +1,38 @@
-# WeCom User Center
+# Slack User Center
+
 ## Feature
-- User login via WeCom QRCode
+
+- User login via slack Account
 
 ## Config
-> You need to create a WeCom App first, and then get the `Corp ID`, `Agent ID` 
and `App Secret` from the App. 
 
-- `Company ID`: WeCom Corp ID
-- `App Secret`: WeCom App Secret
-- `App Agent ID`: WeCom App Agent ID
+To use this plugin, you need to create [a Slack 
App](https://api.slack.com/quickstart) first, set the Scope and Redirect URL 
correctly, and copy the `Client ID`, `Client Secrect`, `Signing Secret` and 
`Webhook URL`. To activate the Slash Command function, you also need to set the 
`slash command` in your app. Here are some examples:
+
+> Scope: chat:write, commands, groups:write, im:write, incoming-webhook, 
mpim:write, users:read, users:read.email
+>
+> RedirectURL: https://Your_Site_URL/answer/api/v1/user-center/login/callback
+>
+> Slash command: 
+>
+> * Command: /ask
+> * Requesti URL: https://Your_Site_URL/answer/api/v1/importer/command
+> * Usage Hint: [Title][Content\][Tag1,Tag2...\]
+
+
+
+- `Client ID`:  Slack App Client ID
+
+- `Client Secret`: Slack App Secret
+
+- `Signing Secret`: Slack App Signing Secret
+
+- `Webhook URL`: find in the `Incoming Webhooks` feature, such as 
`https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX`
 
-Note: WeCom restricts the ip address of the callback url, so you need to add 
the ip address of the server where the project is located to the callback url.
 
-## Preview
-![WeCom Config](./docs/wecom-config.png)
-![WeCom QRCode](./docs/wecom-qrcode.png)
-![WeCom Login](./docs/wecom-login.png)
+Note: A Redirect URL must also use HTTPS. You can configure a Redirect URL and 
scope in the **App Management** page under **OAuth & Permissions**. 
 
 ## Document
-- https://developer.work.weixin.qq.com/document/path/90664
\ No newline at end of file
+- https://api.slack.com/quickstart
+- https://api.slack.com/authentication/oauth-v2
+- https://api.slack.com/messaging/webhooks
+- https://api.slack.com/interactivity/slash-commands
\ No newline at end of file
diff --git a/user-center-slack/client.go b/user-center-slack/client.go
index 3525fd2..d6447b3 100644
--- a/user-center-slack/client.go
+++ b/user-center-slack/client.go
@@ -7,6 +7,7 @@ import (
        "net/http"
        "net/url"
 
+       "github.com/apache/incubator-answer/plugin"
        "github.com/go-resty/resty/v2"
        "github.com/segmentfault/pacman/log"
 )
@@ -18,7 +19,6 @@ type SlackClient struct {
        RedirectURI  string
        AuthedUserID string
 
-       Enabled         bool // 用户是否启用的标记
        UserInfoMapping map[string]*UserInfo
        ChannelMapping  string
 }
@@ -86,7 +86,7 @@ type Member struct {
 func (sc *SlackClient) AuthUser(code string) (info *UserInfo, err error) {
        clientID := sc.ClientID
        clientSecret := sc.ClientSecret
-       redirectURI := 
fmt.Sprintf("%s/answer/api/v1/user-center/login/callback", "https://as.0vo.lol";)
+       redirectURI := 
fmt.Sprintf("%s/answer/api/v1/user-center/login/callback", plugin.SiteURL())
 
        data := url.Values{}
        data.Set("code", code)
@@ -117,12 +117,9 @@ func (sc *SlackClient) AuthUser(code string) (info 
*UserInfo, err error) {
                return nil, fmt.Errorf("Slack API error in AuthUser: %s", 
tokenResp.Error)
        }
 
-       sc.Enabled = true
-       // sc.AccessToken = tokenResp.AccessToken
        sc.AccessToken = tokenResp.AccessToken
        sc.AuthedUserID = tokenResp.AuthedUser.ID
 
-       // Get user detailed information
        return sc.GetUserDetailInfo(sc.AuthedUserID)
 }
 
diff --git a/user-center-slack/config.go b/user-center-slack/config.go
index 561fdf0..897c7a5 100644
--- a/user-center-slack/config.go
+++ b/user-center-slack/config.go
@@ -41,7 +41,6 @@ func NewSlackClientWithConfig(clientID, clientSecret, 
redirectURI string) *Slack
                ClientID:     clientID,
                ClientSecret: clientSecret,
                RedirectURI:  redirectURI,
-               Enabled:      true,
        }
 }
 
@@ -84,7 +83,7 @@ func (uc *UserCenter) ConfigFields() []plugin.ConfigField {
                        UIOptions: plugin.ConfigFieldUIOptions{
                                Text: syncNowLabel,
                                Action: &plugin.UIOptionAction{
-                                       Url:    "/answer/admin/api/slack/sync", 
// 修改为 Slack 的同步 URL
+                                       Url:    "/answer/admin/api/slack/sync",
                                        Method: "get",
                                        Loading: &plugin.LoadingAction{
                                                Text:  
plugin.MakeTranslator(i18n.ConfigSyncNowLabelForDoing),
diff --git a/user-center-slack/go.mod b/user-center-slack/go.mod
index f81ef78..9543b42 100644
--- a/user-center-slack/go.mod
+++ b/user-center-slack/go.mod
@@ -9,10 +9,8 @@ require (
        github.com/apache/incubator-answer-plugins/util v1.0.2
        github.com/gin-gonic/gin v1.10.0
        github.com/go-resty/resty/v2 v2.15.1
-       github.com/jarcoal/httpmock v1.3.1
        github.com/patrickmn/go-cache v2.1.0+incompatible
        github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f
-       github.com/stretchr/testify v1.9.0
 )
 
 require (
@@ -22,7 +20,6 @@ require (
        github.com/bytedance/sonic/loader v0.2.0 // indirect
        github.com/cloudwego/base64x v0.1.4 // indirect
        github.com/cloudwego/iasm v0.2.0 // indirect
-       github.com/davecgh/go-spew v1.1.1 // indirect
        github.com/gabriel-vasile/mimetype v1.4.5 // indirect
        github.com/gin-contrib/sse v0.1.0 // indirect
        github.com/go-playground/locales v0.14.1 // indirect
@@ -41,7 +38,6 @@ require (
        github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // 
indirect
        github.com/modern-go/reflect2 v1.0.2 // indirect
        github.com/pelletier/go-toml/v2 v2.2.3 // indirect
-       github.com/pmezard/go-difflib v1.0.0 // indirect
        github.com/segmentfault/pacman/contrib/i18n 
v0.0.0-20230516093754-b76aef1c1150 // indirect
        github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
        github.com/ugorji/go/codec v1.2.12 // indirect
@@ -55,6 +51,3 @@ require (
        gopkg.in/yaml.v3 v3.0.1 // indirect
        sigs.k8s.io/yaml v1.3.0 // indirect
 )
-
-// replace github.com/Anan1225/incubator-answer-plugins/user-center-slack => 
/root/incubator-answer-plugins/user-center-slack
-replace github.com/apache/incubator-answer => ../../incubator-answer
diff --git a/user-center-slack/go.sum b/user-center-slack/go.sum
index f235a5a..99544a6 100644
--- a/user-center-slack/go.sum
+++ b/user-center-slack/go.sum
@@ -2,6 +2,8 @@ github.com/BurntSushi/toml v1.0.0 
h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU
 github.com/BurntSushi/toml v1.0.0/go.mod 
h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/LinkinStars/go-i18n/v2 v2.2.2 
h1:ZfjpzbW13dv6btv3RALKZkpN9A+7K1JA//2QcNeWaxU=
 github.com/LinkinStars/go-i18n/v2 v2.2.2/go.mod 
h1:hLglSJ4/3M0Y7ZVcoEJI+OwqkglHCA32DdjuJJR2LbM=
+github.com/apache/incubator-answer v1.4.0 
h1:W3y4TAQ4sdzgcqntGqNBPe0BdyeW7+l8FWYBDs9g8+Y=
+github.com/apache/incubator-answer v1.4.0/go.mod 
h1:Q4NkQmBd0sV7t3Cd8NBsWh9w8jFRo/2qjzOw9MlRNwk=
 github.com/apache/incubator-answer-plugins/util v1.0.2 
h1:PontocVaiEm+oTj+4aDonwWDZnxywUeHsaTwlQgclfA=
 github.com/apache/incubator-answer-plugins/util v1.0.2/go.mod 
h1:KPMSiM4ec4uEl2njaGINYuSl6zVmHdvPB2nHUxVcQDo=
 github.com/aymerick/douceur v0.2.0 
h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
@@ -46,8 +48,6 @@ github.com/google/wire v0.5.0 
h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
 github.com/google/wire v0.5.0/go.mod 
h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
 github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
 github.com/gorilla/css v1.0.0/go.mod 
h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
-github.com/jarcoal/httpmock v1.3.1 
h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww=
-github.com/jarcoal/httpmock v1.3.1/go.mod 
h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
 github.com/json-iterator/go v1.1.12 
h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod 
h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/klauspost/cpuid/v2 v2.0.9/go.mod 
h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@@ -62,8 +62,6 @@ github.com/leodido/go-urn v1.4.0 
h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
 github.com/leodido/go-urn v1.4.0/go.mod 
h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
 github.com/mattn/go-isatty v0.0.20 
h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod 
h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/maxatome/go-testdeep v1.12.0 
h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g=
-github.com/maxatome/go-testdeep v1.12.0/go.mod 
h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=
 github.com/microcosm-cc/bluemonday v1.0.21 
h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
 github.com/microcosm-cc/bluemonday v1.0.21/go.mod 
h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod 
h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
diff --git a/user-center-slack/i18n/en_US.yaml 
b/user-center-slack/i18n/en_US.yaml
index 90ac7ef..90d7645 100644
--- a/user-center-slack/i18n/en_US.yaml
+++ b/user-center-slack/i18n/en_US.yaml
@@ -49,11 +49,6 @@ plugin:
             other: Manual Sync Contacts
           description:
             other: Last successful sync
-        authorize_url:
-          title:
-            other: Authorize URL
-          description:
-            other: Slack authorize URL
         client_id:
           title:
             other: Client ID
diff --git a/user-center-slack/i18n/translation.go 
b/user-center-slack/i18n/translation.go
index b2e13ea..188fad2 100644
--- a/user-center-slack/i18n/translation.go
+++ b/user-center-slack/i18n/translation.go
@@ -42,6 +42,8 @@ const (
        ConfigNotificationTitle        = 
"plugin.slack_user_center.backend.config.notification.title"
        ConfigNotificationDescription  = 
"plugin.slack_user_center.backend.config.notification.description"
 
+       UserConfigWebhookURLTitle = 
"plugin.slack_user_center.backend.user_config.webhook_url.title"
+
        UserConfigInboxNotificationsTitle       = 
"plugin.slack_user_center.backend.user_config.inbox_notifications.title"
        UserConfigInboxNotificationsLabel       = 
"plugin.slack_user_center.backend.user_config.inbox_notifications.label"
        UserConfigInboxNotificationsDescription = 
"plugin.slack_user_center.backend.user_config.inbox_notifications.description"
@@ -54,9 +56,25 @@ const (
        UserConfigNewQuestionsForFollowingTagsLabel       = 
"plugin.slack_user_center.backend.user_config.new_questions_for_following_tags.label"
        UserConfigNewQuestionsForFollowingTagsDescription = 
"plugin.slack_user_center.backend.user_config.new_questions_for_following_tags.description"
 
-       TplUpdateQuestion     = 
"plugin.slack_user_center.backend.tpl.update_question"
+       UserConfigUpvotedAnswersTitle       = 
"plugin.slack_user_center.backend.user_config.upvoted_answers.title"
+       UserConfigUpvotedAnswersLabel       = 
"plugin.slack_user_center.backend.user_config.upvoted_answers.label"
+       UserConfigUpvotedAnswersDescription = 
"plugin.slack_user_center.backend.user_config.upvoted_answers.description"
+
+       UserConfigDownvotedAnswersTitle       = 
"plugin.slack_user_center.backend.user_config.downvoted_answers.title"
+       UserConfigDownvotedAnswersLabel       = 
"plugin.slack_user_center.backend.user_config.downvoted_answers.label"
+       UserConfigDownvotedAnswersDescription = 
"plugin.slack_user_center.backend.user_config.downvoted_answers.description"
+
+       UserConfigUpdatedQuestionsTitle       = 
"plugin.slack_user_center.backend.user_config.updated_questions.title"
+       UserConfigUpdatedQuestionsLabel       = 
"plugin.slack_user_center.backend.user_config.updated_questions.label"
+       UserConfigUpdatedQuestionsDescription = 
"plugin.slack_user_center.backend.user_config.updated_questions.description"
+
+       UserConfigUpdatedAnswersTitle       = 
"plugin.slack_user_center.backend.user_config.updated_answers.title"
+       UserConfigUpdatedAnswersLabel       = 
"plugin.slack_user_center.backend.user_config.updated_answers.label"
+       UserConfigUpdatedAnswersDescription = 
"plugin.slack_user_center.backend.user_config.updated_answers.description"
+
+       TplUpdatedQuestions   = 
"plugin.slack_user_center.backend.tpl.update_question"
        TplAnswerTheQuestion  = 
"plugin.slack_user_center.backend.tpl.answer_the_question"
-       TplUpdateAnswer       = 
"plugin.slack_user_center.backend.tpl.update_answer"
+       TplUpdatedAnswers     = 
"plugin.slack_user_center.backend.tpl.update_answer"
        TplAcceptAnswer       = 
"plugin.slack_user_center.backend.tpl.accept_answer"
        TplCommentQuestion    = 
"plugin.slack_user_center.backend.tpl.comment_question"
        TplCommentAnswer      = 
"plugin.slack_user_center.backend.tpl.comment_answer"
@@ -64,4 +82,6 @@ const (
        TplMentionYou         = 
"plugin.slack_user_center.backend.tpl.mention_you"
        TplInvitedYouToAnswer = 
"plugin.slack_user_center.backend.tpl.invited_you_to_answer"
        TplNewQuestion        = 
"plugin.slack_user_center.backend.tpl.new_question"
+       TplUpvotedAnswer      = 
"plugin.slack_user_center.backend.tpl.upvoted_answer"
+       TplDownvotedAnswer    = 
"plugin.slack_user_center.backend.tpl.downvoted_answer"
 )
diff --git a/user-center-slack/i18n/zh_CN.yaml 
b/user-center-slack/i18n/zh_CN.yaml
index 9ff875a..f369ac8 100644
--- a/user-center-slack/i18n/zh_CN.yaml
+++ b/user-center-slack/i18n/zh_CN.yaml
@@ -21,14 +21,14 @@ plugin:
       response:
         sync_now:
           success:
-            other: 联系人同步成功。
+            other: 同步成功。
           failed:
-            other: 联系人同步失败。
+            other: 同步失败。
       info:
         name:
-          other: 企业微信
+          other: Slack
         description:
-          other: 从企业微信获取用户信息并同步到用户中心
+          other: 通过Slack进行登录
       config:
         tip:
           title:
@@ -37,7 +37,7 @@ plugin:
           label:
             other: 打开自动同步
           title:
-            other: 自动同步联系人
+            other: 自动同步
           description:
             other: 每小时自动同步。
         sync_now:
@@ -46,36 +46,31 @@ plugin:
           label_for_doing:
             other: 同步中
           title:
-            other: 手动同步联系人
+            other: 手动同步
           description:
             other: 上次成功同步于
-        authorize_url:
+        client_id:
           title:
-            other: 授权网址
+            other: Client ID
           description:
-            other: 企业微信授权网址
-        corp_id:
+            other: Slack client ID
+        client_secret:
           title:
-            other: 企业 ID
+            other: Client Secret
           description:
-            other: 企业微信企业ID
-        corp_secret:
-          title:
-            other: 应用 Secret
-          description:
-            other: 企业微信应用程序密钥
-        agent_id:
-          title:
-            other: 应用 Agent ID
-          description:
-            other: 企业微信应用程序代理ID
+            other: Slack client secret
         notification:
           label:
             other: 打开通知
           title:
             other: 通知
           description:
-            other: 用户将在企业微信上收到通知。
+            other: 用户将在Slack上收到通知。
+        signing_secret:
+            title:
+              other: Signing Secret
+            description:
+              other: Slack signing secret
       user_config:
         inbox_notifications:
           title:
diff --git a/user-center-slack/notification.go 
b/user-center-slack/notification.go
index 5e754d0..a08b40d 100644
--- a/user-center-slack/notification.go
+++ b/user-center-slack/notification.go
@@ -1,15 +1,11 @@
 package slack_user_center
 
 import (
-       "encoding/json"
-       "fmt"
-       "io/ioutil"
-       "net/http"
-       "net/url"
        "strings"
 
        slackI18n 
"github.com/Anan1225/incubator-answer-plugins/user-center-slack/i18n"
        "github.com/apache/incubator-answer/plugin"
+       "github.com/go-resty/resty/v2"
        "github.com/segmentfault/pacman/i18n"
        "github.com/segmentfault/pacman/log"
 )
@@ -24,7 +20,7 @@ func (uc *UserCenter) GetNewQuestionSubscribers() (userIDs 
[]string) {
        return userIDs
 }
 
-// Notify sends a notification to the user using Slack
+// Notify sends a notification to the user
 func (uc *UserCenter) Notify(msg plugin.NotificationMessage) {
        log.Debugf("try to send notification %+v", msg)
 
@@ -55,6 +51,25 @@ func (uc *UserCenter) Notify(msg plugin.NotificationMessage) 
{
                        log.Debugf("user %s not config the new question 
followed tag", msg.ReceiverUserID)
                        return
                }
+       case plugin.NotificationUpVotedTheAnswer:
+               if !userConfig.UpvotedAnswers {
+                       log.Debugf("user %s not config the new upvoted 
answers", msg.ReceiverUserID)
+               }
+       case plugin.NotificationDownVotedTheAnswer:
+               if !userConfig.DownvotedAnswers {
+                       log.Debugf("user %s not config the new downvoted 
answers", msg.ReceiverUserID)
+               }
+
+       case plugin.NotificationUpdateQuestion:
+               if !userConfig.UpdatedQuestions {
+                       log.Debugf("user %s not config the update question", 
msg.ReceiverUserID)
+                       return
+               }
+       case plugin.NotificationUpdateAnswer:
+               if !userConfig.UpdatedAnswers {
+                       log.Debugf("user %s not config the update answer", 
msg.ReceiverUserID)
+                       return
+               }
        default:
                if !userConfig.InboxNotifications {
                        log.Debugf("user %s not config the inbox notification", 
msg.ReceiverUserID)
@@ -63,6 +78,31 @@ func (uc *UserCenter) Notify(msg plugin.NotificationMessage) 
{
        }
 
        log.Debugf("user %s config the notification", msg.ReceiverUserID)
+
+       if len(userConfig.WebhookURL) == 0 {
+               log.Errorf("user %s has no webhook url", msg.ReceiverUserID)
+               return
+       }
+
+       notificationMsg := renderNotification(msg)
+       // no need to send empty message
+       if len(notificationMsg) == 0 {
+               log.Debugf("this type of notification will be drop, the type is 
%s", msg.Type)
+               return
+       }
+
+       // Create a Resty Client
+       client := resty.New()
+       resp, err := client.R().
+               SetHeader("Content-Type", "application/json").
+               SetBody(NewWebhookReq(notificationMsg)).
+               Post(userConfig.WebhookURL)
+
+       if err != nil {
+               log.Errorf("send message failed: %v %v", err, resp)
+       } else {
+               log.Infof("send message to %s success, resp: %s", 
msg.ReceiverUserID, resp.String())
+       }
 }
 
 // renderNotification generates the notification message based on type
@@ -70,11 +110,11 @@ func renderNotification(msg plugin.NotificationMessage) 
string {
        lang := i18n.Language(msg.ReceiverLang)
        switch msg.Type {
        case plugin.NotificationUpdateQuestion:
-               return plugin.TranslateWithData(lang, 
slackI18n.TplUpdateQuestion, msg)
+               return plugin.TranslateWithData(lang, 
slackI18n.TplUpdatedQuestions, msg)
        case plugin.NotificationAnswerTheQuestion:
                return plugin.TranslateWithData(lang, 
slackI18n.TplAnswerTheQuestion, msg)
        case plugin.NotificationUpdateAnswer:
-               return plugin.TranslateWithData(lang, 
slackI18n.TplUpdateAnswer, msg)
+               return plugin.TranslateWithData(lang, 
slackI18n.TplUpdatedAnswers, msg)
        case plugin.NotificationAcceptAnswer:
                return plugin.TranslateWithData(lang, 
slackI18n.TplAcceptAnswer, msg)
        case plugin.NotificationCommentQuestion:
@@ -90,48 +130,10 @@ func renderNotification(msg plugin.NotificationMessage) 
string {
        case plugin.NotificationNewQuestion, 
plugin.NotificationNewQuestionFollowedTag:
                msg.QuestionTags = strings.Join(strings.Split(msg.QuestionTags, 
","), ", ")
                return plugin.TranslateWithData(lang, slackI18n.TplNewQuestion, 
msg)
+       case plugin.NotificationUpVotedTheAnswer:
+               return plugin.TranslateWithData(lang, 
slackI18n.TplUpvotedAnswer, msg)
+       case plugin.NotificationDownVotedTheAnswer:
+               return plugin.TranslateWithData(lang, 
slackI18n.TplDownvotedAnswer, msg)
        }
        return ""
 }
-
-// SendMessage sends a message to a Slack user using Slack API
-func (sc *SlackClient) SendMessage(userID string, message string) error {
-       data := url.Values{}
-       data.Set("channel", userID) // Slack user ID or channel ID
-       data.Set("text", message)
-
-       req, err := http.NewRequest("POST", 
"https://slack.com/api/chat.postMessage";, strings.NewReader(data.Encode()))
-       if err != nil {
-               return err
-       }
-
-       req.Header.Add("Authorization", "Bearer "+sc.AccessToken)
-       req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
-
-       client := &http.Client{}
-       resp, err := client.Do(req)
-       if err != nil {
-               return err
-       }
-       defer resp.Body.Close()
-
-       body, err := ioutil.ReadAll(resp.Body)
-       if err != nil {
-               return err
-       }
-
-       var result struct {
-               OK    bool   `json:"ok"`
-               Error string `json:"error"`
-       }
-
-       if err := json.Unmarshal(body, &result); err != nil {
-               return err
-       }
-
-       if !result.OK {
-               return fmt.Errorf("Slack API error: %s", result.Error)
-       }
-
-       return nil
-}
diff --git a/user-center-slack/schema.go b/user-center-slack/schema.go
index 3713895..defbec2 100644
--- a/user-center-slack/schema.go
+++ b/user-center-slack/schema.go
@@ -66,3 +66,36 @@ type UserInfo struct {
        Enable      bool  `json:"true"`
        Status      int   `json:"status"`
 }
+
+type WebhookReq struct {
+       Blocks []struct {
+               Type string `json:"type"`
+               Text struct {
+                       Type string `json:"type"`
+                       Text string `json:"text"`
+               } `json:"text"`
+       } `json:"blocks"`
+}
+
+func NewWebhookReq(content string) *WebhookReq {
+       return &WebhookReq{
+               Blocks: []struct {
+                       Type string `json:"type"`
+                       Text struct {
+                               Type string `json:"type"`
+                               Text string `json:"text"`
+                       } `json:"text"`
+               }{
+                       {
+                               Type: "section",
+                               Text: struct {
+                                       Type string `json:"type"`
+                                       Text string `json:"text"`
+                               }{
+                                       Type: "mrkdwn",
+                                       Text: content,
+                               },
+                       },
+               },
+       }
+}
diff --git a/user-center-slack/user_config.go b/user-center-slack/user_config.go
index 428253f..e39c3a8 100644
--- a/user-center-slack/user_config.go
+++ b/user-center-slack/user_config.go
@@ -30,9 +30,14 @@ import (
 )
 
 type UserConfig struct {
-       InboxNotifications           bool `json:"inbox_notifications"`
-       AllNewQuestions              bool `json:"all_new_questions"`
-       NewQuestionsForFollowingTags bool 
`json:"new_questions_for_following_tags"`
+       WebhookURL                   string `json:"webhook_url"`
+       InboxNotifications           bool   `json:"inbox_notifications"`
+       AllNewQuestions              bool   `json:"all_new_questions"`
+       NewQuestionsForFollowingTags bool   
`json:"new_questions_for_following_tags"`
+       UpvotedAnswers               bool   `json:"upvoted_answers"`
+       DownvotedAnswers             bool   `json:"downvoted_answers"`
+       UpdatedQuestions             bool   `json:"updated_questions"`
+       UpdatedAnswers               bool   `json:"updated_answers"`
 }
 
 type UserConfigCache struct {
@@ -69,6 +74,15 @@ func (uc *UserCenter) UserConfigFields() 
[]plugin.ConfigField {
                        },
                })
        }
+       fields = append(fields, plugin.ConfigField{
+               Name:     "webhook_url",
+               Type:     plugin.ConfigTypeInput,
+               Title:    plugin.MakeTranslator(i18n.UserConfigWebhookURLTitle),
+               Required: true,
+               UIOptions: plugin.ConfigFieldUIOptions{
+                       InputType: plugin.InputTypeText,
+               },
+       })
        fields = append(fields, createSwitchConfig(
                "inbox_notifications",
                i18n.UserConfigInboxNotificationsTitle,
@@ -87,6 +101,30 @@ func (uc *UserCenter) UserConfigFields() 
[]plugin.ConfigField {
                i18n.UserConfigNewQuestionsForFollowingTagsLabel,
                i18n.UserConfigNewQuestionsForFollowingTagsDescription,
        ))
+       fields = append(fields, createSwitchConfig(
+               "upvoted_answers",
+               i18n.UserConfigUpvotedAnswersTitle,
+               i18n.UserConfigUpvotedAnswersLabel,
+               i18n.UserConfigUpvotedAnswersDescription,
+       ))
+       fields = append(fields, createSwitchConfig(
+               "downvoted_answers",
+               i18n.UserConfigDownvotedAnswersTitle,
+               i18n.UserConfigDownvotedAnswersLabel,
+               i18n.UserConfigDownvotedAnswersDescription,
+       ))
+       fields = append(fields, createSwitchConfig(
+               "updated_questions",
+               i18n.UserConfigUpdatedQuestionsTitle,
+               i18n.UserConfigUpdatedQuestionsLabel,
+               i18n.UserConfigUpdatedQuestionsDescription,
+       ))
+       fields = append(fields, createSwitchConfig(
+               "updated_answers",
+               i18n.UserConfigUpdatedAnswersTitle,
+               i18n.UserConfigUpdatedAnswersLabel,
+               i18n.UserConfigUpdatedAnswersDescription,
+       ))
        return fields
 }
 

Reply via email to