Compare commits

..

3 Commits

14 changed files with 1738 additions and 950 deletions

3
.gitignore vendored
View File

@ -4,9 +4,6 @@ __debug_bin
server server
.vscode .vscode
# hide the swagger files in the repo
docs/
# Binaries for programs and plugins # Binaries for programs and plugins
*.exe *.exe
*.exe~ *.exe~

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,107 @@
basePath: /api basePath: /api
definitions: definitions:
domain.ArticleAndSourceModel:
properties:
article:
$ref: '#/definitions/domain.ArticleDto'
source:
$ref: '#/definitions/domain.SourceDto'
type: object
domain.ArticleDetailedResponse:
properties:
message:
type: string
payload:
$ref: '#/definitions/domain.ArticleAndSourceModel'
type: object
domain.ArticleDto:
properties:
authorImage:
type: string
authorName:
type: string
description:
type: string
id:
type: integer
isVideo:
type: boolean
pubDate:
type: string
sourceId:
type: integer
tags:
type: string
thumbnail:
type: string
title:
type: string
url:
type: string
type: object
domain.ArticleResponse:
properties:
message:
type: string
payload:
items:
$ref: '#/definitions/domain.ArticleDto'
type: array
type: object
domain.BaseResponse:
properties:
message:
type: string
type: object
domain.DiscordWebHookDto:
properties:
channel:
type: string
enabled:
type: boolean
id:
type: integer
server:
type: string
url:
description: |-
Name string `json:"name"`
Key string `json:"key"`
type: string
type: object
domain.DiscordWebhookResponse:
properties:
message:
type: string
payload:
items:
$ref: '#/definitions/domain.DiscordWebHookDto'
type: array
type: object
domain.SourceDto:
properties:
enabled:
type: boolean
id:
type: integer
name:
type: string
source:
type: string
tags:
type: string
url:
type: string
type: object
domain.SourcesResponse:
properties:
message:
type: string
payload:
items:
$ref: '#/definitions/domain.SourceDto'
type: array
type: object
models.ArticleDetailsDto: models.ArticleDetailsDto:
properties: properties:
authorImage: authorImage:
@ -31,37 +133,6 @@ definitions:
videoWidth: videoWidth:
type: integer type: integer
type: object 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: models.DiscordQueueDetailsDto:
properties: properties:
article: article:
@ -125,61 +196,14 @@ definitions:
sourceid: sourceid:
type: string type: string
type: object type: object
routes.ApiError: v1.ApiError:
properties: properties:
message: message:
type: string type: string
status: status:
type: integer type: integer
type: object type: object
routes.ArticleDetailsResult: v1.ListDiscordWebHooksQueueResults:
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: properties:
message: message:
type: string type: string
@ -190,29 +214,7 @@ definitions:
status: status:
type: integer type: integer
type: object type: object
routes.ListDiscordWebhooks: v1.ListSubscriptionDetails:
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: properties:
message: message:
type: string type: string
@ -223,7 +225,7 @@ definitions:
status: status:
type: integer type: integer
type: object type: object
routes.ListSubscriptions: v1.ListSubscriptions:
properties: properties:
message: message:
type: string type: string
@ -252,14 +254,22 @@ paths:
"200": "200":
description: OK description: OK
schema: schema:
$ref: '#/definitions/routes.ArticlesListResults' $ref: '#/definitions/domain.ArticleResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Lists the top 25 records ordering from newest to oldest. summary: Lists the top 25 records ordering from newest to oldest.
tags: tags:
- Articles - Articles
/articles/{ID}: /articles/{ID}:
get: get:
parameters: parameters:
- description: uuid - description: int
in: path in: path
name: ID name: ID
required: true required: true
@ -270,14 +280,22 @@ paths:
"200": "200":
description: OK description: OK
schema: schema:
$ref: '#/definitions/routes.ArticleGetResults' $ref: '#/definitions/domain.ArticleResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Returns an article based on defined ID. summary: Returns an article based on defined ID.
tags: tags:
- Articles - Articles
/articles/{ID}/details: /articles/{ID}/details:
get: get:
parameters: parameters:
- description: uuid - description: int
in: path in: path
name: ID name: ID
required: true required: true
@ -288,14 +306,22 @@ paths:
"200": "200":
description: OK description: OK
schema: schema:
$ref: '#/definitions/routes.ArticleDetailsResult' $ref: '#/definitions/domain.ArticleDetailedResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Returns an article and source based on defined ID. summary: Returns an article and source based on defined ID.
tags: tags:
- Articles - Articles
/articles/by/sourceid: /articles/by/sourceid:
get: get:
parameters: parameters:
- description: Source ID UUID - description: source id
in: query in: query
name: id name: id
required: true required: true
@ -310,7 +336,15 @@ paths:
"200": "200":
description: OK description: OK
schema: schema:
$ref: '#/definitions/routes.ArticlesListResults' $ref: '#/definitions/domain.ArticleResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Finds the articles based on the SourceID provided. Returns the top summary: Finds the articles based on the SourceID provided. Returns the top
25. 25.
tags: tags:
@ -319,8 +353,20 @@ paths:
get: get:
produces: produces:
- application/json - application/json
responses: {} responses:
summary: Returns the top 100 entries from the queue to be processed. "200":
description: OK
schema:
$ref: '#/definitions/domain.DiscordWebhookResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Returns the top 100
tags: tags:
- Discord - Discord
- Webhook - Webhook
@ -332,7 +378,19 @@ paths:
name: id name: id
required: true required: true
type: string type: string
responses: {} responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.DiscordWebhookResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Deletes a record by ID. summary: Deletes a record by ID.
tags: tags:
- Discord - Discord
@ -344,8 +402,20 @@ paths:
in: path in: path
name: id name: id
required: true required: true
type: string type: integer
responses: {} responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.DiscordWebhookResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Disables a Webhook from being used. summary: Disables a Webhook from being used.
tags: tags:
- Discord - Discord
@ -357,7 +427,7 @@ paths:
in: path in: path
name: id name: id
required: true required: true
type: string type: integer
responses: {} responses: {}
summary: Enables a source to continue processing. summary: Enables a source to continue processing.
tags: tags:
@ -370,30 +440,26 @@ paths:
in: path in: path
name: id name: id
required: true required: true
type: string type: integer
produces: produces:
- application/json - application/json
responses: responses:
"200": "200":
description: OK description: OK
schema: schema:
$ref: '#/definitions/routes.GetDiscordWebhook' $ref: '#/definitions/domain.DiscordWebhookResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Returns the top 100 entries from the queue to be processed. summary: Returns the top 100 entries from the queue to be processed.
tags: tags:
- Discord - Discord
- Webhook - Webhook
patch:
parameters:
- description: id
in: path
name: id
required: true
type: string
responses: {}
summary: Updates a valid discord webhook ID based on the body given.
tags:
- Discord
- Webhook
/discord/webhooks/by/serverAndChannel: /discord/webhooks/by/serverAndChannel:
get: get:
parameters: parameters:
@ -413,7 +479,15 @@ paths:
"200": "200":
description: OK description: OK
schema: schema:
$ref: '#/definitions/routes.ListDiscordWebhooks' $ref: '#/definitions/domain.DiscordWebhookResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Returns all the known web hooks based on the Server and Channel given. summary: Returns all the known web hooks based on the Server and Channel given.
tags: tags:
- Discord - Discord
@ -436,7 +510,19 @@ paths:
name: channel name: channel
required: true required: true
type: string type: string
responses: {} responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.DiscordWebhookResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Creates a new record for a discord web hook to post data to. summary: Creates a new record for a discord web hook to post data to.
tags: tags:
- Discord - Discord
@ -449,23 +535,42 @@ paths:
"200": "200":
description: ok description: ok
schema: schema:
$ref: '#/definitions/routes.ListDiscordWebHooksQueueResults' $ref: '#/definitions/v1.ListDiscordWebHooksQueueResults'
summary: Returns the top 100 entries from the queue to be processed. summary: Returns the top 100 entries from the queue to be processed.
tags: tags:
- Queue - Queue
/settings/{key}:
get:
parameters:
- description: Settings Key value
in: path
name: key
required: true
type: string
produces:
- application/json
responses: {}
summary: Returns a object based on the Key that was given.
tags:
- Settings
/sources: /sources:
get: get:
parameters:
- description: page number
in: query
name: page
type: string
produces: produces:
- application/json - application/json
responses: responses:
"200": "200":
description: ok description: ok
schema: schema:
$ref: '#/definitions/routes.ListSources' $ref: '#/definitions/domain.SourcesResponse'
"400": "400":
description: Unable to reach SQL or Data problems description: Unable to reach SQL or Data problems
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/domain.BaseResponse'
summary: Lists the top 50 records summary: Lists the top 50 records
tags: tags:
- Source - Source
@ -476,26 +581,22 @@ paths:
in: path in: path
name: id name: id
required: true required: true
type: string type: integer
produces: produces:
- application/json - application/json
responses: responses:
"200": "200":
description: ok description: ok
schema: schema:
$ref: '#/definitions/routes.GetSource' $ref: '#/definitions/domain.SourcesResponse'
"204":
description: No record found.
schema:
$ref: '#/definitions/routes.ApiError'
"400": "400":
description: Unable to query SQL. description: Bad Request
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/domain.BaseResponse'
"500": "500":
description: Failed to process data from SQL. description: Internal Server Error
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/domain.BaseResponse'
summary: Returns a single entity by ID summary: Returns a single entity by ID
tags: tags:
- Source - Source
@ -517,8 +618,20 @@ paths:
in: path in: path
name: id name: id
required: true required: true
type: string type: integer
responses: {} responses:
"200":
description: ok
schema:
$ref: '#/definitions/domain.SourcesResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Disables a source from processing. summary: Disables a source from processing.
tags: tags:
- Source - Source
@ -530,7 +643,19 @@ paths:
name: id name: id
required: true required: true
type: string type: string
responses: {} responses:
"200":
description: ok
schema:
$ref: '#/definitions/domain.SourcesResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Enables a source to continue processing. summary: Enables a source to continue processing.
tags: tags:
- Source - Source
@ -542,21 +667,25 @@ paths:
name: source name: source
required: true required: true
type: string type: string
- description: page number
in: query
name: page
type: string
produces: produces:
- application/json - application/json
responses: responses:
"200": "200":
description: ok description: ok
schema: schema:
$ref: '#/definitions/routes.ListSources' $ref: '#/definitions/domain.SourcesResponse'
"400": "400":
description: Unable to query SQL. description: Bad Request
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/domain.BaseResponse'
"500": "500":
description: Problems with data. description: Internal Server Error
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/domain.BaseResponse'
summary: 'Lists the top 50 records based on the name given. Example: reddit' summary: 'Lists the top 50 records based on the name given. Example: reddit'
tags: tags:
- Source - Source
@ -579,19 +708,15 @@ paths:
"200": "200":
description: ok description: ok
schema: schema:
$ref: '#/definitions/routes.GetSource' $ref: '#/definitions/domain.SourcesResponse'
"204":
description: No record found.
schema:
$ref: '#/definitions/routes.ApiError'
"400": "400":
description: Unable to query SQL. description: Bad Request
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/domain.BaseResponse'
"500": "500":
description: Failed to process data from SQL. description: Internal Server Error
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/domain.BaseResponse'
summary: Returns a single entity by ID summary: Returns a single entity by ID
tags: tags:
- Source - Source
@ -608,10 +733,51 @@ paths:
name: url name: url
required: true required: true
type: string type: string
responses: {} responses:
"200":
description: ok
schema:
$ref: '#/definitions/domain.SourcesResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Creates a new reddit source to monitor. summary: Creates a new reddit source to monitor.
tags: tags:
- Source - Source
/sources/new/rss:
post:
parameters:
- description: Site Name
in: query
name: name
required: true
type: string
- description: RSS Url
in: query
name: url
required: true
type: string
responses:
"200":
description: ok
schema:
$ref: '#/definitions/domain.SourcesResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.BaseResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.BaseResponse'
summary: Creates a new rss source to monitor.
tags:
- Source
/sources/new/twitch: /sources/new/twitch:
post: post:
parameters: parameters:
@ -649,15 +815,15 @@ paths:
"200": "200":
description: ok description: ok
schema: schema:
$ref: '#/definitions/routes.ListSubscriptions' $ref: '#/definitions/v1.ListSubscriptions'
"400": "400":
description: Unable to reach SQL. description: Unable to reach SQL.
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/v1.ApiError'
"500": "500":
description: Failed to process data from SQL. description: Failed to process data from SQL.
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/v1.ApiError'
summary: Returns the top 100 entries from the queue to be processed. summary: Returns the top 100 entries from the queue to be processed.
tags: tags:
- Subscription - Subscription
@ -675,7 +841,7 @@ paths:
"200": "200":
description: ok description: ok
schema: schema:
$ref: '#/definitions/routes.ListSubscriptions' $ref: '#/definitions/v1.ListSubscriptions'
summary: Returns the top 100 entries from the queue to be processed. summary: Returns the top 100 entries from the queue to be processed.
tags: tags:
- Subscription - Subscription
@ -693,15 +859,15 @@ paths:
"200": "200":
description: ok description: ok
schema: schema:
$ref: '#/definitions/routes.ListSubscriptions' $ref: '#/definitions/v1.ListSubscriptions'
"400": "400":
description: Unable to reach SQL or Data problems description: Unable to reach SQL or Data problems
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/v1.ApiError'
"500": "500":
description: Data problems description: Data problems
schema: schema:
$ref: '#/definitions/routes.ApiError' $ref: '#/definitions/v1.ApiError'
summary: Returns the top 100 entries from the queue to be processed. summary: Returns the top 100 entries from the queue to be processed.
tags: tags:
- Subscription - Subscription
@ -713,7 +879,7 @@ paths:
"200": "200":
description: ok description: ok
schema: schema:
$ref: '#/definitions/routes.ListSubscriptionDetails' $ref: '#/definitions/v1.ListSubscriptionDetails'
summary: Returns the top 50 entries with full deatils on the source and output. summary: Returns the top 50 entries with full deatils on the source and output.
tags: tags:
- Subscription - Subscription

