diff --git a/models/repo.go b/models/repo.go
index db2694617..4770e5415 100755
--- a/models/repo.go
+++ b/models/repo.go
@@ -2749,15 +2749,10 @@ func ReadLatestFileInRepo(userName, repoName, refName, treePath string) (*RepoFi
log.Error("ReadLatestFileInRepo: Close: %v", err)
}
}()
-
- buf := make([]byte, 1024)
- n, _ := reader.Read(buf)
- if n >= 0 {
- buf = buf[:n]
- }
+ d, _ := ioutil.ReadAll(reader)
commitId := ""
if blob != nil {
commitId = fmt.Sprint(blob.ID)
}
- return &RepoFile{CommitId: commitId, Content: buf}, nil
+ return &RepoFile{CommitId: commitId, Content: d}, nil
}
diff --git a/modules/auth/wechat/auto_reply.go b/modules/auth/wechat/auto_reply.go
new file mode 100644
index 000000000..7d3a30d07
--- /dev/null
+++ b/modules/auth/wechat/auto_reply.go
@@ -0,0 +1,110 @@
+package wechat
+
+import (
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/log"
+ "encoding/json"
+ "github.com/patrickmn/go-cache"
+ "strings"
+ "time"
+)
+
+var WechatReplyCache = cache.New(2*time.Minute, 1*time.Minute)
+
+const (
+ WECHAT_REPLY_CACHE_KEY = "wechat_response"
+)
+
+const (
+ ReplyTypeText = "text"
+ ReplyTypeImage = "image"
+ ReplyTypeVoice = "voice"
+ ReplyTypeVideo = "video"
+ ReplyTypeMusic = "music"
+ ReplyTypeNews = "news"
+)
+
+type AutomaticResponseContent struct {
+ Reply *ReplyContent
+ ReplyType string
+ KeyWords []string
+ IsFullMatch int
+}
+
+type ReplyContent struct {
+ Content string
+ MediaId string
+ Title string
+ Description string
+ MusicUrl string
+ HQMusicUrl string
+ ThumbMediaId string
+}
+
+func GetAutomaticReply(msg string) *AutomaticResponseContent {
+ r, err := LoadAutomaticReplyFromCacheAndDisk()
+ if err != nil {
+ return nil
+ }
+ if r == nil || len(r) == 0 {
+ return nil
+ }
+ for i := 0; i < len(r); i++ {
+ if r[i].IsFullMatch > 0 {
+ for _, v := range r[i].KeyWords {
+ if strings.Contains(msg, v) {
+ return r[i]
+ }
+ }
+ } else if r[i].IsFullMatch == 0 {
+ for _, v := range r[i].KeyWords {
+ if msg == v {
+ return r[i]
+ }
+ }
+ }
+ }
+ return nil
+
+}
+
+func loadAutomaticReplyFromDisk() ([]*AutomaticResponseContent, error) {
+ log.Debug("LoadAutomaticResponseMap from disk")
+ repo, err := models.GetRepositoryByOwnerAndAlias("OpenIOSSG", "promote")
+ if err != nil {
+ log.Error("get notice repo failed, error=%v", err)
+ return nil, err
+ }
+ repoFile, err := models.ReadLatestFileInRepo("OpenIOSSG", repo.Name, "master", "wechat/auto_reply.json")
+ if err != nil {
+ log.Error("GetNewestNotice failed, error=%v", err)
+ return nil, err
+ }
+ res := make([]*AutomaticResponseContent, 0)
+ json.Unmarshal(repoFile.Content, &res)
+ if res == nil || len(res) == 0 {
+ return nil, err
+ }
+ return res, nil
+}
+
+func LoadAutomaticReplyFromCacheAndDisk() ([]*AutomaticResponseContent, error) {
+ v, success := WechatReplyCache.Get(WECHAT_REPLY_CACHE_KEY)
+ if success {
+ log.Debug("LoadAutomaticResponse from cache,value = %v", v)
+ if v == nil {
+ return nil, nil
+ }
+ n := v.([]*AutomaticResponseContent)
+ return n, nil
+ }
+
+ content, err := loadAutomaticReplyFromDisk()
+ if err != nil {
+ log.Error("GetNewestNotice failed, error=%v", err)
+ WechatReplyCache.Set(WECHAT_REPLY_CACHE_KEY, nil, 30*time.Second)
+ return nil, err
+ }
+ WechatReplyCache.Set(WECHAT_REPLY_CACHE_KEY, content, 60*time.Second)
+ return content, nil
+}
diff --git a/modules/auth/wechat/event_handle.go b/modules/auth/wechat/event_handle.go
index b40ab3101..3dd8508cb 100644
--- a/modules/auth/wechat/event_handle.go
+++ b/modules/auth/wechat/event_handle.go
@@ -18,7 +18,7 @@ import (
//
//
//
-type WechatEvent struct {
+type WechatMsg struct {
ToUserName string
FromUserName string
CreateTime int64
@@ -26,9 +26,22 @@ type WechatEvent struct {
Event string
EventKey string
Ticket string
+ Content string
+ MsgId string
+ MsgDataId string
+ Idx string
+}
+
+type MsgReply struct {
+ XMLName xml.Name `xml:"xml"`
+ ToUserName string
+ FromUserName string
+ CreateTime int64
+ MsgType string
+ Content string
}
-type EventReply struct {
+type TextMsgReply struct {
XMLName xml.Name `xml:"xml"`
ToUserName string
FromUserName string
@@ -36,6 +49,71 @@ type EventReply struct {
MsgType string
Content string
}
+type ImageMsgReply struct {
+ XMLName xml.Name `xml:"xml"`
+ ToUserName string
+ FromUserName string
+ CreateTime int64
+ MsgType string
+ Image ImageContent
+}
+type VoiceMsgReply struct {
+ XMLName xml.Name `xml:"xml"`
+ ToUserName string
+ FromUserName string
+ CreateTime int64
+ MsgType string
+ Voice VoiceContent
+}
+type VideoMsgReply struct {
+ XMLName xml.Name `xml:"xml"`
+ ToUserName string
+ FromUserName string
+ CreateTime int64
+ MsgType string
+ Video VideoContent
+}
+type MusicMsgReply struct {
+ XMLName xml.Name `xml:"xml"`
+ ToUserName string
+ FromUserName string
+ CreateTime int64
+ MsgType string
+ Music MusicContent
+}
+type ArticlesMsgReply struct {
+ XMLName xml.Name `xml:"xml"`
+ ToUserName string
+ FromUserName string
+ CreateTime int64
+ MsgType string
+ Articles []ArticlesContent
+}
+
+type ImageContent struct {
+ MediaId string
+}
+type VoiceContent struct {
+ MediaId string
+}
+type VideoContent struct {
+ MediaId string
+ Title string
+ Description string
+}
+type MusicContent struct {
+ Title string
+ Description string
+ MusicUrl string
+ HQMusicUrl string
+ ThumbMediaId string
+}
+type ArticlesContent struct {
+ Title string
+ Description string
+ PicUrl string
+ Url string
+}
const (
WECHAT_EVENT_SUBSCRIBE = "subscribe"
@@ -43,10 +121,11 @@ const (
)
const (
- WECHAT_MSG_TYPE_TEXT = "text"
+ WECHAT_MSG_TYPE_TEXT = "text"
+ WECHAT_MSG_TYPE_EVENT = "event"
)
-func HandleSubscribeEvent(we WechatEvent) string {
+func HandleSubscribeEvent(we WechatMsg) string {
eventKey := we.EventKey
if eventKey == "" {
return ""
diff --git a/routers/authentication/wechat_event.go b/routers/authentication/wechat_event.go
index 9b1cebec6..b8270faee 100644
--- a/routers/authentication/wechat_event.go
+++ b/routers/authentication/wechat_event.go
@@ -14,14 +14,30 @@ import (
// https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Passive_user_reply_message.html
func AcceptWechatEvent(ctx *context.Context) {
b, _ := ioutil.ReadAll(ctx.Req.Request.Body)
- we := wechat.WechatEvent{}
+ we := wechat.WechatMsg{}
xml.Unmarshal(b, &we)
-
+ switch we.MsgType {
+ case wechat.WECHAT_MSG_TYPE_EVENT:
+ HandleEventMsg(ctx, we)
+ case wechat.WECHAT_MSG_TYPE_TEXT:
+ HandleTextMsg(ctx, we)
+ }
log.Info("accept wechat event= %+v", we)
+
+}
+
+// ValidEventSource
+func ValidEventSource(ctx *context.Context) {
+ echostr := ctx.Query("echostr")
+ ctx.Write([]byte(echostr))
+ return
+}
+
+func HandleEventMsg(ctx *context.Context, msg wechat.WechatMsg) {
var replyStr string
- switch we.Event {
+ switch msg.Event {
case wechat.WECHAT_EVENT_SUBSCRIBE, wechat.WECHAT_EVENT_SCAN:
- replyStr = wechat.HandleSubscribeEvent(we)
+ replyStr = wechat.HandleSubscribeEvent(msg)
break
}
@@ -29,9 +45,9 @@ func AcceptWechatEvent(ctx *context.Context) {
log.Info("reply str is empty")
return
}
- reply := &wechat.EventReply{
- ToUserName: we.FromUserName,
- FromUserName: we.ToUserName,
+ reply := &wechat.MsgReply{
+ ToUserName: msg.FromUserName,
+ FromUserName: msg.ToUserName,
CreateTime: time.Now().Unix(),
MsgType: wechat.WECHAT_MSG_TYPE_TEXT,
Content: replyStr,
@@ -39,9 +55,79 @@ func AcceptWechatEvent(ctx *context.Context) {
ctx.XML(200, reply)
}
-// ValidEventSource
-func ValidEventSource(ctx *context.Context) {
- echostr := ctx.Query("echostr")
- ctx.Write([]byte(echostr))
- return
+func HandleTextMsg(ctx *context.Context, msg wechat.WechatMsg) {
+ r := wechat.GetAutomaticReply(msg.Content)
+ if r == nil {
+ log.Info("TextMsg reply is empty")
+ return
+ }
+ reply := buildReplyContent(msg, r)
+ ctx.XML(200, reply)
+}
+
+func buildReplyContent(msg wechat.WechatMsg, r *wechat.AutomaticResponseContent) interface{} {
+ reply := &wechat.MsgReply{
+ ToUserName: msg.FromUserName,
+ FromUserName: msg.ToUserName,
+ CreateTime: time.Now().Unix(),
+ MsgType: r.ReplyType,
+ }
+ switch r.ReplyType {
+ case wechat.ReplyTypeText:
+ return &wechat.TextMsgReply{
+ ToUserName: msg.FromUserName,
+ FromUserName: msg.ToUserName,
+ CreateTime: time.Now().Unix(),
+ MsgType: r.ReplyType,
+ Content: r.Reply.Content,
+ }
+
+ case wechat.ReplyTypeImage:
+ return &wechat.ImageMsgReply{
+ ToUserName: msg.FromUserName,
+ FromUserName: msg.ToUserName,
+ CreateTime: time.Now().Unix(),
+ MsgType: r.ReplyType,
+ Image: wechat.ImageContent{
+ MediaId: r.Reply.MediaId,
+ },
+ }
+ case wechat.ReplyTypeVoice:
+ return &wechat.VoiceMsgReply{
+ ToUserName: msg.FromUserName,
+ FromUserName: msg.ToUserName,
+ CreateTime: time.Now().Unix(),
+ MsgType: r.ReplyType,
+ Voice: wechat.VoiceContent{
+ MediaId: r.Reply.MediaId,
+ },
+ }
+ case wechat.ReplyTypeVideo:
+ return &wechat.VideoMsgReply{
+ ToUserName: msg.FromUserName,
+ FromUserName: msg.ToUserName,
+ CreateTime: time.Now().Unix(),
+ MsgType: r.ReplyType,
+ Video: wechat.VideoContent{
+ MediaId: r.Reply.MediaId,
+ Title: r.Reply.Title,
+ Description: r.Reply.Description,
+ },
+ }
+ case wechat.ReplyTypeMusic:
+ return &wechat.MusicMsgReply{
+ ToUserName: msg.FromUserName,
+ FromUserName: msg.ToUserName,
+ CreateTime: time.Now().Unix(),
+ MsgType: r.ReplyType,
+ Music: wechat.MusicContent{
+ Title: r.Reply.Title,
+ Description: r.Reply.Description,
+ MusicUrl: r.Reply.MusicUrl,
+ HQMusicUrl: r.Reply.HQMusicUrl,
+ ThumbMediaId: r.Reply.ThumbMediaId,
+ },
+ }
+ }
+ return reply
}