169 lines
4.2 KiB
Go
169 lines
4.2 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"compress/gzip"
|
||
|
"encoding/json"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
)
|
||
|
|
||
|
type dataImport struct {
|
||
|
Version int `json:"version"`
|
||
|
Comments []comment `json:"comments"`
|
||
|
Commenters []commenter `json:"commenters"`
|
||
|
}
|
||
|
|
||
|
func domainImportCommento(domain string, url string) (int, error) {
|
||
|
if domain == "" || url == "" {
|
||
|
return 0, errorMissingField
|
||
|
}
|
||
|
|
||
|
resp, err := http.Get(url)
|
||
|
if err != nil {
|
||
|
logger.Errorf("cannot get url: %v", err)
|
||
|
return 0, errorCannotDownloadCommento
|
||
|
}
|
||
|
|
||
|
defer resp.Body.Close()
|
||
|
body, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
logger.Errorf("cannot read body: %v", err)
|
||
|
return 0, errorCannotDownloadCommento
|
||
|
}
|
||
|
|
||
|
zr, err := gzip.NewReader(bytes.NewBuffer(body))
|
||
|
if err != nil {
|
||
|
logger.Errorf("cannot create gzip reader: %v", err)
|
||
|
return 0, errorInternal
|
||
|
}
|
||
|
|
||
|
contents, err := ioutil.ReadAll(zr)
|
||
|
if err != nil {
|
||
|
logger.Errorf("cannot read gzip contents uncompressed: %v", err)
|
||
|
return 0, errorInternal
|
||
|
}
|
||
|
|
||
|
var data dataImport
|
||
|
if err := json.Unmarshal(contents, &data); err != nil {
|
||
|
logger.Errorf("cannot unmarshal JSON at %s: %v", url, err)
|
||
|
return 0, errorInternal
|
||
|
}
|
||
|
|
||
|
if data.Version != 1 {
|
||
|
logger.Errorf("invalid data version (got %d, want 1): %v", data.Version, err)
|
||
|
return 0, errorUnsupportedCommentoImportVersion
|
||
|
}
|
||
|
|
||
|
// Check if imported commentedHex or email exists, creating a map of
|
||
|
// commenterHex (old hex, new hex)
|
||
|
commenterHex := map[string]string{"anonymous": "anonymous"}
|
||
|
for _, commenter := range data.Commenters {
|
||
|
c, err := commenterGetByEmail("commento", commenter.Email)
|
||
|
if err != nil && err != errorNoSuchCommenter {
|
||
|
logger.Errorf("cannot get commenter by email: %v", err)
|
||
|
return 0, errorInternal
|
||
|
}
|
||
|
|
||
|
if err == nil {
|
||
|
commenterHex[commenter.CommenterHex] = c.CommenterHex
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
randomPassword, err := randomHex(32)
|
||
|
if err != nil {
|
||
|
logger.Errorf("cannot generate random password for new commenter: %v", err)
|
||
|
return 0, errorInternal
|
||
|
}
|
||
|
|
||
|
commenterHex[commenter.CommenterHex], err = commenterNew(commenter.Email,
|
||
|
commenter.Name, commenter.Link, commenter.Photo, "commento", randomPassword)
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Create a map of (parent hex, comments)
|
||
|
comments := make(map[string][]comment)
|
||
|
for _, comment := range data.Comments {
|
||
|
parentHex := comment.ParentHex
|
||
|
comments[parentHex] = append(comments[parentHex], comment)
|
||
|
}
|
||
|
|
||
|
// Import comments, creating a map of comment hex (old hex, new hex)
|
||
|
commentHex := map[string]string{"root": "root"}
|
||
|
numImported := 0
|
||
|
keys := []string{"root"}
|
||
|
for i := 0; i < len(keys); i++ {
|
||
|
for _, comment := range comments[keys[i]] {
|
||
|
cHex, ok := commenterHex[comment.CommenterHex]
|
||
|
if !ok {
|
||
|
logger.Errorf("cannot get commenter: %v", err)
|
||
|
return numImported, errorInternal
|
||
|
}
|
||
|
parentHex, ok := commentHex[comment.ParentHex]
|
||
|
if !ok {
|
||
|
logger.Errorf("cannot get parent comment: %v", err)
|
||
|
return numImported, errorInternal
|
||
|
}
|
||
|
|
||
|
hex, err := commentNew(
|
||
|
cHex,
|
||
|
domain,
|
||
|
comment.Path,
|
||
|
parentHex,
|
||
|
comment.Markdown,
|
||
|
comment.State,
|
||
|
comment.CreationDate)
|
||
|
if err != nil {
|
||
|
return numImported, err
|
||
|
}
|
||
|
commentHex[comment.CommentHex] = hex
|
||
|
numImported++
|
||
|
keys = append(keys, comment.CommentHex)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return numImported, nil
|
||
|
}
|
||
|
|
||
|
func domainImportCommentoHandler(w http.ResponseWriter, r *http.Request) {
|
||
|
type request struct {
|
||
|
OwnerToken *string `json:"ownerToken"`
|
||
|
Domain *string `json:"domain"`
|
||
|
URL *string `json:"url"`
|
||
|
}
|
||
|
|
||
|
var x request
|
||
|
if err := bodyUnmarshal(r, &x); err != nil {
|
||
|
bodyMarshal(w, response{"success": false, "message": err.Error()})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
o, err := ownerGetByOwnerToken(*x.OwnerToken)
|
||
|
if err != nil {
|
||
|
bodyMarshal(w, response{"success": false, "message": err.Error()})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
domain := domainStrip(*x.Domain)
|
||
|
isOwner, err := domainOwnershipVerify(o.OwnerHex, domain)
|
||
|
if err != nil {
|
||
|
bodyMarshal(w, response{"success": false, "message": err.Error()})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if !isOwner {
|
||
|
bodyMarshal(w, response{"success": false, "message": errorNotAuthorised.Error()})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
numImported, err := domainImportCommento(domain, *x.URL)
|
||
|
if err != nil {
|
||
|
bodyMarshal(w, response{"success": false, "message": err.Error()})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
bodyMarshal(w, response{"success": true, "numImported": numImported})
|
||
|
}
|