o that is kinda runnin

main
Bel LaPointe 2025-06-04 10:35:44 -06:00
parent 5a343d80f8
commit 80a8577f96
1 changed files with 40 additions and 20 deletions

54
main.go
View File

@ -25,7 +25,6 @@ func main() {
data := os.Args[1] data := os.Args[1]
fromU := os.Args[2] fromU := os.Args[2]
toU := os.Args[3] toU := os.Args[3]
_ = toU
workd, err := ioutil.TempDir(os.TempDir(), "jellyfin-user-clone.*") workd, err := ioutil.TempDir(os.TempDir(), "jellyfin-user-clone.*")
if err != nil { if err != nil {
@ -46,6 +45,12 @@ func main() {
} }
defer jellyfinDB.Close() defer jellyfinDB.Close()
libraryDB, err := sql.Open("sqlite", path.Join(workd, libDB))
if err != nil {
log.Fatalf("%v", err)
}
defer libraryDB.Close()
fromUUID, err := SelectOne[string](jellyfinDB, `SELECT Id FROM Users WHERE Username = $1`, fromU) fromUUID, err := SelectOne[string](jellyfinDB, `SELECT Id FROM Users WHERE Username = $1`, fromU)
if err != nil { if err != nil {
log.Fatalf("%v", err) log.Fatalf("%v", err)
@ -58,14 +63,22 @@ func main() {
if n, err := SelectOne[int](jellyfinDB, `SELECT COUNT(*) FROM Users WHERE Username = $1`, toU); err != nil { if n, err := SelectOne[int](jellyfinDB, `SELECT COUNT(*) FROM Users WHERE Username = $1`, toU); err != nil {
log.Fatalf("%v", err) log.Fatalf("%v", err)
} else if n == 1 { } else if n != 1 {
} else if err := CloneForColumn(jellyfinDB, `Users`, `Username`, fromU, toU, `InternalId`); err != nil { // TODO how is InternalId maintained? Chance? nextID, err := SelectOne[int](libraryDB, `SELECT COALESCE(MAX(userId), 0)+1 FROM UserDatas`)
if err != nil {
log.Fatalf("failed to get max userid ever: %v", err)
}
if err := CloneForColumn(jellyfinDB, `Users`, `Username`, fromU, toU, map[string]any{`InternalId`: nextID}); err != nil {
log.Fatalf("%v", err) log.Fatalf("%v", err)
} else if n, err := SelectOne[int](jellyfinDB, `SELECT COUNT(*) FROM Users WHERE Username = $1`, toU); err != nil { }
if n, err := SelectOne[int](jellyfinDB, `SELECT COUNT(*) FROM Users WHERE Username = $1 AND InternalId = $2`, toU, nextID); err != nil {
log.Fatalf("%v", err) log.Fatalf("%v", err)
} else if n != 1 { } else if n != 1 {
log.Fatalf("still no username=%q after insert", toU) log.Fatalf("still no username=%q after insert", toU)
} }
}
toUUID, err := SelectOne[string](jellyfinDB, `SELECT Id FROM Users WHERE Username = $1`, toU) toUUID, err := SelectOne[string](jellyfinDB, `SELECT Id FROM Users WHERE Username = $1`, toU)
if err != nil { if err != nil {
@ -77,12 +90,6 @@ func main() {
} }
log.Println(toU, toUUID, toID) log.Println(toU, toUUID, toID)
libraryDB, err := sql.Open("sqlite", path.Join(workd, libDB))
if err != nil {
log.Fatalf("%v", err)
}
defer libraryDB.Close()
for _, db := range []*sql.DB{jellyfinDB, libraryDB} { for _, db := range []*sql.DB{jellyfinDB, libraryDB} {
tables, err := Tables(db) tables, err := Tables(db)
if err != nil { if err != nil {
@ -111,13 +118,13 @@ func main() {
if n, err := SelectOne[int](db, fmt.Sprintf(`SELECT COUNT(*) FROM %q WHERE %q = $1`, table, column), fromID); err != nil { if n, err := SelectOne[int](db, fmt.Sprintf(`SELECT COUNT(*) FROM %q WHERE %q = $1`, table, column), fromID); err != nil {
log.Fatalf("%v", err) log.Fatalf("%v", err)
} else if n > 0 { } else if n > 0 {
if err := CloneForColumn(db, table, column, fromID, toID); err != nil { if err := CloneForColumn(db, table, column, fromID, toID, nil); err != nil {
log.Fatalf("%v", err) log.Fatalf("%v", err)
} }
} else if n, err := SelectOne[int](db, fmt.Sprintf(`SELECT COUNT(*) FROM %q WHERE %q = $1`, table, column), fromUUID); err != nil { } else if n, err := SelectOne[int](db, fmt.Sprintf(`SELECT COUNT(*) FROM %q WHERE %q = $1`, table, column), fromUUID); err != nil {
log.Fatalf("%v", err) log.Fatalf("%v", err)
} else if n > 0 { } else if n > 0 {
if err := CloneForColumn(db, table, column, fromUUID, toUUID); err != nil { if err := CloneForColumn(db, table, column, fromUUID, toUUID, nil); err != nil {
log.Fatalf("%v", err) log.Fatalf("%v", err)
} }
} }
@ -126,7 +133,7 @@ func main() {
} }
} }
func CloneForColumn[T any](db *sql.DB, table, column string, from, to T, extraUniques ...string) error { func CloneForColumn[T any](db *sql.DB, table, column string, from, to T, fixed map[string]any) error {
columns, err := Columns(db, table) columns, err := Columns(db, table)
if err != nil { if err != nil {
return err return err
@ -143,8 +150,14 @@ func CloneForColumn[T any](db *sql.DB, table, column string, from, to T, extraUn
log.Printf("unique text columns %+v, unique int columns %+v", uniqueTextColumns, uniqueIntColumns) log.Printf("unique text columns %+v, unique int columns %+v", uniqueTextColumns, uniqueIntColumns)
extraUniques := []string{}
for k := range fixed {
extraUniques = append(extraUniques, k)
}
omit := append(append(extraUniques, uniqueIntColumns...), uniqueTextColumns...) omit := append(append(extraUniques, uniqueIntColumns...), uniqueTextColumns...)
notTheseColumns := slices.DeleteFunc(slices.Clone(columns), func(s string) bool { return s == column || slices.Contains(omit, s) }) notTheseColumns := slices.DeleteFunc(slices.Clone(columns), func(s string) bool {
return s == column || slices.Contains(omit, s) || slices.Contains(extraUniques, s)
})
for i := range notTheseColumns { for i := range notTheseColumns {
notTheseColumns[i] = fmt.Sprintf("%q", notTheseColumns[i]) notTheseColumns[i] = fmt.Sprintf("%q", notTheseColumns[i])
} }
@ -153,7 +166,9 @@ func CloneForColumn[T any](db *sql.DB, table, column string, from, to T, extraUn
if err != nil { if err != nil {
return err return err
} }
uuidGenColumns := slices.DeleteFunc(notNullTextColumns, func(s string) bool { return s == column || !slices.Contains(omit, s) }) uuidGenColumns := slices.DeleteFunc(notNullTextColumns, func(s string) bool {
return s == column || !slices.Contains(omit, s) || slices.Contains(extraUniques, s)
})
for i := range uuidGenColumns { for i := range uuidGenColumns {
uuidGenColumns[i] = fmt.Sprintf("%q", uuidGenColumns[i]) uuidGenColumns[i] = fmt.Sprintf("%q", uuidGenColumns[i])
} }
@ -162,7 +177,9 @@ func CloneForColumn[T any](db *sql.DB, table, column string, from, to T, extraUn
if err != nil { if err != nil {
return err return err
} }
incrGenColumns := slices.DeleteFunc(notNullIntColumns, func(s string) bool { return !slices.Contains(omit, s) }) incrGenColumns := slices.DeleteFunc(notNullIntColumns, func(s string) bool {
return s == column || !slices.Contains(omit, s) || slices.Contains(extraUniques, s)
})
for i := range incrGenColumns { for i := range incrGenColumns {
incrGenColumns[i] = fmt.Sprintf("%q", incrGenColumns[i]) incrGenColumns[i] = fmt.Sprintf("%q", incrGenColumns[i])
} }
@ -180,11 +197,14 @@ func CloneForColumn[T any](db *sql.DB, table, column string, from, to T, extraUn
for _, arg := range args { for _, arg := range args {
values = append(values, *(arg.(*any))) values = append(values, *(arg.(*any)))
} }
for _, k := range extraUniques {
values = append(values, fixed[k])
}
values = append(values, to) values = append(values, to)
q := fmt.Sprintf( q := fmt.Sprintf(
`INSERT INTO %q (%s, %q) VALUES (%s %s)`, `INSERT INTO %q (%s, %q) VALUES (%s %s)`,
table, strings.Join(append(incrGenColumns, append(uuidGenColumns, notTheseColumns...)...), ", "), column, table, strings.Join(append(append(incrGenColumns, append(uuidGenColumns, notTheseColumns...)...), extraUniques...), ", "), column,
selectMaxes, strings.Join(slices.Repeat([]string{"?"}, len(values)), ", "), selectMaxes, strings.Join(slices.Repeat([]string{"?"}, len(values)), ", "),
) )