process_request.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package process
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/eryajf/chatgpt-dingtalk/pkg/db"
  6. "github.com/eryajf/chatgpt-dingtalk/pkg/dingbot"
  7. "github.com/eryajf/chatgpt-dingtalk/pkg/logger"
  8. "github.com/eryajf/chatgpt-dingtalk/public"
  9. "github.com/solywsh/chatgpt"
  10. )
  11. // ProcessRequest 分析处理请求逻辑
  12. func ProcessRequest(rmsg *dingbot.ReceiveMsg) error {
  13. if public.CheckRequest(rmsg) {
  14. content := strings.TrimSpace(rmsg.Text.Content)
  15. switch content {
  16. case "单聊":
  17. public.UserService.SetUserMode(rmsg.GetSenderIdentifier(), content)
  18. _, err := rmsg.ReplyToDingtalk(string(dingbot.TEXT), fmt.Sprintf("=====现在进入与👉%s👈单聊的模式 =====", rmsg.SenderNick))
  19. if err != nil {
  20. logger.Warning(fmt.Errorf("send message error: %v", err))
  21. }
  22. case "串聊":
  23. public.UserService.SetUserMode(rmsg.GetSenderIdentifier(), content)
  24. _, err := rmsg.ReplyToDingtalk(string(dingbot.TEXT), fmt.Sprintf("=====现在进入与👉%s👈串聊的模式 =====", rmsg.SenderNick))
  25. if err != nil {
  26. logger.Warning(fmt.Errorf("send message error: %v", err))
  27. }
  28. case "重置":
  29. // 重置用户对话模式
  30. public.UserService.ClearUserMode(rmsg.GetSenderIdentifier())
  31. // 清空用户对话上下文
  32. public.UserService.ClearUserSessionContext(rmsg.GetSenderIdentifier())
  33. // 清空用户对话的答案ID
  34. public.UserService.ClearAnswerID(rmsg.SenderNick, rmsg.GetChatTitle())
  35. _, err := rmsg.ReplyToDingtalk(string(dingbot.TEXT), fmt.Sprintf("=====已重置与👉%s👈的对话模式,可以开始新的对话=====", rmsg.SenderNick))
  36. if err != nil {
  37. logger.Warning(fmt.Errorf("send message error: %v", err))
  38. }
  39. case "模板":
  40. var title string
  41. for _, v := range *public.Prompt {
  42. title = title + v.Title + " | "
  43. }
  44. _, err := rmsg.ReplyToDingtalk(string(dingbot.MARKDOWN), fmt.Sprintf("%s 您好,当前程序内置集成了这些提示词:\n\n-----\n\n| %s \n\n-----\n\n您可以选择某个提示词作为对话内容的开头。\n\n以周报为例,可发送\"#周报 我本周用Go写了一个钉钉集成ChatGPT的聊天应用\",可将工作内容填充为一篇完整的周报。\n\n-----\n\n若您不清楚某个提示词的所代表的含义,您可以直接发送提示词,例如直接发送\"#周报\"", rmsg.SenderNick, title))
  45. if err != nil {
  46. logger.Warning(fmt.Errorf("send message error: %v", err))
  47. }
  48. case "图片":
  49. _, err := rmsg.ReplyToDingtalk(string(dingbot.MARKDOWN), "发送以 **#图片** 开头的内容,将会触发绘画能力,图片生成之后,将会保存在程序根目录下的 **images目录** \n 如果你绘图没有思路,可以在这两个网站寻找灵感。\n - [https://lexica.art/](https://lexica.art/)\n- [https://www.clickprompt.org/zh-CN/](https://www.clickprompt.org/zh-CN/)")
  50. if err != nil {
  51. logger.Warning(fmt.Errorf("send message error: %v", err))
  52. }
  53. case "余额":
  54. // cacheMsg := public.UserService.GetUserMode("system_balance")
  55. // if cacheMsg == "" {
  56. // rst, err := public.GetBalance()
  57. // if err != nil {
  58. // logger.Warning(fmt.Errorf("get balance error: %v", err))
  59. // return err
  60. // }
  61. // t1 := time.Unix(int64(rst.Grants.Data[0].EffectiveAt), 0)
  62. // t2 := time.Unix(int64(rst.Grants.Data[0].ExpiresAt), 0)
  63. // 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"))
  64. // }
  65. cacheMsg := "官方暂时改写了余额接口,因此暂不提供查询余额功能!2023-04-03"
  66. _, err := rmsg.ReplyToDingtalk(string(dingbot.TEXT), cacheMsg)
  67. if err != nil {
  68. logger.Warning(fmt.Errorf("send message error: %v", err))
  69. }
  70. case "查对话":
  71. msg := "使用如下指令进行查询:\n\n---\n\n**#查对话 username:张三**\n\n---\n\n需要注意格式必须严格与上边一致,否则将会查询失败\n\n只有程序系统管理员有权限查询,即config.yml中的admin_users指定的人员。"
  72. _, err := rmsg.ReplyToDingtalk(string(dingbot.MARKDOWN), msg)
  73. if err != nil {
  74. logger.Warning(fmt.Errorf("send message error: %v", err))
  75. }
  76. default:
  77. if public.FirstCheck(rmsg) {
  78. return Do("串聊", rmsg)
  79. } else {
  80. return Do("单聊", rmsg)
  81. }
  82. }
  83. }
  84. return nil
  85. }
  86. // 执行处理请求
  87. func Do(mode string, rmsg *dingbot.ReceiveMsg) error {
  88. // 先把模式注入
  89. public.UserService.SetUserMode(rmsg.GetSenderIdentifier(), mode)
  90. switch mode {
  91. case "单聊":
  92. qObj := db.Chat{
  93. Username: rmsg.SenderNick,
  94. Source: rmsg.GetChatTitle(),
  95. ChatType: db.Q,
  96. ParentContent: 0,
  97. Content: rmsg.Text.Content,
  98. }
  99. qid, err := qObj.Add()
  100. if err != nil {
  101. logger.Error("往MySQL新增数据失败,错误信息:", err)
  102. }
  103. reply, err := chatgpt.SingleQa(rmsg.Text.Content, rmsg.GetSenderIdentifier())
  104. if err != nil {
  105. logger.Info(fmt.Errorf("gpt request error: %v", err))
  106. if strings.Contains(fmt.Sprintf("%v", err), "maximum text length exceeded") {
  107. public.UserService.ClearUserSessionContext(rmsg.GetSenderIdentifier())
  108. _, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v,看起来是超过最大对话限制了,已自动重置您的对话", err))
  109. if err != nil {
  110. logger.Warning(fmt.Errorf("send message error: %v", err))
  111. return err
  112. }
  113. } else {
  114. _, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v", err))
  115. if err != nil {
  116. logger.Warning(fmt.Errorf("send message error: %v", err))
  117. return err
  118. }
  119. }
  120. }
  121. if reply == "" {
  122. logger.Warning(fmt.Errorf("get gpt result falied: %v", err))
  123. return nil
  124. } else {
  125. reply = strings.TrimSpace(reply)
  126. reply = strings.Trim(reply, "\n")
  127. aObj := db.Chat{
  128. Username: rmsg.SenderNick,
  129. Source: rmsg.GetChatTitle(),
  130. ChatType: db.A,
  131. ParentContent: qid,
  132. Content: reply,
  133. }
  134. _, err := aObj.Add()
  135. if err != nil {
  136. logger.Error("往MySQL新增数据失败,错误信息:", err)
  137. }
  138. logger.Info(fmt.Sprintf("🤖 %s得到的答案: %#v", rmsg.SenderNick, reply))
  139. // 回复@我的用户
  140. _, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), reply)
  141. if err != nil {
  142. logger.Warning(fmt.Errorf("send message error: %v", err))
  143. return err
  144. }
  145. }
  146. case "串聊":
  147. lastAid := public.UserService.GetAnswerID(rmsg.SenderNick, rmsg.GetChatTitle())
  148. qObj := db.Chat{
  149. Username: rmsg.SenderNick,
  150. Source: rmsg.GetChatTitle(),
  151. ChatType: db.Q,
  152. ParentContent: lastAid,
  153. Content: rmsg.Text.Content,
  154. }
  155. qid, err := qObj.Add()
  156. if err != nil {
  157. logger.Error("往MySQL新增数据失败,错误信息:", err)
  158. }
  159. cli, reply, err := chatgpt.ContextQa(rmsg.Text.Content, rmsg.GetSenderIdentifier())
  160. if err != nil {
  161. logger.Info(fmt.Sprintf("gpt request error: %v", err))
  162. if strings.Contains(fmt.Sprintf("%v", err), "maximum text length exceeded") {
  163. public.UserService.ClearUserSessionContext(rmsg.GetSenderIdentifier())
  164. _, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v,看起来是超过最大对话限制了,已自动重置您的对话", err))
  165. if err != nil {
  166. logger.Warning(fmt.Errorf("send message error: %v", err))
  167. return err
  168. }
  169. } else {
  170. _, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v", err))
  171. if err != nil {
  172. logger.Warning(fmt.Errorf("send message error: %v", err))
  173. return err
  174. }
  175. }
  176. }
  177. if reply == "" {
  178. logger.Warning(fmt.Errorf("get gpt result falied: %v", err))
  179. return nil
  180. } else {
  181. reply = strings.TrimSpace(reply)
  182. reply = strings.Trim(reply, "\n")
  183. aObj := db.Chat{
  184. Username: rmsg.SenderNick,
  185. Source: rmsg.GetChatTitle(),
  186. ChatType: db.A,
  187. ParentContent: qid,
  188. Content: reply,
  189. }
  190. aid, err := aObj.Add()
  191. if err != nil {
  192. logger.Error("往MySQL新增数据失败,错误信息:", err)
  193. }
  194. // 将当前回答的ID放入缓存
  195. public.UserService.SetAnswerID(rmsg.SenderNick, rmsg.GetChatTitle(), aid)
  196. logger.Info(fmt.Sprintf("🤖 %s得到的答案: %#v", rmsg.SenderNick, reply))
  197. // 回复@我的用户
  198. _, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), reply)
  199. if err != nil {
  200. logger.Warning(fmt.Errorf("send message error: %v", err))
  201. return err
  202. }
  203. _ = cli.ChatContext.SaveConversation(rmsg.GetSenderIdentifier())
  204. }
  205. default:
  206. }
  207. return nil
  208. }