diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..022d1e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__debug_bin* +templates/*_templ.go +bin/ \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..25ce12b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "preLaunchTask": "just: prebuild", + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceRoot}", + "console": "integratedTerminal", + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..331368d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "editor.tabSize": 2, + "editor.detectIndentation": false, + "editor.insertSpaces": false, +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..3b621d1 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,9 @@ +{ + "version": "2.0.0", + "tasks": [{ + "label": "just: prebuild", + "command": "just", + "args": ["prebuild"], + "type": "shell" + }] +} \ No newline at end of file diff --git a/go.mod b/go.mod index 15fe52e..632e163 100644 --- a/go.mod +++ b/go.mod @@ -10,18 +10,30 @@ require ( ) require ( + github.com/a-h/parse v0.0.0-20250122154542-74294addb73e // indirect + github.com/a-h/templ v0.3.977 // indirect github.com/andybalholm/brotli v1.2.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cli/browser v1.3.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.18.4 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.19 // indirect + github.com/natefinch/atomic v1.0.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.69.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/mod v0.32.0 // indirect golang.org/x/net v0.50.0 // indirect + golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.41.0 // indirect golang.org/x/text v0.34.0 // indirect + golang.org/x/tools v0.41.0 // indirect ) + +tool github.com/a-h/templ/cmd/templ diff --git a/go.sum b/go.sum index 4870de2..0d01cb0 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,20 @@ +github.com/a-h/parse v0.0.0-20250122154542-74294addb73e h1:HjVbSQHy+dnlS6C3XajZ69NYAb5jbGNfHanvm1+iYlo= +github.com/a-h/parse v0.0.0-20250122154542-74294addb73e/go.mod h1:3mnrkvGpurZ4ZrTDbYU84xhwXW2TjTKShSwjRi2ihfQ= +github.com/a-h/templ v0.3.977 h1:kiKAPXTZE2Iaf8JbtM21r54A8bCNsncrfnokZZSrSDg= +github.com/a-h/templ v0.3.977/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo= github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ= github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo= +github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk= github.com/clipperhouse/uax29/v2 v2.6.0 h1:z0cDbUV+aPASdFb2/ndFnS9ts/WNXgTNNGFoKXuhpos= github.com/clipperhouse/uax29/v2 v2.6.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gofiber/fiber/v2 v2.52.11 h1:5f4yzKLcBcF8ha1GQTWB+mpblWz3Vz6nSAbTL31HkWs= github.com/gofiber/fiber/v2 v2.52.11/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= github.com/gofiber/helmet/v2 v2.2.26 h1:KreQVUpCIGppPQ6Yt8qQMaIR4fVXMnvBdsda0dJSsO8= @@ -19,6 +31,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= +github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -32,9 +46,13 @@ github.com/valyala/fasthttp v1.69.0 h1:fNLLESD2SooWeh2cidsuFtOcrEi4uB4m1mPrkJMZy github.com/valyala/fasthttp v1.69.0/go.mod h1:4wA4PfAraPlAsJ5jMSqCE2ug5tqUPwKXxVj8oNECGcw= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -45,5 +63,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= 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= diff --git a/helpers/templates.go b/helpers/templates.go new file mode 100644 index 0000000..c35b055 --- /dev/null +++ b/helpers/templates.go @@ -0,0 +1,11 @@ +package helpers + +import ( + "github.com/a-h/templ" + "github.com/gofiber/fiber/v2" +) + +func TemplRender(c *fiber.Ctx, component templ.Component) error { + c.Set("Content-Type", "text/html") + return component.Render(c.UserContext(), c.Response().BodyWriter()) +} diff --git a/justfile b/justfile new file mode 100644 index 0000000..8fad0a8 --- /dev/null +++ b/justfile @@ -0,0 +1,22 @@ +go := require("go") +templ := require("templ") +air := require("air") + +templ: + templ generate + +prebuild: templ + +run: prebuild + go run main.go + +build: prebuild + go build -o bin/gpx-downloader main.go + +watch: + CI=1 CLICOLOR_FORCE=1 air \ + --build.cmd "just build" \ + --build.bin "./bin/gpx-downloader" \ + -build.include_ext "go,templ" \ + --build.exclude_dir "data" \ + --build.exclude_regex "_templ.go" diff --git a/providers/suisse_mobile.go b/providers/suisse_mobile.go index 493f0bf..815bc70 100644 --- a/providers/suisse_mobile.go +++ b/providers/suisse_mobile.go @@ -14,7 +14,7 @@ import ( func SuisseMobileCheckURL(url string) int { var id int - re := regexp.MustCompile(`https?://(?:www\.)?schweizmobil\.ch/[^/]+/tour/(\d+)`) + re := regexp.MustCompile(`schweizmobil\.ch/[^/]+/tour/(\d+)`) matches := re.FindStringSubmatch(url) if len(matches) > 1 { diff --git a/routes/fetch.go b/routes/fetch.go index f9a1259..dedc5a3 100644 --- a/routes/fetch.go +++ b/routes/fetch.go @@ -3,16 +3,25 @@ package routes import ( "fmt" + "git.readonly.ch/bouzoure/gpx-downloader/helpers" "git.readonly.ch/bouzoure/gpx-downloader/providers" + "git.readonly.ch/bouzoure/gpx-downloader/templates" "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/log" "github.com/tkrajina/gpxgo/gpx" ) func Fetch(c *fiber.Ctx) error { + // In case of error + baseParams := templates.BaseTemplateParams{ + Title: "Error - GPX downloader", + } + var indexParams templates.IndexParams + sourceUrl := c.FormValue("url") if len(sourceUrl) <= 0 { - c.SendStatus(422) - return c.SendString("Error: URL is empty") + indexParams.Error = "Error: URL is empty" + return helpers.TemplRender(c, templates.Index(baseParams, indexParams)) } var gpxFile gpx.GPX @@ -29,18 +38,22 @@ func Fetch(c *fiber.Ctx) error { gpxFile, err = providers.SuisseMobileFetch(suisseMobileId) if err != nil { - return err + log.Error(err) + indexParams.Error = "An error occured" + return helpers.TemplRender(c, templates.Index(baseParams, indexParams)) } } if len(filename) <= 0 { - c.SendStatus(422) - return c.SendString("Error: URL is not supported") + indexParams.Error = "Error: URL is not supported" + return helpers.TemplRender(c, templates.Index(baseParams, indexParams)) } xml, err := gpxFile.ToXml(gpx.ToXmlParams{}) if err != nil { - return err + log.Error(err) + indexParams.Error = "An error occured" + return helpers.TemplRender(c, templates.Index(baseParams, indexParams)) } c.Set("Content-Type", "octet-stream") diff --git a/routes/index.go b/routes/index.go index d53c726..08fab1e 100644 --- a/routes/index.go +++ b/routes/index.go @@ -1,13 +1,16 @@ package routes -import "github.com/gofiber/fiber/v2" +import ( + "git.readonly.ch/bouzoure/gpx-downloader/helpers" + "git.readonly.ch/bouzoure/gpx-downloader/templates" + "github.com/gofiber/fiber/v2" +) func Index(c *fiber.Ctx) error { - c.Set("Content-Type", "text/html") - return c.SendString(` -
- - -
- `) + baseParams := templates.BaseTemplateParams{ + Title: "GPX downloader", + } + var indexParams templates.IndexParams + + return helpers.TemplRender(c, templates.Index(baseParams, indexParams)) } diff --git a/templates/base.templ b/templates/base.templ new file mode 100644 index 0000000..422d6ef --- /dev/null +++ b/templates/base.templ @@ -0,0 +1,49 @@ +package templates + +type BaseTemplateParams struct { + Title string +} + +templ BaseTemplate(params BaseTemplateParams) { + + + + { params.Title } + + + + { children... } + + +} \ No newline at end of file diff --git a/templates/index.templ b/templates/index.templ new file mode 100644 index 0000000..2fae97a --- /dev/null +++ b/templates/index.templ @@ -0,0 +1,26 @@ +package templates + +type IndexParams struct { + Error string +} + +templ Index(baseParams BaseTemplateParams, indexParams IndexParams) { + @BaseTemplate(baseParams) { +
+

GPX downloader

+ + if len(indexParams.Error) <= 0 { +
+ + +
+ } else { +
+ { indexParams.Error } +
+ + Retour + } +
+ } +} \ No newline at end of file