chi was replaced with echo #2

Merged
jtom38 merged 1 commits from features/moved-to-echo into main 2024-04-23 22:18:41 -07:00
12 changed files with 618 additions and 561 deletions
Showing only changes of commit ab026ef471 - Show all commits

25
go.mod
View File

@ -8,11 +8,23 @@ require (
github.com/go-rod/rod v0.107.1
github.com/google/uuid v1.3.0
github.com/joho/godotenv v1.4.0
github.com/labstack/echo/v4 v4.12.0
github.com/mmcdole/gofeed v1.1.3
github.com/nicklaw5/helix/v2 v2.4.0
github.com/robfig/cron/v3 v3.0.1
github.com/swaggo/http-swagger v1.3.0
github.com/swaggo/swag v1.8.2
github.com/swaggo/echo-swagger v1.4.1
github.com/swaggo/swag v1.8.12
)
require (
github.com/ghodss/yaml v1.0.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/swaggo/files/v2 v2.0.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.22.0 // indirect
)
require (
@ -30,13 +42,12 @@ require (
github.com/mmcdole/goxpp v0.0.0-20200921145534-2f3784f67354 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect
github.com/ysmood/goob v0.4.0 // indirect
github.com/ysmood/gson v0.7.2 // indirect
github.com/ysmood/leakless v0.7.0 // indirect
golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.11 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.7.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

57
go.sum
View File

@ -12,6 +12,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
@ -44,6 +46,10 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@ -51,6 +57,11 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
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.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mmcdole/gofeed v1.1.3 h1:pdrvMb18jMSLidGp8j0pLvc9IGziX4vbmvVqmLH6z8o=
github.com/mmcdole/gofeed v1.1.3/go.mod h1:QQO3maftbOu+hiVOGOZDRLymqGQCos4zxbA4j89gMrE=
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf/go.mod h1:pasqhqstspkosTneA62Nc+2p9SOBBYAPbnmRRWPQ0V8=
@ -75,14 +86,19 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe h1:K8pHPVoTgxFJt1lXuIzzOX7zZhZFldJQK/CgKx9BFIc=
github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w=
github.com/swaggo/http-swagger v1.3.0 h1:1+6M4qRorIbdyTWTsGrwnb0r9jGK5dcWN82O6oY/yHQ=
github.com/swaggo/http-swagger v1.3.0/go.mod h1:9glekdg40lwclrrKNRGgj/IMDxpNPZ3kzab4oPcF8EM=
github.com/swaggo/swag v1.8.2 h1:D4aBiVS2a65zhyk3WFqOUz7Rz0sOaUcgeErcid5uGL4=
github.com/swaggo/swag v1.8.2/go.mod h1:jMLeXOOmYyjk8PvHTsXBdrubsNd9gUJTTCzL5iBnseg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/swaggo/echo-swagger v1.4.1 h1:Yf0uPaJWp1uRtDloZALyLnvdBeoEL5Kc7DtnjzO/TUk=
github.com/swaggo/echo-swagger v1.4.1/go.mod h1:C8bSi+9yH2FLZsnhqMZLIZddpUxZdBYuNHbtaS1Hljc=
github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw=
github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w=
github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its=
github.com/urfave/cli v1.22.3/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
github.com/ysmood/goob v0.4.0/go.mod h1:u6yx7ZhS4Exf2MwciFr6nIM8knHQIE22lFpWHnfql18=
github.com/ysmood/got v0.29.5 h1:+wMnm8UjoyYFMfeAsr57a1bahWTkloysc0Hxsu2gmnM=
@ -95,28 +111,32 @@ github.com/ysmood/gson v0.7.2/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3R
github.com/ysmood/leakless v0.7.0 h1:XCGdaPExyoreoQd+H5qgxM3ReNbSPFsEXpSKwbXbwQw=
github.com/ysmood/leakless v0.7.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
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-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA=
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
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/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
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.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
@ -125,5 +145,6 @@ 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/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -0,0 +1,13 @@
package domain
type GetSourceBySourceAndNameParamRequest struct {
Name string `query:"name"`
Source string `query:"source"`
}
type NewSourceParamRequest struct {
Name string `query:"name"`
Url string `query:"url"`
Tags string `query:"tags"`
}

View File

@ -0,0 +1,5 @@
package domain
type ErrorResponse struct {
Message string `json:"message"`
}

View File

@ -5,22 +5,22 @@ import (
"strconv"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
)
func (s *Server) GetArticleRouter() http.Handler {
r := chi.NewRouter()
r.Get("/", s.listArticles)
r.Route("/{ID}", func(r chi.Router) {
r.Get("/", s.getArticle)
r.Get("/details", s.getArticleDetails)
})
r.Get("/by/sourceid", s.ListArticlesBySourceId)
return r
}
//func (s *Handler) GetArticleRouter() http.Handler {
// r := chi.NewRouter()
//
// r.Get("/", s.listArticles)
// r.Route("/{ID}", func(r chi.Router) {
// r.Get("/", s.getArticle)
// r.Get("/details", s.getArticleDetails)
// })
// r.Get("/by/sourceid", s.ListArticlesBySourceId)
//
// return r
//}
type ArticlesListResults struct {
ApiStatusModel
@ -44,7 +44,7 @@ type ArticleDetailsResult struct {
// @Tags Articles
// @Router /articles [get]
// @Success 200 {object} ArticlesListResults "OK"
func (s *Server) listArticles(w http.ResponseWriter, r *http.Request) {
func (s *Handler) listArticles(c echo.Context) error {
p := ArticlesListResults{
ApiStatusModel: ApiStatusModel{
Message: "OK",
@ -52,32 +52,28 @@ func (s *Server) listArticles(w http.ResponseWriter, r *http.Request) {
},
}
query := r.URL.Query()
queryPage := query["page"]
queryPage := c.QueryParam("page")
// if a page number was sent, process it
if len(queryPage) >= 1 {
page, err := strconv.Atoi(query["page"][0])
page, err := strconv.Atoi(queryPage)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, err)
}
res, err := s.dto.ListArticles(r.Context(), 25, page)
res, err := s.dto.ListArticles(c.Request().Context(), 25, page)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
} else {
res, err := s.dto.ListArticles(r.Context(), 25, 0)
res, err := s.dto.ListArticles(c.Request().Context(), 25, 0)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
}
@ -88,7 +84,7 @@ func (s *Server) listArticles(w http.ResponseWriter, r *http.Request) {
// @Tags Articles
// @Router /articles/{ID} [get]
// @Success 200 {object} ArticleGetResults "OK"
func (s *Server) getArticle(w http.ResponseWriter, r *http.Request) {
func (s *Handler) getArticle(c echo.Context) error {
p := ArticleGetResults{
ApiStatusModel: ApiStatusModel{
Message: "OK",
@ -96,22 +92,20 @@ func (s *Server) getArticle(w http.ResponseWriter, r *http.Request) {
},
}
id := chi.URLParam(r, "ID")
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, err)
}
res, err := s.dto.GetArticle(r.Context(), uuid)
res, err := s.dto.GetArticle(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
// GetArticleDetails
@ -121,7 +115,7 @@ func (s *Server) getArticle(w http.ResponseWriter, r *http.Request) {
// @Tags Articles
// @Router /articles/{ID}/details [get]
// @Success 200 {object} ArticleDetailsResult "OK"
func (s *Server) getArticleDetails(w http.ResponseWriter, r *http.Request) {
func (s *Handler) getArticleDetails(c echo.Context) error {
p := ArticleDetailsResult{
ApiStatusModel: ApiStatusModel{
Message: "OK",
@ -129,22 +123,20 @@ func (s *Server) getArticleDetails(w http.ResponseWriter, r *http.Request) {
},
}
id := chi.URLParam(r, "ID")
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, err)
}
res, err := s.dto.GetArticleDetails(r.Context(), uuid)
res, err := s.dto.GetArticleDetails(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
// TODO add page support
@ -156,7 +148,7 @@ func (s *Server) getArticleDetails(w http.ResponseWriter, r *http.Request) {
// @Tags Articles
// @Router /articles/by/sourceid [get]
// @Success 200 {object} ArticlesListResults "OK"
func (s *Server) ListArticlesBySourceId(w http.ResponseWriter, r *http.Request) {
func (s *Handler) ListArticlesBySourceId(c echo.Context) error {
p := ArticlesListResults{
ApiStatusModel: ApiStatusModel{
Message: "OK",
@ -164,41 +156,34 @@ func (s *Server) ListArticlesBySourceId(w http.ResponseWriter, r *http.Request)
},
}
r.URL.Query()
query := r.URL.Query()
_id := query["id"][0]
id := c.QueryParam("id")
uuid, err := uuid.Parse(_id)
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, err)
}
// if a page number was sent, process it
if len(query["page"]) >= 1 {
_page, err := strconv.Atoi(query["page"][0])
if len(c.QueryParam("page")) >= 1 {
_page, err := strconv.Atoi(c.QueryParam("page"))
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, err)
}
res, err := s.dto.ListNewArticlesBySourceId(r.Context(), uuid, 25, _page)
res, err := s.dto.ListNewArticlesBySourceId(c.Request().Context(), uuid, 25, _page)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
s.WriteJson(w, p)
} else {
res, err := s.dto.ListNewArticlesBySourceId(r.Context(), uuid, 25, 0)
res, err := s.dto.ListNewArticlesBySourceId(c.Request().Context(), uuid, 25, 0)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
s.WriteJson(w, p)
}
return c.JSON(http.StatusOK, p)
}

View File

@ -1,15 +1,15 @@
package v1
import (
"encoding/json"
"log"
"fmt"
"net/http"
"strings"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
)
type ListDiscordWebhooks struct {
@ -22,28 +22,12 @@ type GetDiscordWebhook struct {
Payload models.DiscordWebHooksDto `json:"payload"`
}
func (s Server) DiscordWebHookRouter() http.Handler {
r := chi.NewRouter()
r.Get("/", s.ListDiscordWebHooks)
r.Post("/new", s.NewDiscordWebHook)
r.Get("/by/serverAndChannel", s.GetDiscordWebHooksByServerAndChannel)
r.Route("/{ID}", func(r chi.Router) {
r.Get("/", s.GetDiscordWebHooksById)
r.Delete("/", s.deleteDiscordWebHook)
r.Post("/disable", s.disableDiscordWebHook)
r.Post("/enable", s.enableDiscordWebHook)
})
return r
}
// ListDiscordWebhooks
// @Summary Returns the top 100 entries from the queue to be processed.
// @Produce application/json
// @Tags Discord, Webhook
// @Router /discord/webhooks [get]
func (s *Server) ListDiscordWebHooks(w http.ResponseWriter, r *http.Request) {
func (s *Handler) ListDiscordWebHooks(c echo.Context) error {
p := ListDiscordWebhooks{
ApiStatusModel: ApiStatusModel{
Message: "OK",
@ -51,13 +35,12 @@ func (s *Server) ListDiscordWebHooks(w http.ResponseWriter, r *http.Request) {
},
}
res, err := s.dto.ListDiscordWebHooks(r.Context(), 50)
res, err := s.dto.ListDiscordWebHooks(c.Request().Context(), 50)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
// GetDiscordWebHook
@ -67,7 +50,7 @@ func (s *Server) ListDiscordWebHooks(w http.ResponseWriter, r *http.Request) {
// @Tags Discord, Webhook
// @Router /discord/webhooks/{id} [get]
// @Success 200 {object} GetDiscordWebhook "OK"
func (s *Server) GetDiscordWebHooksById(w http.ResponseWriter, r *http.Request) {
func (s *Handler) GetDiscordWebHooksById(c echo.Context) error {
p := GetDiscordWebhook{
ApiStatusModel: ApiStatusModel{
Message: "OK",
@ -75,25 +58,28 @@ func (s *Server) GetDiscordWebHooksById(w http.ResponseWriter, r *http.Request)
},
}
_id := chi.URLParam(r, "ID")
_id := c.Param("ID")
if _id == "" {
s.WriteError(w, "id is missing", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: ErrIdValueMissing,
})
}
uuid, err := uuid.Parse(_id)
if err != nil {
s.WriteError(w, "unable to parse id value", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: ErrUnableToParseId,
})
}
res, err := s.dto.GetDiscordWebhook(r.Context(), uuid)
res, err := s.dto.GetDiscordWebhook(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, "no record found", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: ErrNoRecordFound,
})
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
// GetDiscordWebHookByServerAndChannel
@ -104,7 +90,7 @@ func (s *Server) GetDiscordWebHooksById(w http.ResponseWriter, r *http.Request)
// @Tags Discord, Webhook
// @Router /discord/webhooks/by/serverAndChannel [get]
// @Success 200 {object} ListDiscordWebhooks "OK"
func (s *Server) GetDiscordWebHooksByServerAndChannel(w http.ResponseWriter, r *http.Request) {
func (s *Handler) GetDiscordWebHooksByServerAndChannel(c echo.Context) error {
p := ListDiscordWebhooks{
ApiStatusModel: ApiStatusModel{
Message: "OK",
@ -112,27 +98,29 @@ func (s *Server) GetDiscordWebHooksByServerAndChannel(w http.ResponseWriter, r *
},
}
query := r.URL.Query()
_server := query["server"][0]
_server := c.QueryParam("server")
if _server == "" {
s.WriteError(w, "ID is missing", http.StatusInternalServerError)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: ErrIdValueMissing,
})
}
_channel := query["channel"][0]
_channel := c.QueryParam("channel")
if _channel == "" {
s.WriteError(w, "Channel is missing", http.StatusInternalServerError)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: fmt.Sprintf("%s channel", ErrParameterMissing),
})
}
res, err := s.dto.GetDiscordWebHookByServerAndChannel(r.Context(), _server, _channel)
res, err := s.dto.GetDiscordWebHookByServerAndChannel(c.Request().Context(), _server, _channel)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
// NewDiscordWebHook
@ -142,25 +130,30 @@ func (s *Server) GetDiscordWebHooksByServerAndChannel(w http.ResponseWriter, r *
// @Param channel query string true "Channel name"
// @Tags Discord, Webhook
// @Router /discord/webhooks/new [post]
func (s *Server) NewDiscordWebHook(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
_url := query["url"][0]
_server := query["server"][0]
_channel := query["channel"][0]
func (s *Handler) NewDiscordWebHook(c echo.Context) error {
_url := c.QueryParam("url")
_server := c.QueryParam("server")
_channel := c.QueryParam("channel")
if _url == "" {
http.Error(w, "url is missing a value", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: "url is missing a value",
})
}
if !strings.Contains(_url, "discord.com/api/webhooks") {
http.Error(w, "invalid url", http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: "invalid url",
})
}
if _server == "" {
http.Error(w, "server is missing", http.StatusBadRequest)
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: "server is missing",
})
}
if _channel == "" {
http.Error(w, "channel is missing", http.StatusBadRequest)
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: "channel is missing",
})
}
params := database.CreateDiscordWebHookParams{
ID: uuid.New(),
@ -169,14 +162,9 @@ func (s *Server) NewDiscordWebHook(w http.ResponseWriter, r *http.Request) {
Channel: _channel,
Enabled: true,
}
s.Db.CreateDiscordWebHook(r.Context(), params)
s.Db.CreateDiscordWebHook(c.Request().Context(), params)
bJson, err := json.Marshal(&params)
if err != nil {
log.Panicln(err)
}
w.Header().Set("Content-Type", "application/json")
w.Write(bJson)
return c.JSON(http.StatusOK, params)
}
// DisableDiscordWebHooks
@ -184,25 +172,28 @@ func (s *Server) NewDiscordWebHook(w http.ResponseWriter, r *http.Request) {
// @Param id path string true "id"
// @Tags Discord, Webhook
// @Router /discord/webhooks/{ID}/disable [post]
func (s *Server) disableDiscordWebHook(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "ID")
func (s *Handler) disableDiscordWebHook(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: err.Error(),
})
}
// Check to make sure we can find the record
_, err = s.Db.GetDiscordWebHooksByID(r.Context(), uuid)
_, err = s.Db.GetDiscordWebHooksByID(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return c.JSON(http.StatusInternalServerError, err.Error())
}
err = s.Db.DisableDiscordWebHook(r.Context(), uuid)
err = s.Db.DisableDiscordWebHook(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
return nil
}
// EnableDiscordWebHook
@ -210,23 +201,26 @@ func (s *Server) disableDiscordWebHook(w http.ResponseWriter, r *http.Request) {
// @Param id path string true "id"
// @Tags Discord, Webhook
// @Router /discord/webhooks/{ID}/enable [post]
func (s *Server) enableDiscordWebHook(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "ID")
func (s *Handler) enableDiscordWebHook(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: err.Error(),
})
}
// Check to make sure we can find the record
_, err = s.Db.GetDiscordWebHooksByID(r.Context(), uuid)
_, err = s.Db.GetDiscordWebHooksByID(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return c.JSON(http.StatusInternalServerError, err.Error())
}
err = s.Db.EnableDiscordWebHook(r.Context(), uuid)
err = s.Db.EnableDiscordWebHook(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return c.JSON(http.StatusInternalServerError, err.Error())
}
return nil
}
// DeleteDiscordWebHook
@ -234,26 +228,28 @@ func (s *Server) enableDiscordWebHook(w http.ResponseWriter, r *http.Request) {
// @Param id path string true "id"
// @Tags Discord, Webhook
// @Router /discord/webhooks/{ID} [delete]
func (s *Server) deleteDiscordWebHook(w http.ResponseWriter, r *http.Request) {
func (s *Handler) deleteDiscordWebHook(c echo.Context) error {
//var item model.Sources = model.Sources{}
id := chi.URLParam(r, "ID")
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return c.JSON(http.StatusBadRequest, err.Error())
}
// Check to make sure we can find the record
_, err = s.Db.GetDiscordQueueByID(r.Context(), uuid)
_, err = s.Db.GetDiscordQueueByID(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return c.JSON(http.StatusInternalServerError, err.Error())
}
// Delete the record
err = s.Db.DeleteDiscordWebHooks(r.Context(), uuid)
err = s.Db.DeleteDiscordWebHooks(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return c.JSON(http.StatusInternalServerError, err.Error())
}
return nil
}
// UpdateDiscordWebHook
@ -261,17 +257,19 @@ func (s *Server) deleteDiscordWebHook(w http.ResponseWriter, r *http.Request) {
// @Param id path string true "id"
// @Tags Discord, Webhook
// @Router /discord/webhooks/{id} [patch]
func (s *Server) UpdateDiscordWebHook(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "ID")
func (s *Handler) UpdateDiscordWebHook(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
log.Panicln(err)
return c.JSON(http.StatusInternalServerError, err.Error())
}
// Check to make sure we can find the record
_, err = s.Db.GetDiscordQueueByID(r.Context(), uuid)
_, err = s.Db.GetDiscordQueueByID(c.Request().Context(), uuid)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return c.JSON(http.StatusInternalServerError, err.Error())
}
return nil
}

View File

@ -0,0 +1,151 @@
package v1
import (
"context"
"database/sql"
"github.com/labstack/echo/v4"
_ "github.com/lib/pq"
swagger "github.com/swaggo/echo-swagger"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/dto"
)
type Handler struct {
Router *echo.Echo
Db *database.Queries
dto *dto.DtoClient
//ctx *context.Context
}
const (
HeaderContentType = "Content-Type"
ApplicationJson = "application/json"
ErrParameterIdMissing = "The requested parameter ID was not found."
ErrParameterMissing = "The requested parameter was found found:"
ErrUnableToParseId = "Unable to parse the requested ID."
ErrRecordMissing = "The requested record was not found"
)
var (
ErrIdValueMissing string = "id value is missing"
ErrValueNotUuid string = "a value given was expected to be a uuid but was not correct."
ErrNoRecordFound string = "no record was found."
ErrUnableToConvertToJson string = "Unable to convert to json"
)
func NewServer(ctx context.Context, db *database.Queries) *Handler {
s := &Handler{
//ctx: &ctx,
Db: db,
dto: dto.NewDtoClient(db),
}
db, err := openDatabase(ctx)
if err != nil {
panic(err)
}
s.Db = db
router := echo.New()
router.GET("/swagger/*", swagger.WrapHandler)
v1 := router.Group("/api/v1")
articles := v1.Group("/articles")
articles.GET("/", s.listArticles)
articles.GET("/:id", s.getArticle)
articles.GET("/:id/details", s.getArticleDetails)
articles.GET("/by/source/:id", s.ListArticlesBySourceId)
dwh := v1.Group("/discord/webhooks")
dwh.GET("/", s.ListDiscordWebHooks)
dwh.POST("/new", s.NewDiscordWebHook)
dwh.GET("/by/serverAndChannel", s.GetDiscordWebHooksByServerAndChannel)
dwh.GET("/:ID", s.GetDiscordWebHooksById)
dwh.DELETE("/:ID", s.deleteDiscordWebHook)
dwh.POST("/:ID/disable", s.disableDiscordWebHook)
dwh.POST("/:ID/enable", s.enableDiscordWebHook)
queue := v1.Group("/queue")
queue.GET("/discord/webhooks", s.ListDiscordWebhookQueue) // TODO this needs to be reworked
settings := v1.Group("/settings")
settings.GET("/", s.getSettings)
sources := v1.Group("/sources")
sources.GET("/", s.listSources)
sources.GET("/by/source", s.listSourcesBySource)
sources.GET("/by/sourceAndName", s.GetSourceBySourceAndName)
sources.POST("/new/reddit", s.newRedditSource)
sources.POST("/new/youtube", s.newYoutubeSource)
sources.POST("/new/twitch", s.newTwitchSource)
sources.GET("/:ID/", s.getSources)
sources.DELETE("/:ID/", s.deleteSources)
sources.POST("/:ID/disable", s.disableSource)
sources.POST("/:ID/enable", s.enableSource)
subs := v1.Group("/subscriptions")
subs.GET("/", s.ListSubscriptions)
subs.GET("/details", s.ListSubscriptionDetails)
subs.GET("/by/discordId", s.GetSubscriptionsByDiscordId)
subs.GET("/by/sourceId", s.GetSubscriptionsBySourceId)
subs.POST("/discord/webhook/new", s.newDiscordWebHookSubscription)
subs.DELETE("/discord/webhook/delete", s.DeleteDiscordWebHookSubscription)
return s
}
func openDatabase(ctx context.Context) (*database.Queries, error) {
_env := services.NewConfig()
connString := _env.GetConfig(services.Sql_Connection_String)
db, err := sql.Open("postgres", connString)
if err != nil {
panic(err)
}
queries := database.New(db)
return queries, err
}
func (s *Handler) MountRoutes() {
//s.Router.Get("/swagger/*", httpSwagger.Handler(
// httpSwagger.URL("doc.json"), //The url pointing to API definition
//))
//s.Router.Get("/api/settings", s.getSettings)
//s.Router.Mount("/api/sources", s.GetSourcesRouter())
//s.Router.Mount("/api/subscriptions", s.GetSubscriptionsRouter())
}
type ApiStatusModel struct {
StatusCode int `json:"status"`
Message string `json:"message"`
}
type ApiError struct {
*ApiStatusModel
}
func (s *Handler) WriteError(c echo.Context, errMessage string, HttpStatusCode int) error {
return c.JSON(HttpStatusCode, domain.ErrorResponse{
Message: errMessage,
})
}
//func (s *Handler) WriteJson(w http.ResponseWriter, model interface{}) {
// w.Header().Set(HeaderContentType, ApplicationJson)
//
// bres, err := json.Marshal(model)
// if err != nil {
// s.WriteError(w, err.Error(), http.StatusInternalServerError)
// return
// }
//
// w.Write(bres)
//}

View File

@ -3,8 +3,9 @@ package v1
import (
"net/http"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/go-chi/chi/v5"
"github.com/labstack/echo/v4"
)
type ListDiscordWebHooksQueueResults struct {
@ -12,21 +13,13 @@ type ListDiscordWebHooksQueueResults struct {
Payload []models.DiscordQueueDetailsDto `json:"payload"`
}
func (s *Server) GetQueueRouter() http.Handler {
r := chi.NewRouter()
r.Get("/discord/webhooks", s.ListDiscordWebhookQueue)
return r
}
// GetDiscordQueue
// @Summary Returns the top 100 entries from the queue to be processed.
// @Produce application/json
// @Tags Queue
// @Router /queue/discord/webhooks [get]
// @Success 200 {object} ListDiscordWebHooksQueueResults "ok"
func (s *Server) ListDiscordWebhookQueue(w http.ResponseWriter, r *http.Request) {
func (s *Handler) ListDiscordWebhookQueue(c echo.Context) error {
p := ListDiscordWebHooksQueueResults{
ApiStatusModel: ApiStatusModel{
Message: "OK",
@ -35,12 +28,13 @@ func (s *Server) ListDiscordWebhookQueue(w http.ResponseWriter, r *http.Request)
}
// Get the raw resp from sql
res, err := s.dto.ListDiscordWebhookQueueDetails(r.Context(), 50)
res, err := s.dto.ListDiscordWebhookQueueDetails(c.Request().Context(), 50)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}

View File

@ -1,127 +0,0 @@
package v1
import (
"context"
"database/sql"
"encoding/json"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
_ "github.com/lib/pq"
httpSwagger "github.com/swaggo/http-swagger"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/dto"
)
type Server struct {
Router *chi.Mux
Db *database.Queries
dto *dto.DtoClient
//ctx *context.Context
}
const (
HeaderContentType = "Content-Type"
ApplicationJson = "application/json"
)
var (
ErrIdValueMissing string = "id value is missing"
ErrValueNotUuid string = "a value given was expected to be a uuid but was not correct."
ErrNoRecordFound string = "no record was found."
ErrUnableToConvertToJson string = "Unable to convert to json"
)
func NewServer(ctx context.Context, db *database.Queries) *Server {
s := &Server{
//ctx: &ctx,
Db: db,
dto: dto.NewDtoClient(db),
}
db, err := openDatabase(ctx)
if err != nil {
panic(err)
}
s.Db = db
s.Router = chi.NewRouter()
s.MountMiddleware()
s.MountRoutes()
return s
}
func openDatabase(ctx context.Context) (*database.Queries, error) {
_env := services.NewConfig()
connString := _env.GetConfig(services.Sql_Connection_String)
db, err := sql.Open("postgres", connString)
if err != nil {
panic(err)
}
queries := database.New(db)
return queries, err
}
func (s *Server) MountMiddleware() {
s.Router.Use(middleware.Logger)
s.Router.Use(middleware.Recoverer)
//s.Router.Use(middleware.Heartbeat())
}
func (s *Server) MountRoutes() {
s.Router.Get("/swagger/*", httpSwagger.Handler(
httpSwagger.URL("doc.json"), //The url pointing to API definition
))
s.Router.Mount("/api/articles", s.GetArticleRouter())
s.Router.Mount("/api/queue", s.GetQueueRouter())
s.Router.Mount("/api/discord/webhooks", s.DiscordWebHookRouter())
//s.Router.Get("/api/settings", s.getSettings)
s.Router.Mount("/api/sources", s.GetSourcesRouter())
s.Router.Mount("/api/subscriptions", s.GetSubscriptionsRouter())
}
type ApiStatusModel struct {
StatusCode int `json:"status"`
Message string `json:"message"`
}
type ApiError struct {
*ApiStatusModel
}
func (s *Server) WriteError(w http.ResponseWriter, errMessage string, HttpStatusCode int) {
w.Header().Set(HeaderContentType, ApplicationJson)
e := ApiError{
ApiStatusModel: &ApiStatusModel{
StatusCode: HttpStatusCode,
Message: errMessage,
},
}
b, err := json.Marshal(e)
if err != nil {
http.Error(w, err.Error(), HttpStatusCode)
}
w.Write(b)
}
func (s *Server) WriteJson(w http.ResponseWriter, model interface{}) {
w.Header().Set(HeaderContentType, ApplicationJson)
bres, err := json.Marshal(model)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write(bres)
}

View File

@ -4,41 +4,36 @@ import (
"encoding/json"
"net/http"
"github.com/go-chi/chi/v5"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
)
func (s *Server) getSettings(w http.ResponseWriter, r *http.Request) {
// GetSettings
// @Summary Returns a object based on the Key that was given.
// @Param key path string true "Settings Key value"
// @Produce application/json
// @Tags Settings
// @Router /settings/{key} [get]
w.Header().Set("Content-Type", "application/json")
//var item model.Sources
id := chi.URLParam(r, "ID")
func (s *Handler) getSettings(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: err.Error(),
})
}
res, err := s.Db.GetSourceByID(r.Context(), uuid)
res, err := s.Db.GetSourceByID(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusNotFound)
return
return c.JSON(http.StatusInternalServerError, err.Error())
}
bResult, err := json.Marshal(res)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, err.Error())
}
w.Write(bResult)
return c.JSON(http.StatusOK, bResult)
}

View File

@ -1,34 +1,24 @@
package v1
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
)
func (s *Server) GetSourcesRouter() http.Handler {
func (s *Handler) GetSourcesRouter() http.Handler {
r := chi.NewRouter()
r.Get("/", s.listSources)
r.Get("/by/source", s.listSourcesBySource)
r.Get("/by/sourceAndName", s.GetSourceBySourceAndName)
r.Post("/new/reddit", s.newRedditSource)
r.Post("/new/youtube", s.newYoutubeSource)
r.Post("/new/twitch", s.newTwitchSource)
r.Route("/{ID}", func(p chi.Router) {
p.Get("/", s.getSources)
p.Delete("/", s.deleteSources)
p.Post("/disable", s.disableSource)
p.Post("/enable", s.enableSource)
})
return r
}
@ -50,7 +40,7 @@ type GetSource struct {
// @Router /sources [get]
// @Success 200 {object} ListSources "ok"
// @Failure 400 {object} ApiError "Unable to reach SQL or Data problems"
func (s *Server) listSources(w http.ResponseWriter, r *http.Request) {
func (s *Handler) listSources(c echo.Context) error {
//TODO Add top?
/*
top := chi.URLParam(r, "top")
@ -69,14 +59,15 @@ func (s *Server) listSources(w http.ResponseWriter, r *http.Request) {
}
// Default way of showing all sources
items, err := s.dto.ListSources(r.Context(), 50)
items, err := s.dto.ListSources(c.Request().Context(), 50)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
p.Payload = items
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
// ListSourcesBySource
@ -88,7 +79,7 @@ func (s *Server) listSources(w http.ResponseWriter, r *http.Request) {
// @Success 200 {object} ListSources "ok"
// @Failure 400 {object} ApiError "Unable to query SQL."
// @Failure 500 {object} ApiError "Problems with data."
func (s *Server) listSourcesBySource(w http.ResponseWriter, r *http.Request) {
func (s *Handler) listSourcesBySource(c echo.Context) error {
//TODO Add top?
/*
top := chi.URLParam(r, "top")
@ -106,17 +97,18 @@ func (s *Server) listSourcesBySource(w http.ResponseWriter, r *http.Request) {
},
}
query := r.URL.Query()
source := c.QueryParam("source")
// Shows the list by Sources.source
res, err := s.dto.ListSourcesBySource(r.Context(), query["source"][0])
res, err := s.dto.ListSourcesBySource(c.Request().Context(), source)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
// GetSource
@ -129,7 +121,7 @@ func (s *Server) listSourcesBySource(w http.ResponseWriter, r *http.Request) {
// @Failure 204 {object} ApiError "No record found."
// @Failure 400 {object} ApiError "Unable to query SQL."
// @Failure 500 {object} ApiError "Failed to process data from SQL."
func (s *Server) getSources(w http.ResponseWriter, r *http.Request) {
func (s *Handler) getSources(c echo.Context) error {
payload := GetSource{
ApiStatusModel: ApiStatusModel{
Message: "OK",
@ -137,20 +129,23 @@ func (s *Server) getSources(w http.ResponseWriter, r *http.Request) {
},
}
uuid, err := uuid.Parse(chi.URLParam(r, "ID"))
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: ErrUnableToParseId,
})
}
res, err := s.dto.GetSourceById(r.Context(), uuid)
res, err := s.dto.GetSourceById(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusNoContent)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: ErrNoRecordFound,
})
}
payload.Payload = res
s.WriteJson(w, payload)
return c.JSON(http.StatusOK, payload)
}
// GetSourceByNameAndSource
@ -164,7 +159,7 @@ func (s *Server) getSources(w http.ResponseWriter, r *http.Request) {
// @Failure 204 {object} ApiError "No record found."
// @Failure 400 {object} ApiError "Unable to query SQL."
// @Failure 500 {object} ApiError "Failed to process data from SQL."
func (s *Server) GetSourceBySourceAndName(w http.ResponseWriter, r *http.Request) {
func (s *Handler) GetSourceBySourceAndName(c echo.Context) error {
p := GetSource{
ApiStatusModel: ApiStatusModel{
Message: "OK",
@ -172,27 +167,33 @@ func (s *Server) GetSourceBySourceAndName(w http.ResponseWriter, r *http.Request
},
}
query := r.URL.Query()
name := query["name"][0]
if name == "" {
s.WriteError(w, "Parameter 'name' was missing in the query.", http.StatusInternalServerError)
return
}
source := query["source"][0]
if source == "" {
s.WriteError(w, "The parameter 'source' was missing in the query.", http.StatusInternalServerError)
return
}
item, err := s.dto.GetSourceByNameAndSource(r.Context(), name, source)
var param domain.GetSourceBySourceAndNameParamRequest
err := c.Bind(&param)
if err != nil {
s.WriteError(w, "Unable to find the requested record.", http.StatusInternalServerError)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: err.Error(),
})
}
//name := c.QueryParam("name")
//if name == "" {
// s.WriteError(w, "Parameter 'name' was missing in the query.", http.StatusInternalServerError)
// return c.JSON(http.bad)
//}
//source := query["source"][0]
//if source == "" {
// s.WriteError(w, "The parameter 'source' was missing in the query.", http.StatusInternalServerError)
// return
//}
item, err := s.dto.GetSourceByNameAndSource(c.Request().Context(), param.Name, param.Source)
if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error())
}
p.Payload = item
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
// NewRedditSource
@ -201,19 +202,28 @@ func (s *Server) GetSourceBySourceAndName(w http.ResponseWriter, r *http.Request
// @Param url query string true "url"
// @Tags Source
// @Router /sources/new/reddit [post]
func (s *Server) newRedditSource(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
_name := query["name"][0]
_url := query["url"][0]
func (s *Handler) newRedditSource(c echo.Context) error {
var param domain.NewSourceParamRequest
err := c.Bind(&param)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: err.Error(),
})
}
//query := r.URL.Query()
//_name := query["name"][0]
//_url := query["url"][0]
//_tags := query["tags"][0]
if _url == "" {
s.WriteError(w, "url is missing a value", http.StatusBadRequest)
return
if param.Url == "" {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: "Url is missing a value",
})
}
if !strings.Contains(_url, "reddit.com") {
s.WriteError(w, "invalid url", http.StatusBadRequest)
return
if !strings.Contains(param.Url, "reddit.com") {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: "Invalid URL given",
})
}
/*
@ -223,32 +233,33 @@ func (s *Server) newRedditSource(w http.ResponseWriter, r *http.Request) {
} else {
}
*/
tags := fmt.Sprintf("twitch, %v", _name)
tags := fmt.Sprintf("twitch, %v", param.Name)
params := database.CreateSourceParams{
ID: uuid.New(),
Site: "reddit",
Name: _name,
Name: param.Name,
Source: "reddit",
Type: "feed",
Enabled: true,
Url: _url,
Url: param.Url,
Tags: tags,
}
err := s.Db.CreateSource(r.Context(), params)
err = s.Db.CreateSource(c.Request().Context(), params)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
//s.WriteJson(w, &params)
bJson, err := json.Marshal(&params)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, err.Error())
}
w.Write(bJson)
return c.JSON(http.StatusOK, bJson)
}
// NewYoutubeSource
@ -257,20 +268,29 @@ func (s *Server) newRedditSource(w http.ResponseWriter, r *http.Request) {
// @Param url query string true "url"
// @Tags Source
// @Router /sources/new/youtube [post]
func (s *Server) newYoutubeSource(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
_name := query["name"][0]
_url := query["url"][0]
//_tags := query["tags"][0]
w.Header().Set("Content-Type", "application/json")
if _url == "" {
s.WriteError(w, "url is missing a value", http.StatusBadRequest)
return
func (s *Handler) newYoutubeSource(c echo.Context) error {
var param domain.NewSourceParamRequest
err := c.Bind(&param)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: err.Error(),
})
}
if !strings.Contains(_url, "youtube.com") {
s.WriteError(w, "invalid url", http.StatusBadRequest)
return
//query := r.URL.Query()
//_name := query["name"][0]
//_url := query["url"][0]
////_tags := query["tags"][0]
if param.Url == "" {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: "url is missing a value",
})
}
if !strings.Contains(param.Url, "youtube.com") {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: "Invalid URL",
})
}
/*
@ -279,31 +299,31 @@ func (s *Server) newYoutubeSource(w http.ResponseWriter, r *http.Request) {
} else {
}
*/
tags := fmt.Sprintf("twitch, %v", _name)
tags := fmt.Sprintf("twitch, %v", param.Name)
params := database.CreateSourceParams{
ID: uuid.New(),
Site: "youtube",
Name: _name,
Name: param.Name,
Source: "youtube",
Type: "feed",
Enabled: true,
Url: _url,
Url: param.Url,
Tags: tags,
}
err := s.Db.CreateSource(r.Context(), params)
err = s.Db.CreateSource(context.Background(), params)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, err.Error())
}
bJson, err := json.Marshal(&params)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
w.Write(bJson)
return c.JSON(http.StatusOK, bJson)
}
// NewTwitchSource
@ -311,38 +331,46 @@ func (s *Server) newYoutubeSource(w http.ResponseWriter, r *http.Request) {
// @Param name query string true "name"
// @Tags Source
// @Router /sources/new/twitch [post]
func (s *Server) newTwitchSource(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
func (s *Handler) newTwitchSource(c echo.Context) error {
var param domain.NewSourceParamRequest
err := c.Bind(&param)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: err.Error(),
})
}
query := r.URL.Query()
_name := query["name"][0]
//query := r.URL.Query()
//_name := query["name"][0]
tags := fmt.Sprintf("twitch, %v", _name)
_url := fmt.Sprintf("https://twitch.tv/%v", _name)
tags := fmt.Sprintf("twitch, %v", param.Name)
_url := fmt.Sprintf("https://twitch.tv/%v", param.Name)
params := database.CreateSourceParams{
ID: uuid.New(),
Site: "twitch",
Name: _name,
Name: param.Name,
Source: "twitch",
Type: "api",
Enabled: true,
Url: _url,
Tags: tags,
}
err := s.Db.CreateSource(r.Context(), params)
err = s.Db.CreateSource(c.Request().Context(), params)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
bJson, err := json.Marshal(&params)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
w.Write(bJson)
return c.JSON(http.StatusOK, bJson)
}
// DeleteSource
@ -350,28 +378,29 @@ func (s *Server) newTwitchSource(w http.ResponseWriter, r *http.Request) {
// @Param id path string true "id"
// @Tags Source
// @Router /sources/{id} [POST]
func (s *Server) deleteSources(w http.ResponseWriter, r *http.Request) {
//var item model.Sources = model.Sources{}
id := chi.URLParam(r, "ID")
func (s *Handler) deleteSources(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: err.Error(),
})
}
// Check to make sure we can find the record
_, err = s.Db.GetSourceByID(r.Context(), uuid)
_, err = s.Db.GetSourceByID(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
// Delete the record
err = s.Db.DeleteSource(r.Context(), uuid)
err = s.Db.DeleteSource(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
p := ApiStatusModel{
@ -381,11 +410,12 @@ func (s *Server) deleteSources(w http.ResponseWriter, r *http.Request) {
b, err := json.Marshal(p)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
w.Write(b)
return c.JSON(http.StatusOK, b)
}
// DisableSource
@ -393,22 +423,28 @@ func (s *Server) deleteSources(w http.ResponseWriter, r *http.Request) {
// @Param id path string true "id"
// @Tags Source
// @Router /sources/{id}/disable [post]
func (s *Server) disableSource(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "ID")
func (s *Handler) disableSource(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
Message: err.Error(),
})
}
// Check to make sure we can find the record
_, err = s.Db.GetSourceByID(r.Context(), uuid)
_, err = s.Db.GetSourceByID(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
err = s.Db.DisableSource(r.Context(), uuid)
err = s.Db.DisableSource(context.Background(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
p := ApiStatusModel{
@ -418,11 +454,12 @@ func (s *Server) disableSource(w http.ResponseWriter, r *http.Request) {
b, err := json.Marshal(p)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
w.Write(b)
return c.JSON(http.StatusOK, b)
}
// EnableSource
@ -430,22 +467,26 @@ func (s *Server) disableSource(w http.ResponseWriter, r *http.Request) {
// @Param id path string true "id"
// @Tags Source
// @Router /sources/{id}/enable [post]
func (s *Server) enableSource(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "ID")
func (s *Handler) enableSource(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return c.JSON(http.StatusBadRequest, err.Error())
}
// Check to make sure we can find the record
_, err = s.Db.GetSourceByID(r.Context(), uuid)
_, err = s.Db.GetSourceByID(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
err = s.Db.EnableSource(r.Context(), uuid)
err = s.Db.EnableSource(c.Request().Context(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
p := ApiStatusModel{
@ -455,9 +496,10 @@ func (s *Server) enableSource(w http.ResponseWriter, r *http.Request) {
b, err := json.Marshal(p)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
}
w.Write(b)
return c.JSON(http.StatusOK, b)
}

View File

@ -7,23 +7,10 @@ import (
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
)
func (s *Server) GetSubscriptionsRouter() http.Handler {
r := chi.NewRouter()
r.Get("/", s.ListSubscriptions)
r.Get("/details", s.ListSubscriptionDetails)
r.Get("/by/discordId", s.GetSubscriptionsByDiscordId)
r.Get("/by/sourceId", s.GetSubscriptionsBySourceId)
r.Post("/discord/webhook/new", s.newDiscordWebHookSubscription)
r.Delete("/discord/webhook/delete", s.DeleteDiscordWebHookSubscription)
return r
}
type ListSubscriptions struct {
ApiStatusModel
Payload []models.SubscriptionDto `json:"payload"`
@ -47,7 +34,7 @@ type ListSubscriptionDetails struct {
// @Success 200 {object} ListSubscriptions "ok"
// @Failure 400 {object} ApiError "Unable to reach SQL."
// @Failure 500 {object} ApiError "Failed to process data from SQL."
func (s *Server) ListSubscriptions(w http.ResponseWriter, r *http.Request) {
func (s *Handler) ListSubscriptions(c echo.Context) error {
payload := ListSubscriptions{
ApiStatusModel: ApiStatusModel{
StatusCode: http.StatusOK,
@ -55,14 +42,13 @@ func (s *Server) ListSubscriptions(w http.ResponseWriter, r *http.Request) {
},
}
res, err := s.dto.ListSubscriptions(r.Context(), 50)
res, err := s.dto.ListSubscriptions(c.Request().Context(), 50)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return s.WriteError(c, err.Error(), http.StatusBadRequest)
}
payload.Payload = res
s.WriteJson(w, payload)
return c.JSON(http.StatusOK, payload)
}
// ListSubscriptionDetails
@ -71,7 +57,7 @@ func (s *Server) ListSubscriptions(w http.ResponseWriter, r *http.Request) {
// @Tags Subscription
// @Router /subscriptions/details [get]
// @Success 200 {object} ListSubscriptionDetails "ok"
func (s *Server) ListSubscriptionDetails(w http.ResponseWriter, r *http.Request) {
func (s *Handler) ListSubscriptionDetails(c echo.Context) error {
payload := ListSubscriptionDetails{
ApiStatusModel: ApiStatusModel{
StatusCode: http.StatusOK,
@ -79,14 +65,13 @@ func (s *Server) ListSubscriptionDetails(w http.ResponseWriter, r *http.Request)
},
}
res, err := s.dto.ListSubscriptionDetails(r.Context(), 50)
res, err := s.dto.ListSubscriptionDetails(c.Request().Context(), 50)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return s.WriteError(c, err.Error(), http.StatusInternalServerError)
}
payload.Payload = res
s.WriteJson(w, payload)
return c.JSON(http.StatusOK, payload)
}
// GetSubscriptionsByDiscordId
@ -98,7 +83,7 @@ func (s *Server) ListSubscriptionDetails(w http.ResponseWriter, r *http.Request)
// @Success 200 {object} ListSubscriptions "ok"
// @Failure 400 {object} ApiError "Unable to reach SQL or Data problems"
// @Failure 500 {object} ApiError "Data problems"
func (s *Server) GetSubscriptionsByDiscordId(w http.ResponseWriter, r *http.Request) {
func (s *Handler) GetSubscriptionsByDiscordId(c echo.Context) error {
p := ListSubscriptions{
ApiStatusModel: ApiStatusModel{
StatusCode: http.StatusOK,
@ -106,26 +91,24 @@ func (s *Server) GetSubscriptionsByDiscordId(w http.ResponseWriter, r *http.Requ
},
}
query := r.URL.Query()
if query["id"][0] == "" {
s.WriteError(w, ErrIdValueMissing, http.StatusBadRequest)
return
id := c.QueryParam("id")
if id == "" {
return s.WriteError(c, ErrIdValueMissing, http.StatusBadRequest)
}
uuid, err := uuid.Parse(query["id"][0])
uuid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, ErrValueNotUuid, http.StatusBadRequest)
return
return s.WriteError(c, ErrValueNotUuid, http.StatusBadRequest)
}
res, err := s.dto.ListSubscriptionsByDiscordWebhookId(r.Context(), uuid)
res, err := s.dto.ListSubscriptionsByDiscordWebhookId(context.Background(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusNoContent)
return
return s.WriteError(c, err.Error(), http.StatusNoContent)
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
// GetSubscriptionsBySourceId
@ -135,7 +118,7 @@ func (s *Server) GetSubscriptionsByDiscordId(w http.ResponseWriter, r *http.Requ
// @Tags Subscription
// @Router /subscriptions/by/SourceId [get]
// @Success 200 {object} ListSubscriptions "ok"
func (s *Server) GetSubscriptionsBySourceId(w http.ResponseWriter, r *http.Request) {
func (s *Handler) GetSubscriptionsBySourceId(c echo.Context) error {
p := ListSubscriptions{
ApiStatusModel: ApiStatusModel{
StatusCode: http.StatusOK,
@ -143,27 +126,23 @@ func (s *Server) GetSubscriptionsBySourceId(w http.ResponseWriter, r *http.Reque
},
}
query := r.URL.Query()
_id := query["id"][0]
_id := c.QueryParam("id")
if _id == "" {
s.WriteError(w, ErrIdValueMissing, http.StatusBadRequest)
return
return s.WriteError(c, ErrIdValueMissing, http.StatusBadRequest)
}
uuid, err := uuid.Parse(_id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return s.WriteError(c, err.Error(), http.StatusBadRequest)
}
res, err := s.dto.ListSubscriptionsBySourceId(r.Context(), uuid)
res, err := s.dto.ListSubscriptionsBySourceId(context.Background(), uuid)
if err != nil {
s.WriteError(w, err.Error(), http.StatusNoContent)
return
return s.WriteError(c, err.Error(), http.StatusNoContent)
}
p.Payload = res
s.WriteJson(w, p)
return c.JSON(http.StatusOK, p)
}
// NewDiscordWebHookSubscription
@ -172,42 +151,36 @@ func (s *Server) GetSubscriptionsBySourceId(w http.ResponseWriter, r *http.Reque
// @Param sourceId query string true "sourceId"
// @Tags Subscription
// @Router /subscriptions/discord/webhook/new [post]
func (s *Server) newDiscordWebHookSubscription(w http.ResponseWriter, r *http.Request) {
func (s *Handler) newDiscordWebHookSubscription(c echo.Context) error {
// Extract the values given
query := r.URL.Query()
discordWebHookId := query["discordWebHookId"][0]
sourceId := query["sourceId"][0]
discordWebHookId := c.QueryParam("discordWebHookId")
sourceId := c.QueryParam("sourceId")
// Check to make we didn't get a null
if discordWebHookId == "" {
s.WriteError(w, "invalid discordWebHooksId given", http.StatusBadRequest)
return
return s.WriteError(c, "invalid discordWebHooksId given", http.StatusBadRequest)
}
if sourceId == "" {
s.WriteError(w, "invalid sourceID given", http.StatusBadRequest)
return
return s.WriteError(c, "invalid sourceID given", http.StatusBadRequest)
}
// Validate they are UUID values
uHook, err := uuid.Parse(discordWebHookId)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return s.WriteError(c, err.Error(), http.StatusBadRequest)
}
uSource, err := uuid.Parse(sourceId)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return s.WriteError(c, err.Error(), http.StatusBadRequest)
}
// Check if the sub already exists
_, err = s.Db.QuerySubscriptions(r.Context(), database.QuerySubscriptionsParams{
_, err = s.Db.QuerySubscriptions(c.Request().Context(), database.QuerySubscriptionsParams{
Discordwebhookid: uHook,
Sourceid: uSource,
})
if err == nil {
s.WriteError(w, "a subscription already exists between these two entities", http.StatusBadRequest)
return
return s.WriteError(c, "a subscription already exists between these two entities", http.StatusBadRequest)
}
// Does not exist, so make it.
@ -216,19 +189,17 @@ func (s *Server) newDiscordWebHookSubscription(w http.ResponseWriter, r *http.Re
Discordwebhookid: uHook,
Sourceid: uSource,
}
err = s.Db.CreateSubscription(r.Context(), params)
err = s.Db.CreateSubscription(context.Background(), params)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return s.WriteError(c, err.Error(), http.StatusInternalServerError)
}
bJson, err := json.Marshal(&params)
if err != nil {
s.WriteError(w, err.Error(), http.StatusInternalServerError)
return
return s.WriteError(c, err.Error(), http.StatusInternalServerError)
}
w.Write(bJson)
return c.JSON(http.StatusOK, bJson)
}
// DeleteDiscordWebHookSubscription
@ -236,25 +207,23 @@ func (s *Server) newDiscordWebHookSubscription(w http.ResponseWriter, r *http.Re
// @Param id query string true "id"
// @Tags Subscription
// @Router /subscriptions/discord/webhook/delete [delete]
func (s *Server) DeleteDiscordWebHookSubscription(w http.ResponseWriter, r *http.Request) {
func (s *Handler) DeleteDiscordWebHookSubscription(c echo.Context) error {
var ErrMissingSubscriptionID string = "the request was missing a 'Id'"
query := r.URL.Query()
id := query["id"][0]
id := c.QueryParam("id")
if id == "" {
s.WriteError(w, ErrMissingSubscriptionID, http.StatusBadRequest)
return
return s.WriteError(c, ErrMissingSubscriptionID, http.StatusBadRequest)
}
uid, err := uuid.Parse(query["id"][0])
uid, err := uuid.Parse(id)
if err != nil {
s.WriteError(w, err.Error(), http.StatusBadRequest)
return
return s.WriteError(c, err.Error(), http.StatusBadRequest)
}
err = s.Db.DeleteSubscription(context.Background(), uid)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
return s.WriteError(c, err.Error(), http.StatusInternalServerError)
}
return c.JSON(http.StatusOK, nil)
}