This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

Start of the webserver

author
pds.dad
date (Jun 30, 2026, 7:54 PM -0500) commit fa2ab316 parent a38fd2bd change-id zvuzkmko
+315 -10
+52
.air.toml
··· 1 + root = "." 2 + testdata_dir = "testdata" 3 + tmp_dir = "tmp" 4 + 5 + [build] 6 + args_bin = [] 7 + bin = "./tmp/puzzlemethis" 8 + cmd = "go build -o ./tmp/puzzlemethis ./cmd/puzzlemethis/" 9 + delay = 500 10 + exclude_dir = ["assets", "tmp", "vendor", "testdata"] 11 + exclude_file = [] 12 + exclude_regex = ["_test.go"] 13 + exclude_unchanged = false 14 + follow_symlink = false 15 + full_bin = "" 16 + include_dir = [] 17 + include_ext = ["go", "tpl", "tmpl", "html", "gohtml", "css", "js"] 18 + include_file = [] 19 + kill_delay = "0s" 20 + log = "build-errors.log" 21 + poll = false 22 + poll_interval = 0 23 + post_cmd = [] 24 + pre_cmd = [] 25 + rerun = false 26 + rerun_delay = 500 27 + send_interrupt = false 28 + stop_on_error = true 29 + 30 + [color] 31 + app = "" 32 + build = "yellow" 33 + main = "magenta" 34 + runner = "green" 35 + watcher = "cyan" 36 + 37 + [log] 38 + main_only = false 39 + silent = false 40 + time = false 41 + 42 + [misc] 43 + clean_on_exit = false 44 + 45 + [proxy] 46 + app_port = 0 47 + enabled = false 48 + proxy_port = 0 49 + 50 + [screen] 51 + clear_on_rebuild = true 52 + keep_scroll = true
+1
.gitignore
··· 4 4 puzzles.db-wal 5 5 puzzles.db-shm 6 6 puzzles.db-journal 7 + tmp
+44
cmd/puzzlemethis/main.go
··· 1 + package main 2 + 3 + import ( 4 + "context" 5 + "log/slog" 6 + "os" 7 + "os/signal" 8 + "sync" 9 + "syscall" 10 + 11 + "github.com/spf13/viper" 12 + "tangled.org/pds.dad/PuzzleMeThis/internal" 13 + "tangled.org/pds.dad/PuzzleMeThis/internal/db" 14 + "tangled.org/pds.dad/PuzzleMeThis/internal/server" 15 + ) 16 + 17 + func main() { 18 + internal.LoadConfig() 19 + 20 + gdb, err := db.Open(viper.GetString("database.url")) 21 + if err != nil { 22 + slog.Error("failed to open database", "err", err) 23 + os.Exit(1) 24 + } 25 + 26 + if err := db.Migrate(gdb); err != nil { 27 + slog.Error("failed to migrate database", "err", err) 28 + os.Exit(1) 29 + } 30 + 31 + ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) 32 + defer stop() 33 + 34 + var wg sync.WaitGroup 35 + 36 + wg.Go(func() { 37 + defer stop() 38 + server.RunHTTPServer(ctx, gdb) 39 + }) 40 + 41 + wg.Wait() 42 + slog.Info("bye") 43 + 44 + }
+30 -3
go.mod
··· 1 - module tangled.org/pds.dad/LichessPuzzles 1 + module tangled.org/pds.dad/PuzzleMeThis 2 2 3 3 go 1.25.5 4 4 ··· 11 11 ) 12 12 13 13 require ( 14 + github.com/fsnotify/fsnotify v1.9.0 // indirect 15 + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect 16 + github.com/joho/godotenv v1.5.1 // indirect 17 + github.com/labstack/gommon v0.5.0 // indirect 18 + github.com/mattn/go-colorable v0.1.15 // indirect 19 + github.com/mattn/go-isatty v0.0.22 // indirect 20 + github.com/pelletier/go-toml/v2 v2.2.4 // indirect 21 + github.com/sagikazarmark/locafero v0.11.0 // indirect 22 + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect 23 + github.com/spf13/afero v1.15.0 // indirect 24 + github.com/spf13/cast v1.10.0 // indirect 25 + github.com/spf13/pflag v1.0.10 // indirect 26 + github.com/spf13/viper v1.21.0 // indirect 27 + github.com/subosito/gotenv v1.6.0 // indirect 28 + github.com/valyala/bytebufferpool v1.0.0 // indirect 29 + github.com/valyala/fasttemplate v1.2.2 // indirect 30 + go.yaml.in/yaml/v3 v3.0.4 // indirect 31 + golang.org/x/crypto v0.53.0 // indirect 32 + golang.org/x/net v0.56.0 // indirect 33 + golang.org/x/time v0.15.0 // indirect 34 + ) 35 + 36 + require ( 14 37 github.com/andybalholm/brotli v1.1.1 // indirect 38 + github.com/go-chi/chi/v5 v5.3.0 39 + github.com/google/go-cmp v0.6.0 // indirect 15 40 github.com/google/uuid v1.6.0 // indirect 16 41 github.com/jinzhu/inflection v1.0.0 // indirect 17 42 github.com/jinzhu/now v1.1.5 // indirect 18 43 github.com/klauspost/compress v1.17.9 // indirect 44 + github.com/labstack/echo/v4 v4.15.4 45 + github.com/labstack/echo/v5 v5.2.1 19 46 github.com/mattn/go-sqlite3 v1.14.22 // indirect 20 47 github.com/parquet-go/bitpack v1.0.0 // indirect 21 48 github.com/parquet-go/jsonlite v1.0.0 // indirect 22 49 github.com/pierrec/lz4/v4 v4.1.21 // indirect 23 50 github.com/twpayne/go-geom v1.6.1 // indirect 24 - golang.org/x/sys v0.38.0 // indirect 25 - golang.org/x/text v0.20.0 // indirect 51 + golang.org/x/sys v0.46.0 // indirect 52 + golang.org/x/text v0.38.0 // indirect 26 53 google.golang.org/protobuf v1.34.2 // indirect 27 54 )
+55 -6
go.sum
··· 10 10 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 11 github.com/earthboundkid/versioninfo/v2 v2.24.1 h1:SJTMHaoUx3GzjjnUO1QzP3ZXK6Ee/nbWyCm58eY3oUg= 12 12 github.com/earthboundkid/versioninfo/v2 v2.24.1/go.mod h1:VcWEooDEuyUJnMfbdTh0uFN4cfEIg+kHMuWB2CDCLjw= 13 - github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 14 - github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 13 + github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= 14 + github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= 15 + github.com/go-chi/chi/v5 v5.3.0 h1:halUjDxhshgXHMrao5bB8eNBXo/rnzwr8m5m36glehM= 16 + github.com/go-chi/chi/v5 v5.3.0/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto= 17 + github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= 18 + github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= 19 + github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 20 + github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 15 21 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 16 22 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 17 23 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= ··· 20 26 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 21 27 github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= 22 28 github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 29 + github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= 30 + github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= 23 31 github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= 24 32 github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= 33 + github.com/labstack/echo/v4 v4.15.4 h1:DL45vVYa+BWE+XuW+zZNd9H0YEdZ80UAWJGcTVW4EVs= 34 + github.com/labstack/echo/v4 v4.15.4/go.mod h1:CuMetKIRwsuO/qlAgMq+KTAalwGoB/h4tC+yPdrTj1g= 35 + github.com/labstack/echo/v5 v5.2.1 h1:TzpIksY6zLMzV0T0ycYbvTEoj9w6o6AcL5twg182VTY= 36 + github.com/labstack/echo/v5 v5.2.1/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo= 37 + github.com/labstack/gommon v0.5.0 h1:6VSQ2NOzsnEJ5W6+84E0RbcaDDmgB6NIAzWCczTEe6c= 38 + github.com/labstack/gommon v0.5.0/go.mod h1:Rzlg7HHy1maLfzBYGg9NZcVuz1sA68HHhLjhcEllYE0= 39 + github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= 40 + github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= 41 + github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= 42 + github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= 25 43 github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= 26 44 github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= 27 45 github.com/parquet-go/bitpack v1.0.0 h1:AUqzlKzPPXf2bCdjfj4sTeacrUwsT7NlcYDMUQxPcQA= ··· 30 48 github.com/parquet-go/jsonlite v1.0.0/go.mod h1:nDjpkpL4EOtqs6NQugUsi0Rleq9sW/OtC1NnZEnxzF0= 31 49 github.com/parquet-go/parquet-go v0.30.1 h1:Oy6ganNrAdFiVwy7wNmWagfPTWA2X9Z3tVHBc7JtuX8= 32 50 github.com/parquet-go/parquet-go v0.30.1/go.mod h1:navtkAYr2LGoJVp141oXPlO/sxLvaOe3la2JEoD8+rg= 51 + github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= 52 + github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= 33 53 github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= 34 54 github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 35 55 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 36 56 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 57 + github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= 58 + github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= 59 + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= 60 + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= 61 + github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= 62 + github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= 63 + github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= 64 + github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= 65 + github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= 66 + github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 67 + github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= 68 + github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= 37 69 github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= 38 70 github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 71 + github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= 72 + github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= 39 73 github.com/twpayne/go-geom v1.6.1 h1:iLE+Opv0Ihm/ABIcvQFGIiFBXd76oBIar9drAwHFhR4= 40 74 github.com/twpayne/go-geom v1.6.1/go.mod h1:Kr+Nly6BswFsKM5sd31YaoWS5PeDDH2NftJTK7Gd028= 41 75 github.com/urfave/cli/v3 v3.10.1 h1:7Kx9H50hrHbRbyxgO1KP6/BcbiGRz0uYh5YyQ30JEEY= 42 76 github.com/urfave/cli/v3 v3.10.1/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= 77 + github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 78 + github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 79 + github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= 80 + github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= 43 81 github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= 44 82 github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= 83 + go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= 84 + go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= 85 + golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= 86 + golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= 87 + golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= 88 + golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= 45 89 golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= 46 90 golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 47 - golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= 48 - golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= 49 - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 50 - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 91 + golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= 92 + golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= 93 + golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= 94 + golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= 95 + golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= 96 + golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= 97 + golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= 98 + golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= 51 99 google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= 52 100 google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 101 + gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 53 102 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 54 103 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 55 104 gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
+66
internal/config.go
··· 1 + package internal 2 + 3 + import ( 4 + "errors" 5 + "log/slog" 6 + "os" 7 + "strings" 8 + 9 + "github.com/earthboundkid/versioninfo/v2" 10 + "github.com/joho/godotenv" 11 + "github.com/spf13/viper" 12 + ) 13 + 14 + var userAgentStr = "tap/" + versioninfo.Short() 15 + 16 + func UserAgent() string { 17 + return userAgentStr 18 + } 19 + 20 + // Load initializes the configuration with viper 21 + func LoadConfig() { 22 + if err := godotenv.Load(); err != nil { 23 + slog.Info("No .env file found or error loading it. Using default values and environment variables.") 24 + } 25 + 26 + viper.SetDefault("server.port", "8080") 27 + viper.SetDefault("server.host", "localhost") 28 + viper.SetDefault("database.url", "./puzzles.db") 29 + 30 + viper.AutomaticEnv() 31 + 32 + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) 33 + 34 + // Install the configured logger now that log.format is resolvable from env 35 + // defaults, so the config-read messages below use the chosen format. 36 + SetupLogger() 37 + 38 + viper.SetConfigName("config") 39 + viper.SetConfigType("yaml") 40 + viper.AddConfigPath("./config") 41 + viper.AddConfigPath(".") 42 + 43 + if err := viper.ReadInConfig(); err != nil { 44 + var configFileNotFoundError viper.ConfigFileNotFoundError 45 + if !errors.As(err, &configFileNotFoundError) { 46 + slog.Error("Error reading config file", "err", err) 47 + os.Exit(1) 48 + } 49 + slog.Info("Config file not found, using default values and environment variables") 50 + } else { 51 + slog.Info("Using config file", "file", viper.ConfigFileUsed()) 52 + } 53 + } 54 + 55 + // SetupLogger installs a process-wide slog logger based on the configured 56 + // "log.format". "json" selects a JSON handler; anything else (the default 57 + // "text") selects a human-readable text handler. Output goes to stderr. 58 + func SetupLogger() { 59 + var handler slog.Handler 60 + if viper.GetString("log.format") == "json" { 61 + handler = slog.NewJSONHandler(os.Stderr, nil) 62 + } else { 63 + handler = slog.NewTextHandler(os.Stderr, nil) 64 + } 65 + slog.SetDefault(slog.New(handler)) 66 + }
+1 -1
internal/db/db.go
··· 8 8 "gorm.io/driver/sqlite" 9 9 "gorm.io/gorm" 10 10 "gorm.io/gorm/logger" 11 - "tangled.org/pds.dad/LichessPuzzles/internal/models" 11 + "tangled.org/pds.dad/PuzzleMeThis/internal/models" 12 12 ) 13 13 14 14 // Open opens the SQLite database at path with settings tuned for bulk inserts
+12
internal/server/homeHandlers.go
··· 1 + package server 2 + 3 + import ( 4 + "net/http" 5 + 6 + "github.com/labstack/echo/v5" 7 + ) 8 + 9 + func (s *Server) home(c *echo.Context) error { 10 + c.Logger().Info("home") 11 + return c.String(http.StatusOK, "hey") 12 + }
+54
internal/server/server.go
··· 1 + package server 2 + 3 + import ( 4 + "context" 5 + "errors" 6 + "fmt" 7 + "log/slog" 8 + "net/http" 9 + "time" 10 + 11 + "github.com/labstack/echo/v5" 12 + "github.com/labstack/echo/v5/middleware" 13 + "github.com/spf13/viper" 14 + "gorm.io/gorm" 15 + ) 16 + 17 + type Server struct { 18 + db *gorm.DB 19 + } 20 + 21 + func RunHTTPServer(ctx context.Context, db *gorm.DB) { 22 + 23 + srv := &Server{db: db} 24 + 25 + e := echo.New() 26 + e.Logger = slog.Default() 27 + e.Use(middleware.RequestLogger()) 28 + 29 + //Handlers 30 + e.GET("/", srv.home) 31 + 32 + port := viper.Get("server.port") 33 + host := viper.Get("server.host") 34 + address := fmt.Sprintf("%s:%s", host, port) 35 + s := http.Server{Addr: address, Handler: e} 36 + 37 + go func() { 38 + e.Logger.Info("Starting the server on ", "address", address) 39 + 40 + if err := s.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { 41 + e.Logger.Error("failed to start server", "error", err) 42 + } 43 + e.Logger.Info("server started", "address", address) 44 + }() 45 + 46 + <-ctx.Done() 47 + 48 + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 49 + defer cancel() 50 + if err := s.Shutdown(ctx); err != nil { 51 + e.Logger.Error("failed to stop server", "error", err) 52 + } 53 + 54 + }