View File

@ -23,9 +23,9 @@ type DiscordQueueDto struct {
} }
type DiscordWebHookDto struct { type DiscordWebHookDto struct {
ID uint `json:"id"` ID int64 `json:"id"`
Name string `json:"name"` //Name string `json:"name"`
Key string `json:"key"` //Key string `json:"key"`
Url string `json:"url"` Url string `json:"url"`
Server string `json:"server"` Server string `json:"server"`
Channel string `json:"channel"` Channel string `json:"channel"`

View File

@ -35,8 +35,6 @@ type DiscordWebHookEntity struct {
CreatedAt time.Time CreatedAt time.Time
UpdatedAt time.Time UpdatedAt time.Time
DeletedAt time.Time DeletedAt time.Time
//Name string
//Key string
Url string Url string
Server string Server string
Channel string Channel string

View File

@ -15,7 +15,7 @@ type ArticleAndSourceModel struct {
Source SourceDto `json:"source"` Source SourceDto `json:"source"`
} }
type ArticleDetailResponse struct { type ArticleDetailedResponse struct {
BaseResponse BaseResponse
Payload ArticleAndSourceModel `json:"payload"` Payload ArticleAndSourceModel `json:"payload"`
} }
@ -24,3 +24,8 @@ type DiscordWebhookResponse struct {
BaseResponse BaseResponse
Payload []DiscordWebHookDto `json:"payload"` Payload []DiscordWebHookDto `json:"payload"`
} }
type SourcesResponse struct {
BaseResponse
Payload []SourceDto `json:"payload"`
}

View File

@ -45,7 +45,7 @@ func (s *Handler) listArticles(c echo.Context) error {
// @Produce application/json // @Produce application/json
// @Tags Articles // @Tags Articles
// @Router /articles/{ID} [get] // @Router /articles/{ID} [get]
// @Success 200 {object} ArticleGetResults "OK" // @Success 200 {object} domain.ArticleResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
func (s *Handler) getArticle(c echo.Context) error { func (s *Handler) getArticle(c echo.Context) error {
@ -79,11 +79,11 @@ func (s *Handler) getArticle(c echo.Context) error {
// @Produce application/json // @Produce application/json
// @Tags Articles // @Tags Articles
// @Router /articles/{ID}/details [get] // @Router /articles/{ID}/details [get]
// @Success 200 {object} ArticleDetailsResult "OK" // @Success 200 {object} domain.ArticleDetailedResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
func (s *Handler) getArticleDetails(c echo.Context) error { func (s *Handler) getArticleDetails(c echo.Context) error {
p := domain.ArticleDetailResponse{ p := domain.ArticleDetailedResponse{
BaseResponse: domain.BaseResponse{ BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess, Message: ResponseMessageSuccess,
}, },
@ -115,12 +115,12 @@ func (s *Handler) getArticleDetails(c echo.Context) error {
// ListArticlesBySourceID // ListArticlesBySourceID
// @Summary Finds the articles based on the SourceID provided. Returns the top 25. // @Summary Finds the articles based on the SourceID provided. Returns the top 25.
// @Param id query string true // @Param id query string true "source id"
// @Param page query int false "Page to query" // @Param page query int false "Page to query"
// @Produce application/json // @Produce application/json
// @Tags Articles // @Tags Articles
// @Router /articles/by/sourceid [get] // @Router /articles/by/sourceid [get]
// @Success 200 {object} ArticlesListResults "OK" // @Success 200 {object} domain.ArticleResponse "OK"
// @Failure 400 {object} domain.BaseResponse // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse // @Failure 500 {object} domain.BaseResponse
func (s *Handler) ListArticlesBySourceId(c echo.Context) error { func (s *Handler) ListArticlesBySourceId(c echo.Context) error {

View File

@ -1,84 +1,66 @@
package v1 package v1
import ( import (
"fmt"
"net/http" "net/http"
"strconv"
"strings" "strings"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain" "git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models" "git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"github.com/google/uuid"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
type ListDiscordWebhooks struct {
ApiStatusModel
Payload []models.DiscordWebHooksDto `json:"payload"`
}
type GetDiscordWebhook struct {
ApiStatusModel
Payload models.DiscordWebHooksDto `json:"payload"`
}
// ListDiscordWebhooks // ListDiscordWebhooks
// @Summary Returns the top 100 entries from the queue to be processed. // @Summary Returns the top 100
// @Produce application/json // @Produce application/json
// @Tags Discord, Webhook // @Tags Discord, Webhook
// @Router /discord/webhooks [get] // @Router /discord/webhooks [get]
// @Success 200 {object} domain.DiscordWebhookResponse
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) ListDiscordWebHooks(c echo.Context) error { func (s *Handler) ListDiscordWebHooks(c echo.Context) error {
p := ListDiscordWebhooks{ p := domain.DiscordWebhookResponse{
ApiStatusModel: ApiStatusModel{ BaseResponse: domain.BaseResponse{
Message: "OK", Message: ResponseMessageSuccess,
StatusCode: http.StatusOK,
}, },
} }
res, err := s.dto.ListDiscordWebHooks(c.Request().Context(), 50) res, err := s.repo.DiscordWebHooks.ListByServerName(c.Request().Context(), "")
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, err) return c.JSON(http.StatusInternalServerError, err)
} }
p.Payload = res p.Payload = services.DiscordWebhooksToDto(res)
return c.JSON(http.StatusOK, p) return c.JSON(http.StatusOK, p)
} }
// GetDiscordWebHook // GetDiscordWebHook
// @Summary Returns the top 100 entries from the queue to be processed. // @Summary Returns the top 100 entries from the queue to be processed.
// @Produce application/json // @Produce application/json
// @Param id path string true "id" // @Param id path int true "id"
// @Tags Discord, Webhook // @Tags Discord, Webhook
// @Router /discord/webhooks/{id} [get] // @Router /discord/webhooks/{id} [get]
// @Success 200 {object} GetDiscordWebhook "OK" // @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) GetDiscordWebHooksById(c echo.Context) error { func (s *Handler) GetDiscordWebHooksById(c echo.Context) error {
p := GetDiscordWebhook{ p := domain.DiscordWebhookResponse{
ApiStatusModel: ApiStatusModel{ BaseResponse: domain.BaseResponse{
Message: "OK", Message: ResponseMessageSuccess,
StatusCode: http.StatusOK,
}, },
} }
_id := c.Param("ID") id, err := strconv.Atoi(c.Param("ID"))
if _id == "" { if err != nil {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{ s.WriteError(c, err, http.StatusBadRequest)
Message: ErrIdValueMissing,
})
} }
uuid, err := uuid.Parse(_id) res, err := s.repo.DiscordWebHooks.GetById(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{ s.WriteError(c, err, http.StatusInternalServerError)
Message: ErrUnableToParseId,
})
} }
var dtos []domain.DiscordWebHookDto
res, err := s.dto.GetDiscordWebhook(c.Request().Context(), uuid) dtos = append(dtos, services.DiscordWebhookToDto(res))
if err != nil { p.Payload = dtos
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: ErrNoRecordFound,
})
}
p.Payload = res
return c.JSON(http.StatusOK, p) return c.JSON(http.StatusOK, p)
} }
@ -89,37 +71,32 @@ func (s *Handler) GetDiscordWebHooksById(c echo.Context) error {
// @Param channel query string true "memes" // @Param channel query string true "memes"
// @Tags Discord, Webhook // @Tags Discord, Webhook
// @Router /discord/webhooks/by/serverAndChannel [get] // @Router /discord/webhooks/by/serverAndChannel [get]
// @Success 200 {object} ListDiscordWebhooks "OK" // @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) GetDiscordWebHooksByServerAndChannel(c echo.Context) error { func (s *Handler) GetDiscordWebHooksByServerAndChannel(c echo.Context) error {
p := ListDiscordWebhooks{ p := domain.DiscordWebhookResponse{
ApiStatusModel: ApiStatusModel{ BaseResponse: domain.BaseResponse{
Message: "OK", Message: ResponseMessageSuccess,
StatusCode: http.StatusOK,
}, },
} }
_server := c.QueryParam("server") _server := c.QueryParam("server")
if _server == "" { if _server == "" {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{ s.WriteMessage(c, "server was not defined", http.StatusBadRequest)
Message: ErrIdValueMissing,
})
} }
_channel := c.QueryParam("channel") _channel := c.QueryParam("channel")
if _channel == "" { if _channel == "" {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{ s.WriteMessage(c, "channel was not defined", http.StatusBadRequest)
Message: fmt.Sprintf("%s channel", ErrParameterMissing),
})
} }
res, err := s.dto.GetDiscordWebHookByServerAndChannel(c.Request().Context(), _server, _channel) res, err := s.repo.DiscordWebHooks.ListByServerAndChannel(c.Request().Context(), _server, _channel)
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ s.WriteError(c, err, http.StatusInternalServerError)
Message: err.Error(),
})
} }
p.Payload = res p.Payload = services.DiscordWebhooksToDto(res)
return c.JSON(http.StatusOK, p) return c.JSON(http.StatusOK, p)
} }
@ -130,6 +107,9 @@ func (s *Handler) GetDiscordWebHooksByServerAndChannel(c echo.Context) error {
// @Param channel query string true "Channel name" // @Param channel query string true "Channel name"
// @Tags Discord, Webhook // @Tags Discord, Webhook
// @Router /discord/webhooks/new [post] // @Router /discord/webhooks/new [post]
// @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) NewDiscordWebHook(c echo.Context) error { func (s *Handler) NewDiscordWebHook(c echo.Context) error {
_url := c.QueryParam("url") _url := c.QueryParam("url")
_server := c.QueryParam("server") _server := c.QueryParam("server")
@ -155,26 +135,42 @@ func (s *Handler) NewDiscordWebHook(c echo.Context) error {
Message: "channel is missing", Message: "channel is missing",
}) })
} }
params := database.CreateDiscordWebHookParams{
ID: uuid.New(),
Url: _url,
Server: _server,
Channel: _channel,
Enabled: true,
}
s.Db.CreateDiscordWebHook(c.Request().Context(), params)
return c.JSON(http.StatusOK, params) rows, err := s.repo.DiscordWebHooks.Create(c.Request().Context(), _url, _server, _channel, true)
if err != nil {
s.WriteError(c, err, http.StatusInternalServerError)
}
if rows != 1 {
s.WriteMessage(c, "data was not written to database", http.StatusInternalServerError)
}
item, err := s.repo.DiscordWebHooks.GetByUrl(c.Request().Context(), _url)
if err != nil {
s.WriteError(c, err, http.StatusInternalServerError)
}
var dtos []domain.DiscordWebHookDto
dtos = append(dtos, services.DiscordWebhookToDto(item))
return c.JSON(http.StatusOK, domain.DiscordWebhookResponse{
BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
Payload: dtos,
})
} }
// DisableDiscordWebHooks // DisableDiscordWebHooks
// @Summary Disables a Webhook from being used. // @Summary Disables a Webhook from being used.
// @Param id path string true "id" // @Param id path int true "id"
// @Tags Discord, Webhook // @Tags Discord, Webhook
// @Router /discord/webhooks/{ID}/disable [post] // @Router /discord/webhooks/{ID}/disable [post]
// @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) disableDiscordWebHook(c echo.Context) error { func (s *Handler) disableDiscordWebHook(c echo.Context) error {
id := c.Param("ID") id, err := strconv.Atoi(c.Param("ID"))
uuid, err := uuid.Parse(id)
if err != nil { if err != nil {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{ return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(), Message: err.Error(),
@ -182,45 +178,76 @@ func (s *Handler) disableDiscordWebHook(c echo.Context) error {
} }
// Check to make sure we can find the record // Check to make sure we can find the record
_, err = s.Db.GetDiscordWebHooksByID(c.Request().Context(), uuid) _, err = s.repo.DiscordWebHooks.GetById(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error()) s.WriteError(c, err, http.StatusInternalServerError)
} }
err = s.Db.DisableDiscordWebHook(c.Request().Context(), uuid) // flip the it
updated, err := s.repo.DiscordWebHooks.Disable(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ s.WriteError(c, err, http.StatusInternalServerError)
Message: err.Error(),
})
} }
return nil
// make sure we got a row updated
if updated != 1 {
s.WriteMessage(c, "unexpected number of updates found", http.StatusInternalServerError)
}
item, err := s.repo.DiscordWebHooks.GetById(c.Request().Context(), int64(id))
if err != nil {
s.WriteError(c, err, http.StatusInternalServerError)
}
var dtos []domain.DiscordWebHookDto
dtos = append(dtos, services.DiscordWebhookToDto(item))
return c.JSON(http.StatusOK, domain.DiscordWebhookResponse{
BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
Payload: dtos,
})
} }
// EnableDiscordWebHook // EnableDiscordWebHook
// @Summary Enables a source to continue processing. // @Summary Enables a source to continue processing.
// @Param id path string true "id" // @Param id path int true "id"
// @Tags Discord, Webhook // @Tags Discord, Webhook
// @Router /discord/webhooks/{ID}/enable [post] // @Router /discord/webhooks/{ID}/enable [post]
func (s *Handler) enableDiscordWebHook(c echo.Context) error { func (s *Handler) enableDiscordWebHook(c echo.Context) error {
id := c.Param("ID") id, err := strconv.Atoi(c.Param("ID"))
uuid, err := uuid.Parse(id)
if err != nil { if err != nil {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{ s.WriteError(c, err, http.StatusBadRequest)
Message: err.Error(),
})
} }
// Check to make sure we can find the record // Check to make sure we can find the record
_, err = s.Db.GetDiscordWebHooksByID(c.Request().Context(), uuid) _, err = s.repo.DiscordWebHooks.GetById(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error()) s.WriteError(c, err, http.StatusBadRequest)
} }
err = s.Db.EnableDiscordWebHook(c.Request().Context(), uuid) updated, err := s.repo.DiscordWebHooks.Enable(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error()) s.WriteError(c, err, http.StatusInternalServerError)
} }
return nil
if updated != 1 {
s.WriteMessage(c, "unexpected number of updates found", http.StatusInternalServerError)
}
item, err := s.repo.DiscordWebHooks.GetById(c.Request().Context(), int64(id))
if err != nil {
s.WriteError(c, err, http.StatusInternalServerError)
}
var dtos []domain.DiscordWebHookDto
dtos = append(dtos, services.DiscordWebhookToDto(item))
return c.JSON(http.StatusOK, domain.DiscordWebhookResponse{
BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
Payload: dtos,
})
} }
// DeleteDiscordWebHook // DeleteDiscordWebHook
@ -228,28 +255,44 @@ func (s *Handler) enableDiscordWebHook(c echo.Context) error {
// @Param id path string true "id" // @Param id path string true "id"
// @Tags Discord, Webhook // @Tags Discord, Webhook
// @Router /discord/webhooks/{ID} [delete] // @Router /discord/webhooks/{ID} [delete]
// @Success 200 {object} domain.DiscordWebhookResponse "OK"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) deleteDiscordWebHook(c echo.Context) error { func (s *Handler) deleteDiscordWebHook(c echo.Context) error {
//var item model.Sources = model.Sources{} id, err := strconv.Atoi(c.Param("ID"))
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil { if err != nil {
return c.JSON(http.StatusBadRequest, err.Error()) return c.JSON(http.StatusBadRequest, err.Error())
} }
// Check to make sure we can find the record // Check to make sure we can find the record
_, err = s.Db.GetDiscordQueueByID(c.Request().Context(), uuid) _, err = s.repo.DiscordWebHooks.GetById(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error()) return c.JSON(http.StatusInternalServerError, err.Error())
} }
// Delete the record // Soft delete the record
err = s.Db.DeleteDiscordWebHooks(c.Request().Context(), uuid) updated, err := s.repo.DiscordWebHooks.SoftDelete(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error()) return c.JSON(http.StatusInternalServerError, err.Error())
} }
return nil if updated != 1 {
s.WriteMessage(c, "unexpected number of updates found", http.StatusInternalServerError)
}
item, err := s.repo.DiscordWebHooks.GetById(c.Request().Context(), int64(id))
if err != nil {
s.WriteError(c, err, http.StatusInternalServerError)
}
var dtos []domain.DiscordWebHookDto
dtos = append(dtos, services.DiscordWebhookToDto(item))
return c.JSON(http.StatusOK, domain.DiscordWebhookResponse{
BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
Payload: dtos,
})
} }
// UpdateDiscordWebHook // UpdateDiscordWebHook
@ -257,19 +300,31 @@ func (s *Handler) deleteDiscordWebHook(c echo.Context) error {
// @Param id path string true "id" // @Param id path string true "id"
// @Tags Discord, Webhook // @Tags Discord, Webhook
// @Router /discord/webhooks/{id} [patch] // @Router /discord/webhooks/{id} [patch]
func (s *Handler) UpdateDiscordWebHook(c echo.Context) error { // @Success 200 {object} domain.DiscordWebhookResponse "OK"
id := c.Param("ID") // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
uuid, err := uuid.Parse(id) //func (s *Handler) UpdateDiscordWebHook(c echo.Context) error {
if err != nil { // id, err := strconv.Atoi(c.Param("ID"))
return c.JSON(http.StatusInternalServerError, err.Error()) // if err != nil {
} // return c.JSON(http.StatusInternalServerError, err.Error())
// }
// Check to make sure we can find the record //
_, err = s.Db.GetDiscordQueueByID(c.Request().Context(), uuid) // // Check to make sure we can find the record
if err != nil { // _, err = s.repo.DiscordWebHooks.GetById(c.Request().Context(), int64(id))
return c.JSON(http.StatusInternalServerError, err.Error()) // if err != nil {
} // return c.JSON(http.StatusInternalServerError, err.Error())
// }
return nil //
} // // Soft delete the record
// updated, err := s.repo.DiscordWebHooks(c.Request().Context(), int64(id))
// if err != nil {
// return c.JSON(http.StatusInternalServerError, err.Error())
// }
//
// _, err = s.Db.GetDiscordQueueByID(c.Request().Context(), uuid)
// if err != nil {
// return c.JSON(http.StatusInternalServerError, err.Error())
// }
//
// return nil
//}

View File

@ -23,14 +23,11 @@ type Handler struct {
} }
const ( const (
HeaderContentType = "Content-Type" ErrParameterIdMissing = "The requested parameter ID was not found."
ErrParameterMissing = "The requested parameter was not found found:"
//ApplicationJson = "application/json" ErrUnableToParseId = "Unable to parse the requested ID"
ErrRecordMissing = "The requested record was not found"
ErrParameterIdMissing = "The requested parameter ID was not found." ErrFailedToCreateRecord = "The record was not created due to a database problem"
ErrParameterMissing = "The requested parameter was found found:"
ErrUnableToParseId = "Unable to parse the requested ID."
ErrRecordMissing = "The requested record was not found"
ResponseMessageSuccess = "Success" ResponseMessageSuccess = "Success"
) )
@ -60,14 +57,14 @@ func NewServer(ctx context.Context, db *database.Queries, configs services.Confi
articles.GET("/:id/details", s.getArticleDetails) articles.GET("/:id/details", s.getArticleDetails)
articles.GET("/by/source/:id", s.ListArticlesBySourceId) articles.GET("/by/source/:id", s.ListArticlesBySourceId)
dwh := v1.Group("/discord/webhooks") //dwh := v1.Group("/discord/webhooks")
dwh.GET("/", s.ListDiscordWebHooks) //dwh.GET("/", s.ListDiscordWebHooks)
dwh.POST("/new", s.NewDiscordWebHook) //dwh.POST("/new", s.NewDiscordWebHook)
dwh.GET("/by/serverAndChannel", s.GetDiscordWebHooksByServerAndChannel) //dwh.GET("/by/serverAndChannel", s.GetDiscordWebHooksByServerAndChannel)
dwh.GET("/:ID", s.GetDiscordWebHooksById) //dwh.GET("/:ID", s.GetDiscordWebHooksById)
dwh.DELETE("/:ID", s.deleteDiscordWebHook) //dwh.DELETE("/:ID", s.deleteDiscordWebHook)
dwh.POST("/:ID/disable", s.disableDiscordWebHook) //dwh.POST("/:ID/disable", s.disableDiscordWebHook)
dwh.POST("/:ID/enable", s.enableDiscordWebHook) //dwh.POST("/:ID/enable", s.enableDiscordWebHook)
//queue := v1.Group("/queue") //queue := v1.Group("/queue")
//queue.GET("/discord/webhooks", s.ListDiscordWebhookQueue) // TODO this needs to be reworked //queue.GET("/discord/webhooks", s.ListDiscordWebhookQueue) // TODO this needs to be reworked
@ -79,11 +76,11 @@ func NewServer(ctx context.Context, db *database.Queries, configs services.Confi
sources.GET("/", s.listSources) sources.GET("/", s.listSources)
sources.GET("/by/source", s.listSourcesBySource) sources.GET("/by/source", s.listSourcesBySource)
sources.GET("/by/sourceAndName", s.GetSourceBySourceAndName) sources.GET("/by/sourceAndName", s.GetSourceBySourceAndName)
sources.POST("/new/reddit", s.newRedditSource) //sources.POST("/new/reddit", s.newRedditSource)
sources.POST("/new/youtube", s.newYoutubeSource) //sources.POST("/new/youtube", s.newYoutubeSource)
sources.POST("/new/twitch", s.newTwitchSource) //sources.POST("/new/twitch", s.newTwitchSource)
sources.POST("/new/rss", s.newRssSource)
sources.GET("/:ID/", s.getSources) sources.GET("/:ID/", s.getSource)
sources.DELETE("/:ID/", s.deleteSources) sources.DELETE("/:ID/", s.deleteSources)
sources.POST("/:ID/disable", s.disableSource) sources.POST("/:ID/disable", s.disableSource)
sources.POST("/:ID/enable", s.enableSource) sources.POST("/:ID/enable", s.enableSource)

View File

@ -1 +0,0 @@
package v1_test

View File

@ -5,11 +5,13 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strconv"
"strings" "strings"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database" "git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain" "git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models" "git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
@ -26,115 +28,105 @@ type GetSource struct {
// ListSources // ListSources
// @Summary Lists the top 50 records // @Summary Lists the top 50 records
// @Param page query string false "page number"
// @Produce application/json // @Produce application/json
// @Tags Source // @Tags Source
// @Router /sources [get] // @Router /sources [get]
// @Success 200 {object} ListSources "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse "Unable to reach SQL or Data problems" // @Failure 400 {object} domain.BaseResponse "Unable to reach SQL or Data problems"
func (s *Handler) listSources(c echo.Context) error { func (s *Handler) listSources(c echo.Context) error {
//TODO Add top? resp := domain.SourcesResponse {
/* BaseResponse: domain.BaseResponse{
top := chi.URLParam(r, "top") Message: ResponseMessageSuccess,
topInt, err := strconv.ParseInt(top, 0, 32)
if err != nil {
panic(err)
}
res, err := s.Db.ListSources(r.Context(), int32(topInt))
*/
p := ListSources{
ApiStatusModel: ApiStatusModel{
StatusCode: http.StatusOK,
Message: "OK",
}, },
} }
page, err := strconv.Atoi(c.QueryParam("page"))
if err != nil {
page = 0
}
// Default way of showing all sources // Default way of showing all sources
items, err := s.dto.ListSources(c.Request().Context(), 50) items, err := s.repo.Sources.List(c.Request().Context(), page, 25)
if err != nil { if err != nil {
s.WriteError(c, err, http.StatusInternalServerError) s.WriteError(c, err, http.StatusInternalServerError)
} }
p.Payload = items resp.Payload = services.SourcesToDto(items)
return c.JSON(http.StatusOK, p) return c.JSON(http.StatusOK, resp)
} }
// ListSourcesBySource // ListSourcesBySource
// @Summary Lists the top 50 records based on the name given. Example: reddit // @Summary Lists the top 50 records based on the name given. Example: reddit
// @Param source query string true "Source Name" // @Param source query string true "Source Name"
// @Param page query string false "page number"
// @Produce application/json // @Produce application/json
// @Tags Source // @Tags Source
// @Router /sources/by/source [get] // @Router /sources/by/source [get]
// @Success 200 {object} ListSources "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} ApiError "Unable to query SQL." // @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} ApiError "Problems with data." // @Failure 500 {object} domain.BaseResponse
func (s *Handler) listSourcesBySource(c echo.Context) error { func (s *Handler) listSourcesBySource(c echo.Context) error {
//TODO Add top? resp := domain.SourcesResponse{
/* BaseResponse: domain.BaseResponse{
top := chi.URLParam(r, "top") Message: ResponseMessageSuccess,
topInt, err := strconv.ParseInt(top, 0, 32)
if err != nil {
panic(err)
}
res, err := s.Db.ListSources(r.Context(), int32(topInt))
*/
p := ListSources{
ApiStatusModel: ApiStatusModel{
StatusCode: http.StatusOK,
Message: "OK",
}, },
} }
source := c.QueryParam("source") source := c.QueryParam("source")
if source == "" {
s.WriteMessage(c, fmt.Sprintf("%s source", ErrParameterMissing), http.StatusBadRequest)
}
page, err := strconv.Atoi(c.QueryParam("page"))
if err != nil {
page = 0
}
// Shows the list by Sources.source // Shows the list by Sources.source
res, err := s.dto.ListSourcesBySource(c.Request().Context(), source) items, err := s.repo.Sources.ListBySource(c.Request().Context(), page, 25, source)
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(), Message: err.Error(),
}) })
} }
p.Payload = res resp.Payload = services.SourcesToDto(items)
return c.JSON(http.StatusOK, p) return c.JSON(http.StatusOK, resp)
} }
// GetSource // GetSource
// @Summary Returns a single entity by ID // @Summary Returns a single entity by ID
// @Param id path string true "uuid" // @Param id path int true "uuid"
// @Produce application/json // @Produce application/json
// @Tags Source // @Tags Source
// @Router /sources/{id} [get] // @Router /sources/{id} [get]
// @Success 200 {object} GetSource "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 204 {object} ApiError "No record found." // @Failure 400 {object} domain.BaseResponse
// @Failure 400 {object} ApiError "Unable to query SQL." // @Failure 500 {object} domain.BaseResponse
// @Failure 500 {object} ApiError "Failed to process data from SQL." func (s *Handler) getSource(c echo.Context) error {
func (s *Handler) getSources(c echo.Context) error { resp := domain.SourcesResponse{
payload := GetSource{ BaseResponse: domain.BaseResponse{
ApiStatusModel: ApiStatusModel{ Message: ResponseMessageSuccess,
Message: "OK",
StatusCode: http.StatusOK,
}, },
} }
id := c.Param("ID") id, err := strconv.Atoi(c.Param("ID"))
uuid, err := uuid.Parse(id)
if err != nil { if err != nil {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{ return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: ErrUnableToParseId, Message: ErrUnableToParseId,
}) })
} }
res, err := s.dto.GetSourceById(c.Request().Context(), uuid) item, err := s.repo.Sources.GetById(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ s.WriteError(c, err, http.StatusInternalServerError)
Message: ErrNoRecordFound,
})
} }
payload.Payload = res var dto []domain.SourceDto
return c.JSON(http.StatusOK, payload) dto = append(dto, services.SourceToDto(item))
resp.Payload = dto
return c.JSON(http.StatusOK, resp)
} }
// GetSourceByNameAndSource // GetSourceByNameAndSource
@ -144,15 +136,13 @@ func (s *Handler) getSources(c echo.Context) error {
// @Produce application/json // @Produce application/json
// @Tags Source // @Tags Source
// @Router /sources/by/sourceAndName [get] // @Router /sources/by/sourceAndName [get]
// @Success 200 {object} GetSource "ok" // @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 204 {object} ApiError "No record found." // @Failure 400 {object} domain.BaseResponse
// @Failure 400 {object} ApiError "Unable to query SQL." // @Failure 500 {object} domain.BaseResponse
// @Failure 500 {object} ApiError "Failed to process data from SQL."
func (s *Handler) GetSourceBySourceAndName(c echo.Context) error { func (s *Handler) GetSourceBySourceAndName(c echo.Context) error {
p := GetSource{ resp := domain.SourcesResponse{
ApiStatusModel: ApiStatusModel{ BaseResponse: domain.BaseResponse{
Message: "OK", Message: ResponseMessageSuccess,
StatusCode: http.StatusOK,
}, },
} }
@ -164,25 +154,15 @@ func (s *Handler) GetSourceBySourceAndName(c echo.Context) error {
}) })
} }
//name := c.QueryParam("name") item, err := s.repo.Sources.GetBySourceAndName(c.Request().Context(), param.Source, param.Name)
//if name == "" {
// s.WriteError(w, "Parameter 'name' was missing in the query.", http.StatusInternalServerError)
// return c.JSON(http.bad)
//}
//source := query["source"][0]
//if source == "" {
// s.WriteError(w, "The parameter 'source' was missing in the query.", http.StatusInternalServerError)
// return
//}
item, err := s.dto.GetSourceByNameAndSource(c.Request().Context(), param.Name, param.Source)
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error()) return c.JSON(http.StatusInternalServerError, err.Error())
} }
p.Payload = item var dto []domain.SourceDto
return c.JSON(http.StatusOK, p) dto = append(dto, services.SourceToDto(item))
resp.Payload = dto
return c.JSON(http.StatusOK, resp)
} }
// NewRedditSource // NewRedditSource
@ -191,7 +171,16 @@ func (s *Handler) GetSourceBySourceAndName(c echo.Context) error {
// @Param url query string true "url" // @Param url query string true "url"
// @Tags Source // @Tags Source
// @Router /sources/new/reddit [post] // @Router /sources/new/reddit [post]
// @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) newRedditSource(c echo.Context) error { func (s *Handler) newRedditSource(c echo.Context) error {
resp := domain.SourcesResponse{
BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
}
var param domain.NewSourceParamRequest var param domain.NewSourceParamRequest
err := c.Bind(&param) err := c.Bind(&param)
if err != nil { if err != nil {
@ -199,10 +188,6 @@ func (s *Handler) newRedditSource(c echo.Context) error {
Message: err.Error(), Message: err.Error(),
}) })
} }
//query := r.URL.Query()
//_name := query["name"][0]
//_url := query["url"][0]
//_tags := query["tags"][0]
if param.Url == "" { if param.Url == "" {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{ return c.JSON(http.StatusBadRequest, domain.BaseResponse{
@ -215,40 +200,25 @@ func (s *Handler) newRedditSource(c echo.Context) error {
}) })
} }
/* tags := fmt.Sprintf("twitch, %v, %s", param.Name, param.Tags)
var tags string rows, err := s.repo.Sources.Create(c.Request().Context(), domain.SourceCollectorReddit, param.Name, param.Url, tags, true)
if _tags == "" {
tags = fmt.Sprintf("twitch, %v", _name)
} else {
}
*/
tags := fmt.Sprintf("twitch, %v", param.Name)
params := database.CreateSourceParams{
ID: uuid.New(),
Site: "reddit",
Name: param.Name,
Source: "reddit",
Type: "feed",
Enabled: true,
Url: param.Url,
Tags: tags,
}
err = s.Db.CreateSource(c.Request().Context(), params)
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ s.WriteError(c, err, http.StatusInternalServerError)
Message: err.Error(),
})
} }
//s.WriteJson(w, &params)
bJson, err := json.Marshal(&params) if rows != 1 {
s.WriteMessage(c, ErrFailedToCreateRecord, http.StatusInternalServerError)
}
item, err := s.repo.Sources.GetBySourceAndName(c.Request().Context(), domain.SourceCollectorReddit, param.Name)
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error()) s.WriteError(c, err, http.StatusInternalServerError)
} }
return c.JSON(http.StatusOK, bJson) var dto []domain.SourceDto
dto = append(dto, services.SourceToDto(item))
resp.Payload = dto
return c.JSON(http.StatusOK, resp)
} }
// NewYoutubeSource // NewYoutubeSource
@ -362,6 +332,57 @@ func (s *Handler) newTwitchSource(c echo.Context) error {
return c.JSON(http.StatusOK, bJson) return c.JSON(http.StatusOK, bJson)
} }
// NewRssSource
// @Summary Creates a new rss source to monitor.
// @Param name query string true "Site Name"
// @Param url query string true "RSS Url"
// @Tags Source
// @Router /sources/new/rss [post]
// @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) newRssSource(c echo.Context) error {
resp := domain.SourcesResponse{
BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
}
var param domain.NewSourceParamRequest
err := c.Bind(&param)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(),
})
}
if param.Url == "" {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: "Url is missing a value",
})
}
tags := fmt.Sprintf("rss, %v, %s", param.Name, param.Tags)
rows, err := s.repo.Sources.Create(c.Request().Context(), domain.SourceCollectorRss, param.Name, param.Url, tags, true)
if err != nil {
s.WriteError(c, err, http.StatusInternalServerError)
}
if rows != 1 {
s.WriteMessage(c, ErrFailedToCreateRecord, http.StatusInternalServerError)
}
item, err := s.repo.Sources.GetBySourceAndName(c.Request().Context(), domain.SourceCollectorRss, param.Name)
if err != nil {
s.WriteError(c, err, http.StatusInternalServerError)
}
var dto []domain.SourceDto
dto = append(dto, services.SourceToDto(item))
resp.Payload = dto
return c.JSON(http.StatusOK, resp)
}
// DeleteSource // DeleteSource
// @Summary Marks a source as deleted based on its ID value. // @Summary Marks a source as deleted based on its ID value.
// @Param id path string true "id" // @Param id path string true "id"
@ -409,46 +430,44 @@ func (s *Handler) deleteSources(c echo.Context) error {
// DisableSource // DisableSource
// @Summary Disables a source from processing. // @Summary Disables a source from processing.
// @Param id path string true "id" // @Param id path int true "id"
// @Tags Source // @Tags Source
// @Router /sources/{id}/disable [post] // @Router /sources/{id}/disable [post]
// @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) disableSource(c echo.Context) error { func (s *Handler) disableSource(c echo.Context) error {
id := c.Param("ID") resp := domain.SourcesResponse {
uuid, err := uuid.Parse(id) BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
}
id, err := strconv.Atoi(c.Param("ID"))
if err != nil { if err != nil {
return c.JSON(http.StatusBadRequest, domain.BaseResponse{ s.WriteError(c, err, http.StatusBadRequest)
Message: err.Error(),
})
} }
// Check to make sure we can find the record // Check to make sure we can find the record
_, err = s.Db.GetSourceByID(c.Request().Context(), uuid) _, err = s.repo.Sources.GetById(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ s.WriteError(c, err, http.StatusBadRequest)
Message: err.Error(),
})
} }
err = s.Db.DisableSource(context.Background(), uuid) _, err = s.repo.Sources.Disable(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ s.WriteError(c, err, http.StatusInternalServerError)
Message: err.Error(),
})
} }
p := ApiStatusModel{ item, err := s.repo.Sources.GetById(c.Request().Context(), int64(id))
Message: "OK",
StatusCode: http.StatusOK,
}
b, err := json.Marshal(p)
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ s.WriteError(c, err, http.StatusInternalServerError)
Message: err.Error(),
})
} }
return c.JSON(http.StatusOK, b) var dto []domain.SourceDto
dto = append(dto, services.SourceToDto(item))
resp.Payload = dto
return c.JSON(http.StatusOK, resp)
} }
// EnableSource // EnableSource
@ -456,39 +475,39 @@ func (s *Handler) disableSource(c echo.Context) error {
// @Param id path string true "id" // @Param id path string true "id"
// @Tags Source // @Tags Source
// @Router /sources/{id}/enable [post] // @Router /sources/{id}/enable [post]
// @Success 200 {object} domain.SourcesResponse "ok"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) enableSource(c echo.Context) error { func (s *Handler) enableSource(c echo.Context) error {
id := c.Param("ID") resp := domain.SourcesResponse {
uuid, err := uuid.Parse(id) BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
}
id, err := strconv.Atoi(c.Param("ID"))
if err != nil { if err != nil {
return c.JSON(http.StatusBadRequest, err.Error()) s.WriteError(c, err, http.StatusBadRequest)
} }
// Check to make sure we can find the record // Check to make sure we can find the record
_, err = s.Db.GetSourceByID(c.Request().Context(), uuid) _, err = s.repo.Sources.GetById(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ s.WriteError(c, err, http.StatusBadRequest)
Message: err.Error(),
})
} }
err = s.Db.EnableSource(c.Request().Context(), uuid) _, err = s.repo.Sources.Enable(c.Request().Context(), int64(id))
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ s.WriteError(c, err, http.StatusInternalServerError)
Message: err.Error(),
})
} }
p := ApiStatusModel{ item, err := s.repo.Sources.GetById(c.Request().Context(), int64(id))
Message: "OK",
StatusCode: http.StatusOK,
}
b, err := json.Marshal(p)
if err != nil { if err != nil {
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{ s.WriteError(c, err, http.StatusInternalServerError)
Message: err.Error(),
})
} }
return c.JSON(http.StatusOK, b) var dto []domain.SourceDto
dto = append(dto, services.SourceToDto(item))
resp.Payload = dto
return c.JSON(http.StatusOK, resp)
} }

