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.

268 lines
6.4 KiB

  1. package main
  2. import (
  3. "archive/zip"
  4. "context"
  5. "encoding/json"
  6. "flag"
  7. "fmt"
  8. "git.aiterp.net/rpdata/api/database"
  9. "git.aiterp.net/rpdata/api/database/mongodb"
  10. "git.aiterp.net/rpdata/api/internal/config"
  11. "git.aiterp.net/rpdata/api/models"
  12. "log"
  13. "strings"
  14. "time"
  15. )
  16. var flagDriver = flag.String("driver", "postgres", "The database driver to use.")
  17. var flagHost = flag.String("host", "127.0.0.1", "The host to connect to.")
  18. var flagPort = flag.Int("port", 5432, "The port to connect on.")
  19. var flagDb = flag.String("db", "rpdata", "The database name")
  20. var flagUsername = flag.String("username", "", "")
  21. var flagPassword = flag.String("password", "", "")
  22. var flagMechanism = flag.String("mechanism", "", "")
  23. var flagInputFile = flag.String("infile", "dump.zip", "The file to read from.")
  24. var flagIncludeKeys = flag.Bool("include-keys", false, "Whether to include the keys.")
  25. func main() {
  26. flag.Parse()
  27. cfg := config.Database{
  28. Driver: *flagDriver,
  29. Host: *flagHost,
  30. Port: *flagPort,
  31. Db: *flagDb,
  32. Username: *flagUsername,
  33. Password: *flagPassword,
  34. Mechanism: *flagMechanism,
  35. RestoreIDs: true,
  36. }
  37. mongodb.DisableFixes = true
  38. db, err := database.Init(cfg)
  39. if err != nil {
  40. log.Fatalln("Failed to open database:", err)
  41. }
  42. cfg2 := cfg
  43. cfg2.RestoreIDs = false
  44. zipReader, err := zip.OpenReader(*flagInputFile)
  45. if err != nil {
  46. log.Fatalln("Failed to open input file:", err)
  47. }
  48. defer func() {
  49. err = zipReader.Close()
  50. if err != nil {
  51. log.Fatalln("Failed to close input file:", err)
  52. }
  53. }()
  54. ctx, cancel := context.WithTimeout(context.Background(), time.Minute*30)
  55. defer cancel()
  56. postMap := make(map[string][]*models.Post)
  57. for _, file := range zipReader.File {
  58. if strings.HasSuffix(file.Name, "/") {
  59. continue
  60. }
  61. parts := strings.Split(file.Name, "/")
  62. if len(parts) < 3 || parts[0] != "rpdata_dump_v1" {
  63. log.Fatalln("Unrecognized file path:", file.Name)
  64. }
  65. reader, err := file.Open()
  66. if err != nil {
  67. log.Fatalln("Unrecognized file:", file.Name, err)
  68. }
  69. hideList := make(map[string]bool)
  70. switch parts[1] {
  71. case "character":
  72. {
  73. character := models.Character{}
  74. err := json.NewDecoder(reader).Decode(&character)
  75. if err != nil {
  76. log.Fatalln("Could not parse character:", parts[2], err)
  77. }
  78. _, err = db.Characters().Insert(ctx, character)
  79. if err != nil {
  80. log.Fatalln("Could not insert character:", parts[2], err)
  81. }
  82. log.Println("Character", character.Name, "inserted.")
  83. }
  84. case "channel":
  85. {
  86. channel := models.Channel{}
  87. err := json.NewDecoder(reader).Decode(&channel)
  88. if err != nil {
  89. log.Fatalln("Could not parse channel:", parts[2], err)
  90. }
  91. _, err = db.Channels().Insert(ctx, channel)
  92. if err != nil {
  93. log.Fatalln("Could not insert channel:", parts[2], err)
  94. }
  95. log.Println("Channel", channel.Name, "inserted.")
  96. }
  97. case "change":
  98. {
  99. change := models.Change{}
  100. err := json.NewDecoder(reader).Decode(&change)
  101. if err != nil {
  102. log.Fatalln("Could not parse character:", parts[2], err)
  103. }
  104. _, err = db.Changes().Insert(ctx, change)
  105. if err != nil {
  106. log.Fatalln("Could not insert character:", parts[2], err)
  107. }
  108. if change.Listed {
  109. log.Println("Change", change.ID, "inserted.")
  110. } else {
  111. log.Println("Unlisted change inserted.")
  112. }
  113. }
  114. case "story":
  115. {
  116. story := models.Story{}
  117. err := json.NewDecoder(reader).Decode(&story)
  118. if err != nil {
  119. log.Fatalln("Could not parse story:", parts[2], err)
  120. }
  121. _, err = db.Stories().Insert(ctx, story)
  122. if err != nil {
  123. log.Fatalln("Could not insert story:", parts[2], err)
  124. }
  125. if story.Listed {
  126. log.Println("Story", story.Name, "inserted.")
  127. } else {
  128. log.Println("Unlisted story inserted.")
  129. hideList[story.ID] = true
  130. }
  131. }
  132. case "chapter":
  133. {
  134. chapter := models.Chapter{}
  135. err := json.NewDecoder(reader).Decode(&chapter)
  136. if err != nil {
  137. log.Fatalln("Could not parse story:", parts[2], err)
  138. }
  139. _, err = db.Chapters().Insert(ctx, chapter)
  140. if err != nil {
  141. log.Fatalln("Could not insert story:", parts[2], err)
  142. }
  143. if !hideList[chapter.StoryID] {
  144. log.Println("Chapter", fmt.Sprintf("%s (id: %s)", chapter.Title, chapter.ID), "inserted.")
  145. } else {
  146. log.Println("Unlisted chapter inserted.")
  147. hideList[chapter.ID] = true
  148. }
  149. }
  150. case "comment":
  151. {
  152. comment := models.Comment{}
  153. err := json.NewDecoder(reader).Decode(&comment)
  154. if err != nil {
  155. log.Fatalln("Could not parse story:", parts[2], err)
  156. }
  157. _, err = db.Comments().Insert(ctx, comment)
  158. if err != nil {
  159. log.Fatalln("Could not insert story:", parts[2], err)
  160. }
  161. if !hideList[comment.ChapterID] {
  162. log.Println("Comment", comment.Subject, "inserted.")
  163. } else {
  164. log.Println("Unlisted comment inserted.")
  165. }
  166. }
  167. case "log":
  168. {
  169. logg := models.Log{}
  170. err := json.NewDecoder(reader).Decode(&logg)
  171. if err != nil {
  172. log.Fatalln("Could not parse log:", parts[2], err)
  173. }
  174. _, err = db.Logs().Insert(ctx, logg)
  175. if err != nil {
  176. log.Fatalln("Could not insert log:", parts[2], err)
  177. }
  178. log.Println("Log", logg.Date.Format(time.RFC3339)[:16], logg.ChannelName, "inserted.")
  179. }
  180. case "post":
  181. {
  182. post := models.Post{}
  183. err := json.NewDecoder(reader).Decode(&post)
  184. if err != nil {
  185. log.Fatalln("Could not parse post:", parts[2], err)
  186. }
  187. postMap[post.LogID] = append(postMap[post.LogID], &post)
  188. }
  189. case "user":
  190. {
  191. user := models.User{}
  192. err := json.NewDecoder(reader).Decode(&user)
  193. if err != nil {
  194. log.Fatalln("Could not parse post:", parts[2], err)
  195. }
  196. _, err = db.Users().Insert(ctx, user)
  197. if err != nil {
  198. log.Fatalln("Could not insert user:", parts[2], err)
  199. }
  200. log.Println("User", user.ID, "inserted.")
  201. }
  202. case "key":
  203. {
  204. if !*flagIncludeKeys {
  205. break
  206. }
  207. key := models.Key{}
  208. err := json.NewDecoder(reader).Decode(&key)
  209. if err != nil {
  210. log.Fatalln("Could not parse key:", parts[2], err)
  211. }
  212. _, err = db.Keys().Insert(ctx, key)
  213. if err != nil {
  214. log.Fatalln("Could not insert key:", parts[2], err)
  215. }
  216. log.Println("Key", key.ID, "inserted.")
  217. }
  218. }
  219. _ = reader.Close()
  220. }
  221. for _, posts := range postMap {
  222. _, err = db.Posts().InsertMany(ctx, posts...)
  223. if err != nil {
  224. log.Fatalln("Could not insert post for logId:", posts[0].LogID, err)
  225. }
  226. log.Printf("Inserted %d posts for log %s.", len(posts), posts[0].LogID)
  227. }
  228. }