migratesky/main.go
2025-06-22 21:37:25 +01:00

149 lines
3.7 KiB
Go

package main
import (
"fmt"
"os"
"slices"
"strings"
)
func main() {
if len(os.Args) == 1 || slices.Contains(os.Args, "-help") {
printHelp()
os.Exit(0)
}
var fromUser string
var fromPassword string
var toUser string
var toPassword string
var pdsUrl string
var fromPdsUrl string
var dryrun bool = false
var verbose bool = false
collections := []string{}
i := 1
for {
if i >= len(os.Args) { break }
if os.Args[i][0] != '-' {
collections = append(collections, os.Args[i])
}
getValue := func(i int) (int, string) {
if i + 1 >= len(os.Args) {
fmt.Fprintf(os.Stderr, "-%s requires a value.\n", os.Args[i])
os.Exit(1)
}
return i + 1, os.Args[i + 1]
}
switch os.Args[i][1:] {
case "from":
i, fromUser = getValue(i)
case "frompass":
i, fromPassword = getValue(i)
case "to":
i, toUser = getValue(i)
case "topass":
i, toPassword = getValue(i)
case "pds":
i, pdsUrl = getValue(i)
case "frompds":
i, fromPdsUrl = getValue(i)
case "dryrun":
dryrun = true
case "v":
verbose = true
}
i += 1
}
if fromUser == "" {
fmt.Fprintf(os.Stderr, "missing required argument -from.\n")
os.Exit(1)
}
if fromPassword == "" {
fmt.Fprintf(os.Stderr, "missing required argument -frompass.\n")
os.Exit(1)
}
if toUser == "" {
fmt.Fprintf(os.Stderr, "missing required argument -to.\n")
os.Exit(1)
}
if toPassword == "" {
fmt.Fprintf(os.Stderr, "missing required argument -topass.\n")
os.Exit(1)
}
if pdsUrl == "" {
fmt.Fprintf(os.Stderr, "missing required argument -pds.\n")
os.Exit(1)
}
if fromPdsUrl == "" { fromPdsUrl = pdsUrl }
if len(collections) == 0 {
fmt.Fprintf(os.Stderr, "no action was specified.\n")
os.Exit(1)
}
fromSession, err := CreateSession(fromPdsUrl, fromUser, fromPassword)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to create session for source account: %v\n", err)
os.Exit(1)
}
toSession, err := CreateSession(pdsUrl, toUser, toPassword)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to create session for destination account: %v\n", err)
os.Exit(1)
}
if slices.Contains(collections, "profile") {
err := ImportProfile(fromSession, toSession, dryrun, verbose)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to import profile: %v\n", err)
os.Exit(1)
}
}
if slices.Contains(collections, "preferences") {
err := ImportPreferences(fromSession, toSession, dryrun, verbose)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to import preferences: %v\n", err)
os.Exit(1)
}
}
if slices.Contains(collections, "follows") {
err := ImportFollows(fromSession, toSession, dryrun, verbose)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to import follows: %v\n", err)
os.Exit(1)
}
}
}
func printHelp() {
fmt.Printf(
`usage: %s <-from <identifier>> <-frompass <password>> <-to <identifier>> <-topass <password>> <-pds <pds-url>> [collections...]
required arguments:
-from <identifier>: the source account handle or DID.
-frompass <password>: the source account password.
-to <identifier>: the destination account handle or DID.
-topass <password>: the destination account password.
-pds <pds-url>: the full https:// url of the destination account's PDS.
collections:
profile: imports account profile, including avatar, banner, display name, and description.
follows: imports all following accounts.
preferences: imports account preferences; including feeds, labeller settings, and content filters.
optional arguments:
-frompds <pds-url>: the source account's PDS url (defaults to the value of -pds).
-dryrun: does not import follow records; good for sanity testing!
-v: verbose output
-help: shows this help message.
`,
os.Args[0][strings.LastIndex(os.Args[0], "/") + 1:],
)
}