Compare commits

...

7 Commits

27 changed files with 279 additions and 699 deletions

6
api.http Normal file
View File

@ -0,0 +1,6 @@
### Select Sources fro mthe top
GET http://localhost:8081/api/v1/sources/
### Select Sources by type
GET http://localhost:8081/api/v1/sources/by/source?source=rss

View File

@ -4,13 +4,11 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
"net/http"
_ "github.com/glebarez/go-sqlite" _ "github.com/glebarez/go-sqlite"
"github.com/pressly/goose/v3" "github.com/pressly/goose/v3"
"git.jamestombleson.com/jtom38/newsbot-api/docs" "git.jamestombleson.com/jtom38/newsbot-api/docs"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
v1 "git.jamestombleson.com/jtom38/newsbot-api/internal/handler/v1" v1 "git.jamestombleson.com/jtom38/newsbot-api/internal/handler/v1"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services" "git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/cron" "git.jamestombleson.com/jtom38/newsbot-api/internal/services/cron"
@ -42,19 +40,14 @@ func main() {
panic(err) panic(err)
} }
queries := database.New(db)
c := cron.NewScheduler(ctx, db) c := cron.NewScheduler(ctx, db)
c.Start() c.Start()
server := v1.NewServer(ctx, queries, configs, db) server := v1.NewServer(ctx, configs, db)
fmt.Println("API is online and waiting for requests.") fmt.Println("API is online and waiting for requests.")
fmt.Printf("API: http://%v:8081/api\r\n", configs.ServerAddress) fmt.Printf("API: http://%v:8081/api\r\n", configs.ServerAddress)
fmt.Printf("Swagger: http://%v:8081/swagger/index.html\r\n", configs.ServerAddress) fmt.Printf("Swagger: http://%v:8081/swagger/index.html\r\n", configs.ServerAddress)
err = http.ListenAndServe(":8081", server.Router) server.Router.Start(":8081")
if err != nil {
panic(err)
}
} }

View File

