-
Notifications
You must be signed in to change notification settings - Fork 4
/
sitedbconvert.go
129 lines (108 loc) · 3.23 KB
/
sitedbconvert.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Package sitedbconvert implements the main command for the site-db dump converter.
package sitedbconvert
import (
"context"
"encoding/json"
"os"
"path/filepath"
"time"
"github.com/go-sql-driver/mysql"
"github.com/hortbot/hortbot/internal/cli"
"github.com/hortbot/hortbot/internal/confimport/sitedb"
"github.com/hortbot/hortbot/internal/pkg/docker"
"github.com/jmoiron/sqlx"
"github.com/zikaeroh/ctxlog"
)
const (
filenameChannels = "site_channels.json"
filenameVars = "site_vars.json"
)
type cmd struct {
cli.Common
SiteDumps string `long:"site-dumps" description:"Directory containing coebot.tv database dumps, also where converted files will be placed" required:"true"`
}
// Command returns a fresh site-db-convert command.
func Command() cli.Command {
return &cmd{
Common: cli.Common{
Debug: true,
},
}
}
func (*cmd) Name() string {
return "site-db-convert"
}
func (c *cmd) Main(ctx context.Context, _ []string) {
outDir := filepath.Clean(c.SiteDumps)
if d, err := os.Stat(outDir); err != nil {
if os.IsNotExist(err) {
ctxlog.Fatal(ctx, "output directory does not exist")
}
ctxlog.Fatal(ctx, "error stat-ing output directory", ctxlog.PlainError(err))
} else if !d.IsDir() {
ctxlog.Fatal(ctx, "output is not a directory")
}
const (
password = "password"
dbName = "db"
)
var db *sqlx.DB
const port = "3306/tcp"
container := &docker.Container{
Repository: "mariadb",
Tag: "10.1",
Env: []string{"MYSQL_ROOT_PASSWORD=" + password, "MYSQL_DATABASE=" + dbName},
Mounts: []string{c.SiteDumps + ":/docker-entrypoint-initdb.d"},
Ports: []string{port},
Ready: func(container *docker.Container) error {
connStr := "root:" + password + "@tcp(" + container.GetHostPort(port) + ")/" + dbName
var err error
db, err = sqlx.Open("mysql", connStr)
if err != nil {
return err
}
return db.Ping()
},
ReadyMaxWait: 5 * time.Minute,
ExpirySecs: uint((24 * time.Hour).Seconds()),
}
if err := container.Start(); err != nil {
ctxlog.Fatal(ctx, "error creating database", ctxlog.PlainError(err))
}
defer db.Close()
writeChannels(ctx, db, outDir)
writeVars(ctx, db, outDir)
}
func writeChannels(ctx context.Context, db *sqlx.DB, outDir string) {
channels, err := sitedb.Channels(ctx, db)
if err != nil {
ctxlog.Fatal(ctx, "error querying for channels", ctxlog.PlainError(err))
}
f, err := os.Create(filepath.Join(outDir, filenameChannels))
if err != nil {
ctxlog.Fatal(ctx, "error creating channels file", ctxlog.PlainError(err))
}
defer f.Close()
if err := json.NewEncoder(f).Encode(channels); err != nil {
ctxlog.Fatal(ctx, "error encoding channels", ctxlog.PlainError(err))
}
}
func writeVars(ctx context.Context, db *sqlx.DB, outDir string) {
vars, err := sitedb.Vars(ctx, db)
if err != nil {
ctxlog.Fatal(ctx, "error querying for vars", ctxlog.PlainError(err))
}
f, err := os.Create(filepath.Join(outDir, filenameVars))
if err != nil {
ctxlog.Fatal(ctx, "error creating vars file", ctxlog.PlainError(err))
}
defer f.Close()
if err := json.NewEncoder(f).Encode(vars); err != nil {
ctxlog.Fatal(ctx, "error encoding vars", ctxlog.PlainError(err))
}
}
func init() {
_ = mysql.SetLogger(noLog{})
}
type noLog struct{}
func (noLog) Print(v ...any) {}