// Package migrator provides import/export functionality. It defines Importer and Exporter interfaces // amd implements for disqus (importer only) and "native" remark (both importer and exporter). // Also implements AutoBackup scheduler running exports as backups and saving them locally. package migrator import ( "fmt" "io" "os" log "github.com/go-pkgz/lgr" "github.com/umputun/remark42/backend/app/store" "github.com/umputun/remark42/backend/app/store/service" ) // Importer defines interface to convert posts from external sources type Importer interface { Import(r io.Reader, siteID string) (int, error) } // Exporter defines interface to export comments from internal store type Exporter interface { Export(w io.Writer, siteID string) (int, error) } // Mapper defines interface to convert data in import procedure type Mapper interface { URL(url string) string } // MapperMaker defines function that reads rules from reader and // returns new Mapper with loaded rules. If rules are not valid // it returns error. type MapperMaker func(reader io.Reader) (Mapper, error) // Store defines minimal interface needed to export and import comments type Store interface { Create(comment store.Comment) (commentID string, err error) Find(locator store.Locator, sort string, user store.User) ([]store.Comment, error) List(siteID string, limit, skip int) ([]store.PostInfo, error) DeleteAll(siteID string) error Metas(siteID string) (umetas []service.UserMetaData, pmetas []service.PostMetaData, err error) SetMetas(siteID string, umetas []service.UserMetaData, pmetas []service.PostMetaData) error } // ImportParams defines everything needed to run import type ImportParams struct { DataStore Store InputFile string Provider string SiteID string } var adminUser = store.User{Admin: true} // ImportComments imports from given provider format and saves to store func ImportComments(p ImportParams) (int, error) { log.Printf("[INFO] import from %s (%s) to %s", p.InputFile, p.Provider, p.SiteID) var importer Importer switch p.Provider { case "disqus": importer = &Disqus{DataStore: p.DataStore} case "wordpress": importer = &WordPress{DataStore: p.DataStore} case "commento": importer = &Commento{DataStore: p.DataStore} case "native": importer = &Native{DataStore: p.DataStore} default: return 0, fmt.Errorf("unsupported import provider %s", p.Provider) } fh, err := os.Open(p.InputFile) if err != nil { return 0, fmt.Errorf("can't open import file %s: %w", p.InputFile, err) } defer func() { //nolint:gosec // false positive on defer without error check when it's checked here if err = fh.Close(); err != nil { log.Printf("[WARN] can't close %s, %s", p.InputFile, err) } }() return importer.Import(fh, p.SiteID) }