GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

249 lines
5.2 KiB

  1. package postgres
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "git.aiterp.net/rpdata/api/database/postgres/psqlcore"
  7. "git.aiterp.net/rpdata/api/internal/generate"
  8. "git.aiterp.net/rpdata/api/models"
  9. "strconv"
  10. "time"
  11. )
  12. type logRepository struct {
  13. insertWithIDs bool
  14. db *sql.DB
  15. }
  16. func (r *logRepository) Find(ctx context.Context, id string) (*models.Log, error) {
  17. log, err := psqlcore.New(r.db).SelectLog(ctx, id)
  18. if err != nil {
  19. return nil, err
  20. }
  21. return r.log(log), nil
  22. }
  23. func (r *logRepository) List(ctx context.Context, filter models.LogFilter) ([]*models.Log, error) {
  24. q := psqlcore.New(r.db)
  25. params := psqlcore.SelectLogsParams{
  26. LimitSize: 0,
  27. }
  28. if filter.Search != nil {
  29. params.FilterSearch = true
  30. params.Search = TSQueryFromSearch(*filter.Search)
  31. }
  32. if filter.Open != nil {
  33. params.FilterOpen = true
  34. params.Open = *filter.Open
  35. }
  36. if len(filter.Characters) > 0 {
  37. params.FilterCharacterID = true
  38. params.CharacterIds = filter.Characters
  39. }
  40. if len(filter.Channels) > 0 {
  41. params.FilterChannelName = true
  42. params.ChannelNames = filter.Channels
  43. }
  44. if len(filter.Events) > 0 {
  45. params.FilterEventName = true
  46. params.EventNames = filter.Events
  47. }
  48. if filter.MinDate != nil {
  49. params.FilterEarlistDate = true
  50. params.EarliestDate = *filter.MinDate
  51. }
  52. if filter.MaxDate != nil {
  53. params.FilterLastestDate = true
  54. params.LatestDate = *filter.MaxDate
  55. }
  56. if filter.Limit > 0 {
  57. params.LimitSize = int32(filter.Limit)
  58. }
  59. logs, err := q.SelectLogs(ctx, params)
  60. if err != nil {
  61. return nil, err
  62. }
  63. return r.logs(logs), nil
  64. }
  65. func (r *logRepository) Insert(ctx context.Context, log models.Log) (*models.Log, error) {
  66. tx, err := r.db.BeginTx(ctx, nil)
  67. if err != nil {
  68. return nil, err
  69. }
  70. defer func() { _ = tx.Rollback() }()
  71. q := psqlcore.New(tx)
  72. if !r.insertWithIDs || log.ID == "" {
  73. log.ID = generate.LogID(log)
  74. }
  75. if !r.insertWithIDs || log.ShortID == "" {
  76. next, err := q.IncrementCounter(ctx, "log_short_id")
  77. if err != nil {
  78. return nil, err
  79. }
  80. log.ShortID = fmt.Sprintf("L%d", next)
  81. } else {
  82. n, err := strconv.Atoi(log.ShortID[1:])
  83. if err != nil {
  84. return nil, err
  85. }
  86. err = q.BumpCounter(ctx, psqlcore.BumpCounterParams{
  87. ID: "log_short_id",
  88. Value: int32(n),
  89. })
  90. if err != nil {
  91. return nil, err
  92. }
  93. }
  94. if log.CharacterIDs == nil {
  95. log.CharacterIDs = []string{}
  96. }
  97. err = q.InsertLog(ctx, psqlcore.InsertLogParams{
  98. ID: log.ID,
  99. ShortID: log.ShortID,
  100. Date: log.Date.UTC(),
  101. ChannelName: log.ChannelName,
  102. EventName: log.EventName,
  103. Title: log.Title,
  104. Description: log.Description,
  105. Open: log.Open,
  106. CharacterIds: log.CharacterIDs,
  107. })
  108. if err != nil {
  109. return nil, err
  110. }
  111. err = tx.Commit()
  112. if err != nil {
  113. return nil, err
  114. }
  115. _ = r.updateTags(log)
  116. return &log, nil
  117. }
  118. func (r *logRepository) Update(ctx context.Context, log models.Log, update models.LogUpdate) (*models.Log, error) {
  119. log.ApplyUpdate(update)
  120. err := psqlcore.New(r.db).UpdateLog(ctx, psqlcore.UpdateLogParams{
  121. Title: log.Title,
  122. EventName: log.EventName,
  123. Description: log.Description,
  124. Open: log.Open,
  125. CharacterIds: log.CharacterIDs,
  126. ID: log.ID,
  127. })
  128. if err != nil {
  129. return nil, err
  130. }
  131. _ = r.updateTags(log)
  132. return &log, nil
  133. }
  134. func (r *logRepository) Delete(ctx context.Context, log models.Log) error {
  135. tx, err := r.db.BeginTx(ctx, nil)
  136. if err != nil {
  137. return err
  138. }
  139. defer func() { _ = tx.Rollback() }()
  140. q := psqlcore.New(tx)
  141. err = q.DeleteLog(ctx, log.ID)
  142. if err != nil {
  143. return err
  144. }
  145. err = q.DeletePostsByLogShortID(ctx, log.ShortID)
  146. if err != nil {
  147. return err
  148. }
  149. return tx.Commit()
  150. }
  151. func (r *logRepository) log(log psqlcore.SelectLogRow) *models.Log {
  152. return &models.Log{
  153. ID: log.ID,
  154. ShortID: log.ShortID,
  155. Date: log.Date,
  156. ChannelName: log.ChannelName,
  157. EventName: log.EventName,
  158. Title: log.Title,
  159. Description: log.Description,
  160. Open: log.Open,
  161. CharacterIDs: log.CharacterIds,
  162. }
  163. }
  164. func (r *logRepository) logs(logs []psqlcore.SelectLogsRow) []*models.Log {
  165. results := make([]*models.Log, 0, len(logs))
  166. for _, log := range logs {
  167. results = append(results, r.log(psqlcore.SelectLogRow(log)))
  168. }
  169. return results
  170. }
  171. func (r *logRepository) updateTags(log models.Log) error {
  172. ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  173. defer cancel()
  174. tx, err := r.db.BeginTx(ctx, nil)
  175. if err != nil {
  176. return err
  177. }
  178. defer func() { _ = tx.Rollback() }()
  179. q := psqlcore.New(tx)
  180. err = q.ClearTagsByTarget(ctx, psqlcore.ClearTagsByTargetParams{TargetKind: "Log", TargetID: log.ID})
  181. if err != nil {
  182. return err
  183. }
  184. if len(log.CharacterIDs) > 0 {
  185. err := q.SetCharacterTagsFromIDs(ctx, psqlcore.SetCharacterTagsFromIDsParams{
  186. TargetKind: "log",
  187. TargetID: log.ID,
  188. CharacterIds: log.CharacterIDs,
  189. })
  190. if err != nil {
  191. return err
  192. }
  193. }
  194. err = q.SetLocationTagFromChannelName(ctx, psqlcore.SetLocationTagFromChannelNameParams{
  195. TargetKind: "log",
  196. TargetID: log.ID,
  197. ChannelName: log.ChannelName,
  198. })
  199. if err != nil {
  200. return err
  201. }
  202. if log.EventName != "" {
  203. err := q.SetTag(ctx, psqlcore.SetTagParams{
  204. Tag: "Event:" + log.EventName,
  205. TargetKind: "Log",
  206. TargetID: log.ID,
  207. })
  208. if err != nil {
  209. return err
  210. }
  211. }
  212. return tx.Commit()
  213. }