View File

@ -14,6 +14,7 @@ type Sources interface {
GetById(ctx context.Context, id int64) (domain.SourceEntity, error) GetById(ctx context.Context, id int64) (domain.SourceEntity, error)
GetByDisplayName(ctx context.Context, displayName string) (domain.SourceEntity, error) GetByDisplayName(ctx context.Context, displayName string) (domain.SourceEntity, error)
GetBySource(ctx context.Context, source string) (domain.SourceEntity, error) GetBySource(ctx context.Context, source string) (domain.SourceEntity, error)
GetBySourceAndName(ctx context.Context, source, name string) (domain.SourceEntity, error)
List(ctx context.Context, page, limit int) ([]domain.SourceEntity, error) List(ctx context.Context, page, limit int) ([]domain.SourceEntity, error)
ListBySource(ctx context.Context, page, limit int, source string) ([]domain.SourceEntity, error) ListBySource(ctx context.Context, page, limit int, source string) ([]domain.SourceEntity, error)
Enable(ctx context.Context, id int64) (int64, error) Enable(ctx context.Context, id int64) (int64, error)
@ -115,6 +116,29 @@ func (r sourceRepository) GetBySource(ctx context.Context, source string) (domai
return data[0], nil return data[0], nil
} }
func (r sourceRepository) GetBySourceAndName(ctx context.Context, source, name string) (domain.SourceEntity, error) {
b := sqlbuilder.NewSelectBuilder()
b.Select("*")
b.From("Sources").Where(
b.Equal("Source", source),
b.Equal("Name", name),
)
b.Limit(1)
query, args := b.Build()
rows, err := r.conn.QueryContext(ctx, query, args...)
if err != nil {
return domain.SourceEntity{}, err
}
data, err := r.processRows(rows)
if len(data) == 0 {
return domain.SourceEntity{}, err
}
return data[0], nil
}
func (r sourceRepository) List(ctx context.Context, page, limit int) ([]domain.SourceEntity, error) { func (r sourceRepository) List(ctx context.Context, page, limit int) ([]domain.SourceEntity, error) {
builder := sqlbuilder.NewSelectBuilder() builder := sqlbuilder.NewSelectBuilder()
builder.Select("*") builder.Select("*")

View File

@ -26,6 +26,24 @@ func ArticleToDto(item domain.ArticleEntity) domain.ArticleDto {
} }
} }
func DiscordWebhooksToDto(items []domain.DiscordWebHookEntity) []domain.DiscordWebHookDto{
var dtos []domain.DiscordWebHookDto
for _, item := range items {
dtos = append(dtos, DiscordWebhookToDto(item))
}
return dtos
}
func DiscordWebhookToDto(item domain.DiscordWebHookEntity) domain.DiscordWebHookDto {
return domain.DiscordWebHookDto{
ID: item.ID,
Server: item.Server,
Channel: item.Channel,
Url: item.Url,
Enabled: item.Enabled,
}
}
func SourcesToDto(items []domain.SourceEntity) []domain.SourceDto { func SourcesToDto(items []domain.SourceEntity) []domain.SourceDto {
var dtos []domain.SourceDto var dtos []domain.SourceDto
for _, item := range items { for _, item := range items {