A web blog and personal homepage engine written in Go.
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.
 
 

210 lines
4.9 KiB

  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "sort"
  8. "git.kirsle.net/apps/gophertype/pkg"
  9. "git.kirsle.net/apps/gophertype/pkg/console"
  10. _ "git.kirsle.net/apps/gophertype/pkg/controllers"
  11. "git.kirsle.net/apps/gophertype/pkg/models"
  12. _ "github.com/jinzhu/gorm/dialects/mysql"
  13. _ "github.com/jinzhu/gorm/dialects/postgres"
  14. _ "github.com/jinzhu/gorm/dialects/sqlite"
  15. jsondb "github.com/kirsle/blog/jsondb"
  16. mComments "github.com/kirsle/blog/models/comments"
  17. mPosts "github.com/kirsle/blog/models/posts"
  18. )
  19. // Command-line flags.
  20. var (
  21. optSourceRoot string
  22. optRoot string
  23. // Database option flags.
  24. optSQLite string
  25. optPostgres string
  26. optMySQL string
  27. // Chosen DB options.
  28. dbDriver string
  29. dbPath string
  30. )
  31. // Other global variables
  32. var (
  33. JsonDB *jsondb.DB
  34. )
  35. func init() {
  36. flag.StringVar(&optSourceRoot, "srcroot", "", "User root from old kirsle/blog website")
  37. flag.StringVar(&optRoot, "root", "", "User root for GopherType")
  38. // Database driver. Choose one.
  39. flag.StringVar(&optSQLite, "sqlite3", "", "Use SQLite database, default 'database.sqlite'")
  40. flag.StringVar(&optPostgres, "postgres", "",
  41. "Use Postgres database, format: "+
  42. "host=myhost port=myport user=gorm dbname=gorm password=mypassword")
  43. flag.StringVar(&optMySQL, "mysql", "",
  44. "Use MySQL database, format: "+
  45. "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
  46. }
  47. func main() {
  48. console.SetDebug(false)
  49. flag.Parse()
  50. // Validate the choice of database.
  51. if optSQLite != "" {
  52. dbDriver = "sqlite3"
  53. dbPath = optSQLite
  54. } else if optPostgres != "" {
  55. dbDriver = "postgres"
  56. dbPath = optPostgres
  57. } else if optMySQL != "" {
  58. dbDriver = "mysql"
  59. dbPath = optMySQL
  60. } else {
  61. fmt.Print(
  62. "Specify a DB driver for Gophertype, similar to the gophertype command.",
  63. )
  64. os.Exit(1)
  65. }
  66. // Validate the roots are given.
  67. if optSourceRoot == "" {
  68. fmt.Print(
  69. "Missing -srcroot parameter: this should be the User Root from the legacy kirsle/blog site.",
  70. )
  71. os.Exit(1)
  72. }
  73. if optRoot == "" {
  74. fmt.Print(
  75. "Missing required -root parameter: this is the User Root for Gophertype",
  76. )
  77. }
  78. // Initialize the old JsonDB.
  79. app := gophertype.NewSite(optRoot)
  80. app.UseDB(dbDriver, dbPath)
  81. initJsonDB()
  82. doMigrate()
  83. }
  84. // Initialize the old kirsle/blog JsonDB.
  85. func initJsonDB() {
  86. JsonDB = jsondb.New(filepath.Join(optSourceRoot, ".private"))
  87. mPosts.DB = JsonDB
  88. mComments.DB = JsonDB
  89. }
  90. // doMigrate is the head of the migrate functions.
  91. func doMigrate() {
  92. migratePosts()
  93. migrateComments()
  94. }
  95. // migratePosts migrates blog posts over.
  96. func migratePosts() {
  97. console.Warn("BEGIN: Migrating blog posts")
  98. idx, err := mPosts.GetIndex()
  99. if err != nil {
  100. panic("migratePosts: GetIndex: " + err.Error())
  101. }
  102. // Sort the IDs to make it pretty.
  103. var sortedIds = []int{}
  104. for id := range idx.Posts {
  105. sortedIds = append(sortedIds, id)
  106. }
  107. sort.Ints(sortedIds)
  108. for _, id := range sortedIds {
  109. post, err := mPosts.Load(id)
  110. if err != nil {
  111. panic(fmt.Sprintf("migratePosts: error loading legacy post ID %d: %s", id, err))
  112. }
  113. console.Info("Post ID %d: %s", id, post.Title)
  114. // Create the post in Gophertype.
  115. p := models.Post{
  116. Title: post.Title,
  117. Fragment: post.Fragment,
  118. ContentType: post.ContentType,
  119. AuthorID: uint(post.AuthorID),
  120. Body: post.Body,
  121. Privacy: post.Privacy,
  122. Sticky: post.Sticky,
  123. EnableComments: post.EnableComments,
  124. }
  125. p.ID = uint(post.ID)
  126. p.CreatedAt = post.Created
  127. p.UpdatedAt = post.Updated
  128. // Convert tags.
  129. for _, tag := range post.Tags {
  130. p.Tags = append(p.Tags, models.TaggedPost{
  131. Tag: tag,
  132. })
  133. }
  134. err = p.Save()
  135. if err != nil {
  136. console.Error("Error saving post %d: %s", p.ID, err)
  137. }
  138. }
  139. console.Warn("FINISH: Migrating blog posts")
  140. }
  141. // migrateComments migrates comments over.
  142. func migrateComments() {
  143. console.Warn("BEGIN: Migrating comments")
  144. // Find all the comment threads.
  145. files, err := JsonDB.List("comments/threads")
  146. if err != nil {
  147. panic("Error listing comments: " + err.Error())
  148. }
  149. for _, file := range files {
  150. document := filepath.Base(file)
  151. thread, err := mComments.Load(document)
  152. if err != nil {
  153. panic(fmt.Sprintf("Error loading comment thread %s: %s", file, err))
  154. }
  155. for _, comment := range thread.Comments {
  156. // Migrate to the new model.
  157. com := models.Comment{
  158. Thread: thread.ID,
  159. UserID: uint(comment.UserID),
  160. Name: comment.Name,
  161. Email: comment.Email,
  162. Avatar: comment.Avatar,
  163. Body: comment.Body,
  164. EditToken: comment.EditToken,
  165. DeleteToken: comment.DeleteToken,
  166. }
  167. com.CreatedAt = comment.Created
  168. com.UpdatedAt = comment.Updated
  169. // Special case for guestbook page.
  170. if thread.ID == "guestbook" {
  171. com.OriginURL = "/guestbook"
  172. }
  173. if err := com.Save(); err != nil {
  174. console.Error("Error saving comment: %s", err)
  175. }
  176. }
  177. }
  178. console.Warn("FINISH: Migrating comments")
  179. }