streams.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. package streams
  2. import (
  3. "net/http"
  4. "os"
  5. "strings"
  6. "time"
  7. "github.com/0xJacky/Nginx-UI/internal/config"
  8. "github.com/0xJacky/Nginx-UI/internal/nginx"
  9. "github.com/0xJacky/Nginx-UI/internal/stream"
  10. "github.com/0xJacky/Nginx-UI/query"
  11. "github.com/gin-gonic/gin"
  12. "github.com/sashabaranov/go-openai"
  13. "github.com/uozi-tech/cosy"
  14. )
  15. type Stream struct {
  16. ModifiedAt time.Time `json:"modified_at"`
  17. Advanced bool `json:"advanced"`
  18. Enabled bool `json:"enabled"`
  19. Name string `json:"name"`
  20. Config string `json:"config"`
  21. ChatGPTMessages []openai.ChatCompletionMessage `json:"chatgpt_messages,omitempty"`
  22. Tokenized *nginx.NgxConfig `json:"tokenized,omitempty"`
  23. Filepath string `json:"filepath"`
  24. SyncNodeIDs []uint64 `json:"sync_node_ids" gorm:"serializer:json"`
  25. }
  26. func GetStreams(c *gin.Context) {
  27. name := c.Query("name")
  28. orderBy := c.Query("order_by")
  29. sort := c.DefaultQuery("sort", "desc")
  30. configFiles, err := os.ReadDir(nginx.GetConfPath("streams-available"))
  31. if err != nil {
  32. cosy.ErrHandler(c, err)
  33. return
  34. }
  35. enabledConfig, err := os.ReadDir(nginx.GetConfPath("streams-enabled"))
  36. if err != nil {
  37. cosy.ErrHandler(c, err)
  38. return
  39. }
  40. enabledConfigMap := make(map[string]bool)
  41. for i := range enabledConfig {
  42. enabledConfigMap[enabledConfig[i].Name()] = true
  43. }
  44. var configs []config.Config
  45. for i := range configFiles {
  46. file := configFiles[i]
  47. fileInfo, _ := file.Info()
  48. if !file.IsDir() {
  49. if name != "" && !strings.Contains(file.Name(), name) {
  50. continue
  51. }
  52. configs = append(configs, config.Config{
  53. Name: file.Name(),
  54. ModifiedAt: fileInfo.ModTime(),
  55. Size: fileInfo.Size(),
  56. IsDir: fileInfo.IsDir(),
  57. Enabled: enabledConfigMap[file.Name()],
  58. })
  59. }
  60. }
  61. configs = config.Sort(orderBy, sort, configs)
  62. c.JSON(http.StatusOK, gin.H{
  63. "data": configs,
  64. })
  65. }
  66. func GetStream(c *gin.Context) {
  67. name := c.Param("name")
  68. path := nginx.GetConfPath("streams-available", name)
  69. file, err := os.Stat(path)
  70. if os.IsNotExist(err) {
  71. c.JSON(http.StatusNotFound, gin.H{
  72. "message": "file not found",
  73. })
  74. return
  75. }
  76. enabled := true
  77. if _, err := os.Stat(nginx.GetConfPath("streams-enabled", name)); os.IsNotExist(err) {
  78. enabled = false
  79. }
  80. g := query.ChatGPTLog
  81. chatgpt, err := g.Where(g.Name.Eq(path)).FirstOrCreate()
  82. if err != nil {
  83. cosy.ErrHandler(c, err)
  84. return
  85. }
  86. if chatgpt.Content == nil {
  87. chatgpt.Content = make([]openai.ChatCompletionMessage, 0)
  88. }
  89. s := query.Stream
  90. streamModel, err := s.Where(s.Path.Eq(path)).FirstOrCreate()
  91. if err != nil {
  92. cosy.ErrHandler(c, err)
  93. return
  94. }
  95. if streamModel.Advanced {
  96. origContent, err := os.ReadFile(path)
  97. if err != nil {
  98. cosy.ErrHandler(c, err)
  99. return
  100. }
  101. c.JSON(http.StatusOK, Stream{
  102. ModifiedAt: file.ModTime(),
  103. Advanced: streamModel.Advanced,
  104. Enabled: enabled,
  105. Name: name,
  106. Config: string(origContent),
  107. ChatGPTMessages: chatgpt.Content,
  108. Filepath: path,
  109. SyncNodeIDs: streamModel.SyncNodeIDs,
  110. })
  111. return
  112. }
  113. nginxConfig, err := nginx.ParseNgxConfig(path)
  114. if err != nil {
  115. cosy.ErrHandler(c, err)
  116. return
  117. }
  118. c.JSON(http.StatusOK, Stream{
  119. ModifiedAt: file.ModTime(),
  120. Advanced: streamModel.Advanced,
  121. Enabled: enabled,
  122. Name: name,
  123. Config: nginxConfig.FmtCode(),
  124. Tokenized: nginxConfig,
  125. ChatGPTMessages: chatgpt.Content,
  126. Filepath: path,
  127. SyncNodeIDs: streamModel.SyncNodeIDs,
  128. })
  129. }
  130. func SaveStream(c *gin.Context) {
  131. name := c.Param("name")
  132. var json struct {
  133. Content string `json:"content" binding:"required"`
  134. SyncNodeIDs []uint64 `json:"sync_node_ids"`
  135. Overwrite bool `json:"overwrite"`
  136. }
  137. if !cosy.BindAndValid(c, &json) {
  138. return
  139. }
  140. err := stream.Save(name, json.Content, json.Overwrite, json.SyncNodeIDs)
  141. if err != nil {
  142. cosy.ErrHandler(c, err)
  143. return
  144. }
  145. GetStream(c)
  146. }
  147. func EnableStream(c *gin.Context) {
  148. err := stream.Enable(c.Param("name"))
  149. if err != nil {
  150. cosy.ErrHandler(c, err)
  151. return
  152. }
  153. c.JSON(http.StatusOK, gin.H{
  154. "message": "ok",
  155. })
  156. }
  157. func DisableStream(c *gin.Context) {
  158. err := stream.Disable(c.Param("name"))
  159. if err != nil {
  160. cosy.ErrHandler(c, err)
  161. return
  162. }
  163. c.JSON(http.StatusOK, gin.H{
  164. "message": "ok",
  165. })
  166. }
  167. func DeleteStream(c *gin.Context) {
  168. err := stream.Delete(c.Param("name"))
  169. if err != nil {
  170. cosy.ErrHandler(c, err)
  171. return
  172. }
  173. c.JSON(http.StatusOK, gin.H{
  174. "message": "ok",
  175. })
  176. }
  177. func RenameStream(c *gin.Context) {
  178. oldName := c.Param("name")
  179. var json struct {
  180. NewName string `json:"new_name"`
  181. }
  182. if !cosy.BindAndValid(c, &json) {
  183. return
  184. }
  185. err := stream.Rename(oldName, json.NewName)
  186. if err != nil {
  187. cosy.ErrHandler(c, err)
  188. return
  189. }
  190. c.JSON(http.StatusOK, gin.H{
  191. "message": "ok",
  192. })
  193. }