https://gist.github.com/Peltoche/60b8b81dfbf70164d0e2b88988003229 was used for it, thanks to @Peltoche for publishing it.
134 lines
3.3 KiB
Go
134 lines
3.3 KiB
Go
package migrator
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
|
|
"github.com/umputun/remark42/backend/app/store"
|
|
|
|
log "github.com/go-pkgz/lgr"
|
|
)
|
|
|
|
// Commento implements Importer from commento export json
|
|
type Commento struct {
|
|
DataStore Store
|
|
}
|
|
|
|
// Credit: https://gitlab.com/commento/commento/-/blob/master/api/domain_import_commento.go#L11-L15
|
|
type commentoExport struct {
|
|
Version int `json:"version"`
|
|
Comments []commentoComment `json:"comments"`
|
|
Commenters []commentoCommenter `json:"commenters"`
|
|
}
|
|
|
|
// Credit: https://gitlab.com/commento/commento/-/blob/master/api/comment.go#L7-L20
|
|
type commentoComment struct {
|
|
CommentHex string `json:"commentHex"`
|
|
Domain string `json:"domain,omitempty"`
|
|
Path string `json:"url,omitempty"`
|
|
CommenterHex string `json:"commenterHex"`
|
|
Markdown string `json:"markdown"`
|
|
HTML string `json:"html"`
|
|
ParentHex string `json:"parentHex"`
|
|
Score int `json:"score"`
|
|
State string `json:"state,omitempty"`
|
|
CreationDate time.Time `json:"creationDate"`
|
|
Direction int `json:"direction"`
|
|
Deleted bool `json:"deleted"`
|
|
}
|
|
|
|
// Credit: https://gitlab.com/commento/commento/-/blob/master/api/commenter.go#L7-L16
|
|
type commentoCommenter struct {
|
|
CommenterHex string `json:"commenterHex,omitempty"`
|
|
Email string `json:"email,omitempty"`
|
|
Name string `json:"name"`
|
|
Link string `json:"link"`
|
|
Photo string `json:"photo"`
|
|
Provider string `json:"provider,omitempty"`
|
|
JoinDate time.Time `json:"joinDate,omitempty"`
|
|
IsModerator bool `json:"isModerator"`
|
|
}
|
|
|
|
// Import comments from Commento and save to store
|
|
func (d *Commento) Import(r io.Reader, siteID string) (size int, err error) {
|
|
if e := d.DataStore.DeleteAll(siteID); e != nil {
|
|
return 0, e
|
|
}
|
|
|
|
commentsCh := d.convert(r, siteID)
|
|
failed, passed := 0, 0
|
|
for c := range commentsCh {
|
|
if _, err = d.DataStore.Create(c); err != nil {
|
|
failed++
|
|
continue
|
|
}
|
|
passed++
|
|
}
|
|
|
|
if failed > 0 {
|
|
err = fmt.Errorf("failed to save %d comments", failed)
|
|
if passed == 0 {
|
|
err = fmt.Errorf("import failed")
|
|
}
|
|
}
|
|
|
|
log.Printf("[DEBUG] imported %d comments to site %s", passed, siteID)
|
|
|
|
return passed, err
|
|
}
|
|
|
|
func (d *Commento) convert(r io.Reader, siteID string) (ch chan store.Comment) {
|
|
commentsCh := make(chan store.Comment)
|
|
|
|
decoder := json.NewDecoder(r)
|
|
|
|
go func() {
|
|
var exportedData commentoExport
|
|
err := decoder.Decode(&exportedData)
|
|
if err != nil {
|
|
log.Printf("[WARN] can't decode commento export json, %s", err.Error())
|
|
}
|
|
|
|
usersMap := map[string]store.User{}
|
|
for _, commenter := range exportedData.Commenters {
|
|
usersMap[commenter.CommenterHex] = store.User{
|
|
Name: commenter.Name,
|
|
ID: "commento_" + store.EncodeID(commenter.CommenterHex),
|
|
Picture: commenter.Photo,
|
|
}
|
|
}
|
|
|
|
for _, comment := range exportedData.Comments {
|
|
u, ok := usersMap[comment.CommenterHex]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if comment.Deleted {
|
|
continue
|
|
}
|
|
|
|
c := store.Comment{
|
|
ID: comment.CommentHex,
|
|
Locator: store.Locator{
|
|
URL: comment.Path,
|
|
SiteID: siteID,
|
|
},
|
|
User: u,
|
|
Text: comment.Markdown,
|
|
Timestamp: comment.CreationDate,
|
|
ParentID: comment.ParentHex,
|
|
Imported: true,
|
|
}
|
|
|
|
commentsCh <- c
|
|
}
|
|
|
|
close(commentsCh)
|
|
}()
|
|
|
|
return commentsCh
|
|
}
|