add migration thing

This commit is contained in:
Chris Sexton 2021-12-21 22:36:08 -05:00
parent a34770adaa
commit a7f05c75fd
31 changed files with 1085 additions and 93 deletions

View File

@ -308,6 +308,10 @@ type BlacklistItem struct {
Name string Name string
} }
func (b BlacklistItem) Key() string {
return b.Channel + b.Name
}
type WhitelistItem struct { type WhitelistItem struct {
Name string Name string
} }

4
go.mod
View File

@ -34,6 +34,7 @@ require (
github.com/itchyny/gojq v0.12.3 github.com/itchyny/gojq v0.12.3
github.com/james-bowman/nlp v0.0.0-20191016091239-d9dbfaff30c6 github.com/james-bowman/nlp v0.0.0-20191016091239-d9dbfaff30c6
github.com/james-bowman/sparse v0.0.0-20190423065201-80c6877364c7 // indirect github.com/james-bowman/sparse v0.0.0-20190423065201-80c6877364c7 // indirect
github.com/jmoiron/sqlx v1.3.4
github.com/kennygrant/sanitize v1.2.4 // indirect github.com/kennygrant/sanitize v1.2.4 // indirect
github.com/kevinburke/go-types v0.0.0-20200309064045-f2d4aea18a7a // indirect github.com/kevinburke/go-types v0.0.0-20200309064045-f2d4aea18a7a // indirect
github.com/kevinburke/go.uuid v1.2.0 // indirect github.com/kevinburke/go.uuid v1.2.0 // indirect
@ -58,10 +59,10 @@ require (
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect
github.com/ttacon/libphonenumber v1.1.0 // indirect github.com/ttacon/libphonenumber v1.1.0 // indirect
github.com/velour/velour v0.0.0-20160303155839-8e090e68d158 github.com/velour/velour v0.0.0-20160303155839-8e090e68d158
go.etcd.io/bbolt v1.3.6 // indirect
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
golang.org/x/exp v0.0.0-20191014171548-69215a2ee97e // indirect golang.org/x/exp v0.0.0-20191014171548-69215a2ee97e // indirect
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 // indirect golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 // indirect
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 // indirect golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
gonum.org/v1/gonum v0.6.0 // indirect gonum.org/v1/gonum v0.6.0 // indirect
@ -69,4 +70,5 @@ require (
gopkg.in/go-playground/webhooks.v5 v5.13.0 gopkg.in/go-playground/webhooks.v5 v5.13.0
gopkg.in/sourcemap.v1 v1.0.5 // indirect gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
modernc.org/sqlite v1.14.3
) )

156
go.sum
View File

@ -37,6 +37,8 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc h1:tP7tkU+vIsEOKiK+l/NSLN4uUtkyuxc6hgYpQeCWAeI= github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc h1:tP7tkU+vIsEOKiK+l/NSLN4uUtkyuxc6hgYpQeCWAeI=
github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc/go.mod h1:ORH5Qp2bskd9NzSfKqAF7tKfONsEkCarTE5ESr/RVBw= github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc/go.mod h1:ORH5Qp2bskd9NzSfKqAF7tKfONsEkCarTE5ESr/RVBw=
github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad h1:Qk76DOWdOp+GlyDKBAG3Klr9cn7N+LcYc82AZ2S7+cA= github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad h1:Qk76DOWdOp+GlyDKBAG3Klr9cn7N+LcYc82AZ2S7+cA=
@ -48,6 +50,8 @@ github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17/go.mod h1:HfkOCN
github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4= github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4=
github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
@ -66,6 +70,8 @@ github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82 h1:EvokxLQsaaQjcWVWSV
github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg=
github.com/gonum/internal v0.0.0-20181124074243-f884aa714029 h1:8jtTdc+Nfj9AR+0soOeia9UZSvYBvETVHZrugUowJ7M= github.com/gonum/internal v0.0.0-20181124074243-f884aa714029 h1:8jtTdc+Nfj9AR+0soOeia9UZSvYBvETVHZrugUowJ7M=
github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -83,7 +89,11 @@ github.com/james-bowman/nlp v0.0.0-20191016091239-d9dbfaff30c6 h1:k8+n5sfvxlixRN
github.com/james-bowman/nlp v0.0.0-20191016091239-d9dbfaff30c6/go.mod h1:kixuaexEqWB+mHZNysgnb6mqgGIT25WvD1/tFRRt0J0= github.com/james-bowman/nlp v0.0.0-20191016091239-d9dbfaff30c6/go.mod h1:kixuaexEqWB+mHZNysgnb6mqgGIT25WvD1/tFRRt0J0=
github.com/james-bowman/sparse v0.0.0-20190423065201-80c6877364c7 h1:ph/BDQQDL41apnHSN48I5GyNOQXXAlc79HwGqDSXCss= github.com/james-bowman/sparse v0.0.0-20190423065201-80c6877364c7 h1:ph/BDQQDL41apnHSN48I5GyNOQXXAlc79HwGqDSXCss=
github.com/james-bowman/sparse v0.0.0-20190423065201-80c6877364c7/go.mod h1:G6EcQnwZKsWtItoaQHd+FHPPk6bDeYVJSeeSP9Sge+I= github.com/james-bowman/sparse v0.0.0-20190423065201-80c6877364c7/go.mod h1:G6EcQnwZKsWtItoaQHd+FHPPk6bDeYVJSeeSP9Sge+I=
github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w=
github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o= github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak= github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
github.com/kevinburke/go-types v0.0.0-20200309064045-f2d4aea18a7a h1:Z7+SSApKiwPjNic+NF9+j7h657Uyvdp/jA3iTKhpj4E= github.com/kevinburke/go-types v0.0.0-20200309064045-f2d4aea18a7a h1:Z7+SSApKiwPjNic+NF9+j7h657Uyvdp/jA3iTKhpj4E=
@ -94,11 +104,16 @@ github.com/kevinburke/rest v0.0.0-20200429221318-0d2892b400f8 h1:KpuDJTaTPQAyWqE
github.com/kevinburke/rest v0.0.0-20200429221318-0d2892b400f8/go.mod h1:pD+iEcdAGVXld5foVN4e24zb/6fnb60tgZPZ3P/3T/I= github.com/kevinburke/rest v0.0.0-20200429221318-0d2892b400f8/go.mod h1:pD+iEcdAGVXld5foVN4e24zb/6fnb60tgZPZ3P/3T/I=
github.com/kevinburke/twilio-go v0.0.0-20200424172635-4f0b2357b852 h1:wJMykIkD7A4tlwQNzqBJ23hkLlKtRKYeNNt+n8ASqWE= github.com/kevinburke/twilio-go v0.0.0-20200424172635-4f0b2357b852 h1:wJMykIkD7A4tlwQNzqBJ23hkLlKtRKYeNNt+n8ASqWE=
github.com/kevinburke/twilio-go v0.0.0-20200424172635-4f0b2357b852/go.mod h1:Fm9alkN1/LPVY1eqD/psyMwPWE4VWl4P01/nTYZKzBk= github.com/kevinburke/twilio-go v0.0.0-20200424172635-4f0b2357b852/go.mod h1:Fm9alkN1/LPVY1eqD/psyMwPWE4VWl4P01/nTYZKzBk=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mmcdole/gofeed v1.0.0-beta2 h1:CjQ0ADhAwNSb08zknAkGOEYqr8zfZKfrzgk9BxpWP2E= github.com/mmcdole/gofeed v1.0.0-beta2 h1:CjQ0ADhAwNSb08zknAkGOEYqr8zfZKfrzgk9BxpWP2E=
github.com/mmcdole/gofeed v1.0.0-beta2/go.mod h1:/BF9JneEL2/flujm8XHoxUcghdTV6vvb3xx/vKyChFU= github.com/mmcdole/gofeed v1.0.0-beta2/go.mod h1:/BF9JneEL2/flujm8XHoxUcghdTV6vvb3xx/vKyChFU=
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/S/mDBM5plIU8v/Qhfz41hkDIAI= github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/S/mDBM5plIU8v/Qhfz41hkDIAI=
@ -113,6 +128,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4= github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4=
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
@ -143,12 +160,15 @@ github.com/ttacon/libphonenumber v1.1.0 h1:tC6kE4t8UI4OqQVQjW5q8gSWhG2wnY5moEpSE
github.com/ttacon/libphonenumber v1.1.0/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M= github.com/ttacon/libphonenumber v1.1.0/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M=
github.com/velour/velour v0.0.0-20160303155839-8e090e68d158 h1:p3rTUXxzuKsBOsHlkly7+rj9wagFBKeIsCDKkDII9sw= github.com/velour/velour v0.0.0-20160303155839-8e090e68d158 h1:p3rTUXxzuKsBOsHlkly7+rj9wagFBKeIsCDKkDII9sw=
github.com/velour/velour v0.0.0-20160303155839-8e090e68d158/go.mod h1:Ojy3BTOiOTwpHpw7/HNi+TVTFppao191PQs+Qc3sqpE= github.com/velour/velour v0.0.0-20160303155839-8e090e68d158/go.mod h1:Ojy3BTOiOTwpHpw7/HNi+TVTFppao191PQs+Qc3sqpE=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI= golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI=
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -163,12 +183,15 @@ golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDA
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 h1:DZshvxDdVoeKIbudAdFEKi+f70l51luSy/7b76ibTY0= golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 h1:DZshvxDdVoeKIbudAdFEKi+f70l51luSy/7b76ibTY0=
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@ -182,15 +205,20 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI= golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI=
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
@ -199,8 +227,14 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.6.0 h1:DJy6UzXbahnGUf1ujUNkh/NEtK14qMo2nvlBPs4U5yw= gonum.org/v1/gonum v0.6.0 h1:DJy6UzXbahnGUf1ujUNkh/NEtK14qMo2nvlBPs4U5yw=
gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
@ -219,4 +253,126 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.18 h1:rMZhRcWrba0y3nVmdiQ7kxAgOOSq2m2f2VzjHLgEs6U=
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag=
modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw=
modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ=
modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c=
modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo=
modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg=
modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I=
modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs=
modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8=
modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE=
modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk=
modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w=
modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE=
modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8=
modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc=
modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU=
modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE=
modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk=
modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI=
modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE=
modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg=
modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74=
modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU=
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU=
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc=
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM=
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ=
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84=
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ=
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY=
modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU=
modernc.org/ccgo/v3 v3.12.88/go.mod h1:0MFzUHIuSIthpVZyMWiFYMwjiFnhrN5MkvBrUwON+ZM=
modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko=
modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA=
modernc.org/ccgo/v3 v3.12.95 h1:Ym2JG2G3P4IyZqjTTojHTl7qO0RysXeGSYPSoKPSBxc=
modernc.org/ccgo/v3 v3.12.95/go.mod h1:ZcLyvtocXYi8uF+9Ebm3G8EF8HNY5hGomBqthDp4eC8=
modernc.org/ccorpus v1.11.1 h1:K0qPfpVG1MJh5BYazccnmhywH4zHuOgJXgbjzyp6dWA=
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M=
modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU=
modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE=
modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso=
modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8=
modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8=
modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I=
modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk=
modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY=
modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE=
modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg=
modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM=
modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg=
modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo=
modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8=
modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ=
modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA=
modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM=
modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg=
modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE=
modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM=
modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU=
modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw=
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M=
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18=
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8=
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0=
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI=
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE=
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ=
modernc.org/libc v1.11.90/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
modernc.org/libc v1.11.99/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
modernc.org/libc v1.11.104 h1:gxoa5b3HPo7OzD4tKZjgnwXk/w//u1oovvjSMP3Q96Q=
modernc.org/libc v1.11.104/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.14.3 h1:psrTwgpEujgWEP3FNdsC9yNh5tSeA77U0GeWhHH4XmQ=
modernc.org/sqlite v1.14.3/go.mod h1:xMpicS1i2MJ4C8+Ap0vYBqTwYfpFvdnPE6brbFOtV2Y=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.9.2 h1:YA87dFLOsR2KqMka371a2Xgr+YsyUwo7OmHVSv/kztw=
modernc.org/tcl v1.9.2/go.mod h1:aw7OnlIoiuJgu1gwbTZtrKnGpDqH9wyH++jZcxdqNsg=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.2.20 h1:DyboxM1sJR2NB803j2StnbnL6jcQXz273OhHDGu8dGk=
modernc.org/z v1.2.20/go.mod h1:zU9FiF4PbHdOTUxw+IF8j7ArBMRPsHgq10uVPt6xTzo=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -366,16 +366,18 @@ func (p *AdminPlugin) addBlacklist(channel, plugin string) error {
return fmt.Errorf("you cannot disable the admin plugin") return fmt.Errorf("you cannot disable the admin plugin")
} }
defer p.bot.RefreshPluginBlacklist() defer p.bot.RefreshPluginBlacklist()
return p.store.Upsert(channel+plugin, bot.BlacklistItem{ it := bot.BlacklistItem{
Channel: channel, Channel: channel,
Name: plugin, Name: plugin,
}) }
return p.store.Upsert(it.Key(), it)
} }
func (p *AdminPlugin) rmBlacklist(channel, plugin string) error { func (p *AdminPlugin) rmBlacklist(channel, plugin string) error {
defer p.bot.RefreshPluginBlacklist() defer p.bot.RefreshPluginBlacklist()
return p.store.Delete(channel+plugin, bot.BlacklistItem{ it := bot.BlacklistItem{
Channel: channel, Channel: channel,
Name: plugin, Name: plugin,
}) }
return p.store.Delete(it.Key(), bot.BlacklistItem{})
} }

