<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
這些天在學習Go,也寫了幾篇關於閱讀Gin後端專案程式碼的部落格。但程式設計這種,一定要實際上手練習,要不然都是紙上談兵。於是就想上手自己實際寫一些程式碼來練練手。思來想去,不知道能寫些什麼來練手。後來突然想到,之前寫過用Python做微信聊天機器人(部落格傳送門),當時程式碼沒有放到git上,後來重置了伺服器導致程式碼全部沒了。現在正好苦於不知道做什麼專案練手,可以用Go也實現一套微信聊天機器人。
說幹就幹,照著之前自己寫的部落格,看了下當時Python的程式碼。轉而用Go優化了下並實現。
根據之前Python寫的自動發訊息的機器人可知,要想發訊息就需要三個引數:company_id、secret、angent_id。 對於這三個引數如何獲取,可參考文章開頭的傳送門。整個傳送訊息過程就是 首先通過company_id和secret來呼叫介面獲取token,再通過token和angent_id來給對應介面傳送post請求,就可以把post請求體中的資訊傳送到微信上。
由於目前對Go的專案佈局學習的還不是特別熟練,而且對於專案基礎部分如果從頭開始做的話,需要耗費大量時間。因此我使用了基於開源gin專案進行二次開發的方法,實現這個機器人。
前幾天在學習Gin時,發現了一位老哥封裝了個Gin腳手架,可以達到開箱即用目的。專案地址: github傳送門。 裡邊把讀取組態檔,編寫路由,連線資料庫等多個操作均進行了實現。因此可以基於這個專案來進行二次開發,做微信機器人。
在把專案clone下來後,可以先看下整個專案的佈局,主要的業務核心程式碼都放在了internal 下面。如果我們要實現一個主動給微信發訊息的功能,那麼多說了就是寫一個傳送訊息的方法,讓後端呼叫這個方法即可。
要想基於此專案來開發微信機器人,首先就要將三個引數設定上。專案中,對於各種引數均在config.yaml中設定,因為可以在這個組態檔中增加這三個引數的設定:
然後在程式碼的config/autoload目錄下新增一個weCaht.go 檔案,接收組態檔中的設定。
package autoload type WeChatConfig struct { AgentId string ini:"wechat" yaml:"agent_id" Secret string ini:"wechat" yaml:"secret" CompanyId string ini:"wechat" yaml:"company_id" } var WeChat = WeChatConfig{}
並且,將此設定加入到專案的設定集合中。在config/config.go中新增如下程式碼:
這樣操作,就可以通過程式碼來讀取組態檔了。在其他包中,可以通過如下方式來存取對應的值
config.Config.WeChat.CompanyId //yaml中的company_id欄位
因為要給微信傳送訊息,首先要獲取到token,而官方介紹此token的有效時長為2小時。在之前Python的專案中,是直接將token寫到了檔案中,通過檔案來讀取。在此專案中,我想直接使用redis來儲存。因為使用redis來儲存的話,可以設定key值時長,過了這個時長就自動清除,這樣就方便了許多。
而我們基於這個gin-layout專案中,已經對redis做了一層封裝,具體程式碼可檢視data/redis.go,主要是通過對外暴露一個Rdb的結構體,來操作redis
而目前我們這邊使用redis,只會用到對應的set和get方法。因此我對這個專案中的redis又做了一層封裝。只對外暴露set,get,del方法。
首先將Rdb變數名改為小寫,這樣就代表不對外暴露,然後在此檔案中新增如下程式碼
func SetRedis(key string, value string, t int64) bool { expire := time.Duration(t) * time.Second if err := rdb.Set(ctx, key, value, expire).Err(); err != nil { return false } return true } func GetRedis(key string) string { result, err := rdb.Get(ctx, key).Result() if err != nil { return 「」 } return result } func DelRedis(key string) bool { _, err := rdb.Del(ctx, key).Result() if err != nil { return false } return true }
這樣,後續使用redis時候,只需要呼叫data.SetRedis(xxx) 即可。
然後就是修改組態檔,啟用redis,這裡根據實際的redis設定來寫即可。
在最終給微信伺服器傳送post請求時,對應的請求體格式如下:
{ 「touser」: 「@all」, 「msgtype」: 「text」, 「agentid」: 「xxxxx」, 「text」: {「content」: 「xxxx」} }
因此,接下來可以對這個結構體做一個封裝。在model包下,新建一個send_msg.go檔案
package model type wcSendcontent struct { Content string json:"content" } type WcSendMsg struct { ToUser string json:"touser" MsgType string json:"msgtype" AgentId string json:"agentid" Text wcSendcontent json:"text" } func (t *WcSendMsg) SetMessage(message string) { t.Text.Content = message }
這裡針對message資訊,專門對外暴露了一個方法來進行設定。
在設定好redis,訊息體封裝後,就可以編寫核心的程式碼了。主要就是通過傳送http請求,獲取token,再通過token傳送post請求來傳送訊息。我們可以在service包下新建一個weChat.go的檔案,裡邊新建一個SendWeChat方法來進行訊息傳送操作。
package service import ( 「bytes」 「encoding/json」 「errors」 「fmt」
c "github.com/wannanbigpig/gin-layout/config" "github.com/wannanbigpig/gin-layout/data" "github.com/wannanbigpig/gin-layout/internal/model" log "github.com/wannanbigpig/gin-layout/internal/pkg/logger" "github.com/wannanbigpig/gin-layout/pkg/utils" "go.uber.org/zap"
) /** @description: 給企微傳送訊息 @param {string} message 訊息內容 @param {string} msgType 訊息型別 @return {*} */ func SendWeChat(message string, msgType string) error { redis_key := 「access_token」 // 嘗試從redis中讀取token accessToken := data.GetRedis(redis_key) http := &utils.HttpRequest{} // 若redis中的token已過期,則重新請求api獲取token if accessToken == 「」 { log.Logger.Info(「access token is null, will recall」) getTokenUrl := fmt.Sprintf(「https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s」, c.Config.WeChat.CompanyId, c.Config.WeChat.Secret) log.Logger.Info(「token_url」, zap.String(「url」, getTokenUrl)) http.Request(「GET」, getTokenUrl, nil) ret := make(map[string]interface{}) if err := http.ParseJson(&ret); err != nil { return err } marshal, _ := json.Marshal(ret) log.Logger.Info(string(marshal)) accessToken = fmt.Sprintf("%v", ret[「access_token」]) // 寫入redis 有效期2小時 data.SetRedis(redis_key, accessToken, 7200) } msg := &model.WcSendMsg{ ToUser: 「@all」, MsgType: msgType, AgentId: c.Config.WeChat.AgentId, } msg.SetMessage(message) sendMsgUrl := fmt.Sprintf(「https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%v」, accessToken) log.Logger.Info(「sendMsgUrl = " + string(sendMsgUrl)) header := map[string]string{「Content-Type」: 「application/json」} bytesData, _ := json.Marshal(msg) http.Request(「POST」, sendMsgUrl, bytes.NewReader(bytesData), header) log.Logger.Info(「bytes data = " + string(bytesData)) ret := make(map[string]interface{}) err := http.ParseJson(&ret) if err != nil { return err } if ret[「errcode」].(float64) != 0 { errmsg := fmt.Sprintf(」%v」, ret[「errmsg」]) return errors.New(errmsg) } return nil }
從上面程式碼中可以看出,首先是通過redis來獲取token,若沒有則請求api獲取token,並將其寫入到redis中,有效期為2小時。然後生成一個之前封裝的訊息的結構體,將AgentId和message進行填充後,通過傳送post請求,已達到發訊息的目的。
若想驗證這個方法,可以通過對外提供一個介面,存取此介面後呼叫傳送訊息的方法。
可以在controller目錄下新建一個weChat.go,在裡邊實現一個get請求的方法,獲取請求中的msg引數,然後呼叫剛才實現的傳送企微的方法。
package wechat import ( 「github.com/gin-gonic/gin」 「github.com/wannanbigpig/gin-layout/internal/pkg/error_code」 log 「github.com/wannanbigpig/gin-layout/internal/pkg/logger」 r 「github.com/wannanbigpig/gin-layout/internal/pkg/response」 「github.com/wannanbigpig/gin-layout/internal/service」 ) func SendMsg(c *gin.Context) { msg, ok := c.GetQuery(「msg」) if !ok { msg = 「please input message」 } log.Logger.Info("send wechat message: " + msg) err := service.SendWeChat(msg, 「text」) if err != nil { r.Resp().FailCode(c, error_code.FAILURE, err.Error()) return } r.Success(c, 「success」) }
寫好後,將此方法系結到路由上。在routers包下新建一個weChatRouter.go檔案
package routers import ( 「github.com/gin-gonic/gin」 w 「github.com/wannanbigpig/gin-layout/internal/controller/wechat」 ) func setWeChatRouter(r *gin.Engine) { // version 1 v1 := r.Group(「wechat」) { v1.GET("/send", w.SendMsg) } }
這樣,後續可以通過wechat/send的url來請求這個介面。最後就是呼叫此係結路由的方法,在routers/router.go中新增一行程式碼即可
接下來啟動專案,比如傳送一個msg=Hello,Golang 的請求
curl --location --request GET 「http:// I P : {IP}: IP:{PORT}/wechat/send?msg=Hello,Golang」
執行這個命令,就可以得到本文開頭的截圖。
當然,這個api介面主要是為了讓我們驗證,實際專案執行時,建議不要這麼搞。因為這介面沒有任何鑑權的措施,如果對外暴露了出去,那麼別人也可以肆意的呼叫這個介面給你的企微傳送訊息。
到此這篇關於利用go製作微信機器人的文章就介紹到這了,更多相關go微信機器人內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45