main.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "net/http"
  7. "strings"
  8. "time"
  9. "github.com/eryajf/chatgpt-dingtalk/public"
  10. "github.com/eryajf/chatgpt-dingtalk/public/logger"
  11. "github.com/solywsh/chatgpt"
  12. )
  13. func init() {
  14. public.InitSvc()
  15. }
  16. func main() {
  17. Start()
  18. }
  19. var Welcome string = `Commands:
  20. =================================
  21. 🙋 单聊 👉 单独聊天
  22. 📣 串聊 👉 带上下文聊天
  23. 🔃 重置 👉 重置带上下文聊天
  24. 💵 余额 👉 查询剩余额度
  25. 🚀 帮助 👉 显示帮助信息
  26. =================================
  27. 🚜 例:@我发送 空 或 帮助 将返回此帮助信息
  28. 💪 Power By https://github.com/eryajf/chatgpt-dingtalk
  29. `
  30. // 💵 余额 👉 查看接口可调用额度
  31. func Start() {
  32. // 定义一个处理器函数
  33. handler := func(w http.ResponseWriter, r *http.Request) {
  34. data, err := ioutil.ReadAll(r.Body)
  35. if err != nil {
  36. http.Error(w, err.Error(), http.StatusBadRequest)
  37. logger.Warning(fmt.Sprintf("read request body failed: %v\n", err.Error()))
  38. return
  39. }
  40. if len(data) == 0 {
  41. logger.Warning("回调参数为空,以至于无法正常解析,请检查原因")
  42. return
  43. }
  44. var msgObj = new(public.ReceiveMsg)
  45. err = json.Unmarshal(data, &msgObj)
  46. if err != nil {
  47. logger.Warning(fmt.Errorf("unmarshal request body failed: %v", err))
  48. }
  49. if msgObj.Text.Content == "" || msgObj.ChatbotUserID == "" {
  50. logger.Warning("从钉钉回调过来的内容为空,根据过往的经验,或许重新创建一下机器人,能解决这个问题")
  51. return
  52. }
  53. // TODO: 校验请求
  54. if len(msgObj.Text.Content) == 1 || strings.TrimSpace(msgObj.Text.Content) == "帮助" {
  55. // 欢迎信息
  56. _, err := msgObj.ReplyText(Welcome, msgObj.SenderStaffId)
  57. if err != nil {
  58. logger.Warning(fmt.Errorf("send message error: %v", err))
  59. }
  60. } else {
  61. logger.Info(fmt.Sprintf("dingtalk callback parameters: %#v", msgObj))
  62. err = ProcessRequest(*msgObj)
  63. if err != nil {
  64. logger.Warning(fmt.Errorf("process request failed: %v", err))
  65. }
  66. }
  67. }
  68. // 创建一个新的 HTTP 服务器
  69. server := &http.Server{
  70. Addr: ":8090",
  71. Handler: http.HandlerFunc(handler),
  72. }
  73. // 启动服务器
  74. logger.Info("Start Listen On ", server.Addr)
  75. err := server.ListenAndServe()
  76. if err != nil {
  77. logger.Danger(err)
  78. }
  79. }
  80. func ProcessRequest(rmsg public.ReceiveMsg) error {
  81. content := strings.TrimSpace(rmsg.Text.Content)
  82. switch content {
  83. case "单聊":
  84. public.UserService.SetUserMode(rmsg.SenderStaffId, content)
  85. _, err := rmsg.ReplyText(fmt.Sprintf("=====现在进入与👉%s👈单聊的模式 =====", rmsg.SenderNick), rmsg.SenderStaffId)
  86. if err != nil {
  87. logger.Warning(fmt.Errorf("send message error: %v", err))
  88. }
  89. case "串聊":
  90. public.UserService.SetUserMode(rmsg.SenderStaffId, content)
  91. _, err := rmsg.ReplyText(fmt.Sprintf("=====现在进入与👉%s👈串聊的模式 =====", rmsg.SenderNick), rmsg.SenderStaffId)
  92. if err != nil {
  93. logger.Warning(fmt.Errorf("send message error: %v", err))
  94. }
  95. case "重置":
  96. public.UserService.ClearUserMode(rmsg.SenderStaffId)
  97. public.UserService.ClearUserSessionContext(rmsg.SenderStaffId)
  98. _, err := rmsg.ReplyText(fmt.Sprintf("=====已重置与👉%s👈的对话模式,可以开始新的对话=====", rmsg.SenderNick), rmsg.SenderStaffId)
  99. if err != nil {
  100. logger.Warning(fmt.Errorf("send message error: %v", err))
  101. }
  102. case "余额":
  103. cacheMsg := public.UserService.GetUserMode("system_balance")
  104. if cacheMsg == "" {
  105. rst, err := public.GetBalance()
  106. if err != nil {
  107. logger.Warning(fmt.Errorf("get balance error: %v", err))
  108. return err
  109. }
  110. t1 := time.Unix(int64(rst.Grants.Data[0].EffectiveAt), 0)
  111. t2 := time.Unix(int64(rst.Grants.Data[0].ExpiresAt), 0)
  112. cacheMsg = fmt.Sprintf("💵 已用: 💲%v\n💵 剩余: 💲%v\n⏳ 有效时间: 从 %v 到 %v\n", fmt.Sprintf("%.2f", rst.TotalUsed), fmt.Sprintf("%.2f", rst.TotalAvailable), t1.Format("2006-01-02 15:04:05"), t2.Format("2006-01-02 15:04:05"))
  113. }
  114. _, err := rmsg.ReplyText(cacheMsg, rmsg.SenderStaffId)
  115. if err != nil {
  116. logger.Warning(fmt.Errorf("send message error: %v", err))
  117. }
  118. default:
  119. if public.FirstCheck(rmsg) {
  120. return Do("串聊", rmsg)
  121. } else {
  122. return Do("单聊", rmsg)
  123. }
  124. }
  125. return nil
  126. }
  127. func Do(mode string, rmsg public.ReceiveMsg) error {
  128. // 先把模式注入
  129. public.UserService.SetUserMode(rmsg.SenderStaffId, mode)
  130. switch mode {
  131. case "单聊":
  132. reply, err := SingleQa(rmsg.Text.Content, rmsg.SenderStaffId)
  133. if err != nil {
  134. logger.Info(fmt.Errorf("gpt request error: %v", err))
  135. if strings.Contains(fmt.Sprintf("%v", err), "maximum text length exceeded") {
  136. public.UserService.ClearUserSessionContext(rmsg.SenderStaffId)
  137. _, err = rmsg.ReplyText(fmt.Sprintf("请求openai失败了,错误信息:%v,看起来是超过最大对话限制了,已自动重置您的对话", err), rmsg.SenderStaffId)
  138. if err != nil {
  139. logger.Warning(fmt.Errorf("send message error: %v", err))
  140. return err
  141. }
  142. } else {
  143. _, err = rmsg.ReplyText(fmt.Sprintf("请求openai失败了,错误信息:%v", err), rmsg.SenderStaffId)
  144. if err != nil {
  145. logger.Warning(fmt.Errorf("send message error: %v", err))
  146. return err
  147. }
  148. }
  149. }
  150. if reply == "" {
  151. logger.Warning(fmt.Errorf("get gpt result falied: %v", err))
  152. return nil
  153. } else {
  154. reply = strings.TrimSpace(reply)
  155. reply = strings.Trim(reply, "\n")
  156. // 回复@我的用户
  157. // fmt.Println("单聊结果是:", reply)
  158. _, err = rmsg.ReplyText(reply, rmsg.SenderStaffId)
  159. if err != nil {
  160. logger.Warning(fmt.Errorf("send message error: %v", err))
  161. return err
  162. }
  163. }
  164. case "串聊":
  165. cli, reply, err := ContextQa(rmsg.Text.Content, rmsg.SenderStaffId)
  166. if err != nil {
  167. logger.Info(fmt.Sprintf("gpt request error: %v", err))
  168. if strings.Contains(fmt.Sprintf("%v", err), "maximum text length exceeded") {
  169. public.UserService.ClearUserSessionContext(rmsg.SenderStaffId)
  170. _, err = rmsg.ReplyText(fmt.Sprintf("请求openai失败了,错误信息:%v,看起来是超过最大对话限制了,已自动重置您的对话", err), rmsg.SenderStaffId)
  171. if err != nil {
  172. logger.Warning(fmt.Errorf("send message error: %v", err))
  173. return err
  174. }
  175. } else {
  176. _, err = rmsg.ReplyText(fmt.Sprintf("请求openai失败了,错误信息:%v", err), rmsg.SenderStaffId)
  177. if err != nil {
  178. logger.Warning(fmt.Errorf("send message error: %v", err))
  179. return err
  180. }
  181. }
  182. }
  183. if reply == "" {
  184. logger.Warning(fmt.Errorf("get gpt result falied: %v", err))
  185. return nil
  186. } else {
  187. reply = strings.TrimSpace(reply)
  188. reply = strings.Trim(reply, "\n")
  189. // 回复@我的用户
  190. _, err = rmsg.ReplyText(reply, rmsg.SenderStaffId)
  191. if err != nil {
  192. logger.Warning(fmt.Errorf("send message error: %v", err))
  193. return err
  194. }
  195. _ = cli.ChatContext.SaveConversation(rmsg.SenderStaffId)
  196. }
  197. default:
  198. }
  199. return nil
  200. }
  201. func SingleQa(question, userId string) (answer string, err error) {
  202. chat := chatgpt.New(public.Config.ApiKey, public.Config.HttpProxy, userId, public.Config.SessionTimeout)
  203. defer chat.Close()
  204. return chat.ChatWithContext(question)
  205. }
  206. func ContextQa(question, userId string) (chat *chatgpt.ChatGPT, answer string, err error) {
  207. chat = chatgpt.New(public.Config.ApiKey, public.Config.HttpProxy, userId, public.Config.SessionTimeout)
  208. if public.UserService.GetUserSessionContext(userId) != "" {
  209. err = chat.ChatContext.LoadConversation(userId)
  210. if err != nil {
  211. fmt.Printf("load station failed: %v\n", err)
  212. }
  213. }
  214. answer, err = chat.ChatWithContext(question)
  215. return
  216. }