Compare commits

...

8 Commits

19 changed files with 342 additions and 304 deletions

View File

@ -1,4 +1,4 @@
FROM golang:1.18.4 as build
FROM golang:1.22 as build
COPY . /app
WORKDIR /app

View File

@ -3,33 +3,26 @@ package domain
import "time"
type ArticleDto struct {
ID int64 `json:"id"`
SourceID int64 `json:"sourceId"`
Tags string `json:"tags"`
Title string `json:"title"`
Url string `json:"url"`
PubDate time.Time `json:"pubDate"`
Video string `json:"video"`
VideoHeight uint16 `json:"videoHeight"`
VideoWidth uint16 `json:"videoWidth"`
Thumbnail string `json:"thumbnail"`
Description string `json:"description"`
AuthorName string `json:"authorName"`
AuthorImage string `json:"authorImage"`
ID int64 `json:"id"`
SourceID int64 `json:"sourceId"`
Tags string `json:"tags"`
Title string `json:"title"`
Url string `json:"url"`
PubDate time.Time `json:"pubDate"`
IsVideo bool `json:"isVideo"`
Thumbnail string `json:"thumbnail"`
Description string `json:"description"`
AuthorName string `json:"authorName"`
AuthorImageUrl string `json:"authorImage"`
}
type DiscordQueueDto struct {
//CreatedAt time.Time `json:"createdAt"`
//UpdatedAt time.Time `json:"updatedAt"`
ID int64 `json:"id"`
ArticleId int64 `json:"articleId"`
SourceId int64 `json:"sourceId"`
}
type DiscordWebHookDto struct {
//CreatedAt time.Time `json:"CreatedAt"`
//UpdatedAt time.Time `json:"UpdatedAt"`
//DeletedAt time.Time `json:"DeletedAt"`
ID uint `json:"id"`
Name string `json:"name"`
Key string `json:"key"`
@ -40,18 +33,12 @@ type DiscordWebHookDto struct {
}
type IconDto struct {
//CreatedAt time.Time `json:"CreatedAt"`
//UpdatedAt time.Time `json:"UpdatedAt"`
//DeletedAt time.Time `json:"DeletedAt"`
ID int64 `json:"id"`
FileName string `json:"fileName"`
Site string `json:"site"`
}
type SettingDto struct {
//CreatedAt time.Time `json:"CreatedAt"`
//UpdatedAt time.Time `json:"UpdatedAt"`
//DeletedAt time.Time `json:"DeletedAt"`
ID int64 `json:"id"`
Key string `json:"key"`
Value string `json:"value"`
@ -59,9 +46,6 @@ type SettingDto struct {
}
type SubscriptionDto struct {
//CreatedAt time.Time `json:"CreatedAt"`
//UpdatedAt time.Time `json:"UpdatedAt"`
//DeletedAt time.Time `json:"DeletedAt"`
ID int64 `json:"id"`
SourceID int64 `json:"sourceId"`
SourceType string `json:"sourceType"`
@ -71,16 +55,10 @@ type SubscriptionDto struct {
}
type SourceDto struct {
//CreatedAt time.Time `json:"CreatedAt"`
//UpdatedAt time.Time `json:"UpdatedAt"`
//DeletedAt time.Time `json:"DeletedAt"`
ID int64 `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"`
ID int64 `json:"id"`
Source string `json:"source"`
DisplayName string `json:"name"`
Url string `json:"url"`
Tags string `json:"tags"`
Enabled bool `json:"enabled"`
}

View File

@ -1,5 +1,26 @@
package domain
type ErrorResponse struct {
type BaseResponse struct {
Message string `json:"message"`
}
type ArticleResponse struct {
BaseResponse
Payload []ArticleDto `json:"payload"`
}
type ArticleAndSourceModel struct {
Article ArticleDto `json:"article"`
Source SourceDto `json:"source"`
}
type ArticleDetailResponse struct {
BaseResponse
Payload ArticleAndSourceModel `json:"payload"`
}
type DiscordWebhookResponse struct {
BaseResponse
Payload []DiscordWebHookDto `json:"payload"`
}

View File

@ -4,186 +4,148 @@ import (
"net/http"
"strconv"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/google/uuid"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/services"
"github.com/labstack/echo/v4"
)
//func (s *Handler) GetArticleRouter() http.Handler {
// r := chi.NewRouter()
//
// r.Get("/", s.listArticles)
// r.Route("/{ID}", func(r chi.Router) {
// r.Get("/", s.getArticle)
// r.Get("/details", s.getArticleDetails)
// })
// r.Get("/by/sourceid", s.ListArticlesBySourceId)
//
// return r
//}
type ArticlesListResults struct {
ApiStatusModel
Payload []models.ArticleDto `json:"payload"`
}
type ArticleGetResults struct {
ApiStatusModel
Payload models.ArticleDto `json:"payload"`
}
type ArticleDetailsResult struct {
ApiStatusModel
Payload models.ArticleDetailsDto `json:"payload"`
}
// ListArticles
// @Summary Lists the top 25 records ordering from newest to oldest.
// @Produce application/json
// @Param page query string false "page number"
// @Tags Articles
// @Router /articles [get]
// @Success 200 {object} ArticlesListResults "OK"
// @Success 200 {object} domain.ArticleResponse
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) listArticles(c echo.Context) error {
p := ArticlesListResults{
ApiStatusModel: ApiStatusModel{
Message: "OK",
StatusCode: http.StatusOK,
resp := domain.ArticleResponse{
BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
}
queryPage := c.QueryParam("page")
// if a page number was sent, process it
if len(queryPage) >= 1 {
page, err := strconv.Atoi(queryPage)
if err != nil {
return c.JSON(http.StatusBadRequest, err)
}
res, err := s.dto.ListArticles(c.Request().Context(), 25, page)
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
return c.JSON(http.StatusOK, p)
} else {
res, err := s.dto.ListArticles(c.Request().Context(), 25, 0)
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
return c.JSON(http.StatusOK, p)
page, err := strconv.Atoi(c.QueryParam("page"))
if err != nil {
page = 0
}
res, err := s.repo.Articles.ListByPage(c.Request().Context(), page, 25)
if err != nil {
s.WriteError(c, err, http.StatusInternalServerError)
}
resp.Payload = services.ArticlesToDto(res)
return c.JSON(http.StatusOK, resp)
}
// GetArticle
// @Summary Returns an article based on defined ID.
// @Param ID path string true "uuid"
// @Param ID path string true "int"
// @Produce application/json
// @Tags Articles
// @Router /articles/{ID} [get]
// @Success 200 {object} ArticleGetResults "OK"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) getArticle(c echo.Context) error {
p := ArticleGetResults{
ApiStatusModel: ApiStatusModel{
Message: "OK",
StatusCode: http.StatusOK,
p := domain.ArticleResponse{
BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
}
id := c.Param("ID")
uuid, err := uuid.Parse(id)
idNumber, err := strconv.Atoi(id)
if err != nil {
return c.JSON(http.StatusBadRequest, err)
s.WriteError(c, err, http.StatusBadRequest)
}
res, err := s.dto.GetArticle(c.Request().Context(), uuid)
item, err := s.repo.Articles.GetById(c.Request().Context(), int64(idNumber))
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
var dtos []domain.ArticleDto
dtos = append(dtos, services.ArticleToDto(item))
p.Payload = dtos
return c.JSON(http.StatusOK, p)
}
// GetArticleDetails
// @Summary Returns an article and source based on defined ID.
// @Param ID path string true "uuid"
// @Param ID path string true "int"
// @Produce application/json
// @Tags Articles
// @Router /articles/{ID}/details [get]
// @Success 200 {object} ArticleDetailsResult "OK"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) getArticleDetails(c echo.Context) error {
p := ArticleDetailsResult{
ApiStatusModel: ApiStatusModel{
Message: "OK",
StatusCode: http.StatusOK,
p := domain.ArticleDetailResponse{
BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
Payload: domain.ArticleAndSourceModel{
},
}
id := c.Param("ID")
uuid, err := uuid.Parse(id)
id, err := strconv.Atoi(c.Param("ID"))
if err != nil {
return c.JSON(http.StatusBadRequest, err)
s.WriteError(c, err, http.StatusBadRequest)
}
res, err := s.dto.GetArticleDetails(c.Request().Context(), uuid)
article, err := s.repo.Articles.GetById(c.Request().Context(), int64(id))
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
s.WriteError(c, err, http.StatusInternalServerError)
}
p.Payload = res
source, err := s.repo.Sources.GetById(c.Request().Context(), article.SourceID)
if err != nil {
s.WriteError(c, err, http.StatusInternalServerError)
}
p.Payload.Article = services.ArticleToDto(article)
p.Payload.Source = services.SourceToDto(source)
return c.JSON(http.StatusOK, p)
}
// TODO add page support
// ListArticlesBySourceID
// @Summary Finds the articles based on the SourceID provided. Returns the top 25.
// @Param id query string true "Source ID UUID"
// @Param id query string true
// @Param page query int false "Page to query"
// @Produce application/json
// @Tags Articles
// @Router /articles/by/sourceid [get]
// @Success 200 {object} ArticlesListResults "OK"
// @Failure 400 {object} domain.BaseResponse
// @Failure 500 {object} domain.BaseResponse
func (s *Handler) ListArticlesBySourceId(c echo.Context) error {
p := ArticlesListResults{
ApiStatusModel: ApiStatusModel{
Message: "OK",
StatusCode: http.StatusOK,
p := domain.ArticleResponse{
BaseResponse: domain.BaseResponse{
Message: ResponseMessageSuccess,
},
}
id := c.QueryParam("id")
uuid, err := uuid.Parse(id)
id, err := strconv.Atoi(c.QueryParam("id"))
if err != nil {
return c.JSON(http.StatusBadRequest, err)
s.WriteError(c, err, http.StatusBadRequest)
}
// if a page number was sent, process it
if len(c.QueryParam("page")) >= 1 {
_page, err := strconv.Atoi(c.QueryParam("page"))
if err != nil {
return c.JSON(http.StatusBadRequest, err)
}
res, err := s.dto.ListNewArticlesBySourceId(c.Request().Context(), uuid, 25, _page)
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
} else {
res, err := s.dto.ListNewArticlesBySourceId(c.Request().Context(), uuid, 25, 0)
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = res
// if the page number is missing, default to 0
_page, err := strconv.Atoi(c.QueryParam("page"))
if err != nil {
_page = 0
}
items, err := s.repo.Articles.ListBySource(c.Request().Context(), _page, 25, id, "")
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
p.Payload = services.ArticlesToDto(items)
return c.JSON(http.StatusOK, p)
}

View File

@ -60,21 +60,21 @@ func (s *Handler) GetDiscordWebHooksById(c echo.Context) error {
_id := c.Param("ID")
if _id == "" {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: ErrIdValueMissing,
})
}
uuid, err := uuid.Parse(_id)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: ErrUnableToParseId,
})
}
res, err := s.dto.GetDiscordWebhook(c.Request().Context(), uuid)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: ErrNoRecordFound,
})
}
@ -100,21 +100,21 @@ func (s *Handler) GetDiscordWebHooksByServerAndChannel(c echo.Context) error {
_server := c.QueryParam("server")
if _server == "" {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: ErrIdValueMissing,
})
}
_channel := c.QueryParam("channel")
if _channel == "" {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: fmt.Sprintf("%s channel", ErrParameterMissing),
})
}
res, err := s.dto.GetDiscordWebHookByServerAndChannel(c.Request().Context(), _server, _channel)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -136,22 +136,22 @@ func (s *Handler) NewDiscordWebHook(c echo.Context) error {
_channel := c.QueryParam("channel")
if _url == "" {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: "url is missing a value",
})
}
if !strings.Contains(_url, "discord.com/api/webhooks") {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: "invalid url",
})
}
if _server == "" {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: "server is missing",
})
}
if _channel == "" {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: "channel is missing",
})
}
@ -176,7 +176,7 @@ func (s *Handler) disableDiscordWebHook(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(),
})
}
@ -189,7 +189,7 @@ func (s *Handler) disableDiscordWebHook(c echo.Context) error {
err = s.Db.DisableDiscordWebHook(c.Request().Context(), uuid)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -205,7 +205,7 @@ func (s *Handler) enableDiscordWebHook(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(),
})
}