@ -16,7 +16,7 @@ const docTemplate = `{
"host": "{{.Host}}", "host": "{{.Host}}",
"basePath": "{{.BasePath}}", "basePath": "{{.BasePath}}",
"paths": { "paths": {
"/articles": { "/v1/articles": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -55,7 +55,7 @@ const docTemplate = `{
} }
} }
}, },
"/articles/by/sourceid": { "/v1/articles/by/sourceid": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -101,7 +101,7 @@ const docTemplate = `{
} }
} }
}, },
"/articles/{ID}": { "/v1/articles/{ID}": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -141,7 +141,7 @@ const docTemplate = `{
} }
} }
}, },
"/articles/{ID}/details": { "/v1/articles/{ID}/details": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -181,14 +181,13 @@ const docTemplate = `{
} }
} }
}, },
"/discord/webhooks": { "/v1/discord/webhooks": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
], ],
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Returns the top 100", "summary": "Returns the top 100",
"responses": { "responses": {
@ -213,14 +212,13 @@ const docTemplate = `{
} }
} }
}, },
"/discord/webhooks/by/serverAndChannel": { "/v1/discord/webhooks/by/serverAndChannel": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
], ],
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Returns all the known web hooks based on the Server and Channel given.", "summary": "Returns all the known web hooks based on the Server and Channel given.",
"parameters": [ "parameters": [
@ -261,11 +259,10 @@ const docTemplate = `{
} }
} }
}, },
"/discord/webhooks/new": { "/v1/discord/webhooks/new": {
"post": { "post": {
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Creates a new record for a discord web hook to post data to.", "summary": "Creates a new record for a discord web hook to post data to.",
"parameters": [ "parameters": [
@ -313,11 +310,10 @@ const docTemplate = `{
} }
} }
}, },
"/discord/webhooks/{ID}": { "/v1/discord/webhooks/{ID}": {
"delete": { "delete": {
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Deletes a record by ID.", "summary": "Deletes a record by ID.",
"parameters": [ "parameters": [
@ -351,11 +347,10 @@ const docTemplate = `{
} }
} }
}, },
"/discord/webhooks/{ID}/disable": { "/v1/discord/webhooks/{ID}/disable": {
"post": { "post": {
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Disables a Webhook from being used.", "summary": "Disables a Webhook from being used.",
"parameters": [ "parameters": [
@ -389,11 +384,10 @@ const docTemplate = `{
} }
} }
}, },
"/discord/webhooks/{ID}/enable": { "/v1/discord/webhooks/{ID}/enable": {
"post": { "post": {
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Enables a source to continue processing.", "summary": "Enables a source to continue processing.",
"parameters": [ "parameters": [
@ -408,14 +402,13 @@ const docTemplate = `{
"responses": {} "responses": {}
} }
}, },
"/discord/webhooks/{id}": { "/v1/discord/webhooks/{id}": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
], ],
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Returns the top 100 entries from the queue to be processed.", "summary": "Returns the top 100 entries from the queue to be processed.",
"parameters": [ "parameters": [
@ -449,7 +442,7 @@ const docTemplate = `{
} }
} }
}, },
"/queue/discord/webhooks": { "/v1/queue/discord/webhooks": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -468,7 +461,7 @@ const docTemplate = `{
} }
} }
}, },
"/settings/{key}": { "/v1/settings/{key}": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -489,7 +482,7 @@ const docTemplate = `{
"responses": {} "responses": {}
} }
}, },
"/sources": { "/v1/sources": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -522,7 +515,7 @@ const docTemplate = `{
} }
} }
}, },
"/sources/by/source": { "/v1/sources/by/source": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -568,7 +561,7 @@ const docTemplate = `{
} }
} }
}, },
"/sources/by/sourceAndName": { "/v1/sources/by/sourceAndName": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -615,7 +608,7 @@ const docTemplate = `{
} }
} }
}, },
"/sources/new/reddit": { "/v1/sources/new/reddit": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -659,7 +652,7 @@ const docTemplate = `{
} }
} }
}, },
"/sources/new/rss": { "/v1/sources/new/rss": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -703,7 +696,7 @@ const docTemplate = `{
} }
} }
}, },
"/sources/new/twitch": { "/v1/sources/new/twitch": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -721,7 +714,7 @@ const docTemplate = `{
"responses": {} "responses": {}
} }
}, },
"/sources/new/youtube": { "/v1/sources/new/youtube": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -746,7 +739,7 @@ const docTemplate = `{
"responses": {} "responses": {}
} }
}, },
"/sources/{id}": { "/v1/sources/{id}": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -802,7 +795,7 @@ const docTemplate = `{
"responses": {} "responses": {}
} }
}, },
"/sources/{id}/disable": { "/v1/sources/{id}/disable": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -839,7 +832,7 @@ const docTemplate = `{
} }
} }
}, },
"/sources/{id}/enable": { "/v1/sources/{id}/enable": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -876,7 +869,7 @@ const docTemplate = `{
} }
} }
}, },
"/subscriptions": { "/v1/subscriptions": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -907,7 +900,7 @@ const docTemplate = `{
} }
} }
}, },
"/subscriptions/by/SourceId": { "/v1/subscriptions/by/SourceId": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -935,7 +928,7 @@ const docTemplate = `{
} }
} }
}, },
"/subscriptions/by/discordId": { "/v1/subscriptions/by/discordId": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -975,7 +968,7 @@ const docTemplate = `{
} }
} }
}, },
"/subscriptions/details": { "/v1/subscriptions/details": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -994,7 +987,7 @@ const docTemplate = `{
} }
} }
}, },
"/subscriptions/discord/webhook/delete": { "/v1/subscriptions/discord/webhook/delete": {
"delete": { "delete": {
"tags": [ "tags": [
"Subscription" "Subscription"
@ -1012,7 +1005,7 @@ const docTemplate = `{
"responses": {} "responses": {}
} }
}, },
"/subscriptions/discord/webhook/new": { "/v1/subscriptions/discord/webhook/new": {
"post": { "post": {
"tags": [ "tags": [
"Subscription" "Subscription"

View File

@ -7,7 +7,7 @@
}, },
"basePath": "/api", "basePath": "/api",
"paths": { "paths": {
"/articles": { "/v1/articles": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -46,7 +46,7 @@
} }
} }
}, },
"/articles/by/sourceid": { "/v1/articles/by/sourceid": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -92,7 +92,7 @@
} }
} }
}, },
"/articles/{ID}": { "/v1/articles/{ID}": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -132,7 +132,7 @@
} }
} }
}, },
"/articles/{ID}/details": { "/v1/articles/{ID}/details": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -172,14 +172,13 @@
} }
} }
}, },
"/discord/webhooks": { "/v1/discord/webhooks": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
], ],
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Returns the top 100", "summary": "Returns the top 100",
"responses": { "responses": {
@ -204,14 +203,13 @@
} }
} }
}, },
"/discord/webhooks/by/serverAndChannel": { "/v1/discord/webhooks/by/serverAndChannel": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
], ],
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Returns all the known web hooks based on the Server and Channel given.", "summary": "Returns all the known web hooks based on the Server and Channel given.",
"parameters": [ "parameters": [
@ -252,11 +250,10 @@
} }
} }
}, },
"/discord/webhooks/new": { "/v1/discord/webhooks/new": {
"post": { "post": {
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Creates a new record for a discord web hook to post data to.", "summary": "Creates a new record for a discord web hook to post data to.",
"parameters": [ "parameters": [
@ -304,11 +301,10 @@
} }
} }
}, },
"/discord/webhooks/{ID}": { "/v1/discord/webhooks/{ID}": {
"delete": { "delete": {
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Deletes a record by ID.", "summary": "Deletes a record by ID.",
"parameters": [ "parameters": [
@ -342,11 +338,10 @@
} }
} }
}, },
"/discord/webhooks/{ID}/disable": { "/v1/discord/webhooks/{ID}/disable": {
"post": { "post": {
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Disables a Webhook from being used.", "summary": "Disables a Webhook from being used.",
"parameters": [ "parameters": [
@ -380,11 +375,10 @@
} }
} }
}, },
"/discord/webhooks/{ID}/enable": { "/v1/discord/webhooks/{ID}/enable": {
"post": { "post": {
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Enables a source to continue processing.", "summary": "Enables a source to continue processing.",
"parameters": [ "parameters": [
@ -399,14 +393,13 @@
"responses": {} "responses": {}
} }
}, },
"/discord/webhooks/{id}": { "/v1/discord/webhooks/{id}": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
], ],
"tags": [ "tags": [
"Discord", "DiscordWebhook"
"Webhook"
], ],
"summary": "Returns the top 100 entries from the queue to be processed.", "summary": "Returns the top 100 entries from the queue to be processed.",
"parameters": [ "parameters": [
@ -440,7 +433,7 @@
} }
} }
}, },
"/queue/discord/webhooks": { "/v1/queue/discord/webhooks": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -459,7 +452,7 @@
} }
} }
}, },
"/settings/{key}": { "/v1/settings/{key}": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -480,7 +473,7 @@
"responses": {} "responses": {}
} }
}, },
"/sources": { "/v1/sources": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -513,7 +506,7 @@
} }
} }
}, },
"/sources/by/source": { "/v1/sources/by/source": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -559,7 +552,7 @@
} }
} }
}, },
"/sources/by/sourceAndName": { "/v1/sources/by/sourceAndName": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -606,7 +599,7 @@
} }
} }
}, },
"/sources/new/reddit": { "/v1/sources/new/reddit": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -650,7 +643,7 @@
} }
} }
}, },
"/sources/new/rss": { "/v1/sources/new/rss": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -694,7 +687,7 @@
} }
} }
}, },
"/sources/new/twitch": { "/v1/sources/new/twitch": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -712,7 +705,7 @@
"responses": {} "responses": {}
} }
}, },
"/sources/new/youtube": { "/v1/sources/new/youtube": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -737,7 +730,7 @@
"responses": {} "responses": {}
} }
}, },
"/sources/{id}": { "/v1/sources/{id}": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -793,7 +786,7 @@
"responses": {} "responses": {}
} }
}, },
"/sources/{id}/disable": { "/v1/sources/{id}/disable": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -830,7 +823,7 @@
} }
} }
}, },
"/sources/{id}/enable": { "/v1/sources/{id}/enable": {
"post": { "post": {
"tags": [ "tags": [
"Source" "Source"
@ -867,7 +860,7 @@
} }
} }
}, },
"/subscriptions": { "/v1/subscriptions": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -898,7 +891,7 @@
} }
} }
}, },
"/subscriptions/by/SourceId": { "/v1/subscriptions/by/SourceId": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -926,7 +919,7 @@
} }
} }
}, },
"/subscriptions/by/discordId": { "/v1/subscriptions/by/discordId": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -966,7 +959,7 @@
} }
} }
}, },
"/subscriptions/details": { "/v1/subscriptions/details": {
"get": { "get": {
"produces": [ "produces": [
"application/json" "application/json"
@ -985,7 +978,7 @@
} }
} }
}, },
"/subscriptions/discord/webhook/delete": { "/v1/subscriptions/discord/webhook/delete": {
"delete": { "delete": {
"tags": [ "tags": [
"Subscription" "Subscription"
@ -1003,7 +996,7 @@
"responses": {} "responses": {}
} }
}, },
"/subscriptions/discord/webhook/new": { "/v1/subscriptions/discord/webhook/new": {
"post": { "post": {
"tags": [ "tags": [
"Subscription" "Subscription"

View File

@ -241,7 +241,7 @@ info:
title: NewsBot collector title: NewsBot collector
version: "0.1" version: "0.1"
paths: paths:
/articles: /v1/articles:
get: get:
parameters: parameters:
- description: page number - description: page number
@ -266,7 +266,7 @@ paths:
summary: Lists the top 25 records ordering from newest to oldest. summary: Lists the top 25 records ordering from newest to oldest.
tags: tags:
- Articles - Articles
/articles/{ID}: /v1/articles/{ID}:
get: get:
parameters: parameters:
- description: int - description: int
@ -292,7 +292,7 @@ paths:
summary: Returns an article based on defined ID. summary: Returns an article based on defined ID.
tags: tags:
- Articles - Articles
/articles/{ID}/details: /v1/articles/{ID}/details:
get: get:
parameters: parameters:
- description: int - description: int
@ -318,7 +318,7 @@ paths:
summary: Returns an article and source based on defined ID. summary: Returns an article and source based on defined ID.
tags: tags:
- Articles - Articles
/articles/by/sourceid: /v1/articles/by/sourceid:
get: get:
parameters: parameters:
- description: source id - description: source id
@ -349,7 +349,7 @@ paths:
25. 25.
tags: tags:
- Articles - Articles
/discord/webhooks: /v1/discord/webhooks:
get: get:
produces: produces:
- application/json - application/json
@ -368,9 +368,8 @@ paths:
$ref: '#/definitions/domain.BaseResponse' $ref: '#/definitions/domain.BaseResponse'
summary: Returns the top 100 summary: Returns the top 100
tags: tags:
- Discord - DiscordWebhook
- Webhook /v1/discord/webhooks/{ID}:
/discord/webhooks/{ID}:
delete: delete:
parameters: parameters:
- description: id - description: id
@ -393,9 +392,8 @@ paths:
$ref: '#/definitions/domain.BaseResponse' $ref: '#/definitions/domain.BaseResponse'
summary: Deletes a record by ID. summary: Deletes a record by ID.
tags: tags:
- Discord - DiscordWebhook
- Webhook /v1/discord/webhooks/{ID}/disable:
/discord/webhooks/{ID}/disable:
post: post:
parameters: parameters:
- description: id - description: id
@ -418,9 +416,8 @@ paths:
$ref: '#/definitions/domain.BaseResponse' $ref: '#/definitions/domain.BaseResponse'
summary: Disables a Webhook from being used. summary: Disables a Webhook from being used.
tags: tags:
- Discord - DiscordWebhook
- Webhook /v1/discord/webhooks/{ID}/enable:
/discord/webhooks/{ID}/enable:
post: post:
parameters: parameters:
- description: id - description: id
@ -431,9 +428,8 @@ paths:
responses: {} responses: {}
summary: Enables a source to continue processing. summary: Enables a source to continue processing.
tags: tags:
- Discord - DiscordWebhook
- Webhook /v1/discord/webhooks/{id}:
/discord/webhooks/{id}:
get: get:
parameters: parameters:
- description: id - description: id
@ -458,9 +454,8 @@ paths:
$ref: '#/definitions/domain.BaseResponse' $ref: '#/definitions/domain.BaseResponse'
summary: Returns the top 100 entries from the queue to be processed. summary: Returns the top 100 entries from the queue to be processed.
tags: tags:
- Discord - DiscordWebhook
- Webhook /v1/discord/webhooks/by/serverAndChannel:
/discord/webhooks/by/serverAndChannel:
get: get:
parameters: parameters:
- description: Fancy Server - description: Fancy Server
@ -490,9 +485,8 @@ paths:
$ref: '#/definitions/domain.BaseResponse' $ref: '#/definitions/domain.BaseResponse'
summary: Returns all the known web hooks based on the Server and Channel given. summary: Returns all the known web hooks based on the Server and Channel given.
tags: tags:
- Discord - DiscordWebhook
- Webhook /v1/discord/webhooks/new:
/discord/webhooks/new:
post: post:
parameters: parameters:
- description: url - description: url
@ -525,9 +519,8 @@ paths:
$ref: '#/definitions/domain.BaseResponse' $ref: '#/definitions/domain.BaseResponse'
summary: Creates a new record for a discord web hook to post data to. summary: Creates a new record for a discord web hook to post data to.
tags: tags:
- Discord - DiscordWebhook
- Webhook /v1/queue/discord/webhooks:
/queue/discord/webhooks:
get: get:
produces: produces:
- application/json - application/json
@ -539,7 +532,7 @@ paths:
summary: Returns the top 100 entries from the queue to be processed. summary: Returns the top 100 entries from the queue to be processed.
tags: tags:
- Queue - Queue
/settings/{key}: /v1/settings/{key}:
get: get:
parameters: parameters:
- description: Settings Key value - description: Settings Key value
@ -553,7 +546,7 @@ paths:
summary: Returns a object based on the Key that was given. summary: Returns a object based on the Key that was given.
tags: tags:
- Settings - Settings
/sources: /v1/sources:
get: get:
parameters: parameters:
- description: page number - description: page number
@ -574,7 +567,7 @@ paths:
summary: Lists the top 50 records summary: Lists the top 50 records
tags: tags:
- Source - Source
/sources/{id}: /v1/sources/{id}:
get: get:
parameters: parameters:
- description: uuid - description: uuid
@ -611,7 +604,7 @@ paths:
summary: Marks a source as deleted based on its ID value. summary: Marks a source as deleted based on its ID value.
tags: tags:
- Source - Source
/sources/{id}/disable: /v1/sources/{id}/disable:
post: post:
parameters: parameters:
- description: id - description: id
@ -635,7 +628,7 @@ paths:
summary: Disables a source from processing. summary: Disables a source from processing.
tags: tags:
- Source - Source
/sources/{id}/enable: /v1/sources/{id}/enable:
post: post:
parameters: parameters:
- description: id - description: id
@ -659,7 +652,7 @@ paths:
summary: Enables a source to continue processing. summary: Enables a source to continue processing.
tags: tags:
- Source - Source
/sources/by/source: /v1/sources/by/source:
get: get:
parameters: parameters:
- description: Source Name - description: Source Name
@ -689,7 +682,7 @@ paths:
summary: 'Lists the top 50 records based on the name given. Example: reddit' summary: 'Lists the top 50 records based on the name given. Example: reddit'
tags: tags:
- Source - Source
/sources/by/sourceAndName: /v1/sources/by/sourceAndName:
get: get:
parameters: parameters:
- description: dadjokes - description: dadjokes
@ -720,7 +713,7 @@ paths:
summary: Returns a single entity by ID summary: Returns a single entity by ID
tags: tags:
- Source - Source
/sources/new/reddit: /v1/sources/new/reddit:
post: post:
parameters: parameters:
- description: name - description: name
@ -749,7 +742,7 @@ paths:
summary: Creates a new reddit source to monitor. summary: Creates a new reddit source to monitor.
tags: tags:
- Source - Source
/sources/new/rss: /v1/sources/new/rss:
post: post:
parameters: parameters:
- description: Site Name - description: Site Name
@ -778,7 +771,7 @@ paths:
summary: Creates a new rss source to monitor. summary: Creates a new rss source to monitor.
tags: tags:
- Source - Source
/sources/new/twitch: /v1/sources/new/twitch:
post: post:
parameters: parameters:
- description: name - description: name
@ -790,7 +783,7 @@ paths:
summary: Creates a new twitch source to monitor. summary: Creates a new twitch source to monitor.
tags: tags:
- Source - Source
/sources/new/youtube: /v1/sources/new/youtube:
post: post:
parameters: parameters:
- description: name - description: name
@ -807,7 +800,7 @@ paths:
summary: Creates a new youtube source to monitor. summary: Creates a new youtube source to monitor.
tags: tags:
- Source - Source
/subscriptions: /v1/subscriptions:
get: get:
produces: produces:
- application/json - application/json
@ -827,7 +820,7 @@ paths:
summary: Returns the top 100 entries from the queue to be processed. summary: Returns the top 100 entries from the queue to be processed.
tags: tags:
- Subscription - Subscription
/subscriptions/by/SourceId: /v1/subscriptions/by/SourceId:
get: get:
parameters: parameters:
- description: id - description: id
@ -845,7 +838,7 @@ paths:
summary: Returns the top 100 entries from the queue to be processed. summary: Returns the top 100 entries from the queue to be processed.
tags: tags:
- Subscription - Subscription
/subscriptions/by/discordId: /v1/subscriptions/by/discordId:
get: get:
parameters: parameters:
- description: id - description: id
@ -871,7 +864,7 @@ paths:
summary: Returns the top 100 entries from the queue to be processed. summary: Returns the top 100 entries from the queue to be processed.
tags: tags:
- Subscription - Subscription
/subscriptions/details: /v1/subscriptions/details:
get: get:
produces: produces:
- application/json - application/json
@ -883,7 +876,7 @@ paths:
summary: Returns the top 50 entries with full deatils on the source and output. summary: Returns the top 50 entries with full deatils on the source and output.
tags: tags:
- Subscription - Subscription
/subscriptions/discord/webhook/delete: /v1/subscriptions/discord/webhook/delete:
delete: delete:
parameters: parameters:
- description: id - description: id
@ -895,7 +888,7 @@ paths:
summary: Removes a Discord WebHook Subscription based on the Subscription ID. summary: Removes a Discord WebHook Subscription based on the Subscription ID.
tags: tags:
- Subscription - Subscription
/subscriptions/discord/webhook/new: /v1/subscriptions/discord/webhook/new:
post: post:
parameters: parameters:
- description: discordWebHookId - description: discordWebHookId

2
go.mod
View File

@ -22,6 +22,7 @@ require (
require ( require (
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ghodss/yaml v1.0.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/huandu/xstrings v1.3.2 // indirect github.com/huandu/xstrings v1.3.2 // indirect
github.com/labstack/gommon v0.4.2 // indirect github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
@ -35,6 +36,7 @@ require (
github.com/valyala/fasttemplate v1.2.2 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/sync v0.7.0 // indirect golang.org/x/sync v0.7.0 // indirect
golang.org/x/time v0.5.0 // indirect
modernc.org/libc v1.41.0 // indirect modernc.org/libc v1.41.0 // indirect
modernc.org/mathutil v1.6.0 // indirect modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.2 // indirect modernc.org/memory v1.7.2 // indirect

4
go.sum
View File

@ -31,6 +31,8 @@ github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrK
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-rod/rod v0.107.1 h1:wRxTTAXJ0JUnoSGcyGAOubpdrToWIKPCnLu3av8EDFY= github.com/go-rod/rod v0.107.1 h1:wRxTTAXJ0JUnoSGcyGAOubpdrToWIKPCnLu3av8EDFY=
github.com/go-rod/rod v0.107.1/go.mod h1:Au6ufsz7KyXUJVnw6Ljs1nFpsopy+9AJ/lBwGauYBVg= github.com/go-rod/rod v0.107.1/go.mod h1:Au6ufsz7KyXUJVnw6Ljs1nFpsopy+9AJ/lBwGauYBVg=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -161,6 +163,8 @@ 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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 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/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=

View File

@ -12,8 +12,6 @@ CREATE TABLE Articles (
Url TEXT NOT NULL, Url TEXT NOT NULL,
PubDate DATETIME NOT NULL, PubDate DATETIME NOT NULL,
IsVideo TEXT NOT NULL, IsVideo TEXT NOT NULL,
--VideoHeight int NOT NULL,
--VideoWidth int NOT NULL,
ThumbnailUrl TEXT NOT NULL, ThumbnailUrl TEXT NOT NULL,
Description TEXT NOT NULL, Description TEXT NOT NULL,
AuthorName TEXT NOT NULL, AuthorName TEXT NOT NULL,
@ -34,6 +32,7 @@ CREATE Table DiscordWebHooks (
CreatedAt DATETIME NOT NULL, CreatedAt DATETIME NOT NULL,
UpdatedAt DATETIME NOT NULL, UpdatedAt DATETIME NOT NULL,
DeletedAt DATETIME NOT NULL, DeletedAt DATETIME NOT NULL,
UserID INTEGER NOT NULL,
--Name TEXT NOT NULL, -- Defines webhook purpose --Name TEXT NOT NULL, -- Defines webhook purpose
--Key TEXT, --Key TEXT,
Url TEXT NOT NULL, -- Webhook Url Url TEXT NOT NULL, -- Webhook Url
@ -78,8 +77,9 @@ CREATE TABLE Subscriptions (
CreatedAt DATETIME NOT NULL, CreatedAt DATETIME NOT NULL,
UpdatedAt DATETIME NOT NULL, UpdatedAt DATETIME NOT NULL,
DeletedAt DATETIME, DeletedAt DATETIME,
DiscordWebHookId NUMBER NOT NULL, DiscordWebHookID NUMBER NOT NULL,
SourceId NUMBER NOT NULL SourceID NUMBER NOT NULL,
UserID NUMBER NOT NULL
); );
CREATE TABLE Users ( CREATE TABLE Users (

View File

@ -7,33 +7,33 @@ SELECT 'up SQL query';
-- Final Fantasy XIV Entries -- Final Fantasy XIV Entries
INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES
("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'ffxiv', 'Final Fantasy XIV - NA', TRUE, 'https://na.finalfantasyxiv.com/lodestone/', 'ffxiv, final, fantasy, xiv, na, lodestone'); ("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'Final Fantasy XIV - NA', 'ffxiv', TRUE, 'https://na.finalfantasyxiv.com/lodestone/', 'ffxiv, final, fantasy, xiv, na, lodestone');
INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES
("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'ffxiv', 'Final Fantasy XIV - JP', FALSE, 'https://jp.finalfantasyxiv.com/lodestone/', 'ffxiv, final, fantasy, xiv, jp, lodestone'); ("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'Final Fantasy XIV - JP', 'ffxiv', FALSE, 'https://jp.finalfantasyxiv.com/lodestone/', 'ffxiv, final, fantasy, xiv, jp, lodestone');
INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES
("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'ffxiv', 'Final Fantasy XIV - EU', FALSE, 'https://eu.finalfantasyxiv.com/lodestone/', 'ffxiv, final, fantasy, xiv, eu, lodestone'); ("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'Final Fantasy XIV - EU', 'ffxiv', FALSE, 'https://eu.finalfantasyxiv.com/lodestone/', 'ffxiv, final, fantasy, xiv, eu, lodestone');
INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES
("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'ffxiv', 'Final Fantasy XIV - FR', FALSE, 'https://fr.finalfantasyxiv.com/lodestone/', 'ffxiv, final, fantasy, xiv, fr, lodestone'); ("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'Final Fantasy XIV - FR', 'ffxiv', FALSE, 'https://fr.finalfantasyxiv.com/lodestone/', 'ffxiv, final, fantasy, xiv, fr, lodestone');
INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES
("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'ffxiv', 'Final Fantasy XIV - DE', FALSE, 'https://de.finalfantasyxiv.com/lodestone/', 'ffxiv, final, fantasy, xiv, de, lodestone'); ("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'Final Fantasy XIV - DE', 'ffxiv', FALSE, 'https://de.finalfantasyxiv.com/lodestone/', 'ffxiv, final, fantasy, xiv, de, lodestone');
-- Reddit Entries -- Reddit Entries
INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES
("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'reddit', 'dadjokes', TRUE, 'https://reddit.com/r/dadjokes', 'reddit, dadjokes'); ("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'dadjokes', 'reddit', TRUE, 'https://reddit.com/r/dadjokes', 'reddit, dadjokes');
INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES
("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'reddit', 'steamdeck', TRUE, 'https://reddit.com/r/steamdeck', 'reddit, steam deck, steam, deck'); ("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'steamdeck', 'reddit', TRUE, 'https://reddit.com/r/steamdeck', 'reddit, steam deck, steam, deck');
-- Youtube Entries -- Youtube Entries
INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES
("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'youtube', 'Game Grumps', TRUE, 'https://www.youtube.com/user/GameGrumps', 'youtube, game grumps, game, grumps'); ("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'Game Grumps', 'youtube', TRUE, 'https://www.youtube.com/user/GameGrumps', 'youtube, game grumps, game, grumps');
-- RSS Entries -- RSS Entries
INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES
("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'steampowered', 'steam deck', TRUE, 'https://store.steampowered.com/feeds/news/app/1675200/?cc=US&l=english&snr=1_2108_9__2107', 'rss, steampowered, steam, deck, steam deck'); ("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'steampowered - steam deck', 'rss', TRUE, 'https://store.steampowered.com/feeds/news/app/1675200/?cc=US&l=english&snr=1_2108_9__2107', 'rss, steampowered, steam, deck, steam deck');
-- Twitch Entries -- Twitch Entries
INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabled, Url, Tags) VALUES
("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'twitch', 'Nintendo', TRUE, 'https://twitch.tv/nintendo', 'twitch, nintendo'); ("2024-04-25 18:37:43.852367", "2024-04-25 18:37:43.852367", "0001-01-01 00:00:00", 'Nintendo', 'twitch', TRUE, 'https://twitch.tv/nintendo', 'twitch, nintendo');
-- +goose StatementEnd -- +goose StatementEnd
@ -41,10 +41,10 @@ INSERT INTO sources (CreatedAt, UpdatedAt, DeletedAt, DisplayName, Source, Enabl
-- +goose StatementBegin -- +goose StatementBegin
--SELECT 'down SQL query'; --SELECT 'down SQL query';
DELETE FROM sources where source = 'reddit' and name = 'dadjokes'; DELETE FROM sources where Source = 'reddit' and DisplayName = 'dadjokes';
DELETE FROM sources where source = 'reddit' and name = 'steamdeck'; DELETE FROM sources where Source = 'reddit' and DisplayName = 'steamdeck';
DELETE FROM sources where source = 'ffxiv'; DELETE FROM sources where Source = 'ffxiv';
DELETE FROM sources WHERE source = 'twitch' and name = 'Nintendo'; DELETE FROM sources WHERE Source = 'twitch' and DisplayName = 'Nintendo';
DELETE FROM sources WHERE source = 'youtube' and name = 'Game Grumps'; DELETE FROM sources WHERE Source = 'youtube' and DisplayName = 'Game Grumps';
DELETE FROM SOURCES WHERE source = 'rss' and name = 'steam deck'; DELETE FROM SOURCES WHERE Source = 'rss' and DisplayName = 'steampowered - steam deck';
-- +goose StatementEnd -- +goose StatementEnd

View File

@ -14,7 +14,7 @@ import (
// @Produce application/json // @Produce application/json
// @Param page query string false "page number" // @Param page query string false "page number"
// @Tags Articles // @Tags Articles
// @Router /articles [get] // @Router /v1/articles [get]
// @Success 200 {object} domain.ArticleResponse // @Success 200 {object} domain.ArticleResponse
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -44,7 +44,7 @@ func (s *Handler) listArticles(c echo.Context) error {
// @Param ID path string true "int" // @Param ID path string true "int"
// @Produce application/json // @Produce application/json
// @Tags Articles // @Tags Articles
// @Router /articles/{ID} [get] // @Router /v1/articles/{ID} [get]
// @Success 200 {object} domain.ArticleResponse "OK" // @Success 200 {object} domain.ArticleResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -78,7 +78,7 @@ func (s *Handler) getArticle(c echo.Context) error {
// @Param ID path string true "int" // @Param ID path string true "int"
// @Produce application/json // @Produce application/json
// @Tags Articles // @Tags Articles
// @Router /articles/{ID}/details [get] // @Router /v1/articles/{ID}/details [get]
// @Success 200 {object} domain.ArticleDetailedResponse "OK" // @Success 200 {object} domain.ArticleDetailedResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -119,7 +119,7 @@ func (s *Handler) getArticleDetails(c echo.Context) error {
// @Param page query int false "Page to query" // @Param page query int false "Page to query"
// @Produce application/json // @Produce application/json
// @Tags Articles // @Tags Articles
// @Router /articles/by/sourceid [get] // @Router /v1/articles/by/sourceid [get]
// @Success 200 {object} domain.ArticleResponse "OK" // @Success 200 {object} domain.ArticleResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse

View File

@ -13,8 +13,8 @@ import (
// ListDiscordWebhooks // ListDiscordWebhooks
// @Summary Returns the top 100 // @Summary Returns the top 100
// @Produce application/json // @Produce application/json
// @Tags Discord, Webhook // @Tags DiscordWebhook
// @Router /discord/webhooks [get] // @Router /v1/discord/webhooks [get]
// @Success 200 {object} domain.DiscordWebhookResponse // @Success 200 {object} domain.DiscordWebhookResponse
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -37,8 +37,8 @@ func (s *Handler) ListDiscordWebHooks(c echo.Context) error {
// @Summary Returns the top 100 entries from the queue to be processed. // @Summary Returns the top 100 entries from the queue to be processed.
// @Produce application/json // @Produce application/json
// @Param id path int true "id" // @Param id path int true "id"
// @Tags Discord, Webhook // @Tags DiscordWebhook
// @Router /discord/webhooks/{id} [get] // @Router /v1/discord/webhooks/{id} [get]
// @Success 200 {object} domain.DiscordWebhookResponse "OK" // @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -69,8 +69,8 @@ func (s *Handler) GetDiscordWebHooksById(c echo.Context) error {
// @Produce application/json // @Produce application/json
// @Param server query string true "Fancy Server" // @Param server query string true "Fancy Server"
// @Param channel query string true "memes" // @Param channel query string true "memes"
// @Tags Discord, Webhook // @Tags DiscordWebhook
// @Router /discord/webhooks/by/serverAndChannel [get] // @Router /v1/discord/webhooks/by/serverAndChannel [get]
// @Success 200 {object} domain.DiscordWebhookResponse "OK" // @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -105,8 +105,8 @@ func (s *Handler) GetDiscordWebHooksByServerAndChannel(c echo.Context) error {
// @Param url query string true "url" // @Param url query string true "url"
// @Param server query string true "Server name" // @Param server query string true "Server name"
// @Param channel query string true "Channel name" // @Param channel query string true "Channel name"
// @Tags Discord, Webhook // @Tags DiscordWebhook
// @Router /discord/webhooks/new [post] // @Router /v1/discord/webhooks/new [post]
// @Success 200 {object} domain.DiscordWebhookResponse "OK" // @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -164,8 +164,8 @@ func (s *Handler) NewDiscordWebHook(c echo.Context) error {
// DisableDiscordWebHooks // DisableDiscordWebHooks
// @Summary Disables a Webhook from being used. // @Summary Disables a Webhook from being used.
// @Param id path int true "id" // @Param id path int true "id"
// @Tags Discord, Webhook // @Tags DiscordWebhook
// @Router /discord/webhooks/{ID}/disable [post] // @Router /v1/discord/webhooks/{ID}/disable [post]
// @Success 200 {object} domain.DiscordWebhookResponse "OK" // @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -212,8 +212,8 @@ func (s *Handler) disableDiscordWebHook(c echo.Context) error {
// EnableDiscordWebHook // EnableDiscordWebHook
// @Summary Enables a source to continue processing. // @Summary Enables a source to continue processing.
// @Param id path int true "id" // @Param id path int true "id"
// @Tags Discord, Webhook // @Tags DiscordWebhook
// @Router /discord/webhooks/{ID}/enable [post] // @Router /v1/discord/webhooks/{ID}/enable [post]
func (s *Handler) enableDiscordWebHook(c echo.Context) error { func (s *Handler) enableDiscordWebHook(c echo.Context) error {
id, err := strconv.Atoi(c.Param("ID")) id, err := strconv.Atoi(c.Param("ID"))
if err != nil { if err != nil {
@ -253,8 +253,8 @@ func (s *Handler) enableDiscordWebHook(c echo.Context) error {
// DeleteDiscordWebHook // DeleteDiscordWebHook
// @Summary Deletes a record by ID. // @Summary Deletes a record by ID.
// @Param id path string true "id" // @Param id path string true "id"
// @Tags Discord, Webhook // @Tags DiscordWebhook
// @Router /discord/webhooks/{ID} [delete] // @Router /v1/discord/webhooks/{ID} [delete]
// @Success 200 {object} domain.DiscordWebhookResponse "OK" // @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -298,8 +298,8 @@ func (s *Handler) deleteDiscordWebHook(c echo.Context) error {
// UpdateDiscordWebHook // UpdateDiscordWebHook
// @Summary Updates a valid discord webhook ID based on the body given. // @Summary Updates a valid discord webhook ID based on the body given.
// @Param id path string true "id" // @Param id path string true "id"
// @Tags Discord, Webhook // @Tags DiscordWebhook
// @Router /discord/webhooks/{id} [patch] // @Router /v1/discord/webhooks/{id} [patch]
// @Success 200 {object} domain.DiscordWebhookResponse "OK" // @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse

View File

@ -5,19 +5,19 @@ import (
"database/sql" "database/sql"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
_ "github.com/lib/pq" "github.com/labstack/echo/v4/middleware"
swagger "github.com/swaggo/echo-swagger" swagger "github.com/swaggo/echo-swagger"
_ "git.jamestombleson.com/jtom38/newsbot-api/docs"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database" "git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain" "git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services" "git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services/dto"
) )
type Handler struct { type Handler struct {
Router *echo.Echo Router *echo.Echo
Db *database.Queries Db *database.Queries
dto *dto.DtoClient //dto *dto.DtoClient
config services.Configs config services.Configs
repo services.RepositoryService repo services.RepositoryService
} }
@ -39,23 +39,26 @@ var (
ErrUnableToConvertToJson string = "Unable to convert to json" ErrUnableToConvertToJson string = "Unable to convert to json"
) )
func NewServer(ctx context.Context, db *database.Queries, configs services.Configs, conn *sql.DB) *Handler { func NewServer(ctx context.Context, configs services.Configs, conn *sql.DB) *Handler {
s := &Handler{ s := &Handler{
Db: db, //Db: db,
dto: dto.NewDtoClient(db), //dto: dto.NewDtoClient(db),
config: configs, config: configs,
repo: services.NewRepositoryService(conn), repo: services.NewRepositoryService(conn),
} }
router := echo.New() router := echo.New()
router.Pre(middleware.RemoveTrailingSlash())
router.Pre(middleware.Logger())
router.Pre(middleware.Recover())
router.GET("/swagger/*", swagger.WrapHandler) router.GET("/swagger/*", swagger.WrapHandler)
v1 := router.Group("/api/v1") v1 := router.Group("/api/v1")
articles := v1.Group("/articles") articles := v1.Group("/articles")
articles.GET("/", s.listArticles) articles.GET("", s.listArticles)
articles.GET("/:id", s.getArticle) articles.GET(":id", s.getArticle)
articles.GET("/:id/details", s.getArticleDetails) articles.GET(":id/details", s.getArticleDetails)
articles.GET("/by/source/:id", s.ListArticlesBySourceId) articles.GET("by/source/:id", s.ListArticlesBySourceId)
//dwh := v1.Group("/discord/webhooks") //dwh := v1.Group("/discord/webhooks")
//dwh.GET("/", s.ListDiscordWebHooks) //dwh.GET("/", s.ListDiscordWebHooks)
@ -73,7 +76,7 @@ func NewServer(ctx context.Context, db *database.Queries, configs services.Confi
//settings.GET("/", s.getSettings) //settings.GET("/", s.getSettings)
sources := v1.Group("/sources") sources := v1.Group("/sources")
sources.GET("/", s.listSources) sources.GET("", s.listSources)
sources.GET("/by/source", s.listSourcesBySource) sources.GET("/by/source", s.listSourcesBySource)
sources.GET("/by/sourceAndName", s.GetSourceBySourceAndName) sources.GET("/by/sourceAndName", s.GetSourceBySourceAndName)
//sources.POST("/new/reddit", s.newRedditSource) //sources.POST("/new/reddit", s.newRedditSource)
@ -93,6 +96,7 @@ func NewServer(ctx context.Context, db *database.Queries, configs services.Confi
subs.POST("/discord/webhook/new", s.newDiscordWebHookSubscription) subs.POST("/discord/webhook/new", s.newDiscordWebHookSubscription)
subs.DELETE("/discord/webhook/delete", s.DeleteDiscordWebHookSubscription) subs.DELETE("/discord/webhook/delete", s.DeleteDiscordWebHookSubscription)
s.Router = router
return s return s
} }

View File

@ -3,7 +3,6 @@ package v1
import ( import (
"net/http" "net/http"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models" "git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
@ -17,7 +16,7 @@ type ListDiscordWebHooksQueueResults struct {
// @Summary Returns the top 100 entries from the queue to be processed. // @Summary Returns the top 100 entries from the queue to be processed.
// @Produce application/json // @Produce application/json
// @Tags Queue // @Tags Queue
// @Router /queue/discord/webhooks [get] // @Router /v1/queue/discord/webhooks [get]
// @Success 200 {object} ListDiscordWebHooksQueueResults "ok" // @Success 200 {object} ListDiscordWebHooksQueueResults "ok"
func (s *Handler) ListDiscordWebhookQueue(c echo.Context) error { func (s *Handler) ListDiscordWebhookQueue(c echo.Context) error {
p := ListDiscordWebHooksQueueResults{ p := ListDiscordWebHooksQueueResults{
@ -28,13 +27,13 @@ func (s *Handler) ListDiscordWebhookQueue(c echo.Context) error {
} }
// Get the raw resp from sql // Get the raw resp from sql
res, err := s.dto.ListDiscordWebhookQueueDetails(c.Request().Context(), 50) //res, err := s.dto.ListDiscordWebhookQueueDetails(c.Request().Context(), 50)
if err != nil { //if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ // return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(), // Message: err.Error(),
}) // })
} //}
p.Payload = res //p.Payload = res
return c.JSON(http.StatusOK, p) return c.JSON(http.StatusOK, p)
} }

View File

@ -14,7 +14,7 @@ import (
// @Param key path string true "Settings Key value" // @Param key path string true "Settings Key value"
// @Produce application/json // @Produce application/json
// @Tags Settings // @Tags Settings
// @Router /settings/{key} [get] // @Router /v1/settings/{key} [get]
func (s *Handler) getSettings(c echo.Context) error { func (s *Handler) getSettings(c echo.Context) error {
id := c.Param("ID") id := c.Param("ID")

View File

@ -31,7 +31,7 @@ type GetSource struct {
// @Param page query string false "page number" // @Param page query string false "page number"
// @Produce application/json // @Produce application/json
// @Tags Source // @Tags Source
// @Router /sources [get] // @Router /v1/sources [get]
// @Success 200 {object} domain.SourcesResponse "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse "Unable to reach SQL or Data problems" // @Failure 400 {object} domain.BaseResponse "Unable to reach SQL or Data problems"
func (s *Handler) listSources(c echo.Context) error { func (s *Handler) listSources(c echo.Context) error {
@ -62,7 +62,7 @@ func (s *Handler) listSources(c echo.Context) error {
// @Param page query string false "page number" // @Param page query string false "page number"
// @Produce application/json // @Produce application/json
// @Tags Source // @Tags Source
// @Router /sources/by/source [get] // @Router /v1/sources/by/source [get]
// @Success 200 {object} domain.SourcesResponse "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -100,7 +100,7 @@ func (s *Handler) listSourcesBySource(c echo.Context) error {
// @Param id path int true "uuid" // @Param id path int true "uuid"
// @Produce application/json // @Produce application/json
// @Tags Source // @Tags Source
// @Router /sources/{id} [get] // @Router /v1/sources/{id} [get]
// @Success 200 {object} domain.SourcesResponse "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -135,7 +135,7 @@ func (s *Handler) getSource(c echo.Context) error {
// @Param source query string true "reddit" // @Param source query string true "reddit"
// @Produce application/json // @Produce application/json
// @Tags Source // @Tags Source
// @Router /sources/by/sourceAndName [get] // @Router /v1/sources/by/sourceAndName [get]
// @Success 200 {object} domain.SourcesResponse "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -170,7 +170,7 @@ func (s *Handler) GetSourceBySourceAndName(c echo.Context) error {
// @Param name query string true "name" // @Param name query string true "name"
// @Param url query string true "url" // @Param url query string true "url"
// @Tags Source // @Tags Source
// @Router /sources/new/reddit [post] // @Router /v1/sources/new/reddit [post]
// @Success 200 {object} domain.SourcesResponse "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -226,7 +226,7 @@ func (s *Handler) newRedditSource(c echo.Context) error {
// @Param name query string true "name" // @Param name query string true "name"
// @Param url query string true "url" // @Param url query string true "url"
// @Tags Source // @Tags Source
// @Router /sources/new/youtube [post] // @Router /v1/sources/new/youtube [post]
func (s *Handler) newYoutubeSource(c echo.Context) error { func (s *Handler) newYoutubeSource(c echo.Context) error {
var param domain.NewSourceParamRequest var param domain.NewSourceParamRequest
err := c.Bind(&param) err := c.Bind(&param)
@ -289,7 +289,7 @@ func (s *Handler) newYoutubeSource(c echo.Context) error {
// @Summary Creates a new twitch source to monitor. // @Summary Creates a new twitch source to monitor.
// @Param name query string true "name" // @Param name query string true "name"
// @Tags Source // @Tags Source
// @Router /sources/new/twitch [post] // @Router /v1/sources/new/twitch [post]
func (s *Handler) newTwitchSource(c echo.Context) error { func (s *Handler) newTwitchSource(c echo.Context) error {
var param domain.NewSourceParamRequest var param domain.NewSourceParamRequest
err := c.Bind(&param) err := c.Bind(&param)
@ -337,7 +337,7 @@ func (s *Handler) newTwitchSource(c echo.Context) error {
// @Param name query string true "Site Name" // @Param name query string true "Site Name"
// @Param url query string true "RSS Url" // @Param url query string true "RSS Url"
// @Tags Source // @Tags Source
// @Router /sources/new/rss [post] // @Router /v1/sources/new/rss [post]
// @Success 200 {object} domain.SourcesResponse "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -387,7 +387,7 @@ func (s *Handler) newRssSource(c echo.Context) error {
// @Summary Marks a source as deleted based on its ID value. // @Summary Marks a source as deleted based on its ID value.
// @Param id path string true "id" // @Param id path string true "id"
// @Tags Source // @Tags Source
// @Router /sources/{id} [POST] // @Router /v1/sources/{id} [POST]
func (s *Handler) deleteSources(c echo.Context) error { func (s *Handler) deleteSources(c echo.Context) error {
id := c.Param("ID") id := c.Param("ID")
uuid, err := uuid.Parse(id) uuid, err := uuid.Parse(id)
@ -432,7 +432,7 @@ func (s *Handler) deleteSources(c echo.Context) error {
// @Summary Disables a source from processing. // @Summary Disables a source from processing.
// @Param id path int true "id" // @Param id path int true "id"
// @Tags Source // @Tags Source
// @Router /sources/{id}/disable [post] // @Router /v1/sources/{id}/disable [post]
// @Success 200 {object} domain.SourcesResponse "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
@ -474,7 +474,7 @@ func (s *Handler) disableSource(c echo.Context) error {
// @Summary Enables a source to continue processing. // @Summary Enables a source to continue processing.
// @Param id path string true "id" // @Param id path string true "id"
// @Tags Source // @Tags Source
// @Router /sources/{id}/enable [post] // @Router /v1/sources/{id}/enable [post]
// @Success 200 {object} domain.SourcesResponse "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse

View File

@ -31,7 +31,7 @@ type ListSubscriptionDetails struct {
// @Summary Returns the top 100 entries from the queue to be processed. // @Summary Returns the top 100 entries from the queue to be processed.
// @Produce application/json // @Produce application/json
// @Tags Subscription // @Tags Subscription
// @Router /subscriptions [get] // @Router /v1/subscriptions [get]
// @Success 200 {object} ListSubscriptions "ok" // @Success 200 {object} ListSubscriptions "ok"
// @Failure 400 {object} ApiError "Unable to reach SQL." // @Failure 400 {object} ApiError "Unable to reach SQL."
// @Failure 500 {object} ApiError "Failed to process data from SQL." // @Failure 500 {object} ApiError "Failed to process data from SQL."
@ -43,12 +43,11 @@ func (s *Handler) ListSubscriptions(c echo.Context) error {
}, },
} }
res, err := s.dto.ListSubscriptions(c.Request().Context(), 50) //res, err := s.dto.ListSubscriptions(c.Request().Context(), 50)
if err != nil { //if err != nil {
return s.WriteError(c, err, http.StatusBadRequest) // return s.WriteError(c, err, http.StatusBadRequest)
} //}
//payload.Payload = res
payload.Payload = res
return c.JSON(http.StatusOK, payload) return c.JSON(http.StatusOK, payload)
} }
@ -56,7 +55,7 @@ func (s *Handler) ListSubscriptions(c echo.Context) error {
// @Summary Returns the top 50 entries with full deatils on the source and output. // @Summary Returns the top 50 entries with full deatils on the source and output.
// @Produce application/json // @Produce application/json
// @Tags Subscription // @Tags Subscription
// @Router /subscriptions/details [get] // @Router /v1/subscriptions/details [get]
// @Success 200 {object} ListSubscriptionDetails "ok" // @Success 200 {object} ListSubscriptionDetails "ok"
func (s *Handler) ListSubscriptionDetails(c echo.Context) error { func (s *Handler) ListSubscriptionDetails(c echo.Context) error {
payload := ListSubscriptionDetails{ payload := ListSubscriptionDetails{
@ -66,12 +65,11 @@ func (s *Handler) ListSubscriptionDetails(c echo.Context) error {
}, },
} }
res, err := s.dto.ListSubscriptionDetails(c.Request().Context(), 50) //res, err := s.dto.ListSubscriptionDetails(c.Request().Context(), 50)
if err != nil { //if err != nil {
return s.WriteError(c, err, http.StatusInternalServerError) // return s.WriteError(c, err, http.StatusInternalServerError)
} //}
//payload.Payload = res
payload.Payload = res
return c.JSON(http.StatusOK, payload) return c.JSON(http.StatusOK, payload)
} }
@ -80,7 +78,7 @@ func (s *Handler) ListSubscriptionDetails(c echo.Context) error {
// @Produce application/json // @Produce application/json
// @Param id query string true "id" // @Param id query string true "id"
// @Tags Subscription // @Tags Subscription
// @Router /subscriptions/by/discordId [get] // @Router /v1/subscriptions/by/discordId [get]
// @Success 200 {object} ListSubscriptions "ok" // @Success 200 {object} ListSubscriptions "ok"
// @Failure 400 {object} ApiError "Unable to reach SQL or Data problems" // @Failure 400 {object} ApiError "Unable to reach SQL or Data problems"
// @Failure 500 {object} ApiError "Data problems" // @Failure 500 {object} ApiError "Data problems"
@ -97,18 +95,16 @@ func (s *Handler) GetSubscriptionsByDiscordId(c echo.Context) error {
return s.WriteError(c, errors.New(ErrIdValueMissing), http.StatusBadRequest) return s.WriteError(c, errors.New(ErrIdValueMissing), http.StatusBadRequest)
} }
uuid, err := uuid.Parse(id) //uuid, err := uuid.Parse(id)
if err != nil { //if err != nil {
return s.WriteError(c, errors.New(ErrValueNotUuid), http.StatusBadRequest) // return s.WriteError(c, errors.New(ErrValueNotUuid), http.StatusBadRequest)
//}
} //res, err := s.dto.ListSubscriptionsByDiscordWebhookId(context.Background(), uuid)
//if err != nil {
res, err := s.dto.ListSubscriptionsByDiscordWebhookId(context.Background(), uuid) // return s.WriteError(c, err, http.StatusNoContent)
if err != nil { //}
return s.WriteError(c, err, http.StatusNoContent) //p.Payload = res
}
p.Payload = res
return c.JSON(http.StatusOK, p) return c.JSON(http.StatusOK, p)
} }
@ -117,7 +113,7 @@ func (s *Handler) GetSubscriptionsByDiscordId(c echo.Context) error {
// @Produce application/json // @Produce application/json
// @Param id query string true "id" // @Param id query string true "id"
// @Tags Subscription // @Tags Subscription
// @Router /subscriptions/by/SourceId [get] // @Router /v1/subscriptions/by/SourceId [get]
// @Success 200 {object} ListSubscriptions "ok" // @Success 200 {object} ListSubscriptions "ok"
func (s *Handler) GetSubscriptionsBySourceId(c echo.Context) error { func (s *Handler) GetSubscriptionsBySourceId(c echo.Context) error {
p := ListSubscriptions{ p := ListSubscriptions{
@ -132,17 +128,16 @@ func (s *Handler) GetSubscriptionsBySourceId(c echo.Context) error {
return s.WriteError(c, errors.New(ErrIdValueMissing), http.StatusBadRequest) return s.WriteError(c, errors.New(ErrIdValueMissing), http.StatusBadRequest)
} }
uuid, err := uuid.Parse(_id) //uuid, err := uuid.Parse(_id)
if err != nil { //if err != nil {
return s.WriteError(c, err, http.StatusBadRequest) // return s.WriteError(c, err, http.StatusBadRequest)
} //}
res, err := s.dto.ListSubscriptionsBySourceId(context.Background(), uuid) //res, err := s.dto.ListSubscriptionsBySourceId(context.Background(), uuid)
if err != nil { //if err != nil {
return s.WriteError(c, err, http.StatusNoContent) // return s.WriteError(c, err, http.StatusNoContent)
} //}
//p.Payload = res
p.Payload = res
return c.JSON(http.StatusOK, p) return c.JSON(http.StatusOK, p)
} }
@ -151,7 +146,7 @@ func (s *Handler) GetSubscriptionsBySourceId(c echo.Context) error {
// @Param discordWebHookId query string true "discordWebHookId" // @Param discordWebHookId query string true "discordWebHookId"
// @Param sourceId query string true "sourceId" // @Param sourceId query string true "sourceId"
// @Tags Subscription // @Tags Subscription
// @Router /subscriptions/discord/webhook/new [post] // @Router /v1/subscriptions/discord/webhook/new [post]
func (s *Handler) newDiscordWebHookSubscription(c echo.Context) error { func (s *Handler) newDiscordWebHookSubscription(c echo.Context) error {
// Extract the values given // Extract the values given
discordWebHookId := c.QueryParam("discordWebHookId") discordWebHookId := c.QueryParam("discordWebHookId")
@ -207,7 +202,7 @@ func (s *Handler) newDiscordWebHookSubscription(c echo.Context) error {
// @Summary Removes a Discord WebHook Subscription based on the Subscription ID. // @Summary Removes a Discord WebHook Subscription based on the Subscription ID.
// @Param id query string true "id" // @Param id query string true "id"
// @Tags Subscription // @Tags Subscription
// @Router /subscriptions/discord/webhook/delete [delete] // @Router /v1/subscriptions/discord/webhook/delete [delete]
func (s *Handler) DeleteDiscordWebHookSubscription(c echo.Context) error { func (s *Handler) DeleteDiscordWebHookSubscription(c echo.Context) error {
var ErrMissingSubscriptionID string = "the request was missing a 'Id'" var ErrMissingSubscriptionID string = "the request was missing a 'Id'"

View File

@ -11,9 +11,9 @@ import (
) )
const ( const (
ServerAddress = "SERVER_ADDRESS" ServerAddress = "ServerAddress"
Sql_Connection_String = "SQL_CONNECTION_STRING" //Sql_Connection_String = "SQL_CONNECTION_STRING"
FEATURE_ENABLE_REDDIT_BACKEND = "FEATURE_ENABLE_REDDIT_BACKEND" FEATURE_ENABLE_REDDIT_BACKEND = "FEATURE_ENABLE_REDDIT_BACKEND"
REDDIT_PULL_TOP = "REDDIT_PULL_TOP" REDDIT_PULL_TOP = "REDDIT_PULL_TOP"

View File

@ -10,7 +10,7 @@ import (
func (c *Cron) CollectRssPosts() { func (c *Cron) CollectRssPosts() {
log.Println("Starting ") log.Println("Starting ")
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorRss) sources, err := c.repo.Sources.ListBySource(c.ctx, 0, 1000, domain.SourceCollectorRss)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
@ -27,12 +27,12 @@ func (c *Cron) CollectRssPosts() {
} }
for _, article := range articles { for _, article := range articles {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url) _, err := c.repo.Articles.GetByUrl(c.ctx, article.Url)
if err == nil { if err == nil {
continue continue
} }
rowsCreated, err := c.repo.Articles.CreateFromEntity(*c.ctx, article) rowsCreated, err := c.repo.Articles.CreateFromEntity(c.ctx, article)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
@ -48,7 +48,7 @@ func (c *Cron) CollectRssPosts() {
} }
func (c *Cron) CollectRedditPosts() { func (c *Cron) CollectRedditPosts() {
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorReddit) sources, err := c.repo.Sources.ListBySource(c.ctx, 0, 1000, domain.SourceCollectorReddit)
if err != nil { if err != nil {
log.Printf("[Reddit] No sources found to query - %v\r", err) log.Printf("[Reddit] No sources found to query - %v\r", err)
} }
@ -67,12 +67,12 @@ func (c *Cron) CollectRedditPosts() {
redditArticles := rc.ConvertToArticles(raw) redditArticles := rc.ConvertToArticles(raw)
for _, article := range redditArticles { for _, article := range redditArticles {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url) _, err := c.repo.Articles.GetByUrl(c.ctx, article.Url)
if err == nil { if err == nil {
continue continue
} }
rowsAdded, err := c.repo.Articles.CreateFromEntity(*c.ctx, article) rowsAdded, err := c.repo.Articles.CreateFromEntity(c.ctx, article)
if err != nil { if err != nil {
log.Printf("Failed to add a new reddit article to the database: %s", err) log.Printf("Failed to add a new reddit article to the database: %s", err)
} }
@ -86,7 +86,7 @@ func (c *Cron) CollectRedditPosts() {
} }
func (c *Cron) CollectYoutubePosts() { func (c *Cron) CollectYoutubePosts() {
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorYoutube) sources, err := c.repo.Sources.ListBySource(c.ctx, 0, 1000, domain.SourceCollectorYoutube)
if err != nil { if err != nil {
log.Printf("[Youtube] No sources found to query - %v\r", err) log.Printf("[Youtube] No sources found to query - %v\r", err)
} }
@ -104,12 +104,12 @@ func (c *Cron) CollectYoutubePosts() {
} }
for _, article := range raw { for _, article := range raw {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url) _, err := c.repo.Articles.GetByUrl(c.ctx, article.Url)
if err == nil { if err == nil {
continue continue
} }
rowsAdded, err := c.repo.Articles.CreateFromEntity(*c.ctx, article) rowsAdded, err := c.repo.Articles.CreateFromEntity(c.ctx, article)
if err != nil { if err != nil {
log.Printf("Failed to add a new youtube article to the database: %s", err) log.Printf("Failed to add a new youtube article to the database: %s", err)
} }
@ -127,7 +127,7 @@ func (c *Cron) CollectYoutubePosts() {
} }
func (c *Cron) CollectFfxivPosts() { func (c *Cron) CollectFfxivPosts() {
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorFfxiv) sources, err := c.repo.Sources.ListBySource(c.ctx, 0, 1000, domain.SourceCollectorFfxiv)
if err != nil { if err != nil {
log.Printf("[FFXIV] No sources found to query - %v\r", err) log.Printf("[FFXIV] No sources found to query - %v\r", err)
} }
@ -144,12 +144,12 @@ func (c *Cron) CollectFfxivPosts() {
} }
for _, article := range items { for _, article := range items {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url) _, err := c.repo.Articles.GetByUrl(c.ctx, article.Url)
if err == nil { if err == nil {
continue continue
} }
rowsAdded, err := c.repo.Articles.CreateFromEntity(*c.ctx, article) rowsAdded, err := c.repo.Articles.CreateFromEntity(c.ctx, article)
if err != nil { if err != nil {
log.Printf("Failed to add a new FFXIV article to the database: %s", err) log.Printf("Failed to add a new FFXIV article to the database: %s", err)
} }
@ -167,7 +167,7 @@ func (c *Cron) CollectFfxivPosts() {
} }
func (c *Cron) CollectTwitchPosts() { func (c *Cron) CollectTwitchPosts() {
sources, err := c.repo.Sources.ListBySource(*c.ctx, 0, 1000, domain.SourceCollectorTwitch) sources, err := c.repo.Sources.ListBySource(c.ctx, 0, 1000, domain.SourceCollectorTwitch)
if err != nil { if err != nil {
log.Printf("[Twitch] No sources found to query - %v\r", err) log.Printf("[Twitch] No sources found to query - %v\r", err)
} }
@ -196,12 +196,12 @@ func (c *Cron) CollectTwitchPosts() {
} }
for _, article := range items { for _, article := range items {
_, err := c.repo.Articles.GetByUrl(*c.ctx, article.Url) _, err := c.repo.Articles.GetByUrl(c.ctx, article.Url)
if err == nil { if err == nil {
continue continue
} }
rowsAdded, err := c.repo.Articles.CreateFromEntity(*c.ctx, article) rowsAdded, err := c.repo.Articles.CreateFromEntity(c.ctx, article)
if err != nil { if err != nil {
log.Printf("Failed to add a new Twitch article to the database: %s", err) log.Printf("Failed to add a new Twitch article to the database: %s", err)
} }

View File

@ -13,14 +13,14 @@ import (
type Cron struct { type Cron struct {
Db *database.Queries Db *database.Queries
ctx *context.Context ctx context.Context
timer *cron.Cron timer *cron.Cron
repo services.RepositoryService repo services.RepositoryService
} }
func NewScheduler(ctx context.Context, conn *sql.DB) *Cron { func NewScheduler(ctx context.Context, conn *sql.DB) *Cron {
c := &Cron{ c := &Cron{
ctx: &ctx, ctx: ctx,
repo: services.NewRepositoryService(conn), repo: services.NewRepositoryService(conn),
} }
timer := cron.New() timer := cron.New()
@ -28,11 +28,11 @@ func NewScheduler(ctx context.Context, conn *sql.DB) *Cron {
//timer.AddFunc("*/5 * * * *", func() { go CheckCache() }) //timer.AddFunc("*/5 * * * *", func() { go CheckCache() })
//features := services.GetEnvConfig() //features := services.GetEnvConfig()
timer.AddFunc("5 * * * *", c.CollectRssPosts) timer.AddFunc("5 * * * *", func() { go c.CollectRssPosts() })
//timer.AddFunc("5 1-23 * * *", c.CollectRedditPosts) //timer.AddFunc("10 * * * *", c.CollectRedditPosts)
//timer.AddFunc("10 1-23 * * *", c.CheckYoutube) //timer.AddFunc("15 * * * *", c.CheckYoutube)
//timer.AddFunc("5 5,10,15,20 * * *", c.CheckFfxiv) //timer.AddFunc("20 * * * *", c.CheckFfxiv)
//timer.AddFunc("15 1-23 * * *", c.CheckTwitch) //timer.AddFunc("25 * * * *", c.CheckTwitch)
//timer.AddFunc("*/5 * * * *", c.CheckDiscordQueue) //timer.AddFunc("*/5 * * * *", c.CheckDiscordQueue)
c.timer = timer c.timer = timer

View File

@ -1,140 +0,0 @@
// The converter package lives between the database calls and the API calls.
// This way if any new methods like RPC calls are added later, the API does not need to be reworked as much
package dto
import (
"context"
"strings"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/google/uuid"
)
type DtoClient struct {
db *database.Queries
}
func NewDtoClient(db *database.Queries) *DtoClient {
return &DtoClient{
db: db,
}
}
func (c *DtoClient) ListArticles(ctx context.Context, limit, page int) ([]models.ArticleDto, error) {
var res []models.ArticleDto
a, err := c.db.ListArticles(ctx, database.ListArticlesParams{
Limit: int32(limit),
Offset: int32(limit * page),
})
if err != nil {
return res, err
}
for _, article := range a {
res = append(res, c.convertArticle(article))
}
return res, nil
}
func (c *DtoClient) ListArticlesByPage(ctx context.Context, page, limit int32) ([]models.ArticleDto, error) {
var res []models.ArticleDto
a, err := c.db.ListArticlesByPage(ctx, database.ListArticlesByPageParams{
Limit: limit,
Offset: page * limit,
})
if err != nil {
return res, err
}
for _, article := range a {
res = append(res, c.convertArticle(article))
}
return res, nil
}
func (c *DtoClient) GetArticle(ctx context.Context, ID uuid.UUID) (models.ArticleDto, error) {
a, err := c.db.GetArticleByID(ctx, ID)
if err != nil {
return models.ArticleDto{}, err
}
return c.convertArticle(a), nil
}
func (c *DtoClient) GetArticleDetails(ctx context.Context, ID uuid.UUID) (models.ArticleDetailsDto, error) {
a, err := c.db.GetArticleByID(ctx, ID)
if err != nil {
return models.ArticleDetailsDto{}, err
}
s, err := c.db.GetSourceByID(ctx, a.Sourceid)
if err != nil {
return models.ArticleDetailsDto{}, err
}
res := c.convertArticleDetails(a, s)
return res, nil
}
func (c *DtoClient) ListNewArticlesBySourceId(ctx context.Context, SourceID uuid.UUID, limit, page int) ([]models.ArticleDto, error) {
var res []models.ArticleDto
a, err := c.db.ListNewArticlesBySourceId(ctx, database.ListNewArticlesBySourceIdParams{
Sourceid: SourceID,
Limit: int32(limit),
Offset: int32(limit * page),
})
if err != nil {
return res, err
}
for _, article := range a {
res = append(res, c.convertArticle(article))
}
return res, nil
}
func (c *DtoClient) convertArticle(i database.Article) models.ArticleDto {
return models.ArticleDto{
ID: i.ID,
Source: i.Sourceid,
Tags: c.SplitTags(i.Tags),
Title: i.Title,
Url: i.Url,
Pubdate: i.Pubdate,
Video: i.Video.String,
Videoheight: i.Videoheight,
Videowidth: i.Videoheight,
Thumbnail: i.Thumbnail,
Description: i.Description,
Authorname: i.Authorname.String,
Authorimage: i.Authorimage.String,
}
}
func (c *DtoClient) convertArticleDetails(i database.Article, s database.Source) models.ArticleDetailsDto {
return models.ArticleDetailsDto{
ID: i.ID,
Source: c.ConvertToSource(s),
Tags: c.SplitTags(i.Tags),
Title: i.Title,
Url: i.Url,
Pubdate: i.Pubdate,
Video: i.Video.String,
Videoheight: i.Videoheight,
Videowidth: i.Videoheight,
Thumbnail: i.Thumbnail,
Description: i.Description,
Authorname: i.Authorname.String,
Authorimage: i.Authorimage.String,
}
}
func (c DtoClient) SplitTags(t string) []string {
return strings.Split(t, ", ")
}

View File

@ -1,63 +0,0 @@
package dto
import (
"context"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/google/uuid"
)
func (c *DtoClient) ListDiscordWebHooks(ctx context.Context, total int32) ([]models.DiscordWebHooksDto, error) {
var res []models.DiscordWebHooksDto
items, err := c.db.ListDiscordWebhooks(ctx, total)
if err != nil {
return res, nil
}
for _, item := range items {
res = append(res, c.ConvertDiscordWebhook(item))
}
return res, nil
}
func (c *DtoClient) GetDiscordWebhook(ctx context.Context, id uuid.UUID) (models.DiscordWebHooksDto, error) {
var res models.DiscordWebHooksDto
item, err := c.db.GetDiscordWebHooksByID(ctx, id)
if err != nil {
return res, err
}
return c.ConvertDiscordWebhook(item), nil
}
func (c *DtoClient) GetDiscordWebHookByServerAndChannel(ctx context.Context, server, channel string) ([]models.DiscordWebHooksDto, error) {
var res []models.DiscordWebHooksDto
items, err := c.db.GetDiscordWebHooksByServerAndChannel(ctx, database.GetDiscordWebHooksByServerAndChannelParams{
Server: server,
Channel: channel,
})
if err != nil {
return res, err
}
for _, item := range items {
res = append(res, c.ConvertDiscordWebhook(item))
}
return res, nil
}
func (c *DtoClient) ConvertDiscordWebhook(i database.Discordwebhook) models.DiscordWebHooksDto {
return models.DiscordWebHooksDto{
ID: i.ID,
Url: i.Url,
Server: i.Server,
Channel: i.Channel,
Enabled: i.Enabled,
}
}

View File

@ -1,42 +0,0 @@
package dto
import (
"context"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
)
func (c *DtoClient) ListDiscordWebhookQueue(ctx context.Context, limit int32) {
}
func (c *DtoClient) ListDiscordWebhookQueueDetails(ctx context.Context, limit int32) ([]models.DiscordQueueDetailsDto, error) {
var res []models.DiscordQueueDetailsDto
items, err := c.db.ListDiscordQueueItems(ctx, limit)
if err != nil {
return res, err
}
for _, item := range items {
article, err := c.GetArticleDetails(ctx, item.ID)
if err != nil {
return res, err
}
res = append(res, models.DiscordQueueDetailsDto{
ID: item.ID,
Article: article,
})
}
return res, nil
}
func (c *DtoClient) ConvertToDiscordQueueDto(i database.Discordqueue) models.DiscordQueueDto {
return models.DiscordQueueDto{
ID: i.ID,
Articleid: i.Articleid,
}
}

View File

@ -1,85 +0,0 @@
package dto
import (
"context"
"strings"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/google/uuid"
)
func (c *DtoClient) ListSources(ctx context.Context, limit int32) ([]models.SourceDto, error) {
var res []models.SourceDto
items, err := c.db.ListSources(ctx, limit)
if err != nil {
return res, err
}
for _, item := range items {
res = append(res, c.ConvertToSource(item))
}
return res, nil
}
func (c *DtoClient) ListSourcesBySource(ctx context.Context, sourceName string) ([]models.SourceDto, error) {
var res []models.SourceDto
items, err := c.db.ListSourcesBySource(ctx, strings.ToLower(sourceName))
if err != nil {
return res, err
}
for _, item := range items {
res = append(res, c.ConvertToSource(item))
}
return res, nil
}
func (c *DtoClient) GetSourceById(ctx context.Context, id uuid.UUID) (models.SourceDto, error) {
var res models.SourceDto
item, err := c.db.GetSourceByID(ctx, id)
if err != nil {
return res, err
}
return c.ConvertToSource(item), nil
}
func (c *DtoClient) GetSourceByNameAndSource(ctx context.Context, name, source string) (models.SourceDto, error) {
var res models.SourceDto
item, err := c.db.GetSourceByNameAndSource(ctx, database.GetSourceByNameAndSourceParams{
Name: name,
Source: source,
})
if err != nil {
return res, err
}
return c.ConvertToSource(item), nil
}
func (c *DtoClient) ConvertToSource(i database.Source) models.SourceDto {
var deleted bool
if !i.Deleted.Valid {
deleted = true
}
return models.SourceDto{
ID: i.ID,
Site: i.Site,
Name: i.Name,
Source: i.Source,
Type: i.Type,
Value: i.Value.String,
Enabled: i.Enabled,
Url: i.Url,
Tags: c.SplitTags(i.Tags),
Deleted: deleted,
}
}

View File

@ -1,91 +0,0 @@
package dto
import (
"context"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/google/uuid"
)
func (c *DtoClient) ListSubscriptions(ctx context.Context, limit int32) ([]models.SubscriptionDto, error) {
var res []models.SubscriptionDto
items, err := c.db.ListSubscriptions(ctx, limit)
if err != nil {
return res, err
}
for _, item := range items {
res = append(res, c.ConvertSubscription(item))
}
return res, nil
}
func (c *DtoClient) ListSubscriptionDetails(ctx context.Context, limit int32) ([]models.SubscriptionDetailsDto, error) {
var res []models.SubscriptionDetailsDto
items, err := c.ListSubscriptions(ctx, limit)
if err != nil {
return res, err
}
for _, item := range items {
dwh, err := c.GetDiscordWebhook(ctx, item.DiscordWebhookId)
if err != nil {
return res, err
}
source, err := c.GetSourceById(ctx, item.SourceId)
if err != nil {
return res, err
}
res = append(res, models.SubscriptionDetailsDto{
ID: item.ID,
Source: source,
DiscordWebHook: dwh,
})
}
return res, nil
}
func (c *DtoClient) ListSubscriptionsByDiscordWebhookId(ctx context.Context, id uuid.UUID) ([]models.SubscriptionDto, error) {
var res []models.SubscriptionDto
items, err := c.db.GetSubscriptionsByDiscordWebHookId(ctx, id)
if err != nil {
return res, err
}
for _, item := range items {
res = append(res, c.ConvertSubscription(item))
}
return res, nil
}
func (c *DtoClient) ListSubscriptionsBySourceId(ctx context.Context, id uuid.UUID) ([]models.SubscriptionDto, error) {
var res []models.SubscriptionDto
items, err := c.db.GetSubscriptionsBySourceID(ctx, id)
if err != nil {
return res, err
}
for _, item := range items {
res = append(res, c.ConvertSubscription(item))
}
return res, nil
}
func (c *DtoClient) ConvertSubscription(i database.Subscription) models.SubscriptionDto {
return models.SubscriptionDto{
ID: i.ID,
DiscordWebhookId: i.Discordwebhookid,
SourceId: i.Sourceid,
}
}

View File

@ -2,7 +2,7 @@ package input
import ( import (
"crypto/tls" "crypto/tls"
"io/ioutil" "io"
"log" "log"
"net/http" "net/http"
) )
@ -35,7 +35,7 @@ func getHttpContent(uri string) ([]byte, error) {
} }
defer resp.Body.Close() defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -39,7 +39,11 @@ func (rc rssClient) GetArticles() ([]domain.ArticleEntity, error) {
Description: post.Content, Description: post.Content,
Url: post.Link, Url: post.Link,
PubDate: *post.PublishedParsed, PubDate: *post.PublishedParsed,
AuthorName: post.Author.Email, //AuthorName: post.Authors[0].Email,
}
if len(post.Authors) != 0 {
article.AuthorName = post.Authors[0].Email
} }
var postTags []string var postTags []string
@ -47,6 +51,21 @@ func (rc rssClient) GetArticles() ([]domain.ArticleEntity, error) {
postTags = append(postTags, post.Categories...) postTags = append(postTags, post.Categories...)
article.Tags = strings.Join(postTags, ",") article.Tags = strings.Join(postTags, ",")
/*
pageContent, err := getHttpContent(article.Url)
if err != nil {
continue
}
htmlNode, err := html.Parse(bytes.NewReader(pageContent))
if err != nil {
continue
}
htmlNode.
fmt.Println(htmlNode)
*/
if post.Image == nil { if post.Image == nil {
article.Thumbnail = "" article.Thumbnail = ""
} }

View File

@ -12,10 +12,10 @@ docker-build: ## Generates the docker image
docker image ls | grep newsbot.collector.api docker image ls | grep newsbot.collector.api
migrate-dev: ## Apply sql migrations to dev db migrate-dev: ## Apply sql migrations to dev db
goose -dir "./internal/database/migrations" postgres "user=postgres password=postgres dbname=postgres sslmode=disable" up goose -dir "./internal/database/migrations" sqlite3 ./cmd/newsbot.db up
migrate-dev-down: ## revert sql migrations to dev db migrate-dev-down: ## revert sql migrations to dev db
goose -dir "./internal/database/migrations" postgres "user=postgres password=postgres dbname=postgres sslmode=disable" down goose -dir "./internal/database/migrations" sqlite3 ./cmd/newsbot.db down
swag: ## Generates the swagger documentation with the swag tool swag: ## Generates the swagger documentation with the swag tool
~/go/bin/swag f ~/go/bin/swag f