Because funny
This commit is contained in:
parent
de9439d917
commit
2920dcbfec
11 changed files with 862 additions and 89 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
db.sqlite
|
||||
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
|
28
cmd/dbgen/main.go
Normal file
28
cmd/dbgen/main.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/glebarez/sqlite"
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"git.mstar.dev/mstar/mstar-webserver/storage/models"
|
||||
)
|
||||
|
||||
func main() {
|
||||
g := gen.NewGenerator(gen.Config{
|
||||
OutPath: "./storage/generated",
|
||||
Mode: gen.WithoutContext | gen.WithDefaultQuery | gen.WithQueryInterface, // generate mode
|
||||
})
|
||||
|
||||
gormdb, _ := gorm.Open(sqlite.Open("./db.sqlite"), &gorm.Config{})
|
||||
g.UseDB(gormdb)
|
||||
|
||||
// Generate basic type-safe DAO API for struct `model.User` following conventions
|
||||
g.ApplyBasic(models.Link{})
|
||||
|
||||
// Generate Type Safe API with Dynamic SQL defined on Querier interface for `model.User` and `model.Company`
|
||||
g.ApplyInterface(func(models.ILink) {}, models.Link{})
|
||||
|
||||
// Generate the code
|
||||
g.Execute()
|
||||
}
|
25
go.mod
25
go.mod
|
@ -1,15 +1,36 @@
|
|||
module gitlab.com/evilthings-services/mstar
|
||||
module git.mstar.dev/mstar/mstar-webserver
|
||||
|
||||
go 1.23.4
|
||||
|
||||
require (
|
||||
git.mstar.dev/mstar/goutils v1.6.1
|
||||
git.mstar.dev/mstar/goutils v1.9.1
|
||||
github.com/glebarez/sqlite v1.11.0
|
||||
github.com/rs/zerolog v1.33.0
|
||||
gorm.io/gen v0.3.26
|
||||
gorm.io/gorm v1.25.12
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rs/xid v1.5.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c // indirect
|
||||
gorm.io/driver/mysql v1.5.7 // indirect
|
||||
gorm.io/hints v1.1.0 // indirect
|
||||
gorm.io/plugin/dbresolver v1.5.3 // indirect
|
||||
modernc.org/libc v1.22.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.5.0 // indirect
|
||||
modernc.org/sqlite v1.23.1 // indirect
|
||||
)
|
||||
|
|
141
go.sum
141
go.sum
|
@ -1,22 +1,151 @@
|
|||
git.mstar.dev/mstar/goutils v1.5.4 h1:l/4oQe/fBk9zyXplQkGXbmQndnm0aRdHuy4wgQfNrFo=
|
||||
git.mstar.dev/mstar/goutils v1.5.4/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA=
|
||||
git.mstar.dev/mstar/goutils v1.6.0 h1:2K0KqoymJoEJUIYVHkjJ0GJKGNeWVfHMmpeRMtNiG3Q=
|
||||
git.mstar.dev/mstar/goutils v1.6.0/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA=
|
||||
git.mstar.dev/mstar/goutils v1.6.1 h1:2yr9GYN8CJByZsJRu1pZ6WBp51Nn+3zJq49ky54xYDk=
|
||||
git.mstar.dev/mstar/goutils v1.6.1/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA=
|
||||
git.mstar.dev/mstar/goutils v1.9.0 h1:xF0bsGObxRuRtbB7VArFPBkYVNypc8eWnyWp8bkxyEo=
|
||||
git.mstar.dev/mstar/goutils v1.9.0/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA=
|
||||
git.mstar.dev/mstar/goutils v1.9.1 h1:B4km2Xj0Yq8GHIlAYo45NGMRQRdkr+hV9qdvhTJKuuA=
|
||||
git.mstar.dev/mstar/goutils v1.9.1/go.mod h1:juxY0eZEMnA95fedRp2LVXvUBgEjz66nE8SEdGKcxMA=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/davecgh/go-spew v1.1.0/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.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
|
||||
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
|
||||
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
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/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys=
|
||||
github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI=
|
||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w=
|
||||
github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E=
|
||||
github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
|
||||
github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||
golang.org/x/sys v0.12.0/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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c h1:jWdr7cHgl8c/ua5vYbR2WhSp+NQmzhsj0xoY3foTzW8=
|
||||
gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c/go.mod h1:SH2K9R+2RMjuX1CkCONrPwoe9JzVv2hkQvEu4bXGojE=
|
||||
gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
|
||||
gorm.io/driver/mysql v1.4.4 h1:MX0K9Qvy0Na4o7qSC/YI7XxqUw5KDw01umqgID+svdQ=
|
||||
gorm.io/driver/mysql v1.4.4/go.mod h1:BCg8cKI+R0j/rZRQxeKis/forqRwRSYOR8OM3Wo6hOM=
|
||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/driver/postgres v1.4.5 h1:mTeXTTtHAgnS9PgmhN2YeUbazYpLhUI1doLnw42XUZc=
|
||||
gorm.io/driver/postgres v1.4.5/go.mod h1:GKNQYSJ14qvWkvPwXljMGehpKrhlDNsqYRr5HnYGncg=
|
||||
gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8=
|
||||
gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
|
||||
gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
|
||||
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
|
||||
gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig=
|
||||
gorm.io/gen v0.3.26 h1:sFf1j7vNStimPRRAtH4zz5NiHM+1dr6eA9aaRdplyhY=
|
||||
gorm.io/gen v0.3.26/go.mod h1:a5lq5y3w4g5LMxBcw0wnO6tYUCdNutWODq5LrIt75LE=
|
||||
gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||
gorm.io/gorm v1.22.2/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
gorm.io/hints v1.1.0 h1:Lp4z3rxREufSdxn4qmkK3TLDltrM10FLTHiuqwDPvXw=
|
||||
gorm.io/hints v1.1.0/go.mod h1:lKQ0JjySsPBj3uslFzY3JhYDtqEwzm+G1hv8rWujB6Y=
|
||||
gorm.io/plugin/dbresolver v1.5.0 h1:XVHLxh775eP0CqVh3vcfJtYqja3uFl5Wr3cKlY8jgDY=
|
||||
gorm.io/plugin/dbresolver v1.5.0/go.mod h1:l4Cn87EHLEYuqUncpEeTC2tTJQkjngPSD+lo8hIvcT0=
|
||||
gorm.io/plugin/dbresolver v1.5.3 h1:wFwINGZZmttuu9h7XpvbDHd8Lf9bb8GNzp/NpAMV2wU=
|
||||
gorm.io/plugin/dbresolver v1.5.3/go.mod h1:TSrVhaUg2DZAWP3PrHlDlITEJmNOkL0tFTjvTEsQ4XE=
|
||||
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
|
||||
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
||||
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
|
||||
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
||||
|
|
84
handlers.go
Normal file
84
handlers.go
Normal file
|
@ -0,0 +1,84 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/hlog"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"git.mstar.dev/mstar/mstar-webserver/storage"
|
||||
)
|
||||
|
||||
func handleRoot(w http.ResponseWriter, r *http.Request) {
|
||||
tmpl, err := template.ParseFS(embed_templates, "templates/index.html")
|
||||
if err != nil {
|
||||
http.Error(w, "Couldn't parse template file", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
err = tmpl.Execute(w, nil)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to execute template", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func buildHTTPFileReader(embed_content string) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "%s", embed_content)
|
||||
}
|
||||
}
|
||||
|
||||
func countingRedirect(target string) http.Handler {
|
||||
redirect := http.RedirectHandler(target, http.StatusMovedPermanently)
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info().Msg("Counting redirect")
|
||||
fmt.Println("Counting redirect")
|
||||
if err := storage.IncrementLinkCounter(target); err != nil {
|
||||
log.Error().Err(err).Str("target", target).Msg("Failed to update link")
|
||||
}
|
||||
redirect.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func awawaStream(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, "Disabled until I can find a good way to rate limit the stream")
|
||||
return
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.WriteHeader(206)
|
||||
w.Header().Set("Status", "206")
|
||||
genStub(
|
||||
1024,
|
||||
w,
|
||||
) // Hardcoded. Firefox & Chrome both have this value and a len of 0 wouldn't work
|
||||
hlog.FromRequest(r).Debug().Msg("Starting stream")
|
||||
i := true
|
||||
fmt.Fprint(w, "awawaw")
|
||||
// Only run every 0.2 seconds, aka 5 times a second
|
||||
timer := time.Tick(time.Millisecond * 100)
|
||||
for {
|
||||
select {
|
||||
case <-r.Context().Done():
|
||||
hlog.FromRequest(r).Debug().Msg("Stream done")
|
||||
return
|
||||
case <-timer:
|
||||
hlog.FromRequest(r).Debug().Msg("Stream elem")
|
||||
if i {
|
||||
fmt.Fprint(w, "a")
|
||||
} else {
|
||||
fmt.Fprint(w, "w")
|
||||
}
|
||||
i = !i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func genStub(length int, w http.ResponseWriter) {
|
||||
PreSufLen := len(HTML_PREFIX) + len(HTML_SUFFIX)
|
||||
fmt.Fprint(w, HTML_PREFIX)
|
||||
for i := 0; i < length-PreSufLen; i++ {
|
||||
fmt.Fprint(w, '\u0020')
|
||||
}
|
||||
fmt.Fprint(w, HTML_SUFFIX)
|
||||
}
|
91
main.go
91
main.go
|
@ -4,17 +4,19 @@ import (
|
|||
"context"
|
||||
"embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"git.mstar.dev/mstar/goutils/middleware"
|
||||
httputils "git.mstar.dev/mstar/goutils/http"
|
||||
"git.mstar.dev/mstar/goutils/other"
|
||||
"github.com/rs/zerolog/hlog"
|
||||
"github.com/glebarez/sqlite"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"git.mstar.dev/mstar/mstar-webserver/storage/generated"
|
||||
"git.mstar.dev/mstar/mstar-webserver/storage/models"
|
||||
)
|
||||
|
||||
const HTML_PREFIX = "<!-- "
|
||||
|
@ -42,13 +44,24 @@ var redirectMapping = map[string]string{
|
|||
"/git": "https://git.mstar.dev",
|
||||
"/gitlab": "https://gitlab.com/mstarongitlab",
|
||||
"/github": "https://github.com/mstarongithub",
|
||||
"/fedi": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
||||
"/youtube": "https://www.youtube.com/channel/UC-LklY_wt004i_30xcVohbg",
|
||||
}
|
||||
|
||||
func main() {
|
||||
other.SetupFlags()
|
||||
portFlag := flag.String("port", "8080", "Set the port. Overwrites env vars")
|
||||
flag.Parse()
|
||||
other.ConfigureLoggingFromCliArgs()
|
||||
other.ConfigureLogging(nil)
|
||||
|
||||
db, err := gorm.Open(sqlite.Open("./db.sqlite"), &gorm.Config{})
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to open db file")
|
||||
}
|
||||
generated.SetDefault(db)
|
||||
if err := db.AutoMigrate(&models.Link{}); err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to automigrate db setup")
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/{$}", handleRoot)
|
||||
|
@ -60,7 +73,7 @@ func main() {
|
|||
)
|
||||
|
||||
for k, v := range redirectMapping {
|
||||
mux.Handle(k, http.RedirectHandler(v, http.StatusMovedPermanently))
|
||||
mux.Handle(k, countingRedirect(v))
|
||||
}
|
||||
|
||||
mux.HandleFunc("/cat/awawawa", awawaStream)
|
||||
|
@ -77,13 +90,10 @@ func main() {
|
|||
// Static files not in /static or /.well-known
|
||||
mux.HandleFunc("/robots.txt", buildHTTPFileReader(embed_robots_txt))
|
||||
mux.HandleFunc("/humans.txt", buildHTTPFileReader(embed_humans_txt))
|
||||
mux.HandleFunc("/8ztjw6bhc9.txt", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, "keke")
|
||||
})
|
||||
|
||||
server := http.Server{
|
||||
Addr: ":" + *portFlag,
|
||||
Handler: middleware.ChainMiddlewares(mux, middleware.LoggingMiddleware),
|
||||
Handler: httputils.ChainMiddlewares(mux, httputils.LoggingMiddleware),
|
||||
}
|
||||
exitChan := make(chan os.Signal, 1)
|
||||
signal.Notify(exitChan, os.Interrupt)
|
||||
|
@ -97,68 +107,9 @@ func main() {
|
|||
log.Info().Msg("Shutting down server due to Interrupt")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
|
||||
defer cancel()
|
||||
err := server.Shutdown(ctx)
|
||||
err = server.Shutdown(ctx)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to cleanly shut down")
|
||||
}
|
||||
log.Info().Msg("Clean shutdown complete")
|
||||
}
|
||||
|
||||
func handleRoot(w http.ResponseWriter, r *http.Request) {
|
||||
tmpl, err := template.ParseFS(embed_templates, "templates/index.html")
|
||||
if err != nil {
|
||||
http.Error(w, "Couldn't parse template file", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
err = tmpl.Execute(w, nil)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to execute template", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func buildHTTPFileReader(embed_content string) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "%s", embed_content)
|
||||
}
|
||||
}
|
||||
|
||||
func awawaStream(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, "Disabled until I can find a good way to rate limit the stream")
|
||||
return
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.WriteHeader(206)
|
||||
w.Header().Set("Status", "206")
|
||||
genStub(
|
||||
1024,
|
||||
w,
|
||||
) // Hardcoded. Firefox & Chrome both have this value and a len of 0 wouldn't work
|
||||
hlog.FromRequest(r).Debug().Msg("Starting stream")
|
||||
i := true
|
||||
fmt.Fprint(w, "awawaw")
|
||||
// Only run every 0.2 seconds, aka 5 times a second
|
||||
timer := time.Tick(time.Millisecond * 100)
|
||||
for {
|
||||
select {
|
||||
case <-r.Context().Done():
|
||||
hlog.FromRequest(r).Debug().Msg("Stream done")
|
||||
return
|
||||
case <-timer:
|
||||
hlog.FromRequest(r).Debug().Msg("Stream elem")
|
||||
if i {
|
||||
fmt.Fprint(w, "a")
|
||||
} else {
|
||||
fmt.Fprint(w, "w")
|
||||
}
|
||||
i = !i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func genStub(length int, w http.ResponseWriter) {
|
||||
PreSufLen := len(HTML_PREFIX) + len(HTML_SUFFIX)
|
||||
fmt.Fprint(w, HTML_PREFIX)
|
||||
for i := 0; i < length-PreSufLen; i++ {
|
||||
fmt.Fprint(w, '\u0020')
|
||||
}
|
||||
fmt.Fprint(w, HTML_SUFFIX)
|
||||
}
|
||||
|
|
35
storage/db.go
Normal file
35
storage/db.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"git.mstar.dev/mstar/goutils/other"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"git.mstar.dev/mstar/mstar-webserver/storage/generated"
|
||||
"git.mstar.dev/mstar/mstar-webserver/storage/models"
|
||||
)
|
||||
|
||||
func IncrementLinkCounter(link string) error {
|
||||
model, err := generated.Link.Where(generated.Link.Link.Eq(link)).First()
|
||||
switch err {
|
||||
case gorm.ErrRecordNotFound:
|
||||
log.Info().Msg("Creating link counter")
|
||||
err = generated.Link.Create(&models.Link{Link: link, Count: 1})
|
||||
if err != nil {
|
||||
return other.Error("storage", "failed to create new link entry", err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case nil:
|
||||
log.Info().Uint64("current", model.Count).Msg("Updating link")
|
||||
_, err = generated.Link.Where(generated.Link.Link.Eq(link)).
|
||||
Update(generated.Link.Count_, model.Count+1)
|
||||
if err != nil {
|
||||
return other.Error("storage", "failed to increment link count", err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
default:
|
||||
return other.Error("storage", "failed to find link", err)
|
||||
}
|
||||
}
|
103
storage/generated/gen.go
Normal file
103
storage/generated/gen.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"gorm.io/gen"
|
||||
|
||||
"gorm.io/plugin/dbresolver"
|
||||
)
|
||||
|
||||
var (
|
||||
Q = new(Query)
|
||||
Link *link
|
||||
)
|
||||
|
||||
func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
|
||||
*Q = *Use(db, opts...)
|
||||
Link = &Q.Link
|
||||
}
|
||||
|
||||
func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
|
||||
return &Query{
|
||||
db: db,
|
||||
Link: newLink(db, opts...),
|
||||
}
|
||||
}
|
||||
|
||||
type Query struct {
|
||||
db *gorm.DB
|
||||
|
||||
Link link
|
||||
}
|
||||
|
||||
func (q *Query) Available() bool { return q.db != nil }
|
||||
|
||||
func (q *Query) clone(db *gorm.DB) *Query {
|
||||
return &Query{
|
||||
db: db,
|
||||
Link: q.Link.clone(db),
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Query) ReadDB() *Query {
|
||||
return q.ReplaceDB(q.db.Clauses(dbresolver.Read))
|
||||
}
|
||||
|
||||
func (q *Query) WriteDB() *Query {
|
||||
return q.ReplaceDB(q.db.Clauses(dbresolver.Write))
|
||||
}
|
||||
|
||||
func (q *Query) ReplaceDB(db *gorm.DB) *Query {
|
||||
return &Query{
|
||||
db: db,
|
||||
Link: q.Link.replaceDB(db),
|
||||
}
|
||||
}
|
||||
|
||||
type queryCtx struct {
|
||||
Link ILinkDo
|
||||
}
|
||||
|
||||
func (q *Query) WithContext(ctx context.Context) *queryCtx {
|
||||
return &queryCtx{
|
||||
Link: q.Link.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Query) Transaction(fc func(tx *Query) error, opts ...*sql.TxOptions) error {
|
||||
return q.db.Transaction(func(tx *gorm.DB) error { return fc(q.clone(tx)) }, opts...)
|
||||
}
|
||||
|
||||
func (q *Query) Begin(opts ...*sql.TxOptions) *QueryTx {
|
||||
tx := q.db.Begin(opts...)
|
||||
return &QueryTx{Query: q.clone(tx), Error: tx.Error}
|
||||
}
|
||||
|
||||
type QueryTx struct {
|
||||
*Query
|
||||
Error error
|
||||
}
|
||||
|
||||
func (q *QueryTx) Commit() error {
|
||||
return q.db.Commit().Error
|
||||
}
|
||||
|
||||
func (q *QueryTx) Rollback() error {
|
||||
return q.db.Rollback().Error
|
||||
}
|
||||
|
||||
func (q *QueryTx) SavePoint(name string) error {
|
||||
return q.db.SavePoint(name).Error
|
||||
}
|
||||
|
||||
func (q *QueryTx) RollbackTo(name string) error {
|
||||
return q.db.RollbackTo(name).Error
|
||||
}
|
400
storage/generated/links.gen.go
Normal file
400
storage/generated/links.gen.go
Normal file
|
@ -0,0 +1,400 @@
|
|||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"gorm.io/gorm/schema"
|
||||
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gen/field"
|
||||
|
||||
"gorm.io/plugin/dbresolver"
|
||||
|
||||
"git.mstar.dev/mstar/mstar-webserver/storage/models"
|
||||
)
|
||||
|
||||
func newLink(db *gorm.DB, opts ...gen.DOOption) link {
|
||||
_link := link{}
|
||||
|
||||
_link.linkDo.UseDB(db, opts...)
|
||||
_link.linkDo.UseModel(&models.Link{})
|
||||
|
||||
tableName := _link.linkDo.TableName()
|
||||
_link.ALL = field.NewAsterisk(tableName)
|
||||
_link.ID = field.NewUint(tableName, "id")
|
||||
_link.CreatedAt = field.NewTime(tableName, "created_at")
|
||||
_link.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||
_link.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
_link.Link = field.NewString(tableName, "link")
|
||||
_link.Count_ = field.NewUint64(tableName, "count")
|
||||
|
||||
_link.fillFieldMap()
|
||||
|
||||
return _link
|
||||
}
|
||||
|
||||
type link struct {
|
||||
linkDo
|
||||
|
||||
ALL field.Asterisk
|
||||
ID field.Uint
|
||||
CreatedAt field.Time
|
||||
UpdatedAt field.Time
|
||||
DeletedAt field.Field
|
||||
Link field.String
|
||||
Count_ field.Uint64
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
|
||||
func (l link) Table(newTableName string) *link {
|
||||
l.linkDo.UseTable(newTableName)
|
||||
return l.updateTableName(newTableName)
|
||||
}
|
||||
|
||||
func (l link) As(alias string) *link {
|
||||
l.linkDo.DO = *(l.linkDo.As(alias).(*gen.DO))
|
||||
return l.updateTableName(alias)
|
||||
}
|
||||
|
||||
func (l *link) updateTableName(table string) *link {
|
||||
l.ALL = field.NewAsterisk(table)
|
||||
l.ID = field.NewUint(table, "id")
|
||||
l.CreatedAt = field.NewTime(table, "created_at")
|
||||
l.UpdatedAt = field.NewTime(table, "updated_at")
|
||||
l.DeletedAt = field.NewField(table, "deleted_at")
|
||||
l.Link = field.NewString(table, "link")
|
||||
l.Count_ = field.NewUint64(table, "count")
|
||||
|
||||
l.fillFieldMap()
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *link) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
_f, ok := l.fieldMap[fieldName]
|
||||
if !ok || _f == nil {
|
||||
return nil, false
|
||||
}
|
||||
_oe, ok := _f.(field.OrderExpr)
|
||||
return _oe, ok
|
||||
}
|
||||
|
||||
func (l *link) fillFieldMap() {
|
||||
l.fieldMap = make(map[string]field.Expr, 6)
|
||||
l.fieldMap["id"] = l.ID
|
||||
l.fieldMap["created_at"] = l.CreatedAt
|
||||
l.fieldMap["updated_at"] = l.UpdatedAt
|
||||
l.fieldMap["deleted_at"] = l.DeletedAt
|
||||
l.fieldMap["link"] = l.Link
|
||||
l.fieldMap["count"] = l.Count_
|
||||
}
|
||||
|
||||
func (l link) clone(db *gorm.DB) link {
|
||||
l.linkDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
return l
|
||||
}
|
||||
|
||||
func (l link) replaceDB(db *gorm.DB) link {
|
||||
l.linkDo.ReplaceDB(db)
|
||||
return l
|
||||
}
|
||||
|
||||
type linkDo struct{ gen.DO }
|
||||
|
||||
type ILinkDo interface {
|
||||
gen.SubQuery
|
||||
Debug() ILinkDo
|
||||
WithContext(ctx context.Context) ILinkDo
|
||||
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
|
||||
ReplaceDB(db *gorm.DB)
|
||||
ReadDB() ILinkDo
|
||||
WriteDB() ILinkDo
|
||||
As(alias string) gen.Dao
|
||||
Session(config *gorm.Session) ILinkDo
|
||||
Columns(cols ...field.Expr) gen.Columns
|
||||
Clauses(conds ...clause.Expression) ILinkDo
|
||||
Not(conds ...gen.Condition) ILinkDo
|
||||
Or(conds ...gen.Condition) ILinkDo
|
||||
Select(conds ...field.Expr) ILinkDo
|
||||
Where(conds ...gen.Condition) ILinkDo
|
||||
Order(conds ...field.Expr) ILinkDo
|
||||
Distinct(cols ...field.Expr) ILinkDo
|
||||
Omit(cols ...field.Expr) ILinkDo
|
||||
Join(table schema.Tabler, on ...field.Expr) ILinkDo
|
||||
LeftJoin(table schema.Tabler, on ...field.Expr) ILinkDo
|
||||
RightJoin(table schema.Tabler, on ...field.Expr) ILinkDo
|
||||
Group(cols ...field.Expr) ILinkDo
|
||||
Having(conds ...gen.Condition) ILinkDo
|
||||
Limit(limit int) ILinkDo
|
||||
Offset(offset int) ILinkDo
|
||||
Count() (count int64, err error)
|
||||
Scopes(funcs ...func(gen.Dao) gen.Dao) ILinkDo
|
||||
Unscoped() ILinkDo
|
||||
Create(values ...*models.Link) error
|
||||
CreateInBatches(values []*models.Link, batchSize int) error
|
||||
Save(values ...*models.Link) error
|
||||
First() (*models.Link, error)
|
||||
Take() (*models.Link, error)
|
||||
Last() (*models.Link, error)
|
||||
Find() ([]*models.Link, error)
|
||||
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.Link, err error)
|
||||
FindInBatches(result *[]*models.Link, batchSize int, fc func(tx gen.Dao, batch int) error) error
|
||||
Pluck(column field.Expr, dest interface{}) error
|
||||
Delete(...*models.Link) (info gen.ResultInfo, err error)
|
||||
Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
|
||||
Updates(value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
|
||||
UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateFrom(q gen.SubQuery) gen.Dao
|
||||
Attrs(attrs ...field.AssignExpr) ILinkDo
|
||||
Assign(attrs ...field.AssignExpr) ILinkDo
|
||||
Joins(fields ...field.RelationField) ILinkDo
|
||||
Preload(fields ...field.RelationField) ILinkDo
|
||||
FirstOrInit() (*models.Link, error)
|
||||
FirstOrCreate() (*models.Link, error)
|
||||
FindByPage(offset int, limit int) (result []*models.Link, count int64, err error)
|
||||
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
|
||||
Scan(result interface{}) (err error)
|
||||
Returning(value interface{}, columns ...string) ILinkDo
|
||||
UnderlyingDB() *gorm.DB
|
||||
schema.Tabler
|
||||
}
|
||||
|
||||
func (l linkDo) Debug() ILinkDo {
|
||||
return l.withDO(l.DO.Debug())
|
||||
}
|
||||
|
||||
func (l linkDo) WithContext(ctx context.Context) ILinkDo {
|
||||
return l.withDO(l.DO.WithContext(ctx))
|
||||
}
|
||||
|
||||
func (l linkDo) ReadDB() ILinkDo {
|
||||
return l.Clauses(dbresolver.Read)
|
||||
}
|
||||
|
||||
func (l linkDo) WriteDB() ILinkDo {
|
||||
return l.Clauses(dbresolver.Write)
|
||||
}
|
||||
|
||||
func (l linkDo) Session(config *gorm.Session) ILinkDo {
|
||||
return l.withDO(l.DO.Session(config))
|
||||
}
|
||||
|
||||
func (l linkDo) Clauses(conds ...clause.Expression) ILinkDo {
|
||||
return l.withDO(l.DO.Clauses(conds...))
|
||||
}
|
||||
|
||||
func (l linkDo) Returning(value interface{}, columns ...string) ILinkDo {
|
||||
return l.withDO(l.DO.Returning(value, columns...))
|
||||
}
|
||||
|
||||
func (l linkDo) Not(conds ...gen.Condition) ILinkDo {
|
||||
return l.withDO(l.DO.Not(conds...))
|
||||
}
|
||||
|
||||
func (l linkDo) Or(conds ...gen.Condition) ILinkDo {
|
||||
return l.withDO(l.DO.Or(conds...))
|
||||
}
|
||||
|
||||
func (l linkDo) Select(conds ...field.Expr) ILinkDo {
|
||||
return l.withDO(l.DO.Select(conds...))
|
||||
}
|
||||
|
||||
func (l linkDo) Where(conds ...gen.Condition) ILinkDo {
|
||||
return l.withDO(l.DO.Where(conds...))
|
||||
}
|
||||
|
||||
func (l linkDo) Order(conds ...field.Expr) ILinkDo {
|
||||
return l.withDO(l.DO.Order(conds...))
|
||||
}
|
||||
|
||||
func (l linkDo) Distinct(cols ...field.Expr) ILinkDo {
|
||||
return l.withDO(l.DO.Distinct(cols...))
|
||||
}
|
||||
|
||||
func (l linkDo) Omit(cols ...field.Expr) ILinkDo {
|
||||
return l.withDO(l.DO.Omit(cols...))
|
||||
}
|
||||
|
||||
func (l linkDo) Join(table schema.Tabler, on ...field.Expr) ILinkDo {
|
||||
return l.withDO(l.DO.Join(table, on...))
|
||||
}
|
||||
|
||||
func (l linkDo) LeftJoin(table schema.Tabler, on ...field.Expr) ILinkDo {
|
||||
return l.withDO(l.DO.LeftJoin(table, on...))
|
||||
}
|
||||
|
||||
func (l linkDo) RightJoin(table schema.Tabler, on ...field.Expr) ILinkDo {
|
||||
return l.withDO(l.DO.RightJoin(table, on...))
|
||||
}
|
||||
|
||||
func (l linkDo) Group(cols ...field.Expr) ILinkDo {
|
||||
return l.withDO(l.DO.Group(cols...))
|
||||
}
|
||||
|
||||
func (l linkDo) Having(conds ...gen.Condition) ILinkDo {
|
||||
return l.withDO(l.DO.Having(conds...))
|
||||
}
|
||||
|
||||
func (l linkDo) Limit(limit int) ILinkDo {
|
||||
return l.withDO(l.DO.Limit(limit))
|
||||
}
|
||||
|
||||
func (l linkDo) Offset(offset int) ILinkDo {
|
||||
return l.withDO(l.DO.Offset(offset))
|
||||
}
|
||||
|
||||
func (l linkDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ILinkDo {
|
||||
return l.withDO(l.DO.Scopes(funcs...))
|
||||
}
|
||||
|
||||
func (l linkDo) Unscoped() ILinkDo {
|
||||
return l.withDO(l.DO.Unscoped())
|
||||
}
|
||||
|
||||
func (l linkDo) Create(values ...*models.Link) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return l.DO.Create(values)
|
||||
}
|
||||
|
||||
func (l linkDo) CreateInBatches(values []*models.Link, batchSize int) error {
|
||||
return l.DO.CreateInBatches(values, batchSize)
|
||||
}
|
||||
|
||||
// Save : !!! underlying implementation is different with GORM
|
||||
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
|
||||
func (l linkDo) Save(values ...*models.Link) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return l.DO.Save(values)
|
||||
}
|
||||
|
||||
func (l linkDo) First() (*models.Link, error) {
|
||||
if result, err := l.DO.First(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.Link), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (l linkDo) Take() (*models.Link, error) {
|
||||
if result, err := l.DO.Take(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.Link), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (l linkDo) Last() (*models.Link, error) {
|
||||
if result, err := l.DO.Last(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.Link), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (l linkDo) Find() ([]*models.Link, error) {
|
||||
result, err := l.DO.Find()
|
||||
return result.([]*models.Link), err
|
||||
}
|
||||
|
||||
func (l linkDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.Link, err error) {
|
||||
buf := make([]*models.Link, 0, batchSize)
|
||||
err = l.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
|
||||
defer func() { results = append(results, buf...) }()
|
||||
return fc(tx, batch)
|
||||
})
|
||||
return results, err
|
||||
}
|
||||
|
||||
func (l linkDo) FindInBatches(result *[]*models.Link, batchSize int, fc func(tx gen.Dao, batch int) error) error {
|
||||
return l.DO.FindInBatches(result, batchSize, fc)
|
||||
}
|
||||
|
||||
func (l linkDo) Attrs(attrs ...field.AssignExpr) ILinkDo {
|
||||
return l.withDO(l.DO.Attrs(attrs...))
|
||||
}
|
||||
|
||||
func (l linkDo) Assign(attrs ...field.AssignExpr) ILinkDo {
|
||||
return l.withDO(l.DO.Assign(attrs...))
|
||||
}
|
||||
|
||||
func (l linkDo) Joins(fields ...field.RelationField) ILinkDo {
|
||||
for _, _f := range fields {
|
||||
l = *l.withDO(l.DO.Joins(_f))
|
||||
}
|
||||
return &l
|
||||
}
|
||||
|
||||
func (l linkDo) Preload(fields ...field.RelationField) ILinkDo {
|
||||
for _, _f := range fields {
|
||||
l = *l.withDO(l.DO.Preload(_f))
|
||||
}
|
||||
return &l
|
||||
}
|
||||
|
||||
func (l linkDo) FirstOrInit() (*models.Link, error) {
|
||||
if result, err := l.DO.FirstOrInit(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.Link), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (l linkDo) FirstOrCreate() (*models.Link, error) {
|
||||
if result, err := l.DO.FirstOrCreate(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.Link), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (l linkDo) FindByPage(offset int, limit int) (result []*models.Link, count int64, err error) {
|
||||
result, err = l.Offset(offset).Limit(limit).Find()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if size := len(result); 0 < limit && 0 < size && size < limit {
|
||||
count = int64(size + offset)
|
||||
return
|
||||
}
|
||||
|
||||
count, err = l.Offset(-1).Limit(-1).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (l linkDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
|
||||
count, err = l.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = l.Offset(offset).Limit(limit).Scan(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (l linkDo) Scan(result interface{}) (err error) {
|
||||
return l.DO.Scan(result)
|
||||
}
|
||||
|
||||
func (l linkDo) Delete(models ...*models.Link) (result gen.ResultInfo, err error) {
|
||||
return l.DO.Delete(models)
|
||||
}
|
||||
|
||||
func (l *linkDo) withDO(do gen.Dao) *linkDo {
|
||||
l.DO = *do.(*gen.DO)
|
||||
return l
|
||||
}
|
21
storage/models/link.go
Normal file
21
storage/models/link.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Link struct {
|
||||
gorm.Model
|
||||
Link string
|
||||
Count uint64
|
||||
}
|
||||
|
||||
type ILink interface {
|
||||
|
||||
// UPDATE @@table SET count = count + 1 WHERE link = @link
|
||||
|
||||
// If (NOT EXISTS(SELECT * FROM @@table WHERE link = @link))
|
||||
// BEGIN
|
||||
// INSERT INTO @@table(@link)
|
||||
// IncrementLinkCount(link string) ([]gen.T, error)
|
||||
}
|
|
@ -46,7 +46,7 @@
|
|||
<tr>
|
||||
<td>Bluesky</td>
|
||||
<td>
|
||||
<a href="https://bsky.app/profile/mstar.dev">https://bsky.app/profile/mstar.dev</a>
|
||||
<a href="/bsky">https://bsky.app/profile/mstar.dev</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -58,57 +58,56 @@
|
|||
<tr>
|
||||
<td>Forgejo</td>
|
||||
<td>
|
||||
<a href="https://git.mstar.dev/mstar">https://git.mstar.dev/mstar</a>
|
||||
<a href="/git">https://git.mstar.dev/mstar</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gitlab (not actively used anymore)</td>
|
||||
<td>
|
||||
<a href="https://gitlab.com/mstarongitlab">https://gitlab.com/mstarongitlab</a>
|
||||
<a href="/gitlab">https://gitlab.com/mstarongitlab</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Github (same as Gitlab)</td>
|
||||
<td>
|
||||
<a href="https://github.com/mstarongithub/">https://github.com/mstarongithub/</a>
|
||||
<a href="/github">https://github.com/mstarongithub/</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Twitch</td>
|
||||
<td>
|
||||
<a href="https://twitch.tv/mstarontwitch">https://twitch.tv/mstarontwitch</a>
|
||||
<a href="/twitch">https://twitch.tv/mstarontwitch</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Youtube</td>
|
||||
<td>
|
||||
<a
|
||||
href="https://www.youtube.com/channel/UC-LklY_wt004i_30xcVohbg">https://www.youtube.com/channel/UC-LklY_wt004i_30xcVohbg</a>
|
||||
<a href="/youtube">https://www.youtube.com/channel/UC-LklY_wt004i_30xcVohbg</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- Rickroll -->
|
||||
<td>Fedi</td>
|
||||
<td>
|
||||
<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ">https://woem.men/@mstar</a>
|
||||
<a href="/fedi">https://woem.men/@mstar</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<ul>
|
||||
<li><a href="https://foxgirls.love/web">Fren Erika</a></li>
|
||||
<li><a href="https://foxgirls.love">Fren Rika</a></li>
|
||||
<li><a href="https://linktr.ee/akijam">Fren Aki</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<!--<p>I'm also working on a Fediverse server, <a href="https://git.mstar.dev/mstar/linstrom">Linstrom</a></p>-->
|
||||
<!--<br>-->
|
||||
<p>Todo: Add proper styling</p>
|
||||
<p>Todo: Add proper styling and more information</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<p>Contact: <a href="mailto:me@mstar.dev">me@mstar.dev (<a
|
||||
href="/static/files/other/publickey.me@mstar.dev-27fcaabd3022acff023e6e2a053a2d9af0f03260.asc">Public PGP
|
||||
key</a>)</p>
|
||||
<p>Last updated: 16.01.2025</p>
|
||||
<p>Last updated: 24.03.2025</p>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
|
|
Loading…
Reference in a new issue