View File

@ -15,22 +15,24 @@ import (
)
type Handler struct {
Router *echo.Echo
Db *database.Queries
dto *dto.DtoClient
config services.Configs
sqlConnection *sql.DB
Router *echo.Echo
Db *database.Queries
dto *dto.DtoClient
config services.Configs
repo services.RepositoryService
}
const (
HeaderContentType = "Content-Type"
ApplicationJson = "application/json"
//ApplicationJson = "application/json"
ErrParameterIdMissing = "The requested parameter ID was not found."
ErrParameterMissing = "The requested parameter was found found:"
ErrUnableToParseId = "Unable to parse the requested ID."
ErrRecordMissing = "The requested record was not found"
ResponseMessageSuccess = "Success"
)
var (
@ -42,18 +44,12 @@ var (
func NewServer(ctx context.Context, db *database.Queries, configs services.Configs, conn *sql.DB) *Handler {
s := &Handler{
Db: db,
dto: dto.NewDtoClient(db),
config: configs,
sqlConnection: conn,
Db: db,
dto: dto.NewDtoClient(db),
config: configs,
repo: services.NewRepositoryService(conn),
}
db, err := openDatabase(ctx)
if err != nil {
panic(err)
}
s.Db = db
router := echo.New()
router.GET("/swagger/*", swagger.WrapHandler)
@ -73,11 +69,11 @@ func NewServer(ctx context.Context, db *database.Queries, configs services.Confi
dwh.POST("/:ID/disable", s.disableDiscordWebHook)
dwh.POST("/:ID/enable", s.enableDiscordWebHook)
queue := v1.Group("/queue")
queue.GET("/discord/webhooks", s.ListDiscordWebhookQueue) // TODO this needs to be reworked
//queue := v1.Group("/queue")
//queue.GET("/discord/webhooks", s.ListDiscordWebhookQueue) // TODO this needs to be reworked
settings := v1.Group("/settings")
settings.GET("/", s.getSettings)
//settings := v1.Group("/settings")
//settings.GET("/", s.getSettings)
sources := v1.Group("/sources")
sources.GET("/", s.listSources)
@ -103,28 +99,6 @@ func NewServer(ctx context.Context, db *database.Queries, configs services.Confi
return s
}
func openDatabase(ctx context.Context) (*database.Queries, error) {
_env := services.NewConfig()
connString := _env.GetConfig(services.Sql_Connection_String)
db, err := sql.Open("postgres", connString)
if err != nil {
panic(err)
}
queries := database.New(db)
return queries, err
}
func (s *Handler) MountRoutes() {
//s.Router.Get("/swagger/*", httpSwagger.Handler(
// httpSwagger.URL("doc.json"), //The url pointing to API definition
//))
//s.Router.Get("/api/settings", s.getSettings)
//s.Router.Mount("/api/sources", s.GetSourcesRouter())
//s.Router.Mount("/api/subscriptions", s.GetSubscriptionsRouter())
}
type ApiStatusModel struct {
StatusCode int `json:"status"`
Message string `json:"message"`
@ -134,8 +108,14 @@ type ApiError struct {
*ApiStatusModel
}
func (s *Handler) WriteError(c echo.Context, errMessage string, HttpStatusCode int) error {
return c.JSON(HttpStatusCode, domain.ErrorResponse{
Message: errMessage,
func (s *Handler) WriteError(c echo.Context, errMessage error, HttpStatusCode int) error {
return c.JSON(HttpStatusCode, domain.BaseResponse{
Message: errMessage.Error(),
})
}
func (s *Handler) WriteMessage(c echo.Context, msg string, HttpStatusCode int) error {
return c.JSON(HttpStatusCode, domain.BaseResponse{
Message: msg,
})
}

View File

@ -30,7 +30,7 @@ func (s *Handler) ListDiscordWebhookQueue(c echo.Context) error {
// Get the raw resp from sql
res, err := s.dto.ListDiscordWebhookQueueDetails(c.Request().Context(), 50)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}

View File

@ -20,7 +20,7 @@ func (s *Handler) getSettings(c echo.Context) error {
uuid, err := uuid.Parse(id)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(),
})
}

View File

@ -10,19 +10,10 @@ import (
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain/models"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
)
func (s *Handler) GetSourcesRouter() http.Handler {
r := chi.NewRouter()
return r
}
type ListSources struct {
ApiStatusModel
Payload []models.SourceDto `json:"payload"`
@ -38,8 +29,8 @@ type GetSource struct {
// @Produce application/json
// @Tags Source
// @Router /sources [get]
// @Success 200 {object} ListSources "ok"
// @Failure 400 {object} ApiError "Unable to reach SQL or Data problems"
// @Success 200 {object} ListSources "ok"
// @Failure 400 {object} domain.BaseResponse "Unable to reach SQL or Data problems"
func (s *Handler) listSources(c echo.Context) error {
//TODO Add top?
/*
@ -61,9 +52,7 @@ func (s *Handler) listSources(c echo.Context) error {
// Default way of showing all sources
items, err := s.dto.ListSources(c.Request().Context(), 50)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
Message: err.Error(),
})
s.WriteError(c, err, http.StatusInternalServerError)
}
p.Payload = items
@ -102,7 +91,7 @@ func (s *Handler) listSourcesBySource(c echo.Context) error {
// Shows the list by Sources.source
res, err := s.dto.ListSourcesBySource(c.Request().Context(), source)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -132,14 +121,14 @@ func (s *Handler) getSources(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: ErrUnableToParseId,
})
}
res, err := s.dto.GetSourceById(c.Request().Context(), uuid)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: ErrNoRecordFound,
})
}
@ -170,7 +159,7 @@ func (s *Handler) GetSourceBySourceAndName(c echo.Context) error {
var param domain.GetSourceBySourceAndNameParamRequest
err := c.Bind(&param)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(),
})
}
@ -206,7 +195,7 @@ func (s *Handler) newRedditSource(c echo.Context) error {
var param domain.NewSourceParamRequest
err := c.Bind(&param)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(),
})
}
@ -216,12 +205,12 @@ func (s *Handler) newRedditSource(c echo.Context) error {
//_tags := query["tags"][0]
if param.Url == "" {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: "Url is missing a value",
})
}
if !strings.Contains(param.Url, "reddit.com") {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: "Invalid URL given",
})
}
@ -248,7 +237,7 @@ func (s *Handler) newRedditSource(c echo.Context) error {
}
err = s.Db.CreateSource(c.Request().Context(), params)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -272,7 +261,7 @@ func (s *Handler) newYoutubeSource(c echo.Context) error {
var param domain.NewSourceParamRequest
err := c.Bind(&param)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(),
})
}
@ -283,12 +272,12 @@ func (s *Handler) newYoutubeSource(c echo.Context) error {
////_tags := query["tags"][0]
if param.Url == "" {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: "url is missing a value",
})
}
if !strings.Contains(param.Url, "youtube.com") {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: "Invalid URL",
})
}
@ -318,7 +307,7 @@ func (s *Handler) newYoutubeSource(c echo.Context) error {
bJson, err := json.Marshal(&params)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -335,7 +324,7 @@ func (s *Handler) newTwitchSource(c echo.Context) error {
var param domain.NewSourceParamRequest
err := c.Bind(&param)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(),
})
}
@ -358,14 +347,14 @@ func (s *Handler) newTwitchSource(c echo.Context) error {
}
err = s.Db.CreateSource(c.Request().Context(), params)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
bJson, err := json.Marshal(&params)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -382,7 +371,7 @@ func (s *Handler) deleteSources(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(),
})
}
@ -390,7 +379,7 @@ func (s *Handler) deleteSources(c echo.Context) error {
// Check to make sure we can find the record
_, err = s.Db.GetSourceByID(c.Request().Context(), uuid)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -398,7 +387,7 @@ func (s *Handler) deleteSources(c echo.Context) error {
// Delete the record
err = s.Db.DeleteSource(c.Request().Context(), uuid)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -410,7 +399,7 @@ func (s *Handler) deleteSources(c echo.Context) error {
b, err := json.Marshal(p)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -427,7 +416,7 @@ func (s *Handler) disableSource(c echo.Context) error {
id := c.Param("ID")
uuid, err := uuid.Parse(id)
if err != nil {
return c.JSON(http.StatusBadRequest, domain.ErrorResponse{
return c.JSON(http.StatusBadRequest, domain.BaseResponse{
Message: err.Error(),
})
}
@ -435,14 +424,14 @@ func (s *Handler) disableSource(c echo.Context) error {
// Check to make sure we can find the record
_, err = s.Db.GetSourceByID(c.Request().Context(), uuid)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
err = s.Db.DisableSource(context.Background(), uuid)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -454,7 +443,7 @@ func (s *Handler) disableSource(c echo.Context) error {
b, err := json.Marshal(p)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -477,14 +466,14 @@ func (s *Handler) enableSource(c echo.Context) error {
// Check to make sure we can find the record
_, err = s.Db.GetSourceByID(c.Request().Context(), uuid)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
err = s.Db.EnableSource(c.Request().Context(), uuid)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}
@ -496,7 +485,7 @@ func (s *Handler) enableSource(c echo.Context) error {
b, err := json.Marshal(p)
if err != nil {
return c.JSON(http.StatusInternalServerError, domain.ErrorResponse{
return c.JSON(http.StatusInternalServerError, domain.BaseResponse{
Message: err.Error(),
})
}

View File

@ -3,6 +3,7 @@ package v1
import (
"context"
"encoding/json"
"errors"
"net/http"
"git.jamestombleson.com/jtom38/newsbot-api/internal/database"
@ -44,7 +45,7 @@ func (s *Handler) ListSubscriptions(c echo.Context) error {
res, err := s.dto.ListSubscriptions(c.Request().Context(), 50)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusBadRequest)
return s.WriteError(c, err, http.StatusBadRequest)
}
payload.Payload = res
@ -67,7 +68,7 @@ func (s *Handler) ListSubscriptionDetails(c echo.Context) error {
res, err := s.dto.ListSubscriptionDetails(c.Request().Context(), 50)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusInternalServerError)
return s.WriteError(c, err, http.StatusInternalServerError)
}
payload.Payload = res
@ -93,18 +94,18 @@ func (s *Handler) GetSubscriptionsByDiscordId(c echo.Context) error {
id := c.QueryParam("id")
if id == "" {
return s.WriteError(c, ErrIdValueMissing, http.StatusBadRequest)
return s.WriteError(c, errors.New(ErrIdValueMissing), http.StatusBadRequest)
}
uuid, err := uuid.Parse(id)
if err != nil {
return s.WriteError(c, ErrValueNotUuid, http.StatusBadRequest)
return s.WriteError(c, errors.New(ErrValueNotUuid), http.StatusBadRequest)
}
res, err := s.dto.ListSubscriptionsByDiscordWebhookId(context.Background(), uuid)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusNoContent)
return s.WriteError(c, err, http.StatusNoContent)
}
p.Payload = res
@ -128,17 +129,17 @@ func (s *Handler) GetSubscriptionsBySourceId(c echo.Context) error {
_id := c.QueryParam("id")
if _id == "" {
return s.WriteError(c, ErrIdValueMissing, http.StatusBadRequest)
return s.WriteError(c, errors.New(ErrIdValueMissing), http.StatusBadRequest)
}
uuid, err := uuid.Parse(_id)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusBadRequest)
return s.WriteError(c, err, http.StatusBadRequest)
}
res, err := s.dto.ListSubscriptionsBySourceId(context.Background(), uuid)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusNoContent)
return s.WriteError(c, err, http.StatusNoContent)
}
p.Payload = res
@ -158,20 +159,20 @@ func (s *Handler) newDiscordWebHookSubscription(c echo.Context) error {
// Check to make we didn't get a null
if discordWebHookId == "" {
return s.WriteError(c, "invalid discordWebHooksId given", http.StatusBadRequest)
return s.WriteError(c, errors.New("invalid discordWebHooksId given"), http.StatusBadRequest)
}
if sourceId == "" {
return s.WriteError(c, "invalid sourceID given", http.StatusBadRequest)
return s.WriteError(c, errors.New("invalid sourceID given"), http.StatusBadRequest)
}
// Validate they are UUID values
uHook, err := uuid.Parse(discordWebHookId)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusBadRequest)
return s.WriteError(c, err, http.StatusBadRequest)
}
uSource, err := uuid.Parse(sourceId)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusBadRequest)
return s.WriteError(c, err, http.StatusBadRequest)
}
// Check if the sub already exists
@ -180,7 +181,7 @@ func (s *Handler) newDiscordWebHookSubscription(c echo.Context) error {
Sourceid: uSource,
})
if err == nil {
return s.WriteError(c, "a subscription already exists between these two entities", http.StatusBadRequest)
return s.WriteError(c, errors.New("a subscription already exists between these two entities"), http.StatusBadRequest)
}
// Does not exist, so make it.
@ -191,12 +192,12 @@ func (s *Handler) newDiscordWebHookSubscription(c echo.Context) error {
}
err = s.Db.CreateSubscription(context.Background(), params)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusInternalServerError)
return s.WriteError(c, err, http.StatusInternalServerError)
}
bJson, err := json.Marshal(&params)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusInternalServerError)
return s.WriteError(c, err, http.StatusInternalServerError)
}
return c.JSON(http.StatusOK, bJson)
@ -212,17 +213,17 @@ func (s *Handler) DeleteDiscordWebHookSubscription(c echo.Context) error {
id := c.QueryParam("id")
if id == "" {
return s.WriteError(c, ErrMissingSubscriptionID, http.StatusBadRequest)
return s.WriteError(c, errors.New(ErrMissingSubscriptionID), http.StatusBadRequest)
}
uid, err := uuid.Parse(id)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusBadRequest)
return s.WriteError(c, err, http.StatusBadRequest)
}
err = s.Db.DeleteSubscription(context.Background(), uid)
if err != nil {
return s.WriteError(c, err.Error(), http.StatusInternalServerError)
return s.WriteError(c, err, http.StatusInternalServerError)
}
return c.JSON(http.StatusOK, nil)

View File

@ -1,6 +1,7 @@
package repository
import (
"context"
"database/sql"
"errors"
"fmt"
@ -12,9 +13,19 @@ import (
const (
ArticleOrderByPublishDateDesc = "pubDate desc"
ArticleOrderByPublishDatAsc = "pubDate asc"
ArticleOrderByPublishDateAsc = "pubDate asc"
)
type ArticlesRepo interface {
GetById(ctx context.Context, id int64) (domain.ArticleEntity, error)
GetByUrl(ctx context.Context, url string) (domain.ArticleEntity, error)
ListTop(ctx context.Context, limit int) ([]domain.ArticleEntity, error)
ListByPage(ctx context.Context, page, limit int) ([]domain.ArticleEntity, error)
ListByPublishDate(ctx context.Context, page, limit int, orderBy string) ([]domain.ArticleEntity, error)
ListBySource(ctx context.Context, page, limit, sourceId int, orderBy string) ([]domain.ArticleEntity, error)
Create(ctx context.Context, sourceId int64, tags, title, url, thumbnailUrl, description, authorName, authorImageUrl string, pubDate time.Time, isVideo bool) (int64, error)
}
type ArticleRepository struct {
conn *sql.DB
defaultLimit int
@ -29,7 +40,7 @@ func NewArticleRepository(conn *sql.DB) ArticleRepository {
}
}
func (ar ArticleRepository) GetById(id int64) (domain.ArticleEntity, error) {
func (ar ArticleRepository) GetById(ctx context.Context, id int64) (domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles").Where(
@ -38,7 +49,7 @@ func (ar ArticleRepository) GetById(id int64) (domain.ArticleEntity, error) {
builder.Limit(1)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
rows, err := ar.conn.QueryContext(ctx, query, args...)
if err != nil {
return domain.ArticleEntity{}, err
}
@ -51,7 +62,7 @@ func (ar ArticleRepository) GetById(id int64) (domain.ArticleEntity, error) {
return data[0], nil
}
func (ar ArticleRepository) GetByUrl(url string) (domain.ArticleEntity, error) {
func (ar ArticleRepository) GetByUrl(ctx context.Context, url string) (domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles").Where(
@ -60,7 +71,7 @@ func (ar ArticleRepository) GetByUrl(url string) (domain.ArticleEntity, error) {
builder.Limit(1)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
rows, err := ar.conn.QueryContext(ctx, query, args...)
if err != nil {
return domain.ArticleEntity{}, err
}
@ -73,14 +84,14 @@ func (ar ArticleRepository) GetByUrl(url string) (domain.ArticleEntity, error) {
return data[0], nil
}
func (ar ArticleRepository) ListTop(limit int) ([]domain.ArticleEntity, error) {
func (ar ArticleRepository) ListTop(ctx context.Context, limit int) ([]domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles")
builder.Limit(limit)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
rows, err := ar.conn.QueryContext(ctx, query, args...)
if err != nil {
return []domain.ArticleEntity{}, err
}
@ -93,16 +104,16 @@ func (ar ArticleRepository) ListTop(limit int) ([]domain.ArticleEntity, error) {
return data, nil
}
func (ar ArticleRepository) ListByPage(page, limit int) ([]domain.ArticleEntity, error) {
func (ar ArticleRepository) ListByPage(ctx context.Context, page, limit int) ([]domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles")
builder.OrderBy("pubdate desc")
builder.OrderBy(ArticleOrderByPublishDateDesc)
builder.Offset(page * limit)
builder.Limit(limit)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
rows, err := ar.conn.QueryContext(ctx, query, args...)
if err != nil {
return []domain.ArticleEntity{}, err
}
@ -115,7 +126,7 @@ func (ar ArticleRepository) ListByPage(page, limit int) ([]domain.ArticleEntity,
return data, nil
}
func (ar ArticleRepository) ListByPublishDate(page, limit int, orderBy string) ([]domain.ArticleEntity, error) {
func (ar ArticleRepository) ListByPublishDate(ctx context.Context, page, limit int, orderBy string) ([]domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles")
@ -126,7 +137,7 @@ func (ar ArticleRepository) ListByPublishDate(page, limit int, orderBy string) (
builder.Limit(limit)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
rows, err := ar.conn.QueryContext(ctx, query, args...)
if err != nil {
return []domain.ArticleEntity{}, err
}
@ -138,7 +149,7 @@ func (ar ArticleRepository) ListByPublishDate(page, limit int, orderBy string) (
return data, nil
}
func (ar ArticleRepository) ListBySource(page, limit int, orderBy string) ([]domain.ArticleEntity, error) {
func (ar ArticleRepository) ListBySource(ctx context.Context, page, limit, sourceId int, orderBy string) ([]domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles")
@ -146,11 +157,14 @@ func (ar ArticleRepository) ListBySource(page, limit int, orderBy string) ([]dom
if orderBy != "" {
builder.OrderBy(orderBy)
}
builder.Where(
builder.Equal("SourceId", sourceId),
)
builder.Offset(50)
builder.Limit(page * limit)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
rows, err := ar.conn.QueryContext(ctx, query, args...)
if err != nil {
return []domain.ArticleEntity{}, err
}
@ -162,7 +176,7 @@ func (ar ArticleRepository) ListBySource(page, limit int, orderBy string) ([]dom
return data, nil
}
func (ar ArticleRepository) Create(sourceId int64, tags, title, url, thumbnailUrl, description, authorName, authorImageUrl string, pubDate time.Time, isVideo bool) (int64, error) {
func (ar ArticleRepository) Create(ctx context.Context, sourceId int64, tags, title, url, thumbnailUrl, description, authorName, authorImageUrl string, pubDate time.Time, isVideo bool) (int64, error) {
dt := time.Now()
queryBuilder := sqlbuilder.NewInsertBuilder()
queryBuilder.InsertInto("articles")
@ -170,7 +184,7 @@ func (ar ArticleRepository) Create(sourceId int64, tags, title, url, thumbnailUr
queryBuilder.Values(dt, dt, timeZero, sourceId, tags, title, url, pubDate, isVideo, thumbnailUrl, description, authorName, authorImageUrl)
query, args := queryBuilder.Build()
_, err := ar.conn.Exec(query, args...)
_, err := ar.conn.ExecContext(ctx, query, args...)
if err != nil {
return 0, err
}

View File

@ -1,6 +1,7 @@
package repository_test
import (
"context"
"testing"
"time"
@ -21,7 +22,7 @@ func TestCreateArticle(t *testing.T) {
defer db.Close()
r := repository.NewArticleRepository(db)
created, err := r.Create(1, "", "unit test", articleFakeDotCom, "", "testing", "", "", time.Now(), false)
created, err := r.Create(context.Background(), 1, "", "unit test", articleFakeDotCom, "", "testing", "", "", time.Now(), false)
if err != nil {
t.Log(err)
t.FailNow()
@ -48,7 +49,7 @@ func TestArticleByUrl(t *testing.T) {
t.FailNow()
}
article, err := r.GetByUrl(articleFakeDotCom)
article, err := r.GetByUrl(context.Background(), articleFakeDotCom)
if err != nil {
t.Log(err)
t.FailNow()
@ -73,7 +74,7 @@ func TestPullingMultipleArticlesWithLimit(t *testing.T) {
insertFakeArticles(r, "u3", 0)
insertFakeArticles(r, "u4", 0)
items, err := r.ListTop(3)
items, err := r.ListTop(context.Background(), 3)
if err != nil {
t.Log(err)
t.FailNow()
@ -98,7 +99,7 @@ func TestPullingMultipleArticlesWithPaging(t *testing.T) {
insertFakeArticles(r, "u3", 0)
insertFakeArticles(r, "u4", 0)
items, err := r.ListByPage(2, 1)
items, err := r.ListByPage(context.Background(), 2, 1)
if err != nil {
t.Log(err)
t.FailNow()
@ -125,7 +126,7 @@ func TestPullingByPublishDate(t *testing.T) {
insertFakeArticles(r, "u1", -1)
insertFakeArticles(r, "u1", -2)
items, err := r.ListByPublishDate(0, 2, repository.ArticleOrderByPublishDateDesc)
items, err := r.ListByPublishDate(context.Background(), 0, 2, repository.ArticleOrderByPublishDateDesc)
if err != nil {
t.Log(err)
t.FailNow()
@ -147,7 +148,7 @@ func TestPullingByPublishDate(t *testing.T) {
func insertFakeArticles(r repository.ArticleRepository, title string, daysOld int) error {
pubDate := time.Now().AddDate(0,0, daysOld)
_, err := r.Create(1, "", title, articleFakeDotCom, "", "testing", "", "", pubDate, false)
_, err := r.Create(context.Background(), 1, "", title, articleFakeDotCom, "", "testing", "", "", pubDate, false)
if err != nil {
return err
}

View File

@ -9,6 +9,19 @@ import (
"github.com/huandu/go-sqlbuilder"
)
type DiscordWebHookRepo interface{
Create(ctx context.Context, url, server, channel string, enabled bool) (int64, error)
Enable(ctx context.Context, id int64) (int64, error)
Disable(ctx context.Context, id int64) (int64, error)
SoftDelete(ctx context.Context, id int64) (int64, error)
Restore(ctx context.Context, id int64) (int64, error)
Delete(ctx context.Context, id int64) (int64, error)
GetById(ctx context.Context, id int64) (domain.DiscordWebHookEntity, error)
GetByUrl(ctx context.Context, url string) (domain.DiscordWebHookEntity, error)
ListByServerName(ctx context.Context, name string) ([]domain.DiscordWebHookEntity, error)
ListByServerAndChannel(ctx context.Context, server, channel string) ([]domain.DiscordWebHookEntity, error)
}
type discordWebHookRepository struct {
conn *sql.DB
}

View File

@ -14,7 +14,7 @@ const (
refreshTokenTableName = "RefreshTokens"
)
type RefreshTokenTable interface {
type RefreshToken interface {
Create(username string, token string) (int64, error)
GetByUsername(name string) (domain.RefreshTokenEntity, error)
DeleteById(id int64) (int64, error)

View File

@ -9,6 +9,20 @@ import (
"github.com/huandu/go-sqlbuilder"
)
type Sources interface {
Create(ctx context.Context, source, displayName, url, tags string, enabled bool) (int64, error)
GetById(ctx context.Context, id int64) (domain.SourceEntity, error)
GetByDisplayName(ctx context.Context, displayName string) (domain.SourceEntity, error)
GetBySource(ctx context.Context, source string) (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)
Enable(ctx context.Context, id int64) (int64, error)
Disable(ctx context.Context, id int64) (int64, error)
SoftDelete(ctx context.Context, id int64) (int64, error)
Restore(ctx context.Context, id int64) (int64, error)
Delete(ctx context.Context, id int64) (int64, error)
}
type sourceRepository struct {
conn *sql.DB
}

View File

@ -17,7 +17,7 @@ const (
ErrUserNotFound string = "requested user was not found"
)
type IUserTable interface {
type Users interface {
GetByName(name string) (domain.UserEntity, error)
Create(name, password, scope string) (int64, error)
Update(id int, entity domain.UserEntity) error
@ -27,17 +27,17 @@ type IUserTable interface {
}
// Creates a new instance of UserRepository with the bound sql
func NewUserRepository(conn *sql.DB) UserRepository {
return UserRepository{
func NewUserRepository(conn *sql.DB) userRepository {
return userRepository{
connection: conn,
}
}
type UserRepository struct {
type userRepository struct {
connection *sql.DB
}
func (ur UserRepository) GetByName(name string) (domain.UserEntity, error) {
func (ur userRepository) GetByName(name string) (domain.UserEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*").From("users").Where(
builder.E("Name", name),
@ -57,7 +57,7 @@ func (ur UserRepository) GetByName(name string) (domain.UserEntity, error) {
return data[0], nil
}
func (ur UserRepository) Create(name, password, scope string) (int64, error) {
func (ur userRepository) Create(name, password, scope string) (int64, error) {
passwordBytes := []byte(password)
hash, err := bcrypt.GenerateFromPassword(passwordBytes, bcrypt.DefaultCost)
if err != nil {
@ -79,11 +79,11 @@ func (ur UserRepository) Create(name, password, scope string) (int64, error) {
return 1, nil
}
func (ur UserRepository) Update(id int, entity domain.UserEntity) error {
func (ur userRepository) Update(id int, entity domain.UserEntity) error {
return errors.New("not implemented")
}
func (ur UserRepository) UpdatePassword(name, password string) error {
func (ur userRepository) UpdatePassword(name, password string) error {
_, err := ur.GetByName(name)
if err != nil {
return nil
@ -97,7 +97,7 @@ func (ur UserRepository) UpdatePassword(name, password string) error {
// If the hash matches what we have in the database, an error will not be returned.
// If the user does not exist or the hash does not match, an error will be returned
func (ur UserRepository) CheckUserHash(name, password string) error {
func (ur userRepository) CheckUserHash(name, password string) error {
record, err := ur.GetByName(name)
if err != nil {
return err
@ -111,7 +111,7 @@ func (ur UserRepository) CheckUserHash(name, password string) error {
return nil
}
func (ur UserRepository) UpdateScopes(name, scope string) error {
func (ur userRepository) UpdateScopes(name, scope string) error {
builder := sqlbuilder.NewUpdateBuilder()
builder.Update("users")
builder.Set(
@ -129,7 +129,7 @@ func (ur UserRepository) UpdateScopes(name, scope string) error {
return nil
}
func (ur UserRepository) processRows(rows *sql.Rows) []domain.UserEntity {
func (ur userRepository) processRows(rows *sql.Rows) []domain.UserEntity {
items := []domain.UserEntity{}
for rows.Next() {

View File

@ -1,6 +1,25 @@
package services
type RepositoryService struct {
import (
"database/sql"
"git.jamestombleson.com/jtom38/newsbot-api/internal/repository"
)
type RepositoryService struct {
Articles repository.ArticlesRepo
DiscordWebHooks repository.DiscordWebHookRepo
Sources repository.Sources
Users repository.Users
RefreshTokens repository.RefreshToken
}
func NewRepositoryService(conn *sql.DB) RepositoryService {
return RepositoryService{
Articles: repository.NewArticleRepository(conn),
DiscordWebHooks: repository.NewDiscordWebHookRepository(conn),
Sources: repository.NewSourceRepository(conn),
Users: repository.NewUserRepository(conn),
RefreshTokens: repository.NewRefreshTokenRepository(conn),
}
}

View File

@ -0,0 +1,46 @@
package services
import "git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
func ArticlesToDto(items []domain.ArticleEntity) []domain.ArticleDto {
var dtos []domain.ArticleDto
for _, item := range items {
dtos = append(dtos, ArticleToDto(item))
}
return dtos
}
func ArticleToDto(item domain.ArticleEntity) domain.ArticleDto {
return domain.ArticleDto{
ID: item.ID,
SourceID: item.SourceID,
Tags: item.Tags,
Title: item.Title,
Url: item.Url,
PubDate: item.PubDate,
IsVideo: item.IsVideo,
Thumbnail: item.Thumbnail,
Description: item.Description,
AuthorName: item.AuthorName,
AuthorImageUrl: item.AuthorImageUrl,
}
}
func SourcesToDto(items []domain.SourceEntity) []domain.SourceDto {
var dtos []domain.SourceDto
for _, item := range items {
dtos = append(dtos, SourceToDto(item))
}
return dtos
}
func SourceToDto(item domain.SourceEntity) domain.SourceDto {
return domain.SourceDto{
ID: item.ID,
Source: item.Source,
DisplayName: item.DisplayName,
Url: item.Url,
Tags: item.Tags,
Enabled: item.Enabled,
}
}

View File

@ -18,8 +18,8 @@ migrate-dev-down: ## revert sql migrations to dev db
goose -dir "./internal/database/migrations" postgres "user=postgres password=postgres dbname=postgres sslmode=disable" down
swag: ## Generates the swagger documentation with the swag tool
~/go/bin/swag f
~/go/bin/swag i
~/go/bin/swag f
~/go/bin/swag init -g cmd/server.go
gensql: ## Generates SQL code with sqlc
sqlc generate