Features/delete source and first dto (#36)
* updated db, added dto for ListSources, and added delete source * updated from model > models * updated to models * sources now sends back a standard message * updated subscription routes to have beter logid and swagger details * moved the dto objects back to modles given they are not bound to the database * cleaned up how we return the error * cleaned up swag and updated models to take from the base apistatusmodel. less human errors this way * cleaned up swag and updated models * swag updated * updated queue to return a router and also renamed it as it will hold all queue info later on * removed config tag * added subscription details route * article routes have been moved to support dto * updated discordwebhooks to use dto * updated discordwebhookqueue to return details on the items via dto * removed the example routes * updated sources to use dto * subscriptions moved to dto * generated swag
This commit is contained in:
parent
a2147294d5
commit
ada453e08a
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.13.0
|
||||
// sqlc v1.16.0
|
||||
|
||||
package database
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.13.0
|
||||
// sqlc v1.16.0
|
||||
|
||||
package database
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.13.0
|
||||
// sqlc v1.16.0
|
||||
// source: query.sql
|
||||
|
||||
package database
|
||||
|
1122
docs/docs.go
1122
docs/docs.go
File diff suppressed because it is too large
Load Diff
1122
docs/swagger.json
1122
docs/swagger.json
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,239 @@
|
||||
basePath: /api
|
||||
definitions:
|
||||
models.ArticleDetailsDto:
|
||||
properties:
|
||||
authorImage:
|
||||
type: string
|
||||
authorName:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
pubdate:
|
||||
type: string
|
||||
source:
|
||||
$ref: '#/definitions/models.SourceDto'
|
||||
tags:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
thumbnail:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
video:
|
||||
type: string
|
||||
videoHeight:
|
||||
type: integer
|
||||
videoWidth:
|
||||
type: integer
|
||||
type: object
|
||||
models.ArticleDto:
|
||||
properties:
|
||||
authorImage:
|
||||
type: string
|
||||
authorName:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
pubdate:
|
||||
type: string
|
||||
sourceid:
|
||||
type: string
|
||||
tags:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
thumbnail:
|
||||
type: string
|
||||
title:
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
video:
|
||||
type: string
|
||||
videoHeight:
|
||||
type: integer
|
||||
videoWidth:
|
||||
type: integer
|
||||
type: object
|
||||
models.DiscordQueueDetailsDto:
|
||||
properties:
|
||||
article:
|
||||
$ref: '#/definitions/models.ArticleDetailsDto'
|
||||
id:
|
||||
type: string
|
||||
type: object
|
||||
models.DiscordWebHooksDto:
|
||||
properties:
|
||||
ID:
|
||||
type: string
|
||||
channel:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
server:
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
type: object
|
||||
models.SourceDto:
|
||||
properties:
|
||||
deleted:
|
||||
type: boolean
|
||||
enabled:
|
||||
type: boolean
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
site:
|
||||
type: string
|
||||
source:
|
||||
type: string
|
||||
tags:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type:
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
type: object
|
||||
models.SubscriptionDetailsDto:
|
||||
properties:
|
||||
discordwebhook:
|
||||
$ref: '#/definitions/models.DiscordWebHooksDto'
|
||||
id:
|
||||
type: string
|
||||
source:
|
||||
$ref: '#/definitions/models.SourceDto'
|
||||
type: object
|
||||
models.SubscriptionDto:
|
||||
properties:
|
||||
discordwebhookid:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
sourceid:
|
||||
type: string
|
||||
type: object
|
||||
routes.ApiError:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
routes.ArticleDetailsResult:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
payload:
|
||||
$ref: '#/definitions/models.ArticleDetailsDto'
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
routes.ArticleGetResults:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
payload:
|
||||
$ref: '#/definitions/models.ArticleDto'
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
routes.ArticlesListResults:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
payload:
|
||||
items:
|
||||
$ref: '#/definitions/models.ArticleDto'
|
||||
type: array
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
routes.GetDiscordWebhook:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
payload:
|
||||
$ref: '#/definitions/models.DiscordWebHooksDto'
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
routes.GetSource:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
payload:
|
||||
$ref: '#/definitions/models.SourceDto'
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
routes.ListDiscordWebHooksQueueResults:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
payload:
|
||||
items:
|
||||
$ref: '#/definitions/models.DiscordQueueDetailsDto'
|
||||
type: array
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
routes.ListDiscordWebhooks:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
payload:
|
||||
items:
|
||||
$ref: '#/definitions/models.DiscordWebHooksDto'
|
||||
type: array
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
routes.ListSources:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
payload:
|
||||
items:
|
||||
$ref: '#/definitions/models.SourceDto'
|
||||
type: array
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
routes.ListSubscriptionDetails:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
payload:
|
||||
items:
|
||||
$ref: '#/definitions/models.SubscriptionDetailsDto'
|
||||
type: array
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
routes.ListSubscriptions:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
payload:
|
||||
items:
|
||||
$ref: '#/definitions/models.SubscriptionDto'
|
||||
type: array
|
||||
status:
|
||||
type: integer
|
||||
type: object
|
||||
info:
|
||||
contact: {}
|
||||
title: NewsBot collector
|
||||
@ -8,7 +243,11 @@ paths:
|
||||
get:
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ArticlesListResults'
|
||||
summary: Lists the top 50 records
|
||||
tags:
|
||||
- Articles
|
||||
@ -17,15 +256,37 @@ paths:
|
||||
parameters:
|
||||
- description: uuid
|
||||
in: path
|
||||
name: id
|
||||
name: ID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ArticleGetResults'
|
||||
summary: Returns an article based on defined ID.
|
||||
tags:
|
||||
- Articles
|
||||
/articles/{ID}/details:
|
||||
get:
|
||||
parameters:
|
||||
- description: uuid
|
||||
in: path
|
||||
name: ID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ArticleDetailsResult'
|
||||
summary: Returns an article and source based on defined ID.
|
||||
tags:
|
||||
- Articles
|
||||
/articles/by/sourceid:
|
||||
get:
|
||||
parameters:
|
||||
@ -36,184 +297,15 @@ paths:
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ArticlesListResults'
|
||||
summary: Finds the articles based on the SourceID provided. Returns the top
|
||||
50.
|
||||
tags:
|
||||
- Articles
|
||||
/articles/by/tag:
|
||||
get:
|
||||
parameters:
|
||||
- description: Tag name
|
||||
in: query
|
||||
name: tag
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
summary: Finds the articles based on the SourceID provided. Returns the top
|
||||
50.
|
||||
tags:
|
||||
- Articles
|
||||
/config/sources:
|
||||
get:
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
summary: Lists the top 50 records
|
||||
tags:
|
||||
- Config
|
||||
- Source
|
||||
/config/sources/{id}:
|
||||
get:
|
||||
parameters:
|
||||
- description: uuid
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
summary: Returns a single entity by ID
|
||||
tags:
|
||||
- Config
|
||||
- Source
|
||||
post:
|
||||
parameters:
|
||||
- description: id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Marks a source as deleted based on its ID value.
|
||||
tags:
|
||||
- Source
|
||||
/config/sources/{id}/disable:
|
||||
post:
|
||||
parameters:
|
||||
- description: id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Disables a source from processing.
|
||||
tags:
|
||||
- Config
|
||||
- Source
|
||||
/config/sources/{id}/enable:
|
||||
post:
|
||||
parameters:
|
||||
- description: id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Enables a source to continue processing.
|
||||
tags:
|
||||
- Config
|
||||
- Source
|
||||
/config/sources/by/source:
|
||||
get:
|
||||
parameters:
|
||||
- description: Source Name
|
||||
in: query
|
||||
name: source
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
summary: 'Lists the top 50 records based on the name given. Example: reddit'
|
||||
tags:
|
||||
- Config
|
||||
- Source
|
||||
/config/sources/by/sourceAndName:
|
||||
get:
|
||||
parameters:
|
||||
- description: dadjokes
|
||||
in: query
|
||||
name: name
|
||||
required: true
|
||||
type: string
|
||||
- description: reddit
|
||||
in: query
|
||||
name: source
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
summary: Returns a single entity by ID
|
||||
tags:
|
||||
- Config
|
||||
- Source
|
||||
/config/sources/new/reddit:
|
||||
post:
|
||||
parameters:
|
||||
- description: name
|
||||
in: query
|
||||
name: name
|
||||
required: true
|
||||
type: string
|
||||
- description: url
|
||||
in: query
|
||||
name: url
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Creates a new reddit source to monitor.
|
||||
tags:
|
||||
- Config
|
||||
- Source
|
||||
- Reddit
|
||||
/config/sources/new/twitch:
|
||||
post:
|
||||
parameters:
|
||||
- description: name
|
||||
in: query
|
||||
name: name
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Creates a new twitch source to monitor.
|
||||
tags:
|
||||
- Config
|
||||
- Source
|
||||
- Twitch
|
||||
/config/sources/new/youtube:
|
||||
post:
|
||||
parameters:
|
||||
- description: name
|
||||
in: query
|
||||
name: name
|
||||
required: true
|
||||
type: string
|
||||
- description: url
|
||||
in: query
|
||||
name: url
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Creates a new youtube source to monitor.
|
||||
tags:
|
||||
- Config
|
||||
- Source
|
||||
- YouTube
|
||||
/discord/queue:
|
||||
get:
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
summary: Returns the top 100 entries from the queue to be processed.
|
||||
tags:
|
||||
- Debug
|
||||
- Discord
|
||||
- Queue
|
||||
/discord/webhooks:
|
||||
get:
|
||||
produces:
|
||||
@ -221,10 +313,9 @@ paths:
|
||||
responses: {}
|
||||
summary: Returns the top 100 entries from the queue to be processed.
|
||||
tags:
|
||||
- Config
|
||||
- Discord
|
||||
- Webhook
|
||||
/discord/webhooks/{id}:
|
||||
/discord/webhooks/{ID}:
|
||||
delete:
|
||||
parameters:
|
||||
- description: id
|
||||
@ -235,9 +326,35 @@ paths:
|
||||
responses: {}
|
||||
summary: Deletes a record by ID.
|
||||
tags:
|
||||
- Config
|
||||
- Discord
|
||||
- Webhook
|
||||
/discord/webhooks/{ID}/disable:
|
||||
post:
|
||||
parameters:
|
||||
- description: id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Disables a Webhook from being used.
|
||||
tags:
|
||||
- Discord
|
||||
- Webhook
|
||||
/discord/webhooks/{ID}/enable:
|
||||
post:
|
||||
parameters:
|
||||
- description: id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Enables a source to continue processing.
|
||||
tags:
|
||||
- Discord
|
||||
- Webhook
|
||||
/discord/webhooks/{id}:
|
||||
get:
|
||||
parameters:
|
||||
- description: id
|
||||
@ -247,10 +364,13 @@ paths:
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/routes.GetDiscordWebhook'
|
||||
summary: Returns the top 100 entries from the queue to be processed.
|
||||
tags:
|
||||
- Config
|
||||
- Discord
|
||||
- Webhook
|
||||
patch:
|
||||
@ -263,35 +383,6 @@ paths:
|
||||
responses: {}
|
||||
summary: Updates a valid discord webhook ID based on the body given.
|
||||
tags:
|
||||
- Config
|
||||
- Discord
|
||||
- Webhook
|
||||
/discord/webhooks/{id}/disable:
|
||||
post:
|
||||
parameters:
|
||||
- description: id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Disables a Webhook from being used.
|
||||
tags:
|
||||
- Config
|
||||
- Discord
|
||||
- Webhook
|
||||
/discord/webhooks/{id}/enable:
|
||||
post:
|
||||
parameters:
|
||||
- description: id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Enables a source to continue processing.
|
||||
tags:
|
||||
- Config
|
||||
- Discord
|
||||
- Webhook
|
||||
/discord/webhooks/by/serverAndChannel:
|
||||
@ -309,10 +400,13 @@ paths:
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ListDiscordWebhooks'
|
||||
summary: Returns all the known web hooks based on the Server and Channel given.
|
||||
tags:
|
||||
- Config
|
||||
- Discord
|
||||
- Webhook
|
||||
/discord/webhooks/new:
|
||||
@ -336,62 +430,229 @@ paths:
|
||||
responses: {}
|
||||
summary: Creates a new record for a discord web hook to post data to.
|
||||
tags:
|
||||
- Config
|
||||
- Discord
|
||||
- Webhook
|
||||
/hello/{who}:
|
||||
/queue/discord/webhooks:
|
||||
get:
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: ok
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ListDiscordWebHooksQueueResults'
|
||||
summary: Returns the top 100 entries from the queue to be processed.
|
||||
tags:
|
||||
- Queue
|
||||
/sources:
|
||||
get:
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: ok
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ListSources'
|
||||
"400":
|
||||
description: Unable to reach SQL or Data problems
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
summary: Lists the top 50 records
|
||||
tags:
|
||||
- Source
|
||||
/sources/{id}:
|
||||
get:
|
||||
parameters:
|
||||
- description: Who
|
||||
- description: uuid
|
||||
in: path
|
||||
name: who
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- text/plain
|
||||
responses: {}
|
||||
summary: Responds back with "Hello x" depending on param passed in.
|
||||
tags:
|
||||
- Debug
|
||||
/helloworld:
|
||||
get:
|
||||
produces:
|
||||
- text/plain
|
||||
responses: {}
|
||||
summary: Responds back with "Hello world!"
|
||||
tags:
|
||||
- Debug
|
||||
/ping:
|
||||
get:
|
||||
produces:
|
||||
- text/plain
|
||||
responses: {}
|
||||
summary: Sends back "pong". Good to test with.
|
||||
tags:
|
||||
- Debug
|
||||
/settings/{key}:
|
||||
get:
|
||||
parameters:
|
||||
- description: Settings Key value
|
||||
in: path
|
||||
name: key
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
summary: Returns a object based on the Key that was given.
|
||||
responses:
|
||||
"200":
|
||||
description: ok
|
||||
schema:
|
||||
$ref: '#/definitions/routes.GetSource'
|
||||
"204":
|
||||
description: No record found.
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
"400":
|
||||
description: Unable to query SQL.
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
"500":
|
||||
description: Failed to process data from SQL.
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
summary: Returns a single entity by ID
|
||||
tags:
|
||||
- Settings
|
||||
- Source
|
||||
post:
|
||||
parameters:
|
||||
- description: id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Marks a source as deleted based on its ID value.
|
||||
tags:
|
||||
- Source
|
||||
/sources/{id}/disable:
|
||||
post:
|
||||
parameters:
|
||||
- description: id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Disables a source from processing.
|
||||
tags:
|
||||
- Source
|
||||
/sources/{id}/enable:
|
||||
post:
|
||||
parameters:
|
||||
- description: id
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Enables a source to continue processing.
|
||||
tags:
|
||||
- Source
|
||||
/sources/by/source:
|
||||
get:
|
||||
parameters:
|
||||
- description: Source Name
|
||||
in: query
|
||||
name: source
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: ok
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ListSources'
|
||||
"400":
|
||||
description: Unable to query SQL.
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
"500":
|
||||
description: Problems with data.
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
summary: 'Lists the top 50 records based on the name given. Example: reddit'
|
||||
tags:
|
||||
- Source
|
||||
/sources/by/sourceAndName:
|
||||
get:
|
||||
parameters:
|
||||
- description: dadjokes
|
||||
in: query
|
||||
name: name
|
||||
required: true
|
||||
type: string
|
||||
- description: reddit
|
||||
in: query
|
||||
name: source
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: ok
|
||||
schema:
|
||||
$ref: '#/definitions/routes.GetSource'
|
||||
"204":
|
||||
description: No record found.
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
"400":
|
||||
description: Unable to query SQL.
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
"500":
|
||||
description: Failed to process data from SQL.
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
summary: Returns a single entity by ID
|
||||
tags:
|
||||
- Source
|
||||
/sources/new/reddit:
|
||||
post:
|
||||
parameters:
|
||||
- description: name
|
||||
in: query
|
||||
name: name
|
||||
required: true
|
||||
type: string
|
||||
- description: url
|
||||
in: query
|
||||
name: url
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Creates a new reddit source to monitor.
|
||||
tags:
|
||||
- Source
|
||||
/sources/new/twitch:
|
||||
post:
|
||||
parameters:
|
||||
- description: name
|
||||
in: query
|
||||
name: name
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Creates a new twitch source to monitor.
|
||||
tags:
|
||||
- Source
|
||||
/sources/new/youtube:
|
||||
post:
|
||||
parameters:
|
||||
- description: name
|
||||
in: query
|
||||
name: name
|
||||
required: true
|
||||
type: string
|
||||
- description: url
|
||||
in: query
|
||||
name: url
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Creates a new youtube source to monitor.
|
||||
tags:
|
||||
- Source
|
||||
/subscriptions:
|
||||
get:
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
responses:
|
||||
"200":
|
||||
description: ok
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ListSubscriptions'
|
||||
"400":
|
||||
description: Unable to reach SQL.
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
"500":
|
||||
description: Failed to process data from SQL.
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
summary: Returns the top 100 entries from the queue to be processed.
|
||||
tags:
|
||||
- Subscription
|
||||
/subscriptions/byDiscordId:
|
||||
/subscriptions/by/SourceId:
|
||||
get:
|
||||
parameters:
|
||||
- description: id
|
||||
@ -401,11 +662,15 @@ paths:
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
responses:
|
||||
"200":
|
||||
description: ok
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ListSubscriptions'
|
||||
summary: Returns the top 100 entries from the queue to be processed.
|
||||
tags:
|
||||
- Subscription
|
||||
/subscriptions/bySourceId:
|
||||
/subscriptions/by/discordId:
|
||||
get:
|
||||
parameters:
|
||||
- description: id
|
||||
@ -415,26 +680,47 @@ paths:
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses: {}
|
||||
responses:
|
||||
"200":
|
||||
description: ok
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ListSubscriptions'
|
||||
"400":
|
||||
description: Unable to reach SQL or Data problems
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
"500":
|
||||
description: Data problems
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ApiError'
|
||||
summary: Returns the top 100 entries from the queue to be processed.
|
||||
tags:
|
||||
- Subscription
|
||||
/subscriptions/details:
|
||||
get:
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: ok
|
||||
schema:
|
||||
$ref: '#/definitions/routes.ListSubscriptionDetails'
|
||||
summary: Returns the top 50 entries with full deatils on the source and output.
|
||||
tags:
|
||||
- Subscription
|
||||
/subscriptions/discord/webhook/delete:
|
||||
delete:
|
||||
parameters:
|
||||
- description: Id
|
||||
- description: id
|
||||
in: query
|
||||
name: Id
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
responses: {}
|
||||
summary: Removes a Discord WebHook Subscription based on the Subscription ID.
|
||||
tags:
|
||||
- Config
|
||||
- Source
|
||||
- Discord
|
||||
- Subscription
|
||||
/subscriptions/new/discordwebhook:
|
||||
/subscriptions/discord/webhook/new:
|
||||
post:
|
||||
parameters:
|
||||
- description: discordWebHookId
|
||||
|
@ -1,4 +1,4 @@
|
||||
package model
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
@ -1,4 +1,4 @@
|
||||
package model
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
129
domain/models/dto.go
Normal file
129
domain/models/dto.go
Normal file
@ -0,0 +1,129 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
)
|
||||
|
||||
type ArticleDto struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Source uuid.UUID `json:"sourceid"`
|
||||
Tags []string `json:"tags"`
|
||||
Title string `json:"title"`
|
||||
Url string `json:"url"`
|
||||
Pubdate time.Time `json:"pubdate"`
|
||||
Video string `json:"video"`
|
||||
Videoheight int32 `json:"videoHeight"`
|
||||
Videowidth int32 `json:"videoWidth"`
|
||||
Thumbnail string `json:"thumbnail"`
|
||||
Description string `json:"description"`
|
||||
Authorname string `json:"authorName"`
|
||||
Authorimage string `json:"authorImage"`
|
||||
}
|
||||
|
||||
type ArticleDetailsDto struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Source SourceDto `json:"source"`
|
||||
Tags []string `json:"tags"`
|
||||
Title string `json:"title"`
|
||||
Url string `json:"url"`
|
||||
Pubdate time.Time `json:"pubdate"`
|
||||
Video string `json:"video"`
|
||||
Videoheight int32 `json:"videoHeight"`
|
||||
Videowidth int32 `json:"videoWidth"`
|
||||
Thumbnail string `json:"thumbnail"`
|
||||
Description string `json:"description"`
|
||||
Authorname string `json:"authorName"`
|
||||
Authorimage string `json:"authorImage"`
|
||||
}
|
||||
|
||||
type DiscordWebHooksDto struct {
|
||||
ID uuid.UUID `json:"ID"`
|
||||
Url string `json:"url"`
|
||||
Server string `json:"server"`
|
||||
Channel string `json:"channel"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
func ConvertToDiscordWebhookDto(i database.Discordwebhook) DiscordWebHooksDto {
|
||||
return DiscordWebHooksDto{
|
||||
ID: i.ID,
|
||||
Url: i.Url,
|
||||
Server: i.Server,
|
||||
Channel: i.Channel,
|
||||
Enabled: i.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
type SourceDto struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Site string `json:"site"`
|
||||
Name string `json:"name"`
|
||||
Source string `json:"source"`
|
||||
Type string `json:"type"`
|
||||
Value string `json:"value"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Url string `json:"url"`
|
||||
Tags []string `json:"tags"`
|
||||
Deleted bool `json:"deleted"`
|
||||
}
|
||||
|
||||
func ConvertToSourceDto(i database.Source) SourceDto {
|
||||
var deleted bool
|
||||
if !i.Deleted.Valid {
|
||||
deleted = true
|
||||
}
|
||||
|
||||
return 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: splitTags(i.Tags),
|
||||
Deleted: deleted,
|
||||
}
|
||||
}
|
||||
|
||||
type DiscordQueueDto struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Articleid uuid.UUID `json:"articleId"`
|
||||
}
|
||||
|
||||
type DiscordQueueDetailsDto struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Article ArticleDetailsDto `json:"article"`
|
||||
}
|
||||
|
||||
type SubscriptionDto struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
DiscordWebhookId uuid.UUID `json:"discordwebhookid"`
|
||||
SourceId uuid.UUID `json:"sourceid"`
|
||||
}
|
||||
|
||||
func ConvertToSubscriptionDto(i database.Subscription) SubscriptionDto {
|
||||
c := SubscriptionDto{
|
||||
ID: i.ID,
|
||||
DiscordWebhookId: i.Discordwebhookid,
|
||||
SourceId: i.Sourceid,
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
type SubscriptionDetailsDto struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Source SourceDto `json:"source"`
|
||||
DiscordWebHook DiscordWebHooksDto `json:"discordwebhook"`
|
||||
}
|
||||
|
||||
func splitTags(t string) []string {
|
||||
items := strings.Split(t, ", ")
|
||||
return items
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package model
|
||||
package models
|
||||
|
||||
// This is the root Json object. It does not contain data that we care about though.
|
||||
type RedditJsonContent struct {
|
115
dto/articles.go
Normal file
115
dto/articles.go
Normal file
@ -0,0 +1,115 @@
|
||||
// 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"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
type DtoClient struct {
|
||||
db *database.Queries
|
||||
}
|
||||
|
||||
func NewDtoClient(db *database.Queries) DtoClient {
|
||||
return DtoClient{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (c DtoClient) ListArticles(ctx context.Context, limit int) ([]models.ArticleDto, error) {
|
||||
var res []models.ArticleDto
|
||||
|
||||
a, err := c.db.ListArticles(ctx, int32(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) GetArticlesBySourceId(ctx context.Context, SourceID uuid.UUID) ([]models.ArticleDto, error) {
|
||||
var res []models.ArticleDto
|
||||
a, err := c.db.GetArticlesBySourceId(ctx, SourceID)
|
||||
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, ", ")
|
||||
}
|
63
dto/discordwebhooks.go
Normal file
63
dto/discordwebhooks.go
Normal file
@ -0,0 +1,63 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
42
dto/queue.go
Normal file
42
dto/queue.go
Normal file
@ -0,0 +1,42 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/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,
|
||||
}
|
||||
}
|
85
dto/sources.go
Normal file
85
dto/sources.go
Normal file
@ -0,0 +1,85 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
91
dto/subscriptions.go
Normal file
91
dto/subscriptions.go
Normal file
@ -0,0 +1,91 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
13
main.go
13
main.go
@ -2,9 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/docs"
|
||||
"github.com/jtom38/newsbot/collector/routes"
|
||||
"github.com/jtom38/newsbot/collector/services/config"
|
||||
@ -20,16 +22,23 @@ func main() {
|
||||
docs.SwaggerInfo.Host = fmt.Sprintf("%v:8081", address)
|
||||
|
||||
ctx := context.Background()
|
||||
db, err := sql.Open("postgres", cfg.GetConfig(config.Sql_Connection_String))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
queries := database.New(db)
|
||||
|
||||
c := cron.New(ctx)
|
||||
c.Start()
|
||||
|
||||
server := routes.NewServer(ctx)
|
||||
server := routes.NewServer(ctx, queries)
|
||||
|
||||
fmt.Println("API is online and waiting for requests.")
|
||||
fmt.Printf("API: http://%v:8081/api\r\n", address)
|
||||
fmt.Printf("Swagger: http://%v:8081/swagger/index.html\r\n", address)
|
||||
|
||||
err := http.ListenAndServe(":8081", server.Router)
|
||||
err = http.ListenAndServe(":8081", server.Router)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -6,61 +6,156 @@ import (
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
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.GetArticlesBySourceId)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
type ArticlesListResults struct {
|
||||
ApiStatusModel
|
||||
Payload []models.ArticleDto `json:"payload"`
|
||||
}
|
||||
|
||||
// ListArticles
|
||||
// @Summary Lists the top 50 records
|
||||
// @Produce application/json
|
||||
// @Tags Articles
|
||||
// @Router /articles [get]
|
||||
// @Success 200 {object} ArticlesListResults "OK"
|
||||
func (s *Server) listArticles(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
res, err := s.Db.ListArticlesByDate(*s.ctx, 50)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
p := ArticlesListResults{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
|
||||
res, err := s.dto.ListArticles(r.Context(), 50)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
p.Payload = res
|
||||
|
||||
bres, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Write(bres)
|
||||
}
|
||||
|
||||
// GetArticleById
|
||||
type ArticleGetResults struct {
|
||||
ApiStatusModel
|
||||
Payload models.ArticleDto `json:"payload"`
|
||||
}
|
||||
|
||||
// GetArticle
|
||||
// @Summary Returns an article based on defined ID.
|
||||
// @Param id path string true "uuid"
|
||||
// @Param ID path string true "uuid"
|
||||
// @Produce application/json
|
||||
// @Tags Articles
|
||||
// @Router /articles/{ID} [get]
|
||||
func (s *Server) getArticleById(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
// @Success 200 {object} ArticleGetResults "OK"
|
||||
func (s *Server) getArticle(w http.ResponseWriter, r *http.Request) {
|
||||
p := ArticleGetResults {
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
|
||||
id := chi.URLParam(r, "ID")
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := s.Db.GetArticleByID(*s.ctx, uuid)
|
||||
res, err := s.dto.GetArticle(r.Context(), uuid)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
p.Payload = res
|
||||
|
||||
bres, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(bres)
|
||||
}
|
||||
|
||||
type ArticleDetailsResult struct {
|
||||
ApiStatusModel
|
||||
Payload models.ArticleDetailsDto `json:"payload"`
|
||||
}
|
||||
|
||||
// GetArticleDetails
|
||||
// @Summary Returns an article and source based on defined ID.
|
||||
// @Param ID path string true "uuid"
|
||||
// @Produce application/json
|
||||
// @Tags Articles
|
||||
// @Router /articles/{ID}/details [get]
|
||||
// @Success 200 {object} ArticleDetailsResult "OK"
|
||||
func (s *Server) getArticleDetails(w http.ResponseWriter, r *http.Request) {
|
||||
p := ArticleDetailsResult {
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
|
||||
id := chi.URLParam(r, "ID")
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := s.dto.GetArticleDetails(r.Context(), uuid)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
p.Payload = res
|
||||
|
||||
bres, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(bres)
|
||||
}
|
||||
|
||||
type ArticlesBySourceIDResults struct {
|
||||
ApiStatusModel
|
||||
Payload []models.ArticleDto `json:"payload"`
|
||||
}
|
||||
|
||||
// TODO add page support
|
||||
// GetArticlesBySourceID
|
||||
// @Summary Finds the articles based on the SourceID provided. Returns the top 50.
|
||||
@ -68,6 +163,7 @@ func (s *Server) getArticleById(w http.ResponseWriter, r *http.Request) {
|
||||
// @Produce application/json
|
||||
// @Tags Articles
|
||||
// @Router /articles/by/sourceid [get]
|
||||
// @Success 200 {object} ArticlesListResults "OK"
|
||||
func (s *Server) GetArticlesBySourceId(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
@ -77,56 +173,20 @@ func (s *Server) GetArticlesBySourceId(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
uuid, err := uuid.Parse(_id)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := s.Db.GetNewArticlesBySourceId(*s.ctx, uuid)
|
||||
//res, err := s.Db.GetArticlesBySourceId(*s.ctx, uuid)
|
||||
res, err := s.dto.GetArticlesBySourceId(r.Context(), uuid)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
w.Write(bres)
|
||||
}
|
||||
|
||||
// TODO add page support
|
||||
// GetArticlesByTag
|
||||
// @Summary Finds the articles based on the SourceID provided. Returns the top 50.
|
||||
// @Param tag query string true "Tag name"
|
||||
// @Produce application/json
|
||||
// @Tags Articles
|
||||
// @Router /articles/by/tag [get]
|
||||
func (s *Server) GetArticlesByTag(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
r.URL.Query()
|
||||
query := r.URL.Query()
|
||||
_id := query["tag"][0]
|
||||
|
||||
uuid, err := uuid.Parse(_id)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
res, err := s.Db.GetArticlesBySourceId(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(bres)
|
||||
|
@ -1,29 +0,0 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// GetDiscordQueue
|
||||
// @Summary Returns the top 100 entries from the queue to be processed.
|
||||
// @Produce application/json
|
||||
// @Tags Debug, Discord, Queue
|
||||
// @Router /discord/queue [get]
|
||||
func (s *Server) GetDiscordQueue(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
res, err := s.Db.ListDiscordQueueItems(*s.ctx, 100)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
w.Write(bres)
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -10,62 +9,106 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
// GetDiscordWebHooks
|
||||
// @Summary Returns the top 100 entries from the queue to be processed.
|
||||
// @Produce application/json
|
||||
// @Tags Config, Discord, Webhook
|
||||
// @Router /discord/webhooks [get]
|
||||
func (s *Server) GetDiscordWebHooks(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
func (s Server) DiscordWebHookRouter() http.Handler {
|
||||
r := chi.NewRouter()
|
||||
|
||||
res, err := s.Db.ListDiscordWebhooks(*s.ctx, 100)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
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
|
||||
}
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
type ListDiscordWebhooks struct {
|
||||
ApiStatusModel
|
||||
Payload []models.DiscordWebHooksDto `json:"payload"`
|
||||
}
|
||||
|
||||
// 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) {
|
||||
p := ListDiscordWebhooks{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
|
||||
res, err := s.dto.ListDiscordWebHooks(r.Context(), 50)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
p.Payload = res
|
||||
|
||||
bres, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(bres)
|
||||
}
|
||||
|
||||
type GetDiscordWebhook struct {
|
||||
ApiStatusModel
|
||||
Payload models.DiscordWebHooksDto `json:"payload"`
|
||||
}
|
||||
|
||||
// GetDiscordWebHook
|
||||
// @Summary Returns the top 100 entries from the queue to be processed.
|
||||
// @Produce application/json
|
||||
// @Param id path string true "id"
|
||||
// @Tags Config, Discord, Webhook
|
||||
// @Tags Discord, Webhook
|
||||
// @Router /discord/webhooks/{id} [get]
|
||||
// @Success 200 {object} GetDiscordWebhook "OK"
|
||||
func (s *Server) GetDiscordWebHooksById(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
p := GetDiscordWebhook{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
|
||||
_id := chi.URLParam(r, "ID")
|
||||
if _id == "" {
|
||||
http.Error(w, "id is missing", http.StatusBadRequest)
|
||||
s.WriteError(w, "id is missing", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
uuid, err := uuid.Parse(_id)
|
||||
if err != nil {
|
||||
http.Error(w, "unable to parse id value", http.StatusBadRequest)
|
||||
s.WriteError(w, "unable to parse id value", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := s.Db.GetDiscordWebHooksByID(*s.ctx, uuid)
|
||||
res, err := s.dto.GetDiscordWebhook(r.Context(), uuid)
|
||||
if err != nil {
|
||||
http.Error(w, "no record found", http.StatusBadRequest)
|
||||
s.WriteError(w, "no record found", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
p.Payload = res
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
bres, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
http.Error(w, "unable to convert to json", http.StatusBadRequest)
|
||||
panic(err)
|
||||
s.WriteError(w, "unable to convert to json", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(bres)
|
||||
@ -76,49 +119,55 @@ func (s *Server) GetDiscordWebHooksById(w http.ResponseWriter, r *http.Request)
|
||||
// @Produce application/json
|
||||
// @Param server query string true "Fancy Server"
|
||||
// @Param channel query string true "memes"
|
||||
// @Tags Config, Discord, Webhook
|
||||
// @Tags Discord, Webhook
|
||||
// @Router /discord/webhooks/by/serverAndChannel [get]
|
||||
// @Success 200 {object} ListDiscordWebhooks "OK"
|
||||
func (s *Server) GetDiscordWebHooksByServerAndChannel(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
p := ListDiscordWebhooks{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
|
||||
query := r.URL.Query()
|
||||
_server := query["server"][0]
|
||||
if _server == "" {
|
||||
http.Error(w, "ID is missing", http.StatusInternalServerError)
|
||||
s.WriteError(w, "ID is missing", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
_channel := query["channel"][0]
|
||||
if _channel == "" {
|
||||
http.Error(w, "Channel is missing", http.StatusInternalServerError)
|
||||
s.WriteError(w, "Channel is missing", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := s.Db.GetDiscordWebHooksByServerAndChannel(context.Background(), database.GetDiscordWebHooksByServerAndChannelParams{
|
||||
Server: _server,
|
||||
Channel: _channel,
|
||||
})
|
||||
res, err := s.dto.GetDiscordWebHookByServerAndChannel(r.Context(), _server, _channel)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
p.Payload = res
|
||||
|
||||
bres, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
http.Error(w, "unable to convert to json", http.StatusInternalServerError)
|
||||
panic(err)
|
||||
s.WriteError(w, "unable to convert to json", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(bres)
|
||||
}
|
||||
|
||||
|
||||
// NewDiscordWebHook
|
||||
// @Summary Creates a new record for a discord web hook to post data to.
|
||||
// @Param url query string true "url"
|
||||
// @Param server query string true "Server name"
|
||||
// @Param channel query string true "Channel name"
|
||||
// @Tags Config, Discord, Webhook
|
||||
// @Tags Discord, Webhook
|
||||
// @Router /discord/webhooks/new [post]
|
||||
func (s *Server) NewDiscordWebHook(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query()
|
||||
@ -160,82 +209,84 @@ func (s *Server) NewDiscordWebHook(w http.ResponseWriter, r *http.Request) {
|
||||
// DisableDiscordWebHooks
|
||||
// @Summary Disables a Webhook from being used.
|
||||
// @Param id path string true "id"
|
||||
// @Tags Config, Discord, Webhook
|
||||
// @Router /discord/webhooks/{id}/disable [post]
|
||||
// @Tags Discord, Webhook
|
||||
// @Router /discord/webhooks/{ID}/disable [post]
|
||||
func (s *Server) disableDiscordWebHook(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "ID")
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Check to make sure we can find the record
|
||||
_, err = s.Db.GetDiscordWebHooksByID(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = s.Db.DisableDiscordWebHook(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
// EnableDiscordWebHook
|
||||
// @Summary Enables a source to continue processing.
|
||||
// @Param id path string true "id"
|
||||
// @Tags Config, Discord, Webhook
|
||||
// @Router /discord/webhooks/{id}/enable [post]
|
||||
// @Tags Discord, Webhook
|
||||
// @Router /discord/webhooks/{ID}/enable [post]
|
||||
func (s *Server) enableDiscordWebHook(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "ID")
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// Check to make sure we can find the record
|
||||
_, err = s.Db.GetDiscordWebHooksByID(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
|
||||
err = s.Db.EnableDiscordWebHook(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteDiscordWebHook
|
||||
// @Summary Deletes a record by ID.
|
||||
// @Param id path string true "id"
|
||||
// @Tags Config, Discord, Webhook
|
||||
// @Router /discord/webhooks/{id} [delete]
|
||||
// @Tags Discord, Webhook
|
||||
// @Router /discord/webhooks/{ID} [delete]
|
||||
func (s *Server) deleteDiscordWebHook(w http.ResponseWriter, r *http.Request) {
|
||||
//var item model.Sources = model.Sources{}
|
||||
|
||||
id := chi.URLParam(r, "ID")
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// Check to make sure we can find the record
|
||||
_, err = s.Db.GetDiscordQueueByID(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// Delete the record
|
||||
err = s.Db.DeleteDiscordWebHooks(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateDiscordWebHook
|
||||
// @Summary Updates a valid discord webhook ID based on the body given.
|
||||
// @Param id path string true "id"
|
||||
// @Tags Config, Discord, Webhook
|
||||
// @Tags Discord, Webhook
|
||||
// @Router /discord/webhooks/{id} [patch]
|
||||
func (s *Server) UpdateDiscordWebHook(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "ID")
|
||||
|
57
routes/queue.go
Normal file
57
routes/queue.go
Normal file
@ -0,0 +1,57 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
func (s *Server) GetQueueRouter() http.Handler {
|
||||
r := chi.NewRouter()
|
||||
|
||||
r.Get("/discord/webhooks", s.ListDiscordWebhookQueue)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
type ListDiscordWebHooksQueueResults struct {
|
||||
ApiStatusModel
|
||||
Payload []models.DiscordQueueDetailsDto `json:"payload"`
|
||||
}
|
||||
|
||||
// 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) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
p := ListDiscordWebHooksQueueResults{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
// Get the raw resp from sql
|
||||
res, err := s.dto.ListDiscordWebhookQueueDetails(r.Context(), 50)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
p.Payload = res
|
||||
|
||||
// convert to json
|
||||
b, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(b)
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
func RootRoutes() chi.Router {
|
||||
app := chi.NewRouter()
|
||||
app.Route("/", func(r chi.Router) {
|
||||
r.Get("/helloworld", helloWorld)
|
||||
r.Get("/ping", ping)
|
||||
r.Route("/hello/{who}", func(r chi.Router) {
|
||||
r.Get("/", helloWho)
|
||||
})
|
||||
})
|
||||
return app
|
||||
}
|
||||
|
||||
// HelloWorld
|
||||
// @Summary Responds back with "Hello world!"
|
||||
// @Produce plain
|
||||
// @Tags Debug
|
||||
// @Router /helloworld [get]
|
||||
func helloWorld(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("Hello World!"))
|
||||
}
|
||||
|
||||
// Ping
|
||||
// @Summary Sends back "pong". Good to test with.
|
||||
// @Produce plain
|
||||
// @Tags Debug
|
||||
// @Router /ping [get]
|
||||
func ping(w http.ResponseWriter, r *http.Request) {
|
||||
msg := "pong"
|
||||
w.Write([]byte(msg))
|
||||
}
|
||||
|
||||
// HelloWho
|
||||
// @Summary Responds back with "Hello x" depending on param passed in.
|
||||
// @Param who path string true "Who"
|
||||
// @Produce plain
|
||||
// @Tags Debug
|
||||
// @Router /hello/{who} [get]
|
||||
func helloWho(w http.ResponseWriter, r *http.Request) {
|
||||
msg := fmt.Sprintf("Hello %v", chi.URLParam(r, "who"))
|
||||
w.Write([]byte(msg))
|
||||
}
|
107
routes/server.go
107
routes/server.go
@ -3,8 +3,8 @@ package routes
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
//"net/http"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
@ -12,15 +12,23 @@ import (
|
||||
httpSwagger "github.com/swaggo/http-swagger"
|
||||
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/dto"
|
||||
"github.com/jtom38/newsbot/collector/services/config"
|
||||
)
|
||||
|
||||
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."
|
||||
@ -28,16 +36,18 @@ var (
|
||||
ErrUnableToConvertToJson string = "Unable to convert to json"
|
||||
)
|
||||
|
||||
func NewServer(ctx context.Context) *Server {
|
||||
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
|
||||
//db, err := openDatabase(ctx)
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
//s.Db = db
|
||||
|
||||
s.Router = chi.NewRouter()
|
||||
s.MountMiddleware()
|
||||
@ -68,56 +78,37 @@ func (s *Server) MountRoutes() {
|
||||
httpSwagger.URL("doc.json"), //The url pointing to API definition
|
||||
))
|
||||
|
||||
/* Root Routes */
|
||||
s.Router.Get("/api/helloworld", helloWorld)
|
||||
s.Router.Get("/api/hello/{who}", helloWho)
|
||||
s.Router.Get("/api/ping", ping)
|
||||
s.Router.Mount("/api/articles", s.GetArticleRouter())
|
||||
s.Router.Mount("/api/queue", s.GetQueueRouter())
|
||||
s.Router.Mount("/api/discord/webhooks", s.DiscordWebHookRouter())
|
||||
|
||||
/* Article Routes */
|
||||
s.Router.Get("/api/articles", s.listArticles)
|
||||
s.Router.Route("/api/articles/{ID}", func(r chi.Router) {
|
||||
r.Get("/", s.getArticleById)
|
||||
})
|
||||
s.Router.Get("/api/articles/by/sourceid", s.GetArticlesBySourceId)
|
||||
//s.Router.Get("/api/settings", s.getSettings)
|
||||
|
||||
/* Discord Queue */
|
||||
s.Router.Get("/api/discord/queue", s.GetDiscordQueue)
|
||||
|
||||
/* Discord WebHooks */
|
||||
s.Router.Post("/api/discord/webhooks/new", s.NewDiscordWebHook)
|
||||
s.Router.Get("/api/discord/webhooks", s.GetDiscordWebHooks)
|
||||
//s.Router.Get("/api/discord/webhooks/byId", s.GetDiscordWebHooksById)
|
||||
s.Router.Get("/api/discord/webhooks/by/serverAndChannel", s.GetDiscordWebHooksByServerAndChannel)
|
||||
|
||||
s.Router.Route("/api/discord/webhooks/{ID}", func(r chi.Router) {
|
||||
r.Get("/", s.GetDiscordWebHooksById)
|
||||
r.Delete("/", s.deleteDiscordWebHook)
|
||||
r.Post("/disable", s.disableDiscordWebHook)
|
||||
r.Post("/enable", s.enableDiscordWebHook)
|
||||
})
|
||||
|
||||
/* Settings */
|
||||
s.Router.Get("/api/settings", s.getSettings)
|
||||
|
||||
/* Source Routes */
|
||||
s.Router.Get("/api/config/sources", s.listSources)
|
||||
s.Router.Get("/api/config/sources/by/source", s.listSourcesBySource)
|
||||
s.Router.Post("/api/config/sources/new/reddit", s.newRedditSource)
|
||||
s.Router.Post("/api/config/sources/new/youtube", s.newYoutubeSource)
|
||||
s.Router.Post("/api/config/sources/new/twitch", s.newTwitchSource)
|
||||
s.Router.Route("/api/config/sources/{ID}", func(r chi.Router) {
|
||||
r.Get("/", s.getSources)
|
||||
r.Delete("/", s.deleteSources)
|
||||
r.Post("/disable", s.disableSource)
|
||||
r.Post("/enable", s.enableSource)
|
||||
//r.Post("/delete", )
|
||||
})
|
||||
s.Router.Get("/api/config/sources/by/sourceAndName", s.GetSourceBySourceAndName)
|
||||
|
||||
/* Subscriptions */
|
||||
s.Router.Get("/api/subscriptions", s.ListSubscriptions)
|
||||
s.Router.Get("/api/subscriptions/byDiscordId", s.GetSubscriptionsByDiscordId)
|
||||
s.Router.Get("/api/subscriptions/bySourceId", s.GetSubscriptionsBySourceId)
|
||||
s.Router.Post("/api/subscriptions/new/discordwebhook", s.newDiscordWebHookSubscription)
|
||||
s.Router.Delete("/api/subscriptions/discord/webhook/delete", s.DeleteDiscordWebHookSubscription)
|
||||
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) {
|
||||
e := ApiError{
|
||||
ApiStatusModel: &ApiStatusModel{
|
||||
StatusCode: http.StatusInternalServerError,
|
||||
Message: errMessage,
|
||||
},
|
||||
}
|
||||
|
||||
b, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
w.Write(b)
|
||||
}
|
||||
|
@ -2,43 +2,43 @@ package routes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
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]
|
||||
func (s *Server) getSettings(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
//var item model.Sources
|
||||
id := chi.URLParam(r, "ID")
|
||||
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := s.Db.GetSourceByID(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
//itemId := fmt.Sprint(item.ID)
|
||||
//if id != itemId {
|
||||
// log.Panicln("Unable to find the requested record. Either unable to access SQL or the record does not exist.")
|
||||
//}
|
||||
|
||||
bResult, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(bResult)
|
||||
}
|
||||
|
@ -1,23 +1,55 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
func (s *Server) 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
|
||||
}
|
||||
|
||||
type ListSources struct {
|
||||
ApiStatusModel
|
||||
Payload []models.SourceDto `json:"payload"`
|
||||
}
|
||||
|
||||
type GetSource struct {
|
||||
ApiStatusModel
|
||||
Payload models.SourceDto `json:"payload"`
|
||||
}
|
||||
|
||||
// ListSources
|
||||
// @Summary Lists the top 50 records
|
||||
// @Produce application/json
|
||||
// @Tags Config, Source
|
||||
// @Router /config/sources [get]
|
||||
// @Tags Source
|
||||
// @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) {
|
||||
//TODO Add top?
|
||||
/*
|
||||
@ -29,35 +61,41 @@ func (s *Server) listSources(w http.ResponseWriter, r *http.Request) {
|
||||
res, err := s.Db.ListSources(*s.ctx, int32(topInt))
|
||||
*/
|
||||
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
result := ListSources{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
StatusCode: http.StatusOK,
|
||||
Message: "OK",
|
||||
},
|
||||
}
|
||||
|
||||
// Default way of showing all sources
|
||||
res, err := s.Db.ListSources(*s.ctx, 50)
|
||||
items, err := s.dto.ListSources(r.Context(), 50)
|
||||
if err != nil {
|
||||
http.Error(w, "url is missing a value", http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var dto []database.SourceDto
|
||||
for _, item := range res {
|
||||
dto = append(dto, database.ConvertToSourceDto(item))
|
||||
}
|
||||
result.Payload = items
|
||||
|
||||
bResult, err := json.Marshal(dto)
|
||||
bResult, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
http.Error(w, "unable to convert to json", http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(bResult)
|
||||
|
||||
}
|
||||
|
||||
// ListSourcesBySource
|
||||
// @Summary Lists the top 50 records based on the name given. Example: reddit
|
||||
// @Param source query string true "Source Name"
|
||||
// @Produce application/json
|
||||
// @Tags Config, Source
|
||||
// @Router /config/sources/by/source [get]
|
||||
// @Tags Source
|
||||
// @Router /sources/by/source [get]
|
||||
// @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) {
|
||||
//TODO Add top?
|
||||
/*
|
||||
@ -68,23 +106,33 @@ func (s *Server) listSourcesBySource(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
res, err := s.Db.ListSources(*s.ctx, int32(topInt))
|
||||
*/
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
|
||||
result := ListSources{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
StatusCode: http.StatusOK,
|
||||
Message: "OK",
|
||||
},
|
||||
}
|
||||
|
||||
query := r.URL.Query()
|
||||
_source := query["source"][0]
|
||||
|
||||
// Shows the list by Sources.source
|
||||
res, err := s.Db.ListSourcesBySource(*s.ctx, strings.ToLower(_source))
|
||||
res, err := s.dto.ListSourcesBySource(r.Context(), _source)
|
||||
if err != nil {
|
||||
http.Error(w, "invalid source is missing a value", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
bResult, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
http.Error(w, "unable to convert to json", http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
result.Payload = res
|
||||
|
||||
bResult, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(bResult)
|
||||
}
|
||||
|
||||
@ -92,29 +140,43 @@ func (s *Server) listSourcesBySource(w http.ResponseWriter, r *http.Request) {
|
||||
// @Summary Returns a single entity by ID
|
||||
// @Param id path string true "uuid"
|
||||
// @Produce application/json
|
||||
// @Tags Config, Source
|
||||
// @Router /config/sources/{id} [get]
|
||||
// @Tags Source
|
||||
// @Router /sources/{id} [get]
|
||||
// @Success 200 {object} GetSource "ok"
|
||||
// @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) {
|
||||
id := chi.URLParam(r, "ID")
|
||||
payload := GetSource{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
|
||||
id := chi.URLParam(r, "ID")
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
http.Error(w, "id is not a uuid", http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := s.Db.GetSourceByID(*s.ctx, uuid)
|
||||
res, err := s.dto.GetSourceById(r.Context(), uuid)
|
||||
if err != nil {
|
||||
http.Error(w, "invalid id was given", http.StatusBadRequest)
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
bResult, err := json.Marshal(res)
|
||||
payload.Payload = res
|
||||
|
||||
bResult, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(bResult)
|
||||
}
|
||||
|
||||
@ -123,37 +185,48 @@ func (s *Server) getSources(w http.ResponseWriter, r *http.Request) {
|
||||
// @Param name query string true "dadjokes"
|
||||
// @Param source query string true "reddit"
|
||||
// @Produce application/json
|
||||
// @Tags Config, Source
|
||||
// @Router /config/sources/by/sourceAndName [get]
|
||||
// @Tags Source
|
||||
// @Router /sources/by/sourceAndName [get]
|
||||
// @Success 200 {object} GetSource "ok"
|
||||
// @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) {
|
||||
query := r.URL.Query()
|
||||
p := GetSource{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
query := r.URL.Query()
|
||||
name := query["name"][0]
|
||||
if name == "" {
|
||||
http.Error(w, "Parameter 'name' was missing in the query.", http.StatusInternalServerError)
|
||||
s.WriteError(w, "Parameter 'name' was missing in the query.", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
source := query["source"][0]
|
||||
if source == "" {
|
||||
http.Error(w, "The parameter 'source' was missing in the query.", http.StatusInternalServerError)
|
||||
s.WriteError(w, "The parameter 'source' was missing in the query.", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
item, err := s.Db.GetSourceByNameAndSource(context.Background(), database.GetSourceByNameAndSourceParams{
|
||||
Name: name,
|
||||
Source: source,
|
||||
})
|
||||
item, err := s.dto.GetSourceByNameAndSource(r.Context(), name, source)
|
||||
if err != nil {
|
||||
http.Error(w, "Unable to find the requested record.", http.StatusInternalServerError)
|
||||
s.WriteError(w, "Unable to find the requested record.", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
p.Payload = item
|
||||
|
||||
bResult, err := json.Marshal(item)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
w.Write(bResult)
|
||||
}
|
||||
|
||||
@ -161,20 +234,22 @@ func (s *Server) GetSourceBySourceAndName(w http.ResponseWriter, r *http.Request
|
||||
// @Summary Creates a new reddit source to monitor.
|
||||
// @Param name query string true "name"
|
||||
// @Param url query string true "url"
|
||||
// @Tags Config, Source, Reddit
|
||||
// @Router /config/sources/new/reddit [post]
|
||||
// @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]
|
||||
//_tags := query["tags"][0]
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if _url == "" {
|
||||
http.Error(w, "url is missing a value", http.StatusBadRequest)
|
||||
s.WriteError(w, "url is missing a value", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if !strings.Contains(_url, "reddit.com") {
|
||||
http.Error(w, "invalid url", http.StatusBadRequest)
|
||||
s.WriteError(w, "invalid url", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -197,13 +272,18 @@ func (s *Server) newRedditSource(w http.ResponseWriter, r *http.Request) {
|
||||
Url: _url,
|
||||
Tags: tags,
|
||||
}
|
||||
s.Db.CreateSource(*s.ctx, params)
|
||||
err := s.Db.CreateSource(*s.ctx, params)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bJson, err := json.Marshal(¶ms)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
w.Write(bJson)
|
||||
}
|
||||
|
||||
@ -211,20 +291,21 @@ func (s *Server) newRedditSource(w http.ResponseWriter, r *http.Request) {
|
||||
// @Summary Creates a new youtube source to monitor.
|
||||
// @Param name query string true "name"
|
||||
// @Param url query string true "url"
|
||||
// @Tags Config, Source, YouTube
|
||||
// @Router /config/sources/new/youtube [post]
|
||||
// @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 == "" {
|
||||
http.Error(w, "url is missing a value", http.StatusBadRequest)
|
||||
s.WriteError(w, "url is missing a value", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if !strings.Contains(_url, "youtube.com") {
|
||||
http.Error(w, "invalid url", http.StatusBadRequest)
|
||||
s.WriteError(w, "invalid url", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -246,22 +327,29 @@ func (s *Server) newYoutubeSource(w http.ResponseWriter, r *http.Request) {
|
||||
Url: _url,
|
||||
Tags: tags,
|
||||
}
|
||||
s.Db.CreateSource(*s.ctx, params)
|
||||
err := s.Db.CreateSource(*s.ctx, params)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bJson, err := json.Marshal(¶ms)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
w.Write(bJson)
|
||||
}
|
||||
|
||||
// NewTwitchSource
|
||||
// @Summary Creates a new twitch source to monitor.
|
||||
// @Param name query string true "name"
|
||||
// @Tags Config, Source, Twitch
|
||||
// @Router /config/sources/new/twitch [post]
|
||||
// @Tags Source
|
||||
// @Router /sources/new/twitch [post]
|
||||
func (s *Server) newTwitchSource(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
query := r.URL.Query()
|
||||
_name := query["name"][0]
|
||||
|
||||
@ -278,13 +366,18 @@ func (s *Server) newTwitchSource(w http.ResponseWriter, r *http.Request) {
|
||||
Url: _url,
|
||||
Tags: tags,
|
||||
}
|
||||
s.Db.CreateSource(*s.ctx, params)
|
||||
err := s.Db.CreateSource(*s.ctx, params)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bJson, err := json.Marshal(¶ms)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
w.Write(bJson)
|
||||
}
|
||||
|
||||
@ -292,73 +385,115 @@ func (s *Server) newTwitchSource(w http.ResponseWriter, r *http.Request) {
|
||||
// @Summary Marks a source as deleted based on its ID value.
|
||||
// @Param id path string true "id"
|
||||
// @Tags Source
|
||||
// @Router /config/sources/{id} [POST]
|
||||
// @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")
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Check to make sure we can find the record
|
||||
_, err = s.Db.GetSourceByID(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete the record
|
||||
err = s.Db.DeleteSource(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
p := ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
// DisableSource
|
||||
// @Summary Disables a source from processing.
|
||||
// @Param id path string true "id"
|
||||
// @Tags Config, Source
|
||||
// @Router /config/sources/{id}/disable [post]
|
||||
// @Tags Source
|
||||
// @Router /sources/{id}/disable [post]
|
||||
func (s *Server) disableSource(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "ID")
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// Check to make sure we can find the record
|
||||
_, err = s.Db.GetSourceByID(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
err = s.Db.DisableSource(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
p := ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
// EnableSource
|
||||
// @Summary Enables a source to continue processing.
|
||||
// @Param id path string true "id"
|
||||
// @Tags Config, Source
|
||||
// @Router /config/sources/{id}/enable [post]
|
||||
// @Tags Source
|
||||
// @Router /sources/{id}/enable [post]
|
||||
func (s *Server) enableSource(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "ID")
|
||||
uuid, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// Check to make sure we can find the record
|
||||
_, err = s.Db.GetSourceByID(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
err = s.Db.EnableSource(*s.ctx, uuid)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
p := ApiStatusModel{
|
||||
Message: "OK",
|
||||
StatusCode: http.StatusOK,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(b)
|
||||
}
|
||||
|
@ -5,64 +5,149 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
type GetSubscription struct {
|
||||
ApiStatusModel
|
||||
Payload models.SubscriptionDto `json:"payload"`
|
||||
}
|
||||
|
||||
// GetSubscriptions
|
||||
// @Summary Returns the top 100 entries from the queue to be processed.
|
||||
// @Produce application/json
|
||||
// @Tags Subscription
|
||||
// @Router /subscriptions [get]
|
||||
// @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) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
res, err := s.Db.ListSubscriptions(*s.ctx, 100)
|
||||
if err != nil {
|
||||
w.Write([]byte(err.Error()))
|
||||
panic(err)
|
||||
payload := ListSubscriptions{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
StatusCode: http.StatusOK,
|
||||
Message: "OK",
|
||||
},
|
||||
}
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
res, err := s.dto.ListSubscriptions(r.Context(), 50)
|
||||
if err != nil {
|
||||
http.Error(w, ErrUnableToConvertToJson, http.StatusBadRequest)
|
||||
panic(err)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
payload.Payload = res
|
||||
|
||||
bres, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(bres)
|
||||
}
|
||||
|
||||
type ListSubscriptionDetails struct {
|
||||
ApiStatusModel
|
||||
Payload []models.SubscriptionDetailsDto `json:"payload"`
|
||||
}
|
||||
|
||||
// ListSubscriptionDetails
|
||||
// @Summary Returns the top 50 entries with full deatils on the source and output.
|
||||
// @Produce application/json
|
||||
// @Tags Subscription
|
||||
// @Router /subscriptions/details [get]
|
||||
// @Success 200 {object} ListSubscriptionDetails "ok"
|
||||
func (s Server) ListSubscriptionDetails(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
payload := ListSubscriptionDetails{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
StatusCode: http.StatusOK,
|
||||
Message: "OK",
|
||||
},
|
||||
}
|
||||
|
||||
res, err := s.dto.ListSubscriptionDetails(r.Context(), 50)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
payload.Payload = res
|
||||
|
||||
b, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
// GetSubscriptionsByDiscordId
|
||||
// @Summary Returns the top 100 entries from the queue to be processed.
|
||||
// @Produce application/json
|
||||
// @Param id query string true "id"
|
||||
// @Tags Subscription
|
||||
// @Router /subscriptions/byDiscordId [get]
|
||||
// @Router /subscriptions/by/discordId [get]
|
||||
// @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) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set(HeaderContentType, ApplicationJson)
|
||||
|
||||
p := ListSubscriptions{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
StatusCode: http.StatusOK,
|
||||
Message: "OK",
|
||||
},
|
||||
}
|
||||
|
||||
query := r.URL.Query()
|
||||
_id := query["id"][0]
|
||||
if _id == "" {
|
||||
http.Error(w, ErrIdValueMissing, http.StatusBadRequest)
|
||||
s.WriteError(w, ErrIdValueMissing, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
uuid, err := uuid.Parse(_id)
|
||||
if err != nil {
|
||||
http.Error(w, ErrValueNotUuid, http.StatusBadRequest)
|
||||
s.WriteError(w, ErrValueNotUuid, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := s.Db.GetSubscriptionsByDiscordWebHookId(*s.ctx, uuid)
|
||||
res, err := s.dto.ListSubscriptionsByDiscordWebhookId(r.Context(), uuid)
|
||||
if err != nil {
|
||||
http.Error(w, ErrNoRecordFound, http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
p.Payload = res
|
||||
|
||||
bres, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
http.Error(w, ErrUnableToConvertToJson, http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -74,32 +159,42 @@ func (s *Server) GetSubscriptionsByDiscordId(w http.ResponseWriter, r *http.Requ
|
||||
// @Produce application/json
|
||||
// @Param id query string true "id"
|
||||
// @Tags Subscription
|
||||
// @Router /subscriptions/bySourceId [get]
|
||||
// @Router /subscriptions/by/SourceId [get]
|
||||
// @Success 200 {object} ListSubscriptions "ok"
|
||||
func (s *Server) GetSubscriptionsBySourceId(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
p := ListSubscriptions{
|
||||
ApiStatusModel: ApiStatusModel{
|
||||
StatusCode: http.StatusOK,
|
||||
Message: "OK",
|
||||
},
|
||||
}
|
||||
|
||||
query := r.URL.Query()
|
||||
_id := query["id"][0]
|
||||
if _id == "" {
|
||||
http.Error(w, ErrIdValueMissing, http.StatusBadRequest)
|
||||
s.WriteError(w, ErrIdValueMissing, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
uuid, err := uuid.Parse(_id)
|
||||
if err != nil {
|
||||
http.Error(w, ErrValueNotUuid, http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := s.Db.GetSubscriptionsByDiscordWebHookId(*s.ctx, uuid)
|
||||
res, err := s.dto.ListSubscriptionsBySourceId(r.Context(), uuid)
|
||||
if err != nil {
|
||||
http.Error(w, ErrNoRecordFound, http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
bres, err := json.Marshal(res)
|
||||
p.Payload = res
|
||||
|
||||
bres, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
http.Error(w, ErrUnableToConvertToJson, http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -111,48 +206,44 @@ func (s *Server) GetSubscriptionsBySourceId(w http.ResponseWriter, r *http.Reque
|
||||
// @Param discordWebHookId query string true "discordWebHookId"
|
||||
// @Param sourceId query string true "sourceId"
|
||||
// @Tags Subscription
|
||||
// @Router /subscriptions/new/discordwebhook [post]
|
||||
// @Router /subscriptions/discord/webhook/new [post]
|
||||
func (s *Server) newDiscordWebHookSubscription(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
// Extract the values given
|
||||
query := r.URL.Query()
|
||||
discordWebHookId := query["discordWebHookId"][0]
|
||||
sourceId := query["sourceId"][0]
|
||||
|
||||
// Check to make we didnt get a null
|
||||
// Check to make we didn't get a null
|
||||
if discordWebHookId == "" {
|
||||
http.Error(w, "invalid discordWebHooksId given", http.StatusBadRequest)
|
||||
s.WriteError(w, "invalid discordWebHooksId given", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if sourceId == "" {
|
||||
http.Error(w, "invalid sourceID given", http.StatusBadRequest)
|
||||
s.WriteError(w, "invalid sourceID given", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Valide they are UUID values
|
||||
// Validate they are UUID values
|
||||
uHook, err := uuid.Parse(discordWebHookId)
|
||||
if err != nil {
|
||||
http.Error(w, "DiscordWebHooksID was not a uuid value.", http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
uSource, err := uuid.Parse(sourceId)
|
||||
if err != nil {
|
||||
http.Error(w, "SourceId was not a uuid value", http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the sub already exists
|
||||
item, err := s.Db.QuerySubscriptions(*s.ctx, database.QuerySubscriptionsParams{
|
||||
_, err = s.Db.QuerySubscriptions(*s.ctx, database.QuerySubscriptionsParams{
|
||||
Discordwebhookid: uHook,
|
||||
Sourceid: uSource,
|
||||
})
|
||||
if err == nil {
|
||||
bJson, err := json.Marshal(&item)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(bJson)
|
||||
s.WriteError(w, "a subscription already exists between these two entities", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -162,29 +253,39 @@ func (s *Server) newDiscordWebHookSubscription(w http.ResponseWriter, r *http.Re
|
||||
Discordwebhookid: uHook,
|
||||
Sourceid: uSource,
|
||||
}
|
||||
s.Db.CreateSubscription(*s.ctx, params)
|
||||
err = s.Db.CreateSubscription(*s.ctx, params)
|
||||
if err != nil {
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bJson, err := json.Marshal(¶ms)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
w.Write(bJson)
|
||||
}
|
||||
|
||||
// DeleteDiscordWebHookSubscription
|
||||
// @Summary Removes a Discord WebHook Subscription based on the Subscription ID.
|
||||
// @Param Id query string true "Id"
|
||||
// @Tags Config, Source, Discord, Subscription
|
||||
// @Param id query string true "id"
|
||||
// @Tags Subscription
|
||||
// @Router /subscriptions/discord/webhook/delete [delete]
|
||||
func (s *Server) DeleteDiscordWebHookSubscription(w http.ResponseWriter, r *http.Request) {
|
||||
var ErrMissingSubscriptionID string = "Request was missing a 'Id' or was a invalid UUID."
|
||||
var ErrMissingSubscriptionID string = "the request was missing a 'Id'"
|
||||
query := r.URL.Query()
|
||||
|
||||
uid, err := uuid.Parse(query["Id"][0])
|
||||
id := query["id"][0]
|
||||
if id == "" {
|
||||
s.WriteError(w, ErrMissingSubscriptionID, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
uid, err := uuid.Parse(query["id"][0])
|
||||
if err != nil {
|
||||
http.Error(w, ErrMissingSubscriptionID, http.StatusBadRequest)
|
||||
s.WriteError(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
|
12
services/cache/cache.go
vendored
12
services/cache/cache.go
vendored
@ -3,7 +3,7 @@ package cache
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jtom38/newsbot/collector/domain/model"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
type CacheClient struct {
|
||||
@ -19,7 +19,7 @@ func NewCacheClient(group string) CacheClient {
|
||||
}
|
||||
|
||||
func (cc *CacheClient) Insert(key string, value string) {
|
||||
item := model.CacheItem{
|
||||
item := models.CacheItem{
|
||||
Key: key,
|
||||
Value: value,
|
||||
Group: cc.group,
|
||||
@ -29,7 +29,7 @@ func (cc *CacheClient) Insert(key string, value string) {
|
||||
cacheStorage = append(cacheStorage, &item)
|
||||
}
|
||||
|
||||
func (cc *CacheClient) FindByKey(key string) (*model.CacheItem, error) {
|
||||
func (cc *CacheClient) FindByKey(key string) (*models.CacheItem, error) {
|
||||
for _, item := range cacheStorage {
|
||||
if item.Group != cc.group {
|
||||
continue
|
||||
@ -46,10 +46,10 @@ func (cc *CacheClient) FindByKey(key string) (*model.CacheItem, error) {
|
||||
return item, nil
|
||||
}
|
||||
|
||||
return &model.CacheItem{}, ErrCacheRecordMissing
|
||||
return &models.CacheItem{}, ErrCacheRecordMissing
|
||||
}
|
||||
|
||||
func (cc *CacheClient) FindByValue(value string) (*model.CacheItem, error) {
|
||||
func (cc *CacheClient) FindByValue(value string) (*models.CacheItem, error) {
|
||||
for _, item := range cacheStorage {
|
||||
if item.Group != cc.group {
|
||||
continue
|
||||
@ -65,5 +65,5 @@ func (cc *CacheClient) FindByValue(value string) (*model.CacheItem, error) {
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
return &model.CacheItem{}, ErrCacheRecordMissing
|
||||
return &models.CacheItem{}, ErrCacheRecordMissing
|
||||
}
|
||||
|
4
services/cache/common.go
vendored
4
services/cache/common.go
vendored
@ -3,11 +3,11 @@ package cache
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/jtom38/newsbot/collector/domain/model"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
var (
|
||||
cacheStorage []*model.CacheItem
|
||||
cacheStorage []*models.CacheItem
|
||||
|
||||
ErrCacheRecordMissing = errors.New("unable to find the requested record")
|
||||
)
|
||||
|
6
services/cache/monitor.go
vendored
6
services/cache/monitor.go
vendored
@ -3,7 +3,7 @@ package cache
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jtom38/newsbot/collector/domain/model"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
)
|
||||
|
||||
// When a record becomes tainted, it needs to be renewed or it will be dropped from the cache.
|
||||
@ -36,8 +36,8 @@ func (cam CacheAgeMonitor) CheckExpiredEntries() {
|
||||
}
|
||||
|
||||
// This creates a new slice and skips over the item that needs to be dropped
|
||||
func (cam CacheAgeMonitor) removeEntry(index int) []*model.CacheItem {
|
||||
var temp []*model.CacheItem
|
||||
func (cam CacheAgeMonitor) removeEntry(index int) []*models.CacheItem {
|
||||
var temp []*models.CacheItem
|
||||
for i, item := range cacheStorage {
|
||||
if i != index {
|
||||
temp = append(temp, item)
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"github.com/go-rod/rod"
|
||||
"github.com/go-rod/rod/lib/launcher"
|
||||
"github.com/jtom38/newsbot/collector/database"
|
||||
"github.com/jtom38/newsbot/collector/domain/model"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
"github.com/jtom38/newsbot/collector/services/config"
|
||||
)
|
||||
|
||||
@ -65,8 +65,8 @@ func (rc *RedditClient) GetPage(parser *rod.Browser, url string) *rod.Page {
|
||||
|
||||
// GetContent() reaches out to Reddit and pulls the Json data.
|
||||
// It will then convert the data to a struct and return the struct.
|
||||
func (rc *RedditClient) GetContent() (model.RedditJsonContent, error) {
|
||||
var items model.RedditJsonContent = model.RedditJsonContent{}
|
||||
func (rc *RedditClient) GetContent() (models.RedditJsonContent, error) {
|
||||
var items models.RedditJsonContent = models.RedditJsonContent{}
|
||||
|
||||
// TODO Wire this to support the config options
|
||||
Url := fmt.Sprintf("%v.json", rc.record.Url)
|
||||
@ -88,7 +88,7 @@ func (rc *RedditClient) GetContent() (model.RedditJsonContent, error) {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (rc *RedditClient) ConvertToArticles(items model.RedditJsonContent) []database.Article {
|
||||
func (rc *RedditClient) ConvertToArticles(items models.RedditJsonContent) []database.Article {
|
||||
var redditArticles []database.Article
|
||||
for _, item := range items.Data.Children {
|
||||
var article database.Article
|
||||
@ -104,7 +104,7 @@ func (rc *RedditClient) ConvertToArticles(items model.RedditJsonContent) []datab
|
||||
|
||||
// ConvertToArticle() will take the reddit model struct and convert them over to Article structs.
|
||||
// This data can be passed to the database.
|
||||
func (rc *RedditClient) convertToArticle(source model.RedditPost) (database.Article, error) {
|
||||
func (rc *RedditClient) convertToArticle(source models.RedditPost) (database.Article, error) {
|
||||
var item database.Article
|
||||
|
||||
if source.Content == "" && source.Url != "" {
|
||||
@ -131,7 +131,7 @@ func (rc *RedditClient) convertToArticle(source model.RedditPost) (database.Arti
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (rc *RedditClient) convertPicturePost(source model.RedditPost) database.Article {
|
||||
func (rc *RedditClient) convertPicturePost(source models.RedditPost) database.Article {
|
||||
var item = database.Article{
|
||||
Sourceid: rc.record.ID,
|
||||
Title: source.Title,
|
||||
@ -149,7 +149,7 @@ func (rc *RedditClient) convertPicturePost(source model.RedditPost) database.Art
|
||||
return item
|
||||
}
|
||||
|
||||
func (rc *RedditClient) convertTextPost(source model.RedditPost) database.Article {
|
||||
func (rc *RedditClient) convertTextPost(source models.RedditPost) database.Article {
|
||||
var item = database.Article{
|
||||
Sourceid: rc.record.ID,
|
||||
Tags: "a",
|
||||
@ -164,7 +164,7 @@ func (rc *RedditClient) convertTextPost(source model.RedditPost) database.Articl
|
||||
return item
|
||||
}
|
||||
|
||||
func (rc *RedditClient) convertVideoPost(source model.RedditPost) database.Article {
|
||||
func (rc *RedditClient) convertVideoPost(source models.RedditPost) database.Article {
|
||||
var item = database.Article{
|
||||
Sourceid: rc.record.ID,
|
||||
Tags: "a",
|
||||
@ -180,7 +180,7 @@ func (rc *RedditClient) convertVideoPost(source model.RedditPost) database.Artic
|
||||
}
|
||||
|
||||
// This post is nothing more then a redirect to another location.
|
||||
func (rc *RedditClient) convertRedirectPost(source model.RedditPost) database.Article {
|
||||
func (rc *RedditClient) convertRedirectPost(source models.RedditPost) database.Article {
|
||||
var item = database.Article{
|
||||
Sourceid: rc.record.ID,
|
||||
Tags: "a",
|
||||
|
@ -4,16 +4,16 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/jtom38/newsbot/collector/domain/model"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
"github.com/jtom38/newsbot/collector/services/cache"
|
||||
"github.com/mmcdole/gofeed"
|
||||
)
|
||||
|
||||
type rssClient struct {
|
||||
SourceRecord model.Sources
|
||||
SourceRecord models.Sources
|
||||
}
|
||||
|
||||
func NewRssClient(sourceRecord model.Sources) rssClient {
|
||||
func NewRssClient(sourceRecord models.Sources) rssClient {
|
||||
client := rssClient{
|
||||
SourceRecord: sourceRecord,
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ package input_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jtom38/newsbot/collector/domain/model"
|
||||
"github.com/jtom38/newsbot/collector/domain/models"
|
||||
"github.com/jtom38/newsbot/collector/services/input"
|
||||
)
|
||||
|
||||
var rssRecord = model.Sources{
|
||||
var rssRecord = models.Sources{
|
||||
ID: 1,
|
||||
Name: "ArsTechnica",
|
||||
Url: "https://feeds.arstechnica.com/arstechnica/index",
|
||||
|
Loading…
Reference in New Issue
Block a user