View File

@ -43,7 +43,7 @@ type PassEntry struct {
// Should be null unless inserting a new entry // Should be null unless inserting a new entry
Pass string `json:"pass"` Pass string `json:"pass"`
encodedPass []byte `json:"encodedPass"` EncodedPass []byte `db:"encoded_pass" json:"encodedPass"`
Cost int `json:"cost"` Cost int `json:"cost"`
} }
@ -52,11 +52,11 @@ func (p *PassEntry) EncodePass() {
if err != nil { if err != nil {
log.Error().Err(err).Msg("could not hash password") log.Error().Err(err).Msg("could not hash password")
} }
p.encodedPass = encoded p.EncodedPass = encoded
} }
func (p *PassEntry) Compare(pass string) bool { func (p *PassEntry) Compare(pass string) bool {
if err := bcrypt.CompareHashAndPassword(p.encodedPass, []byte(pass)); err != nil { if err := bcrypt.CompareHashAndPassword(p.EncodedPass, []byte(pass)); err != nil {
log.Error().Err(err).Msg("failure to match password") log.Error().Err(err).Msg("failure to match password")
return false return false
} }
@ -111,18 +111,18 @@ func (p *AdminPlugin) handleAppPassAPI(w http.ResponseWriter, r *http.Request) {
req.PassEntry.EncodePass() req.PassEntry.EncodePass()
check := bcrypt.CompareHashAndPassword(req.PassEntry.encodedPass, []byte(req.PassEntry.Pass)) check := bcrypt.CompareHashAndPassword(req.PassEntry.EncodedPass, []byte(req.PassEntry.Pass))
entry := PassEntry{ entry := PassEntry{
Secret: req.PassEntry.Secret, Secret: req.PassEntry.Secret,
encodedPass: req.PassEntry.encodedPass, EncodedPass: req.PassEntry.EncodedPass,
Cost: req.PassEntry.Cost, Cost: req.PassEntry.Cost,
Pass: "", Pass: "",
} }
log.Debug(). log.Debug().
Str("secret", req.PassEntry.Secret). Str("secret", req.PassEntry.Secret).
Str("encoded", string(req.PassEntry.encodedPass)). Str("encoded", string(req.PassEntry.EncodedPass)).
Str("password", string(req.PassEntry.Pass)). Str("password", string(req.PassEntry.Pass)).
Interface("check", check). Interface("check", check).
Msg("debug pass creation") Msg("debug pass creation")

View File

@ -36,13 +36,13 @@ type Item struct {
UserID string UserID string
} }
type alias struct { type Alias struct {
store *bh.Store store *bh.Store
created bool created bool
ID uint64 `boltholdKey:"ID"` ID uint64 `boltholdKey:"ID"`
Item string Item string
PointsTo string `db:"PointsTo"` PointsTo string `db:"points_to"`
} }
// GetItems returns all counters // GetItems returns all counters
@ -110,17 +110,17 @@ func Leader(store *bh.Store, itemName string) ([]Item, error) {
} }
func RmAlias(store *bh.Store, aliasName string) error { func RmAlias(store *bh.Store, aliasName string) error {
a := &alias{} a := &Alias{}
if err := store.FindOne(a, bh.Where("Item").Eq(aliasName)); err != nil { if err := store.FindOne(a, bh.Where("Item").Eq(aliasName)); err != nil {
return err return err
} }
return store.Delete(a.ID, alias{}) return store.Delete(a.ID, Alias{})
} }
func MkAlias(store *bh.Store, aliasName, pointsTo string) (*alias, error) { func MkAlias(store *bh.Store, aliasName, pointsTo string) (*Alias, error) {
aliasName = strings.ToLower(aliasName) aliasName = strings.ToLower(aliasName)
pointsTo = strings.ToLower(pointsTo) pointsTo = strings.ToLower(pointsTo)
alias := &alias{ alias := &Alias{
store: store, store: store,
Item: aliasName, Item: aliasName,
PointsTo: pointsTo, PointsTo: pointsTo,
@ -134,7 +134,7 @@ func MkAlias(store *bh.Store, aliasName, pointsTo string) (*alias, error) {
func GetItem(store *bh.Store, itemName string) ([]Item, error) { func GetItem(store *bh.Store, itemName string) ([]Item, error) {
itemName = trimUnicode(itemName) itemName = trimUnicode(itemName)
var items []Item var items []Item
var a alias var a Alias
if err := store.FindOne(&a, bh.Where("Item").Eq(itemName)); err == nil { if err := store.FindOne(&a, bh.Where("Item").Eq(itemName)); err == nil {
itemName = a.PointsTo itemName = a.PointsTo
} else { } else {
@ -162,7 +162,7 @@ func GetUserItem(store *bh.Store, nick, id, itemName string) (*Item, error) {
item.Nick = nick item.Nick = nick
item.Item = itemName item.Item = itemName
item.UserID = id item.UserID = id
var a alias var a Alias
err := store.FindOne(&a, bh.Where("Item").Eq(itemName)) err := store.FindOne(&a, bh.Where("Item").Eq(itemName))
if err == nil { if err == nil {
log.Debug().Msgf("itemName now is %s", a.PointsTo) log.Debug().Msgf("itemName now is %s", a.PointsTo)

View File

@ -236,7 +236,7 @@ func parseCmd(r *regexp.Regexp, body string) cmd {
return out return out
} }
type goal struct { type Goal struct {
ID uint64 `boltholdKey:"ID"` ID uint64 `boltholdKey:"ID"`
Kind string Kind string
Who string Who string
@ -246,8 +246,8 @@ type goal struct {
gp *GoalsPlugin gp *GoalsPlugin
} }
func (p *GoalsPlugin) newGoal(kind, who, what string, amount int) *goal { func (p *GoalsPlugin) newGoal(kind, who, what string, amount int) *Goal {
return &goal{ return &Goal{
ID: 0, ID: 0,
Kind: kind, Kind: kind,
Who: who, Who: who,
@ -257,8 +257,8 @@ func (p *GoalsPlugin) newGoal(kind, who, what string, amount int) *goal {
} }
} }
func (p *GoalsPlugin) getGoal(who, what string) ([]*goal, error) { func (p *GoalsPlugin) getGoal(who, what string) ([]*Goal, error) {
gs := []*goal{} gs := []*Goal{}
err := p.store.Find(&gs, bh.Where("Who").Eq(who).And("What").Eq(what)) err := p.store.Find(&gs, bh.Where("Who").Eq(who).And("What").Eq(what))
if err != nil { if err != nil {
return nil, err return nil, err
@ -269,8 +269,8 @@ func (p *GoalsPlugin) getGoal(who, what string) ([]*goal, error) {
return gs, nil return gs, nil
} }
func (p *GoalsPlugin) getGoalKind(kind, who, what string) (*goal, error) { func (p *GoalsPlugin) getGoalKind(kind, who, what string) (*Goal, error) {
g := &goal{gp: p} g := &Goal{gp: p}
err := p.store.FindOne(g, bh.Where("Kind").Eq(kind).And("Who").Eq(who).And("What").Eq(what)) err := p.store.FindOne(g, bh.Where("Kind").Eq(kind).And("Who").Eq(who).And("What").Eq(what))
if err != nil { if err != nil {
return nil, err return nil, err
@ -278,7 +278,7 @@ func (p *GoalsPlugin) getGoalKind(kind, who, what string) (*goal, error) {
return g, nil return g, nil
} }
func (g *goal) Save() error { func (g *Goal) Save() error {
err := g.gp.store.Insert(bh.NextSequence(), g) err := g.gp.store.Insert(bh.NextSequence(), g)
if err != nil { if err != nil {
return err return err
@ -286,11 +286,11 @@ func (g *goal) Save() error {
return nil return nil
} }
func (g goal) Delete() error { func (g Goal) Delete() error {
if g.ID == 0 { if g.ID == 0 {
return nil return nil
} }
err := g.gp.store.Delete(goal{}, g.ID) err := g.gp.store.Delete(Goal{}, g.ID)
return err return err
} }
@ -313,7 +313,7 @@ func (p *GoalsPlugin) update(r bot.Request, u counter.Update) {
var now = time.Now var now = time.Now
func (p *GoalsPlugin) calculateRemaining(i *counter.Item, g *goal) int { func (p *GoalsPlugin) calculateRemaining(i *counter.Item, g *Goal) int {
today := float64(now().YearDay()) today := float64(now().YearDay())
thisYear := time.Date(now().Year(), 0, 0, 0, 0, 0, 0, time.UTC) thisYear := time.Date(now().Year(), 0, 0, 0, 0, 0, 0, time.UTC)
nextYear := time.Date(now().Year()+1, 0, 0, 0, 0, 0, 0, time.UTC) nextYear := time.Date(now().Year()+1, 0, 0, 0, 0, 0, 0, time.UTC)
@ -328,7 +328,7 @@ func (p *GoalsPlugin) calculateRemaining(i *counter.Item, g *goal) int {
return diff return diff
} }
func (p *GoalsPlugin) remainingText(i *counter.Item, g *goal) string { func (p *GoalsPlugin) remainingText(i *counter.Item, g *Goal) string {
remaining := p.calculateRemaining(i, g) remaining := p.calculateRemaining(i, g)
txt := "" txt := ""
if remaining < 0 { if remaining < 0 {

View File

@ -61,7 +61,7 @@ func TestRemainingSomeToGo(t *testing.T) {
Count: 190, Count: 190,
} }
g := goal{ g := Goal{
ID: 0, ID: 0,
Kind: "", Kind: "",
Who: "", Who: "",
@ -92,7 +92,7 @@ func TestRemainingAheadOfCurve(t *testing.T) {
Count: 200, Count: 200,
} }
g := goal{ g := Goal{
ID: 0, ID: 0,
Kind: "", Kind: "",
Who: "", Who: "",

View File

@ -44,7 +44,7 @@ func New(b bot.Bot) *InventoryPlugin {
} }
type Item struct { type Item struct {
Name string `boltholdKey:"Name"` Name string `db:"item" boltholdKey:"Name"`
} }
func (p *InventoryPlugin) giveItemFilter(input string) string { func (p *InventoryPlugin) giveItemFilter(input string) string {

View File

@ -39,13 +39,13 @@ func (p *LastPlugin) register() {
{ {
Kind: bot.Message, IsCmd: true, Kind: bot.Message, IsCmd: true,
Regex: regexp.MustCompile(`(?i)^who killed the channel\??$`), Regex: regexp.MustCompile(`(?i)^who killed the channel\??$`),
HelpText: "Find out who had last yesterday", HelpText: "Find out who had Last yesterday",
Handler: p.whoKilled, Handler: p.whoKilled,
}, },
{ {
Kind: bot.Message, IsCmd: true, Kind: bot.Message, IsCmd: true,
Regex: regexp.MustCompile(`(?i)^who killed #?(?P<channel>\S+)\??$`), Regex: regexp.MustCompile(`(?i)^who killed #?(?P<channel>\S+)\??$`),
HelpText: "Find out who had last yesterday in a channel", HelpText: "Find out who had Last yesterday in a channel",
Handler: p.whoKilledChannel, Handler: p.whoKilledChannel,
}, },
{ {
@ -59,7 +59,7 @@ func (p *LastPlugin) register() {
} }
func (p *LastPlugin) enabled_channel(r bot.Request) bool { func (p *LastPlugin) enabled_channel(r bot.Request) bool {
chs := p.c.GetArray("last.channels", []string{}) chs := p.c.GetArray("Last.channels", []string{})
for _, ch := range chs { for _, ch := range chs {
if r.Msg.Channel == ch { if r.Msg.Channel == ch {
return true return true
@ -103,14 +103,14 @@ func (p *LastPlugin) recordLast(r bot.Request) bool {
return false return false
} }
invalidUsers := p.c.GetArray("last.invalidUsers", []string{"unknown"}) invalidUsers := p.c.GetArray("Last.invalidUsers", []string{"unknown"})
for _, u := range invalidUsers { for _, u := range invalidUsers {
if who == u { if who == u {
return false return false
} }
} }
l := &last{ l := &Last{
Day: day.Unix(), Day: day.Unix(),
TS: time.Now().Unix(), TS: time.Now().Unix(),
Channel: ch, Channel: ch,
@ -118,26 +118,27 @@ func (p *LastPlugin) recordLast(r bot.Request) bool {
Message: r.Msg.Body, Message: r.Msg.Body,
} }
// todo: I think last might depend on a key being something more real // todo: I think Last might depend on a key being something more real
return p.store.Insert(bh.NextSequence(), l) == nil return p.store.Insert(bh.NextSequence(), l) == nil
} }
type last struct { type Last struct {
ID uint64 `boltholdKey:"ID"`
Day int64 Day int64
TS int64 TS int64 `db:"ts"`
Channel string Channel string `db:"channel"`
Who string Who string `db:"who"`
Message string Message string `db:"message"`
} }
func (p *LastPlugin) yesterdaysLast(ch string) (last, error) { func (p *LastPlugin) yesterdaysLast(ch string) (Last, error) {
l := last{} l := Last{}
midnight := first.Midnight(time.Now()) midnight := first.Midnight(time.Now())
q := `select * from last where channel = ? and day < ? and day >= ? order by day limit 1` q := `select * from Last where channel = ? and day < ? and day >= ? order by day limit 1`
log.Debug().Str("q", q).Msgf("yesterdaysLast: %d to %d", midnight.Unix(), midnight.Add(-24*time.Hour).Unix()) log.Debug().Str("q", q).Msgf("yesterdaysLast: %d to %d", midnight.Unix(), midnight.Add(-24*time.Hour).Unix())
err := p.store.FindOne(&l, bh.Where("Channel").Eq(ch).And("Day").Lt(midnight.Unix()).And("Day").Ge(midnight.Add(-24*time.Hour).Unix())) err := p.store.FindOne(&l, bh.Where("Channel").Eq(ch).And("Day").Lt(midnight.Unix()).And("Day").Ge(midnight.Add(-24*time.Hour).Unix()))
if err != nil { if err != nil {
return last{}, err return Last{}, err
} }
return l, nil return l, nil
} }
@ -163,12 +164,12 @@ func (p *LastPlugin) whoKilledChannel(r bot.Request) bool {
func (p *LastPlugin) sayLast(c bot.Connector, chFrom, chTo string, force bool) { func (p *LastPlugin) sayLast(c bot.Connector, chFrom, chTo string, force bool) {
l, err := p.yesterdaysLast(chFrom) l, err := p.yesterdaysLast(chFrom)
if err != nil || l.Day == 0 { if err != nil || l.Day == 0 {
log.Error().Err(err).Interface("last", l).Msgf("Couldn't find last") log.Error().Err(err).Interface("Last", l).Msgf("Couldn't find Last")
if force { if force {
p.b.Send(c, bot.Message, chTo, "I couldn't find a last.") p.b.Send(c, bot.Message, chTo, "I couldn't find a Last.")
} }
return return
} }
msg := fmt.Sprintf(`%s killed the channel last night by saying "%s"`, l.Who, l.Message) msg := fmt.Sprintf(`%s killed the channel Last night by saying "%s"`, l.Who, l.Message)
p.b.Send(c, bot.Message, chTo, msg) p.b.Send(c, bot.Message, chTo, msg)
} }

View File

@ -38,7 +38,7 @@ type Bid struct {
PlacedScore int `db:"placed_score"` PlacedScore int `db:"placed_score"`
ProcessedScore int `db:"processed_score"` ProcessedScore int `db:"processed_score"`
Placed time.Time Placed time.Time
Processed bool Processed time.Time
} }
type Balance struct { type Balance struct {
@ -108,7 +108,7 @@ func (w *Webshit) Check(last int64) ([]WeeklyResult, int64, error) {
// Delete all those bids // Delete all those bids
if err = w.store.UpdateMatching(Bid{}, bh.Where("Processed").Eq(false), func(record interface{}) error { if err = w.store.UpdateMatching(Bid{}, bh.Where("Processed").Eq(false), func(record interface{}) error {
r := record.(*Bid) r := record.(*Bid)
r.Processed = true r.Processed = time.Now()
return w.store.Update(r.ID, r) return w.store.Update(r.ID, r)
}); err != nil { }); err != nil {
return nil, 0, err return nil, 0, err

View File

@ -38,10 +38,10 @@ type ReminderPlugin struct {
type Reminder struct { type Reminder struct {
ID uint64 `boltholdKey:"ID"` ID uint64 `boltholdKey:"ID"`
From string From string `db:"fromWho"`
Who string Who string `db:"toWho"`
What string What string
When time.Time When time.Time `db:"remindWhen"`
Channel string Channel string
} }

View File

@ -63,8 +63,8 @@ func (p *RestPlugin) register() {
HelpText: "Lists all REST functions", HelpText: "Lists all REST functions",
Handler: p.listWires}, Handler: p.listWires},
bot.HandlerSpec{Kind: bot.Message, IsCmd: true, bot.HandlerSpec{Kind: bot.Message, IsCmd: true,
Regex: regexp.MustCompile(`(?i)^rm wire (?P<id>\d+)$`), Regex: regexp.MustCompile(`(?i)^rm Wire (?P<id>\d+)$`),
HelpText: "Removes a wire by ID (use list to view)", HelpText: "Removes a Wire by ID (use list to view)",
Handler: p.rmWire}, Handler: p.rmWire},
bot.HandlerSpec{Kind: bot.Message, IsCmd: true, bot.HandlerSpec{Kind: bot.Message, IsCmd: true,
Regex: regexp.MustCompile("(?i)^testwire `(?P<parse>[^`]+)` to (?P<url>\\S+) `(?P<returnField>[^`]+)` => (?P<text>.*)$"), Regex: regexp.MustCompile("(?i)^testwire `(?P<parse>[^`]+)` to (?P<url>\\S+) `(?P<returnField>[^`]+)` => (?P<text>.*)$"),
@ -75,7 +75,7 @@ func (p *RestPlugin) register() {
HelpText: "Tests a new REST function", HelpText: "Tests a new REST function",
Handler: p.handleTestWire}, Handler: p.handleTestWire},
bot.HandlerSpec{Kind: bot.Message, IsCmd: true, bot.HandlerSpec{Kind: bot.Message, IsCmd: true,
Regex: regexp.MustCompile("(?i)^wire `(?P<parse>[^`]+)` to (?P<url>\\S+) `(?P<returnField>[^`]+)`$"), Regex: regexp.MustCompile("(?i)^Wire `(?P<parse>[^`]+)` to (?P<url>\\S+) `(?P<returnField>[^`]+)`$"),
HelpText: "Registers a new REST function", HelpText: "Registers a new REST function",
Handler: p.handleWire}, Handler: p.handleWire},
bot.HandlerSpec{Kind: bot.Message, IsCmd: true, bot.HandlerSpec{Kind: bot.Message, IsCmd: true,
@ -89,7 +89,7 @@ func (p *RestPlugin) register() {
panic(err) panic(err)
} }
for _, w := range wires { for _, w := range wires {
p.b.RegisterRegex(p, bot.Message, w.ParseRegex.Regexp, p.mkHandler(w)) p.b.RegisterRegex(p, bot.Message, w.regex, p.mkHandler(w))
} }
p.b.RegisterRegex(p, bot.Help, regexp.MustCompile(`.*`), func(r bot.Request) bool { p.b.RegisterRegex(p, bot.Help, regexp.MustCompile(`.*`), func(r bot.Request) bool {
out := "Rest commands:\n" out := "Rest commands:\n"
@ -142,20 +142,21 @@ func (s *ScanableURL) Scan(src interface{}) error {
return nil return nil
} }
type wire struct { type Wire struct {
// ID // ID
ID int64 `boltholdIndex:"ID"` ID int64 `boltholdIndex:"ID"`
// The URL to make a request to // The URL to make a request to
URL ScanableURL URL ScanableURL
// The regex which will trigger this REST action // The regex which will trigger this REST action
ParseRegex ScanableRegexp `db:"parse_regex"` ParseRegex string `db:"parse_regex"`
regex *regexp.Regexp
// The JSON field that will contain the REST return value // The JSON field that will contain the REST return value
ReturnField string `db:"return_field"` ReturnField string `db:"return_field"`
// Body parse for POST // Body parse for POST
Body string `db:"body"` Body string `db:"body"`
} }
func (w wire) String() string { func (w Wire) String() string {
msg := "Wire:" msg := "Wire:"
msg += fmt.Sprintf("\nURL: %s", w.URL) msg += fmt.Sprintf("\nURL: %s", w.URL)
msg += fmt.Sprintf("\nParsing to trigger: `%s`", w.ParseRegex) msg += fmt.Sprintf("\nParsing to trigger: `%s`", w.ParseRegex)
@ -163,18 +164,18 @@ func (w wire) String() string {
return msg return msg
} }
func (p *RestPlugin) getWires() ([]wire, error) { func (p *RestPlugin) getWires() ([]Wire, error) {
wires := []wire{} wires := []Wire{}
err := p.store.Find(&wires, &bh.Query{}) err := p.store.Find(&wires, &bh.Query{})
return wires, err return wires, err
} }
func (p *RestPlugin) deleteWire(id int64) error { func (p *RestPlugin) deleteWire(id int64) error {
err := p.store.Delete(id, wire{}) err := p.store.Delete(id, Wire{})
return err return err
} }
func (w *wire) Update(store *bh.Store) error { func (w *Wire) Update(store *bh.Store) error {
if w.ID == -1 { if w.ID == -1 {
return w.Save(store) return w.Save(store)
} }
@ -182,7 +183,7 @@ func (w *wire) Update(store *bh.Store) error {
return err return err
} }
func (w *wire) Save(store *bh.Store) error { func (w *Wire) Save(store *bh.Store) error {
if w.ID > -1 { if w.ID > -1 {
return w.Update(store) return w.Update(store)
} }
@ -209,21 +210,22 @@ func (p *RestPlugin) rmWire(r bot.Request) bool {
id, _ := strconv.ParseInt(r.Values["id"], 10, 64) id, _ := strconv.ParseInt(r.Values["id"], 10, 64)
err := p.deleteWire(id) err := p.deleteWire(id)
if err != nil { if err != nil {
p.b.Send(r.Conn, bot.Message, r.Msg.Channel, "Could not delete wire: "+err.Error()) p.b.Send(r.Conn, bot.Message, r.Msg.Channel, "Could not delete Wire: "+err.Error())
return true return true
} }
p.b.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("Deleted wire: %d", id)) p.b.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("Deleted Wire: %d", id))
return true return true
} }
func (p *RestPlugin) mkWire(r bot.Request) (wire, error) { func (p *RestPlugin) mkWire(r bot.Request) (Wire, error) {
var w wire var w Wire
var err error var err error
// if it's not a POST, this will be empty (and indicate we will use GET) // if it's not a POST, this will be empty (and indicate we will use GET)
w.Body = r.Values["body"] w.Body = r.Values["body"]
w.ParseRegex.Regexp, err = regexp.Compile(r.Values["parse"]) w.ParseRegex = r.Values["parse"]
w.regex, err = regexp.Compile(r.Values["parse"])
if err != nil { if err != nil {
return w, err return w, err
} }
@ -239,7 +241,7 @@ func (p *RestPlugin) mkWire(r bot.Request) (wire, error) {
} }
func (p *RestPlugin) handleWire(r bot.Request) bool { func (p *RestPlugin) handleWire(r bot.Request) bool {
var w wire var w Wire
var msg string var msg string
var err error var err error
w, err = p.mkWire(r) w, err = p.mkWire(r)
@ -252,7 +254,7 @@ func (p *RestPlugin) handleWire(r bot.Request) bool {
msg = err.Error() msg = err.Error()
goto SEND goto SEND
} }
p.b.RegisterRegex(p, bot.Message, w.ParseRegex.Regexp, p.mkHandler(w)) p.b.RegisterRegex(p, bot.Message, w.regex, p.mkHandler(w))
msg = fmt.Sprintf("Saved %s", w) msg = fmt.Sprintf("Saved %s", w)
SEND: SEND:
p.b.Send(r.Conn, bot.Message, r.Msg.Channel, msg) p.b.Send(r.Conn, bot.Message, r.Msg.Channel, msg)
@ -267,11 +269,11 @@ func (p *RestPlugin) handleTestWire(r bot.Request) bool {
return true return true
} }
h := p.mkHandler(w) h := p.mkHandler(w)
r.Values = bot.ParseValues(w.ParseRegex.Regexp, text) r.Values = bot.ParseValues(w.regex, text)
return h(r) return h(r)
} }
func (p *RestPlugin) mkHandler(w wire) bot.ResponseHandler { func (p *RestPlugin) mkHandler(w Wire) bot.ResponseHandler {
return func(r bot.Request) bool { return func(r bot.Request) bool {
if r.Msg.User.Name == p.b.Config().GetString("nick", "") { if r.Msg.User.Name == p.b.Config().GetString("nick", "") {
return false return false
@ -309,7 +311,7 @@ func (p *RestPlugin) mkHandler(w wire) bot.ResponseHandler {
if p.handleErr(err, r) { if p.handleErr(err, r) {
return true return true
} }
// Note, we will expect this is formatted good enough to send over the wire (?) // Note, we will expect this is formatted good enough to send over the Wire (?)
log.Debug(). log.Debug().
Interface("values", values). Interface("values", values).
Str("URL", newURL.String()). Str("URL", newURL.String()).

View File

@ -24,35 +24,35 @@ func New(b bot.Bot) *TellPlugin {
return tp return tp
} }
type tell struct { type Tell struct {
ID int `boltholdIndex:"ID"` ID int `boltholdIndex:"ID"`
Who string Who string
What string What string
} }
func (t *TellPlugin) getTells() []tell { func (t *TellPlugin) getTells() []Tell {
result := []tell{} result := []Tell{}
t.store.Find(&result, &bh.Query{}) t.store.Find(&result, &bh.Query{})
return result return result
} }
func (t *TellPlugin) rmTell(entry tell) { func (t *TellPlugin) rmTell(entry Tell) {
if err := t.store.Delete(entry.ID, tell{}); err != nil { if err := t.store.Delete(entry.ID, Tell{}); err != nil {
log.Error().Err(err).Msg("could not remove tell") log.Error().Err(err).Msg("could not remove Tell")
} }
} }
func (t *TellPlugin) addTell(who, what string) error { func (t *TellPlugin) addTell(who, what string) error {
tell := tell{Who: who, What: what} tell := Tell{Who: who, What: what}
err := t.store.Insert(bh.NextSequence(), tell) err := t.store.Insert(bh.NextSequence(), tell)
if err != nil { if err != nil {
log.Error().Err(err).Msg("could not add tell") log.Error().Err(err).Msg("could not add Tell")
} }
return err return err
} }
func (t *TellPlugin) check(who string) []tell { func (t *TellPlugin) check(who string) []Tell {
result := []tell{} result := []Tell{}
tells := t.getTells() tells := t.getTells()
for _, e := range tells { for _, e := range tells {
if e.Who == who { if e.Who == who {
@ -79,7 +79,7 @@ func (t *TellPlugin) checkValidTarget(ch, target string) bool {
} }
func (t *TellPlugin) troll(who string) bool { func (t *TellPlugin) troll(who string) bool {
targets := t.b.Config().GetArray("tell.troll", []string{}) targets := t.b.Config().GetArray("Tell.troll", []string{})
for _, target := range targets { for _, target := range targets {
if who == target { if who == target {
return true return true
@ -89,13 +89,13 @@ func (t *TellPlugin) troll(who string) bool {
} }
func (t *TellPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool { func (t *TellPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
if strings.HasPrefix(strings.ToLower(message.Body), "tell ") || if strings.HasPrefix(strings.ToLower(message.Body), "Tell ") ||
strings.HasPrefix(strings.ToLower(message.Body), "tellah ") { strings.HasPrefix(strings.ToLower(message.Body), "tellah ") {
parts := strings.Split(message.Body, " ") parts := strings.Split(message.Body, " ")
target := strings.ToLower(parts[1]) target := strings.ToLower(parts[1])
if !t.checkValidTarget(message.Channel, target) { if !t.checkValidTarget(message.Channel, target) {
if t.troll(message.User.Name) { if t.troll(message.User.Name) {
t.b.Send(c, bot.Message, message.Channel, fmt.Sprintf("Okay. I'll tell %s.", target)) t.b.Send(c, bot.Message, message.Channel, fmt.Sprintf("Okay. I'll Tell %s.", target))
return true return true
} }
return false return false
@ -103,7 +103,7 @@ func (t *TellPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message
newMessage := strings.Join(parts[2:], " ") newMessage := strings.Join(parts[2:], " ")
newMessage = fmt.Sprintf("Hey, %s. %s said: %s", target, message.User.Name, newMessage) newMessage = fmt.Sprintf("Hey, %s. %s said: %s", target, message.User.Name, newMessage)
t.addTell(target, newMessage) t.addTell(target, newMessage)
t.b.Send(c, bot.Message, message.Channel, fmt.Sprintf("Okay. I'll tell %s.", target)) t.b.Send(c, bot.Message, message.Channel, fmt.Sprintf("Okay. I'll Tell %s.", target))
return true return true
} }
uname := strings.ToLower(message.User.Name) uname := strings.ToLower(message.User.Name)

31
util/migrate/apppass.go Normal file
View File

@ -0,0 +1,31 @@
package main
import (
"github.com/jmoiron/sqlx"
"github.com/rs/zerolog/log"
bh "github.com/timshannon/bolthold"
)
type PassEntry struct {
ID int64 `json:"id"`
Secret string `json:"secret"`
// Should be null unless inserting a new entry
Pass string `json:"pass"`
EncodedPass []byte `db:"encoded_pass"`
Cost int `json:"cost"`
}
func migrateApppass(db *sqlx.DB, store *bh.Store) error {
all := []PassEntry{}
log.Printf("Migrating %T", all)
if err := db.Select(&all, `select * from apppass`); err != nil {
return err
}
for _, i := range all {
if err := store.Insert(i.ID, i); err != nil {
return err
}
}
return nil
}

63
util/migrate/awards.go Normal file
View File

@ -0,0 +1,63 @@
package main
import (
"database/sql"
"github.com/jmoiron/sqlx"
"github.com/rs/zerolog/log"
bh "github.com/timshannon/bolthold"
goals2 "github.com/velour/catbase/plugins/goals"
)
type Trophy struct {
Emojy string
Description string
Creator string
}
type Award struct {
ID int64 `boltholderid:"ID"`
Holder string
Emojy string
Description string
Granted sql.NullTime
Amount int64
}
func migrateAwards(db *sqlx.DB, store *bh.Store) error {
awards := []Award{}
log.Printf("Migrating %T", awards)
err := db.Select(&awards, `select * from awards`)
if err != nil {
return err
}
for _, a := range awards {
err := store.Insert(a.ID, a)
if err != nil {
return err
}
}
log.Printf("Migrated %d awards", len(awards))
trophies := []Trophy{}
err = db.Select(&trophies, `select * from trophies`)
for _, t := range trophies {
err := store.Insert(t.Emojy, t)
if err != nil {
return err
}
}
log.Printf("Migrated %d trophies", len(trophies))
goals := []goals2.Goal{}
log.Printf("Migrating %T", goals)
if err := db.Select(&goals, `select * from goals`); err != nil {
return err
}
for _, i := range goals {
if err := store.Insert(i.ID, i); err != nil {
return err
}
}
return nil
}

103
util/migrate/babbler.go Normal file
View File

@ -0,0 +1,103 @@
package main
import (
"database/sql"
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
"log"
"time"
)
type Babbler struct {
BabblerID uint64 `db:"id" boltholdKey:"BabblerID"`
Name string `db:"babbler"`
}
type BabblerWord struct {
WordID uint64 `db:"id" boltholdKey:"WordID"`
Word string `db:"word"`
}
type BabblerNode struct {
NodeID uint64 `db:"id" boltholdKey:"NodeID"`
BabblerID uint64 `db:"babblerId"`
WordID uint64 `db:"wordId"`
Root uint64 `db:"root"`
RootFrequency int64 `db:"rootFrequency"`
}
type BabblerArc struct {
ArcID uint64 `db:"id" boltholdKey:"ArcID"`
FromNodeID uint64 `db:"fromNodeId"`
ToNodeID uint64 `db:"toNodeId"`
Frequency int64 `db:"frequency"`
}
func migrateBabbler(db *sqlx.DB, store *bh.Store) error {
allBabblers := []Babbler{}
err := db.Select(&allBabblers, `select * from babblers`)
if err != nil {
return err
}
t0 := time.Now()
for _, b := range allBabblers {
err := store.Insert(b.BabblerID, b)
if err != nil {
return err
}
}
log.Printf("Migrated %d babblers took %v", len(allBabblers), time.Now().Sub(t0))
allNodes := []BabblerNode{}
err = db.Select(&allNodes, `select * from babblerNodes`)
if err != nil && err != sql.ErrNoRows {
return err
}
if err == sql.ErrNoRows || len(allNodes) == 0 {
log.Printf("Finished all windows")
return nil
}
log.Printf("Have %d nodes to insert", len(allNodes))
nodeMap := map[uint64]bool{}
for _, n := range allNodes {
if nodeMap[n.NodeID] {
log.Fatalf("Duplicate ID: %v: %#v", n.NodeID, n)
}
nodeMap[n.NodeID] = true
}
for _, b := range allNodes {
err := store.Insert(b.NodeID, b)
if err != nil {
log.Printf("error trying to insert node: %#v", b)
}
}
log.Printf("Migrated %d nodes", len(allNodes))
allWords := []BabblerWord{}
err = db.Select(&allWords, `select * from babblerWords`)
if err != nil {
return err
}
for _, b := range allWords {
err := store.Insert(b.WordID, b)
if err != nil {
return err
}
}
log.Printf("Migrated %d words", len(allWords))
allArcs := []BabblerArc{}
err = db.Select(&allArcs, `select * from babblerArcs`)
if err != nil {
return err
}
for _, b := range allArcs {
err := store.Insert(b.ArcID, b)
if err != nil {
return err
}
}
log.Printf("Migrated %d arcs", len(allArcs))
return nil
}

31
util/migrate/beers.go Normal file
View File

@ -0,0 +1,31 @@
package main
import (
"github.com/jmoiron/sqlx"
"github.com/rs/zerolog/log"
bh "github.com/timshannon/bolthold"
)
type untappdUser struct {
ID uint64 `db:"id"`
UntappdUser string `db:"untappdUser" boltholdKey:"UntappdUser"`
Channel string `db:"channel"`
LastCheckin int `db:"lastCheckin"`
ChanNick string `db:"chanNick"`
}
func migrateBeers(db *sqlx.DB, store *bh.Store) error {
users := []untappdUser{}
err := db.Select(&users, `select * from untappd`)
if err != nil {
return err
}
for _, u := range users {
err = store.Insert(u.UntappdUser, u)
if err != nil {
return err
}
}
log.Printf("Migrated %d untappd users", len(users))
return nil
}

View File

@ -0,0 +1,32 @@
package main
import (
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
"github.com/velour/catbase/bot"
"log"
)
func migrateBlackWhite(db *sqlx.DB, store *bh.Store) error {
allBlack := []bot.BlacklistItem{}
allWhite := []bot.WhitelistItem{}
log.Printf("Migrating %T", allBlack)
if err := db.Select(&allBlack, `select * from pluginBlacklist`); err != nil {
return err
}
for _, i := range allBlack {
if err := store.Insert(i.Key(), i); err != nil {
return err
}
}
log.Printf("Migrating %T", allWhite)
if err := db.Select(&allWhite, `select * from pluginWhitelist`); err != nil {
return err
}
for _, i := range allWhite {
if err := store.Insert(i.Name, i); err != nil {
return err
}
}
return nil
}

61
util/migrate/config.go Normal file
View File

@ -0,0 +1,61 @@
package main
import (
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
"go.etcd.io/bbolt"
"log"
)
type Value struct {
// Key is the key field of the table
Key string `db:"key" json:"key"`
// Value represents the secret that must not be shared
Value string `db:"value" json:"value"`
}
// Secret is a separate type (for storage differentiation)
type Secret Value
func migrateConfig(db *sqlx.DB, store *bh.Store) error {
allValues := []Value{}
err := db.Select(&allValues, `select * from config`)
if err != nil {
return err
}
for _, v := range allValues {
err = store.Insert(v.Key, v)
if err != nil {
return err
}
}
log.Printf("Migrated %d values", len(allValues))
allSecrets := []Secret{}
err = db.Select(&allSecrets, `select * from secrets`)
if err != nil {
return err
}
for _, v := range allSecrets {
err = store.Insert(v.Key, v)
if err != nil {
return err
}
}
log.Printf("Migrated %d secrets", len(allSecrets))
return nil
}
func rmConfig(store *bh.Store) {
store.Bolt().Batch(func(tx *bbolt.Tx) error {
tx.DeleteBucket([]byte("variables"))
return nil
})
store.Bolt().Batch(func(tx *bbolt.Tx) error {
tx.DeleteBucket([]byte("secrets"))
return nil
})
}

44
util/migrate/counter.go Normal file
View File

@ -0,0 +1,44 @@
package main
import (
"database/sql"
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
counter2 "github.com/velour/catbase/plugins/counter"
"log"
)
type ItemSQL struct {
counter2.Item
UserID sql.NullString
}
func migrateCounter(db *sqlx.DB, store *bh.Store) error {
all := []ItemSQL{}
log.Printf("Migrating %T", all)
if err := db.Select(&all, `select * from counter`); err != nil {
return err
}
for _, i := range all {
it := i.Item
if i.UserID.Valid {
it.UserID = i.UserID.String
}
if err := store.Insert(i.ID, it); err != nil {
return err
}
}
aliases := []counter2.Alias{}
log.Printf("Migrating %T", aliases)
if err := db.Select(&aliases, `select * from counter_alias`); err != nil {
return err
}
for _, i := range all {
if err := store.Insert(i.ID, i); err != nil {
return err
}
}
return nil
}

69
util/migrate/fact.go Normal file
View File

@ -0,0 +1,69 @@
package main
import (
"github.com/rs/zerolog/log"
bh "github.com/timshannon/bolthold"
_ "modernc.org/sqlite"
"time"
"github.com/jmoiron/sqlx"
)
type SQLFactoid struct {
Factoid
Created int64
Accessed int64
}
type Factoid struct {
ID uint64 `boltholdKey:"ID"`
Fact string
Tidbit string
Verb string
Owner string
Created time.Time
Accessed time.Time
Count int
}
type Alias struct {
Fact string
Next string
}
func migrateFacts(db *sqlx.DB, store *bh.Store) error {
q := `select * from factoid`
allFacts := []SQLFactoid{}
if err := db.Select(&allFacts, q); err != nil {
return err
}
for _, sqlf := range allFacts {
f := sqlf.Factoid
f.Accessed = time.Unix(sqlf.Accessed, 0)
f.Created = time.Unix(sqlf.Created, 0)
if err := store.Insert(f.ID, f); err != nil {
return err
}
}
log.Printf("Migrated %d facts", len(allFacts))
q = `select * from factoid_alias`
allAliases := []Alias{}
if err := db.Select(&allAliases, q); err != nil {
return err
}
for _, f := range allAliases {
if err := store.Insert(bh.NextSequence(), &f); err != nil {
return err
}
}
log.Printf("Migrated %d aliases", len(allAliases))
return nil
}

33
util/migrate/first.go Normal file
View File

@ -0,0 +1,33 @@
package main
import (
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
first2 "github.com/velour/catbase/plugins/first"
"log"
"time"
)
type FirstEntrySQL struct {
first2.FirstEntry
Day int64
Time int64
}
func migrateFirst(db *sqlx.DB, store *bh.Store) error {
all := []FirstEntrySQL{}
log.Printf("Migrating %T", all)
if err := db.Select(&all, `select * from first`); err != nil {
return err
}
for _, i := range all {
fe := i.FirstEntry
fe.Day = time.Unix(i.Day, 0)
fe.Time = time.Unix(i.Time, 0)
if err := store.Insert(i.ID, fe); err != nil {
return err
}
}
return nil
}

22
util/migrate/inventory.go Normal file
View File

@ -0,0 +1,22 @@
package main
import (
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
inventory2 "github.com/velour/catbase/plugins/inventory"
"log"
)
func migrateInventory(db *sqlx.DB, store *bh.Store) error {
allItems := []inventory2.Item{}
log.Printf("Migrating %T", allItems)
if err := db.Select(&allItems, `select * from inventory`); err != nil {
return err
}
for _, i := range allItems {
if err := store.Insert(i.Name, i); err != nil {
return err
}
}
return nil
}

22
util/migrate/last.go Normal file
View File

@ -0,0 +1,22 @@
package main
import (
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
last2 "github.com/velour/catbase/plugins/last"
"log"
)
func migrateLast(db *sqlx.DB, store *bh.Store) error {
allLast := []last2.Last{}
log.Printf("Migrating %T", allLast)
if err := db.Select(&allLast, `select * from last`); err != nil {
return err
}
for _, i := range allLast {
if err := store.Insert(bh.NextSequence(), &i); err != nil {
return err
}
}
return nil
}

156
util/migrate/main.go Normal file
View File

@ -0,0 +1,156 @@
package main
import (
"flag"
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
"go.etcd.io/bbolt"
"log"
)
var (
dbPath = flag.String("db", "catbase.db", "path to sqlite db")
storePath = flag.String("store", "catbase.store", "path to bolthold store")
fact = flag.Bool("fact", false, "migrate facts")
config = flag.Bool("config", false, "migrate config")
babbler = flag.Bool("babbler", false, "migrate babbler")
beers = flag.Bool("beers", false, "migrate beers")
awards = flag.Bool("awards", false, "migrate awards")
webshit = flag.Bool("webshit", false, "migrate webshit")
wire = flag.Bool("wire", false, "migrate wires")
tell = flag.Bool("tell", false, "migrate tell")
sms = flag.Bool("sms", false, "migrate sms")
reminders = flag.Bool("reminders", false, "migrate reminders")
blackWhiteLists = flag.Bool("blackWhite", false, "migrate black and white lists")
last = flag.Bool("last", false, "migrate last")
inventory = flag.Bool("inventory", false, "migrate inventory")
first = flag.Bool("first", false, "migrate first")
counter = flag.Bool("counter", false, "migrate counter")
apppass = flag.Bool("apppass", false, "migrate apppass")
nobabbler = flag.Bool("nobabbler", true, "don't migrate the babbler")
rmconfig = flag.Bool("rmconfig", false, "remove config")
all = flag.Bool("all", false, "migrate all")
)
func main() {
flag.Parse()
db, err := sqlx.Open("sqlite", *dbPath)
if err != nil {
log.Fatal(err)
}
store, err := bh.Open(*storePath, 0666, &bh.Options{
Options: &bbolt.Options{
NoFreelistSync: true,
FreelistType: "hashmap",
NoSync: true,
},
})
if err != nil {
log.Fatal(err)
}
if *rmconfig {
rmConfig(store)
return
}
if *fact || *all {
if err := migrateFacts(db, store); err != nil {
log.Fatal(err)
}
}
if *config {
if err := migrateConfig(db, store); err != nil {
log.Fatal(err)
}
}
if *babbler || *all && !*nobabbler {
if err := migrateBabbler(db, store); err != nil {
log.Fatal(err)
}
}
if *beers || *all {
if err := migrateBeers(db, store); err != nil {
log.Fatal(err)
}
}
if *awards || *all {
if err := migrateAwards(db, store); err != nil {
log.Fatal(err)
}
}
if *webshit || *all {
if err := migrateWebshit(db, store); err != nil {
log.Fatal(err)
}
}
if *wire || *all {
if err := migrateWires(db, store); err != nil {
log.Fatal(err)
}
}
if *tell || *all {
if err := migrateTell(db, store); err != nil {
log.Fatal(err)
}
}
if *sms || *all {
if err := migrateSMS(db, store); err != nil {
log.Fatal(err)
}
}
if *reminders || *all {
if err := migrateReminders(db, store); err != nil {
log.Fatal(err)
}
}
if *blackWhiteLists || *all {
if err := migrateBlackWhite(db, store); err != nil {
log.Fatal(err)
}
}
if *last || *all {
if err := migrateLast(db, store); err != nil {
log.Fatal(err)
}
}
if *inventory || *all {
if err := migrateInventory(db, store); err != nil {
log.Fatal(err)
}
}
if *first || *all {
if err := migrateFirst(db, store); err != nil {
log.Fatal(err)
}
}
if *counter || *all {
if err := migrateCounter(db, store); err != nil {
log.Fatal(err)
}
}
if *apppass || *all {
if err := migrateApppass(db, store); err != nil {
log.Fatal(err)
}
}
}

31
util/migrate/reminders.go Normal file
View File

@ -0,0 +1,31 @@
package main
import (
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
"github.com/velour/catbase/plugins/reminder"
"log"
"time"
)
type ReminderSQL struct {
reminder.Reminder
When string `db:"remindWhen"`
}
func migrateReminders(db *sqlx.DB, store *bh.Store) error {
allReminders := []ReminderSQL{}
log.Printf("Migrating %T", allReminders)
if err := db.Select(&allReminders, `select * from reminders`); err != nil {
return err
}
for _, r := range allReminders {
rem := r.Reminder
rem.When, _ = time.Parse("2006-01-02 15:04:05", r.When)
if err := store.Insert(r.ID, rem); err != nil {
return err
}
}
return nil
}

22
util/migrate/sms.go Normal file
View File

@ -0,0 +1,22 @@
package main
import (
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
sms2 "github.com/velour/catbase/plugins/sms"
"log"
)
func migrateSMS(db *sqlx.DB, store *bh.Store) error {
smses := []sms2.Person{}
log.Printf("Migrating %T", smses)
if err := db.Select(&smses, `select * from sms`); err != nil {
return err
}
for _, s := range smses {
if err := store.Insert(s.Who, s); err != nil {
return err
}
}
return nil
}

24
util/migrate/tell.go Normal file
View File

@ -0,0 +1,24 @@
package main
import (
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
tell2 "github.com/velour/catbase/plugins/tell"
"log"
)
func migrateTell(db *sqlx.DB, store *bh.Store) error {
tells := []tell2.Tell{}
log.Printf("Migrating %T", tells)
if err := db.Select(&tells, `select * from tell`); err != nil {
return err
}
for _, t := range tells {
if err := store.Insert(t.ID, t); err != nil {
return err
}
}
return nil
}

48
util/migrate/webshit.go Normal file
View File

@ -0,0 +1,48 @@
package main
import (
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
webshit2 "github.com/velour/catbase/plugins/newsbid/webshit"
"log"
"time"
)
type BidSQL struct {
webshit2.Bid
Placed int64
Processed int64
}
func migrateWebshit(db *sqlx.DB, store *bh.Store) error {
balances := []webshit2.Balance{}
bids := []BidSQL{}
log.Printf("Migrating %T", balances)
if err := db.Select(&balances, `select * from webshit_balances`); err != nil {
return err
}
for _, b := range balances {
if err := store.Insert(b.User, b); err != nil {
return err
}
}
log.Printf("Migrating %T", bids)
if err := db.Select(&bids, `select * from webshit_bids`); err != nil {
return err
}
for _, b := range bids {
bid := b.Bid
bid.Placed = time.Unix(b.Placed, 0)
bid.Processed = time.Unix(b.Processed, 0)
if err := store.Insert(b.ID, bid); err != nil {
return err
}
}
return nil
}

33
util/migrate/wires.go Normal file
View File

@ -0,0 +1,33 @@
package main
import (
"github.com/jmoiron/sqlx"
bh "github.com/timshannon/bolthold"
"github.com/velour/catbase/plugins/rest"
"log"
"net/url"
)
type WireSQL struct {
rest.Wire
// The URL to make a request to
URL string
}
func migrateWires(db *sqlx.DB, store *bh.Store) error {
wires := []WireSQL{}
log.Printf("Migrating %T", wires)
if err := db.Select(&wires, `select * from wires`); err != nil {
return err
}
for _, w := range wires {
wire := w.Wire
u, _ := url.Parse(w.URL)
wire.URL = rest.ScanableURL{u}
if err := store.Insert(w.ID, wire); err != nil {
return err
}
}
return nil
}