0.0.1
This commit is contained in:
parent
14e82f3298
commit
b94abfe75b
44
cmd/main.go
44
cmd/main.go
@ -1,6 +1,24 @@
|
||||
package main
|
||||
|
||||
import "donat-widget/internal/app/http"
|
||||
import (
|
||||
"context"
|
||||
"donat-widget/internal/app/http"
|
||||
"donat-widget/internal/config"
|
||||
)
|
||||
|
||||
import (
|
||||
"donat-widget/infrastructure/pg"
|
||||
"donat-widget/infrastructure/weed"
|
||||
)
|
||||
|
||||
import (
|
||||
WidgetRepo "donat-widget/internal/repository/widget"
|
||||
DonatRepo "donat-widget/internal/repository/widget/donat"
|
||||
MediaRepo "donat-widget/internal/repository/widget/media"
|
||||
WidgetService "donat-widget/internal/service/widget"
|
||||
DonatService "donat-widget/internal/service/widget/donat"
|
||||
MediaService "donat-widget/internal/service/widget/media"
|
||||
)
|
||||
|
||||
// @title Widget service
|
||||
// @version 1.0
|
||||
@ -10,6 +28,26 @@ import "donat-widget/internal/app/http"
|
||||
// @BasePath /api/widget
|
||||
|
||||
func main() {
|
||||
httpServer := http.NewApp()
|
||||
http.Run(httpServer)
|
||||
cfg := config.Init()
|
||||
|
||||
// INFRASTRUCTURE
|
||||
db := pg.NewPgPool(context.Background(), cfg.Db.Username, cfg.Db.Password, cfg.Db.Host, cfg.Db.Port, cfg.Db.DBName)
|
||||
storage := weed.NewWeed(cfg.Storage.Filer, cfg.Storage.Master)
|
||||
|
||||
// REPOSITORIES
|
||||
widgetRepo := WidgetRepo.New(db)
|
||||
mediaRepo := MediaRepo.New(db, storage)
|
||||
donatRepo := DonatRepo.New(db)
|
||||
|
||||
// SERVICES
|
||||
widgetService := WidgetService.New(widgetRepo, donatRepo)
|
||||
mediaService := MediaService.New(mediaRepo)
|
||||
donatService := DonatService.New(donatRepo)
|
||||
|
||||
http.NewApp(
|
||||
db,
|
||||
widgetService,
|
||||
mediaService,
|
||||
donatService,
|
||||
)
|
||||
}
|
||||
|
@ -33,28 +33,6 @@ func NewPgPool(
|
||||
return pgInstance
|
||||
}
|
||||
|
||||
func (pg *Postgres) CreateTable(ctx context.Context) error {
|
||||
_, err := pg.db.Exec(ctx, createTableQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = pg.db.Exec(ctx, onUpdateTableQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pg *Postgres) DropTable(ctx context.Context) error {
|
||||
_, err := pg.db.Exec(ctx, dropTableQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pg *Postgres) Exec(ctx context.Context, query string, args ...interface{}) (pgconn.CommandTag, error) {
|
||||
result, err := pg.db.Exec(ctx, query, args...)
|
||||
if err != nil {
|
||||
@ -70,3 +48,20 @@ func (pg *Postgres) Query(ctx context.Context, query string, args ...interface{}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (pg *Postgres) CreateTable(ctx context.Context, query string) error {
|
||||
_, err := pg.db.Exec(ctx, query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pg *Postgres) DropTable(ctx context.Context, query string) error {
|
||||
_, err := pg.db.Exec(ctx, query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1,50 +0,0 @@
|
||||
package pg
|
||||
|
||||
var createTableQuery = `
|
||||
CREATE TABLE IF NOT EXISTS widgets (
|
||||
id SERIAL PRIMARY KEY,
|
||||
streamer_id INTEGER NOT NULL,
|
||||
template_id INTEGER NOT NULL,
|
||||
background_url TEXT DEFAULT '',
|
||||
image_url TEXT DEFAULT '',
|
||||
audio_url TEXT DEFAULT '',
|
||||
duration INTEGER DEFAULT 30,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS donats (
|
||||
id SERIAL PRIMARY KEY,
|
||||
widget_id INTEGER NOT NULL,
|
||||
text TEXT DEFAULT '',
|
||||
amount TEXT DEFAULT '',
|
||||
donat_user TEXT DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
`
|
||||
|
||||
var onUpdateTableQuery = `
|
||||
CREATE OR REPLACE FUNCTION update_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
|
||||
CREATE TRIGGER update_updated_at_trigger
|
||||
BEFORE UPDATE ON widgets
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE update_updated_at();
|
||||
|
||||
CREATE TRIGGER update_updated_at_trigger
|
||||
BEFORE UPDATE ON donats
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE update_updated_at();
|
||||
`
|
||||
|
||||
var dropTableQuery = `
|
||||
DROP TABLE IF EXISTS widgets;
|
||||
DROP TABLE IF EXISTS donats;
|
||||
`
|
@ -17,7 +17,7 @@ func NewWeed(
|
||||
filer string,
|
||||
masterUrl string,
|
||||
|
||||
) (*Weed, error) {
|
||||
) *Weed {
|
||||
filers := []string{filer}
|
||||
sw, err := goseaweedfs.NewSeaweed(
|
||||
masterUrl,
|
||||
@ -26,9 +26,9 @@ func NewWeed(
|
||||
&http.Client{Timeout: 5 * time.Minute},
|
||||
)
|
||||
if err != nil {
|
||||
return &Weed{}, err
|
||||
panic("Failed to create seaweed: " + err.Error())
|
||||
}
|
||||
return &Weed{sw}, err
|
||||
return &Weed{sw}
|
||||
|
||||
}
|
||||
|
||||
|
@ -8,22 +8,6 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type donatSetter interface {
|
||||
SetDonat(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
text string,
|
||||
amount model.DonatAmount,
|
||||
donatUser string,
|
||||
) error
|
||||
}
|
||||
type SetDonatRequest struct {
|
||||
WidgetID model.WidgetID `json:"widgetID" validate:"required"`
|
||||
Text string `json:"text" validate:"required"`
|
||||
Amount model.DonatAmount `json:"amount" validate:"required"`
|
||||
DonatUser string `json:"donatUser" validate:"required"`
|
||||
}
|
||||
|
||||
// SetDonat
|
||||
//
|
||||
// @Description Set donat
|
||||
@ -32,7 +16,7 @@ type SetDonatRequest struct {
|
||||
// @Produce json
|
||||
// @Param RegisterData body SetDonatRequest true "Set donat"
|
||||
// @Router /api/widget/donat/set [post]
|
||||
func SetDonat(donatService donatSetter) echo.HandlerFunc {
|
||||
func SetDonat(donatService model.DonatService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
@ -63,13 +47,6 @@ func SetDonat(donatService donatSetter) echo.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
type donatDeleter interface {
|
||||
DeleteDonat(
|
||||
ctx context.Context,
|
||||
DonatID model.DonatID,
|
||||
) error
|
||||
}
|
||||
|
||||
// DeleteDonat
|
||||
//
|
||||
// @Description Delete donat
|
||||
@ -77,7 +54,7 @@ type donatDeleter interface {
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Router /api/widget/donat/delete/{donatID} [post]
|
||||
func DeleteDonat(donatService donatDeleter) echo.HandlerFunc {
|
||||
func DeleteDonat(donatService model.DonatService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
|
10
internal/api/http/handlers/widget/donat/models.go
Normal file
10
internal/api/http/handlers/widget/donat/models.go
Normal file
@ -0,0 +1,10 @@
|
||||
package donat
|
||||
|
||||
import "donat-widget/internal/model"
|
||||
|
||||
type SetDonatRequest struct {
|
||||
WidgetID model.WidgetID `json:"widgetID" validate:"required"`
|
||||
Text string `json:"text" validate:"required"`
|
||||
Amount model.DonatAmount `json:"amount" validate:"required"`
|
||||
DonatUser string `json:"donatUser" validate:"required"`
|
||||
}
|
@ -8,18 +8,6 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type FileSetter interface {
|
||||
SetMediaFile(
|
||||
ctx context.Context,
|
||||
mediaType model.MediaType,
|
||||
widgetID model.WidgetID,
|
||||
file model.UploadFile,
|
||||
filename string,
|
||||
size int64,
|
||||
collection string,
|
||||
) error
|
||||
}
|
||||
|
||||
// SetMediaFile
|
||||
//
|
||||
// @Description Upload media
|
||||
@ -29,7 +17,7 @@ type FileSetter interface {
|
||||
// @Param file formData file true "File to upload"
|
||||
// @Param widgetId path int true "Widget ID"
|
||||
// @Router /api/widget/media/{mediaType}/upload [post]
|
||||
func SetMediaFile(service FileSetter) echo.HandlerFunc {
|
||||
func SetMediaFile(service model.MediaService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
@ -67,14 +55,6 @@ func SetMediaFile(service FileSetter) echo.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
type FileGetter interface {
|
||||
GetMediaFile(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
mediaType model.MediaType,
|
||||
) (model.DownloadFile, error)
|
||||
}
|
||||
|
||||
// GetMediaFile
|
||||
//
|
||||
// @Description Get media
|
||||
@ -83,7 +63,7 @@ type FileGetter interface {
|
||||
// @Param widgetId path int true "Widget ID"
|
||||
// @Param mediaType path string true "'background' or 'image' or 'audio'"
|
||||
// @Router /api/widget/media/{mediaType}/get/{widgetID} [post]
|
||||
func GetMediaFile(service FileGetter) echo.HandlerFunc {
|
||||
func GetMediaFile(service model.MediaService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
@ -109,19 +89,7 @@ func GetMediaFile(service FileGetter) echo.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
type FileUpdater interface {
|
||||
UpdateMediaFile(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
mediaType model.MediaType,
|
||||
file model.UploadFile,
|
||||
filename string,
|
||||
size int64,
|
||||
collection string,
|
||||
) error
|
||||
}
|
||||
|
||||
func UpdateMediaFile(service FileUpdater) echo.HandlerFunc {
|
||||
func UpdateMediaFile(service model.MediaService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
@ -160,25 +128,12 @@ func UpdateMediaFile(service FileUpdater) echo.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
type UrlSetter interface {
|
||||
SetMediaUrl(
|
||||
ctx context.Context,
|
||||
mediaType model.MediaType,
|
||||
widgetID model.WidgetID,
|
||||
mediaURL model.MediaUrl,
|
||||
) error
|
||||
}
|
||||
type SetRequest struct {
|
||||
WidgetID model.WidgetID `json:"widgetID" validate:"required"`
|
||||
MediaUrl model.MediaUrl `json:"mediaUrl" validate:"required"`
|
||||
}
|
||||
|
||||
// SetMediaUrl
|
||||
//
|
||||
// @Description Set media URL
|
||||
// @Param mediaType path string true "'background' or 'image' or 'audio'"
|
||||
// @Router /api/widget/media/{mediaType}/set [post]
|
||||
func SetMediaUrl(service UrlSetter) echo.HandlerFunc {
|
||||
func SetMediaUrl(service model.MediaService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
|
8
internal/api/http/handlers/widget/media/models.go
Normal file
8
internal/api/http/handlers/widget/media/models.go
Normal file
@ -0,0 +1,8 @@
|
||||
package media
|
||||
|
||||
import "donat-widget/internal/model"
|
||||
|
||||
type SetRequest struct {
|
||||
WidgetID model.WidgetID `json:"widgetID" validate:"required"`
|
||||
MediaUrl model.MediaUrl `json:"mediaUrl" validate:"required"`
|
||||
}
|
27
internal/api/http/handlers/widget/models.go
Normal file
27
internal/api/http/handlers/widget/models.go
Normal file
@ -0,0 +1,27 @@
|
||||
package widget
|
||||
|
||||
import "donat-widget/internal/model"
|
||||
|
||||
type CreateWidgetRequest struct {
|
||||
StreamerID model.StreamerID `json:"streamerID" validate:"required"`
|
||||
TemplateID model.TemplateID `json:"templateID" validate:"required"`
|
||||
}
|
||||
type CreateWidgetResponse struct {
|
||||
WidgetID model.WidgetID `json:"widgetID"`
|
||||
}
|
||||
|
||||
type GetWidgetInfoResponse struct {
|
||||
AudioUrl model.MediaUrl `json:"audioUrl"`
|
||||
ImageUrl model.MediaUrl `json:"imageUrl"`
|
||||
Text string `json:"text"`
|
||||
Amount model.DonatAmount `json:"amount"`
|
||||
DonatUser string `json:"donatUser"`
|
||||
Display model.Display `json:"display"`
|
||||
Duration model.Duration `json:"duration"`
|
||||
DonatID model.DonatID `json:"donatID"`
|
||||
}
|
||||
|
||||
type UpdateDurationRequest struct {
|
||||
WidgetID model.WidgetID `json:"widgetID" validate:"required"`
|
||||
Duration model.Duration `json:"duration" validate:"required"`
|
||||
}
|
@ -8,21 +8,6 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type widgetCreator interface {
|
||||
CreateWidget(
|
||||
ctx context.Context,
|
||||
streamerID model.StreamerID,
|
||||
templateID model.TemplateID,
|
||||
) (model.WidgetID, error)
|
||||
}
|
||||
type CreateWidgetRequest struct {
|
||||
StreamerID model.StreamerID `json:"streamerID" validate:"required"`
|
||||
TemplateID model.TemplateID `json:"templateID" validate:"required"`
|
||||
}
|
||||
type CreateWidgetResponse struct {
|
||||
WidgetID model.WidgetID `json:"widgetID"`
|
||||
}
|
||||
|
||||
// CreateWidget
|
||||
//
|
||||
// @Description Create widget
|
||||
@ -32,7 +17,7 @@ type CreateWidgetResponse struct {
|
||||
// @Param RegisterData body CreateWidgetRequest true "Create widget"
|
||||
// @Success 200 {object} CreateWidgetResponse
|
||||
// @Router /api/widget/create [post]
|
||||
func CreateWidget(widgetService widgetCreator) echo.HandlerFunc {
|
||||
func CreateWidget(widgetService model.WidgetService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
@ -63,13 +48,6 @@ func CreateWidget(widgetService widgetCreator) echo.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
type widgetHTMLGetter interface {
|
||||
GetWidgetHTML(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
) (model.WidgetHTML, error)
|
||||
}
|
||||
|
||||
// GetWidgetHTML @Description Get widget
|
||||
//
|
||||
// @Tags Widget
|
||||
@ -77,7 +55,7 @@ type widgetHTMLGetter interface {
|
||||
// @Produce json
|
||||
// @Success 200
|
||||
// @Router /api/widget/html/{widgetID} [get]
|
||||
func GetWidgetHTML(widgetService widgetHTMLGetter) echo.HandlerFunc {
|
||||
func GetWidgetHTML(widgetService model.WidgetService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
@ -98,24 +76,6 @@ func GetWidgetHTML(widgetService widgetHTMLGetter) echo.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
type widgetInfoGetter interface {
|
||||
GetWidgetInfo(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
) (*model.DonatAndWidget, error)
|
||||
}
|
||||
|
||||
type GetInfoResponse struct {
|
||||
AudioUrl model.MediaUrl `json:"audioUrl"`
|
||||
ImageUrl model.MediaUrl `json:"imageUrl"`
|
||||
Text string `json:"text"`
|
||||
Amount model.DonatAmount `json:"amount"`
|
||||
DonatUser string `json:"donatUser"`
|
||||
Display model.Display `json:"display"`
|
||||
Duration model.Duration `json:"duration"`
|
||||
DonatID model.DonatID `json:"donatID"`
|
||||
}
|
||||
|
||||
// GetWidgetInfo
|
||||
//
|
||||
// @Description Widget Info
|
||||
@ -124,7 +84,7 @@ type GetInfoResponse struct {
|
||||
// @Produce json
|
||||
// @Param widgetID path int true "Widget ID"
|
||||
// @Router /api/widget/info/{widgetID} [get]
|
||||
func GetWidgetInfo(widgetService widgetInfoGetter) echo.HandlerFunc {
|
||||
func GetWidgetInfo(widgetService model.WidgetService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
@ -139,14 +99,14 @@ func GetWidgetInfo(widgetService widgetInfoGetter) echo.HandlerFunc {
|
||||
}
|
||||
|
||||
if !donatAndWidget.Display {
|
||||
response := GetInfoResponse{
|
||||
response := GetWidgetInfoResponse{
|
||||
Display: donatAndWidget.Display,
|
||||
}
|
||||
slog.Info("Get widget info successfully")
|
||||
return request.JSON(200, response)
|
||||
}
|
||||
|
||||
response := GetInfoResponse{
|
||||
response := GetWidgetInfoResponse{
|
||||
AudioUrl: donatAndWidget.Widget.AudioUrl,
|
||||
ImageUrl: donatAndWidget.Widget.ImageUrl,
|
||||
Text: donatAndWidget.Donat.Text,
|
||||
@ -161,19 +121,6 @@ func GetWidgetInfo(widgetService widgetInfoGetter) echo.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
type widgetDurationUpdater interface {
|
||||
UpdateWidgetDuration(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
duration model.Duration,
|
||||
) error
|
||||
}
|
||||
|
||||
type UpdateDurationRequest struct {
|
||||
WidgetID model.WidgetID `json:"widgetID" validate:"required"`
|
||||
Duration model.Duration `json:"duration" validate:"required"`
|
||||
}
|
||||
|
||||
// UpdateDuration
|
||||
//
|
||||
// @Description UpdateDuration
|
||||
@ -183,7 +130,7 @@ type UpdateDurationRequest struct {
|
||||
// @Param UpdateData body UpdateDurationRequest true "UpdateDuration"
|
||||
// @Success 200
|
||||
// @Router /api/widget/duration/update [post]
|
||||
func UpdateDuration(widgetService widgetDurationUpdater) echo.HandlerFunc {
|
||||
func UpdateDuration(widgetService model.WidgetService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
@ -197,7 +144,7 @@ func UpdateDuration(widgetService widgetDurationUpdater) echo.HandlerFunc {
|
||||
return echo.NewHTTPError(400, err.Error())
|
||||
}
|
||||
|
||||
err = widgetService.UpdateWidgetDuration(
|
||||
err = widgetService.UpdateDuration(
|
||||
ctx,
|
||||
widgetData.WidgetID,
|
||||
widgetData.Duration,
|
||||
|
@ -2,124 +2,77 @@ package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"donat-widget/internal/model/sql"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/swaggo/echo-swagger"
|
||||
"log/slog"
|
||||
"os"
|
||||
)
|
||||
|
||||
import (
|
||||
"donat-widget/infrastructure/pg"
|
||||
"donat-widget/infrastructure/weed"
|
||||
"donat-widget/internal/config"
|
||||
"donat-widget/internal/model"
|
||||
"donat-widget/pkg/validator"
|
||||
)
|
||||
|
||||
import (
|
||||
widgetHandler "donat-widget/internal/api/http/handlers/widget"
|
||||
widgetService "donat-widget/internal/service/widget"
|
||||
|
||||
mediaHandler "donat-widget/internal/api/http/handlers/widget/media"
|
||||
mediaService "donat-widget/internal/service/widget/media"
|
||||
|
||||
donatHandler "donat-widget/internal/api/http/handlers/widget/donat"
|
||||
donatService "donat-widget/internal/service/widget/donat"
|
||||
. "donat-widget/internal/api/http/handlers/widget"
|
||||
. "donat-widget/internal/api/http/handlers/widget/donat"
|
||||
. "donat-widget/internal/api/http/handlers/widget/media"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
Config *config.Config
|
||||
}
|
||||
var PREFIX = "/api/widget"
|
||||
|
||||
func NewApp() *echo.Echo {
|
||||
app := &App{}
|
||||
_ = app.InitLogger()
|
||||
app.Config = app.InitConfig()
|
||||
db := app.initDB()
|
||||
storage := app.InitStorage()
|
||||
server := InitHTTPServer()
|
||||
InitHandlers(server, db, storage)
|
||||
|
||||
return server
|
||||
}
|
||||
|
||||
func Run(server *echo.Echo) {
|
||||
server.Logger.Fatal(server.Start(":8002"))
|
||||
}
|
||||
|
||||
func InitHTTPServer() *echo.Echo {
|
||||
func NewApp(
|
||||
db model.Db,
|
||||
widgetService model.WidgetService,
|
||||
mediaService model.MediaService,
|
||||
donatService model.DonatService,
|
||||
) {
|
||||
server := echo.New()
|
||||
server.Validator = validator.NewValidator()
|
||||
return server
|
||||
}
|
||||
|
||||
func (a *App) InitConfig() *config.Config {
|
||||
cfg := config.Init()
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (a *App) InitLogger() *slog.Logger {
|
||||
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
|
||||
slog.SetDefault(logger)
|
||||
return logger
|
||||
}
|
||||
|
||||
func (a *App) InitStorage() *weed.Weed {
|
||||
storage, err := weed.NewWeed(
|
||||
a.Config.Storage.Filer,
|
||||
a.Config.Storage.Master,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return storage
|
||||
}
|
||||
|
||||
func (a *App) initDB() *pg.Postgres {
|
||||
|
||||
db := pg.NewPgPool(
|
||||
context.Background(),
|
||||
a.Config.Db.Username,
|
||||
a.Config.Db.Password,
|
||||
a.Config.Db.Host,
|
||||
a.Config.Db.Port,
|
||||
a.Config.Db.DBName,
|
||||
)
|
||||
return db
|
||||
}
|
||||
|
||||
func InitHandlers(
|
||||
server *echo.Echo,
|
||||
db *pg.Postgres,
|
||||
storage model.Storage,
|
||||
) {
|
||||
PREFIX := "/api/widget"
|
||||
server.GET(PREFIX+"/docs/*", echoSwagger.WrapHandler)
|
||||
server.GET(PREFIX+"/table/create", CreateTale(db))
|
||||
server.GET(PREFIX+"/table/drop", DropTale(db))
|
||||
|
||||
widgetSvc := widgetService.New(db)
|
||||
server.GET(PREFIX+"/create", widgetHandler.CreateWidget(widgetSvc))
|
||||
server.GET(PREFIX+"/html/:widgetID", widgetHandler.GetWidgetHTML(widgetSvc))
|
||||
server.GET(PREFIX+"/info/:widgetID", widgetHandler.GetWidgetInfo(widgetSvc))
|
||||
server.GET(PREFIX+"/duration/update", widgetHandler.UpdateDuration(widgetSvc))
|
||||
IncludeWidgetHandlers(server, widgetService)
|
||||
IncludeMediaHandlers(server, mediaService)
|
||||
IncludeDonatHandlers(server, donatService)
|
||||
|
||||
mediaSvc := mediaService.New(db, storage)
|
||||
server.POST(PREFIX+"/media/:mediaType/upload", mediaHandler.SetMediaFile(mediaSvc))
|
||||
server.GET(PREFIX+"/media/:mediaType/get/:widgetID", mediaHandler.GetMediaFile(mediaSvc))
|
||||
server.POST(PREFIX+"/media/:mediaType/set", mediaHandler.SetMediaUrl(mediaSvc))
|
||||
|
||||
donatSvc := donatService.New(db)
|
||||
server.POST(PREFIX+"/donat/set", donatHandler.SetDonat(donatSvc))
|
||||
server.DELETE(PREFIX+"/donat/delete/:donatID", donatHandler.DeleteDonat(donatSvc))
|
||||
server.Logger.Fatal(server.Start(":8002"))
|
||||
}
|
||||
|
||||
func CreateTale(db *pg.Postgres) echo.HandlerFunc {
|
||||
func IncludeDonatHandlers(
|
||||
server *echo.Echo,
|
||||
donatService model.DonatService,
|
||||
) {
|
||||
server.POST(PREFIX+"/donat/set", SetDonat(donatService))
|
||||
server.DELETE(PREFIX+"/donat/delete/:donatID", DeleteDonat(donatService))
|
||||
}
|
||||
|
||||
func IncludeMediaHandlers(
|
||||
server *echo.Echo,
|
||||
mediaService model.MediaService,
|
||||
) {
|
||||
server.POST(PREFIX+"/media/:mediaType/upload", SetMediaFile(mediaService))
|
||||
server.POST(PREFIX+"/media/:mediaType/set", SetMediaUrl(mediaService))
|
||||
server.GET(PREFIX+"/media/:mediaType/get/:widgetID", GetMediaFile(mediaService))
|
||||
}
|
||||
|
||||
func IncludeWidgetHandlers(
|
||||
server *echo.Echo,
|
||||
widgetService model.WidgetService,
|
||||
) {
|
||||
server.POST(PREFIX+"/create", CreateWidget(widgetService))
|
||||
server.PATCH(PREFIX+"/duration/update", UpdateDuration(widgetService))
|
||||
server.GET(PREFIX+"/html/:widgetID", GetWidgetHTML(widgetService))
|
||||
server.GET(PREFIX+"/info/:widgetID", GetWidgetInfo(widgetService))
|
||||
}
|
||||
|
||||
func CreateTale(db model.Db) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
err := db.CreateTable(ctx)
|
||||
err := db.CreateTable(ctx, sql.CreateTableQuery)
|
||||
if err != nil {
|
||||
slog.Error("db.CreateTable: ", err)
|
||||
return err
|
||||
@ -130,11 +83,11 @@ func CreateTale(db *pg.Postgres) echo.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func DropTale(db *pg.Postgres) echo.HandlerFunc {
|
||||
func DropTale(db model.Db) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
|
||||
err := db.DropTable(ctx)
|
||||
err := db.DropTable(ctx, sql.DropTableQuery)
|
||||
if err != nil {
|
||||
slog.Error("db.DropTable: ", err)
|
||||
return err
|
||||
|
@ -3,108 +3,64 @@ package model
|
||||
import (
|
||||
"context"
|
||||
"github.com/jackc/pgx/v5"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type Storage interface {
|
||||
Upload(
|
||||
file UploadFile,
|
||||
filename string,
|
||||
size int64,
|
||||
collection string,
|
||||
) (FileData, error)
|
||||
Download(
|
||||
FileID FileID,
|
||||
) (DownloadFile, error)
|
||||
Update(
|
||||
file UploadFile,
|
||||
fileID FileID,
|
||||
filename string,
|
||||
size int64,
|
||||
collection string,
|
||||
) error
|
||||
type WidgetService interface {
|
||||
CreateWidget(ctx context.Context, streamerID StreamerID, templateId TemplateID) (WidgetID, error)
|
||||
DeleteWidget(ctx context.Context, widgetID WidgetID) error
|
||||
UpdateDuration(ctx context.Context, widgetID WidgetID, duration Duration) error
|
||||
GetWidgetInfo(ctx context.Context, widgetID WidgetID) (*DonatAndWidget, error)
|
||||
GetWidgetHTML(ctx context.Context, widgetID WidgetID) (WidgetHTML, error)
|
||||
}
|
||||
|
||||
type WidgetRepo interface {
|
||||
CreateWidget(
|
||||
ctx context.Context,
|
||||
streamerID StreamerID,
|
||||
templateId TemplateID,
|
||||
) (WidgetID, error)
|
||||
|
||||
DeleteWidget(
|
||||
ctx context.Context,
|
||||
widgetID WidgetID,
|
||||
) error
|
||||
|
||||
GetWidget(
|
||||
ctx context.Context,
|
||||
widgetID WidgetID,
|
||||
) (*Widget, error)
|
||||
|
||||
UpdateWidgetDuration(
|
||||
ctx context.Context,
|
||||
widgetID WidgetID,
|
||||
duration Duration,
|
||||
) error
|
||||
CreateWidget(ctx context.Context, streamerID StreamerID, templateId TemplateID) (WidgetID, error)
|
||||
DeleteWidget(ctx context.Context, widgetID WidgetID) error
|
||||
UpdateDuration(ctx context.Context, widgetID WidgetID, duration Duration) error
|
||||
GetWidget(ctx context.Context, widgetID WidgetID) (*Widget, error)
|
||||
}
|
||||
|
||||
type DonatRepo interface {
|
||||
SetDonat(
|
||||
ctx context.Context,
|
||||
widgetID WidgetID,
|
||||
text string,
|
||||
amount DonatAmount,
|
||||
donatUser string,
|
||||
) error
|
||||
GetDonat(
|
||||
ctx context.Context,
|
||||
widgetID WidgetID,
|
||||
) ([]*Donat, error)
|
||||
DeleteDonat(
|
||||
ctx context.Context,
|
||||
donatID DonatID,
|
||||
) error
|
||||
type MediaService interface {
|
||||
SetMediaFile(ctx context.Context, mediaType MediaType, widgetID WidgetID, file UploadFile, filename string, size int64, collection string) error
|
||||
SetMediaUrl(ctx context.Context, mediaType MediaType, widgetID WidgetID, mediaURL MediaUrl) error
|
||||
UpdateMediaFile(ctx context.Context, widgetID WidgetID, mediaType MediaType, file UploadFile, filename string, size int64, collection string) error
|
||||
GetMediaFile(ctx context.Context, widgetID WidgetID, mediaType MediaType) (DownloadFile, error)
|
||||
}
|
||||
|
||||
type MediaRepo interface {
|
||||
SetMediaFile(
|
||||
file UploadFile,
|
||||
filename string,
|
||||
size int64,
|
||||
collection string,
|
||||
) (FileID, error)
|
||||
GetMediaFile(
|
||||
fileID FileID,
|
||||
) (DownloadFile, error)
|
||||
GetMediaUrl(
|
||||
ctx context.Context,
|
||||
widgetID WidgetID,
|
||||
mediaType MediaType,
|
||||
) (MediaUrl, error)
|
||||
SetMediaUrl(
|
||||
ctx context.Context,
|
||||
widgetID WidgetID,
|
||||
mediaUrl MediaUrl,
|
||||
mediaType MediaType,
|
||||
) error
|
||||
UpdateMediaFile(
|
||||
ctx context.Context,
|
||||
widgetID WidgetID,
|
||||
file UploadFile,
|
||||
fileID FileID,
|
||||
filename string,
|
||||
size int64,
|
||||
collection string,
|
||||
mediaType MediaType,
|
||||
) error
|
||||
SetMediaFile(file UploadFile, filename string, size int64, collection string) (FileID, error)
|
||||
GetMediaFile(fileID FileID) (DownloadFile, error)
|
||||
GetMediaUrl(ctx context.Context, widgetID WidgetID, mediaType MediaType) (MediaUrl, error)
|
||||
SetMediaUrl(ctx context.Context, widgetID WidgetID, mediaUrl MediaUrl, mediaType MediaType) error
|
||||
UpdateMediaFile(ctx context.Context, widgetID WidgetID, file UploadFile, fileID FileID, filename string, size int64, collection string, mediaType MediaType) error
|
||||
}
|
||||
|
||||
type DonatService interface {
|
||||
SetDonat(ctx context.Context, widgetID WidgetID, text string, amount DonatAmount, donatUser string) error
|
||||
DeleteDonat(ctx context.Context, DonatID DonatID) error
|
||||
}
|
||||
|
||||
type DonatRepo interface {
|
||||
SetDonat(ctx context.Context, widgetID WidgetID, text string, amount DonatAmount, donatUser string) error
|
||||
GetDonat(ctx context.Context, widgetID WidgetID) ([]*Donat, error)
|
||||
DeleteDonat(ctx context.Context, donatID DonatID) error
|
||||
}
|
||||
|
||||
type Error interface {
|
||||
Error() string
|
||||
}
|
||||
|
||||
type Storage interface {
|
||||
Upload(file UploadFile, filename string, size int64, collection string) (FileData, error)
|
||||
Download(FileID FileID) (DownloadFile, error)
|
||||
Update(file UploadFile, fileID FileID, filename string, size int64, collection string) error
|
||||
}
|
||||
|
||||
type Db interface {
|
||||
Exec(ctx context.Context, query string, args ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(ctx context.Context, query string, args ...interface{}) (pgx.Rows, error)
|
||||
CreateTable(ctx context.Context, query string) error
|
||||
DropTable(ctx context.Context, query string) error
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -16,6 +18,34 @@ type Widget struct {
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func (widget *Widget) GetMediaUrl(mediaType MediaType) MediaUrl {
|
||||
var mediaUrl MediaUrl
|
||||
if mediaType == "background_url" {
|
||||
mediaUrl = widget.BackgroundUrl
|
||||
} else if mediaType == "image_url" {
|
||||
mediaUrl = widget.ImageUrl
|
||||
} else if mediaType == "audio_url" {
|
||||
mediaUrl = widget.AudioUrl
|
||||
}
|
||||
return mediaUrl
|
||||
}
|
||||
|
||||
func (widget *Widget) NormalizeUrl() {
|
||||
selfDomain := "http://localhost:8002/api/widget/media"
|
||||
strWidgetID := strconv.Itoa(int(widget.ID))
|
||||
if !strings.Contains(string(widget.ImageUrl), "http") && widget.ImageUrl != "" {
|
||||
widget.ImageUrl = MediaUrl(selfDomain + "/image/get/" + strWidgetID)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(widget.BackgroundUrl), "http") && widget.BackgroundUrl != "" {
|
||||
widget.BackgroundUrl = MediaUrl(selfDomain + "/background/get/" + strWidgetID)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(widget.AudioUrl), "http") && widget.AudioUrl != "" {
|
||||
widget.AudioUrl = MediaUrl(selfDomain + "/audio/get/" + strWidgetID)
|
||||
}
|
||||
}
|
||||
|
||||
type Donat struct {
|
||||
ID DonatID
|
||||
WidgetID WidgetID
|
||||
|
48
internal/model/sql/model.go
Normal file
48
internal/model/sql/model.go
Normal file
@ -0,0 +1,48 @@
|
||||
package sql
|
||||
|
||||
var CreateTableQuery = `
|
||||
CREATE TABLE IF NOT EXISTS widgets (
|
||||
id SERIAL PRIMARY KEY,
|
||||
streamer_id INTEGER NOT NULL,
|
||||
template_id INTEGER NOT NULL,
|
||||
background_url TEXT DEFAULT '',
|
||||
image_url TEXT DEFAULT '',
|
||||
audio_url TEXT DEFAULT '',
|
||||
duration INTEGER DEFAULT 30,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS donats (
|
||||
id SERIAL PRIMARY KEY,
|
||||
widget_id INTEGER NOT NULL,
|
||||
text TEXT DEFAULT '',
|
||||
amount TEXT DEFAULT '',
|
||||
donat_user TEXT DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
|
||||
CREATE TRIGGER update_updated_at_trigger
|
||||
BEFORE UPDATE ON widgets
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE update_updated_at();
|
||||
|
||||
CREATE TRIGGER update_updated_at_trigger
|
||||
BEFORE UPDATE ON donats
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE update_updated_at();
|
||||
`
|
||||
|
||||
var DropTableQuery = `
|
||||
DROP TABLE IF EXISTS widgets;
|
||||
DROP TABLE IF EXISTS donats;
|
||||
`
|
53
internal/model/sql/query.go
Normal file
53
internal/model/sql/query.go
Normal file
@ -0,0 +1,53 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
"donat-widget/internal/model"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var CreateWidgetQuery = `
|
||||
INSERT INTO widgets (streamer_id, template_id)
|
||||
VALUES (@streamer_id, @template_id);
|
||||
`
|
||||
|
||||
var SetDonatQuery = `
|
||||
INSERT INTO donats (widget_id, text, amount, donat_user)
|
||||
VALUES (@widget_id, @text, @amount, @donat_user);
|
||||
`
|
||||
|
||||
var DeleteDonatQuery = `
|
||||
DELETE FROM donats WHERE id = (@id);
|
||||
`
|
||||
|
||||
var UpdateDurationQuery = `
|
||||
UPDATE widgets
|
||||
SET duration = (@duration)
|
||||
WHERE id = (@id)
|
||||
`
|
||||
|
||||
func UpdateMediaUrlQuery(mediaType model.MediaType) string {
|
||||
query := fmt.Sprintf(`
|
||||
UPDATE widgets
|
||||
SET %s = (@%s)
|
||||
WHERE id = (@id)
|
||||
`, mediaType, mediaType)
|
||||
return query
|
||||
}
|
||||
|
||||
var GetDonatQuery = `
|
||||
SELECT * FROM donats WHERE widget_id = (@widget_id);
|
||||
`
|
||||
|
||||
var GetWidgetQuery = `
|
||||
SELECT * FROM widgets
|
||||
WHERE id = (@id);
|
||||
`
|
||||
|
||||
func GetMediaUrl(mediaType model.MediaType) string {
|
||||
query := fmt.Sprintf(`
|
||||
SELECT %s
|
||||
FROM widgets
|
||||
WHERE id = (@id)
|
||||
`, mediaType)
|
||||
return query
|
||||
}
|
@ -5,6 +5,8 @@ import (
|
||||
"mime/multipart"
|
||||
)
|
||||
|
||||
type QueryArgs map[string]any
|
||||
|
||||
type StreamerID int
|
||||
type WidgetID int
|
||||
type TemplateID int
|
||||
|
@ -3,15 +3,16 @@ package donat
|
||||
import (
|
||||
"context"
|
||||
"donat-widget/internal/model"
|
||||
"donat-widget/internal/model/sql"
|
||||
"github.com/georgysavva/scany/v2/pgxscan"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
func New(
|
||||
db model.Db,
|
||||
) *RepoDonat {
|
||||
return &RepoDonat{db}
|
||||
func New(db model.Db) *RepoDonat {
|
||||
return &RepoDonat{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
type RepoDonat struct {
|
||||
@ -25,23 +26,18 @@ func (repoDonat *RepoDonat) SetDonat(
|
||||
amount model.DonatAmount,
|
||||
donatUser string,
|
||||
) error {
|
||||
query := `
|
||||
INSERT INTO donats (widget_id, text, amount, donat_user)
|
||||
VALUES (@widget_id, @text, @amount, @donat_user);
|
||||
`
|
||||
|
||||
args := pgx.NamedArgs{
|
||||
args := model.QueryArgs{
|
||||
"widget_id": widgetID,
|
||||
"text": text,
|
||||
"amount": amount,
|
||||
"donat_user": donatUser,
|
||||
}
|
||||
|
||||
_, err := repoDonat.db.Query(ctx, query, args)
|
||||
_, err := repoDonat.db.Query(ctx, sql.SetDonatQuery, args)
|
||||
if err != nil {
|
||||
slog.Error("repoDonat.db.Query: " + err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -49,21 +45,16 @@ func (repoDonat *RepoDonat) GetDonat(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
) ([]*model.Donat, error) {
|
||||
query := `
|
||||
SELECT * FROM donats WHERE widget_id = (@widget_id);
|
||||
`
|
||||
|
||||
args := pgx.NamedArgs{
|
||||
"widget_id": widgetID,
|
||||
}
|
||||
|
||||
rows, err := repoDonat.db.Query(ctx, query, args)
|
||||
rows, err := repoDonat.db.Query(ctx, sql.GetDonatQuery, args)
|
||||
if err != nil {
|
||||
slog.Error("repoDonat.db.Query: " + err.Error())
|
||||
return nil, err
|
||||
}
|
||||
var donats []*model.Donat
|
||||
|
||||
var donats []*model.Donat
|
||||
err = pgxscan.ScanAll(&donats, rows)
|
||||
if err != nil {
|
||||
slog.Error("repoMedia.pgxscan.ScanAll: " + err.Error())
|
||||
@ -77,15 +68,10 @@ func (repoDonat *RepoDonat) DeleteDonat(
|
||||
ctx context.Context,
|
||||
donatID model.DonatID,
|
||||
) error {
|
||||
query := `
|
||||
DELETE FROM donats WHERE id = (@id);
|
||||
`
|
||||
|
||||
args := pgx.NamedArgs{
|
||||
"id": donatID,
|
||||
}
|
||||
|
||||
_, err := repoDonat.db.Query(ctx, query, args)
|
||||
_, err := repoDonat.db.Query(ctx, sql.DeleteDonatQuery, args)
|
||||
if err != nil {
|
||||
slog.Error("repoDonat.db.Query: " + err.Error())
|
||||
return err
|
||||
|
@ -3,10 +3,9 @@ package media
|
||||
import (
|
||||
"context"
|
||||
"donat-widget/internal/model"
|
||||
"donat-widget/internal/model/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/georgysavva/scany/v2/pgxscan"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
@ -14,7 +13,10 @@ func New(
|
||||
db model.Db,
|
||||
storage model.Storage,
|
||||
) *RepoMedia {
|
||||
return &RepoMedia{db, storage}
|
||||
return &RepoMedia{
|
||||
db: db,
|
||||
storage: storage,
|
||||
}
|
||||
}
|
||||
|
||||
type RepoMedia struct {
|
||||
@ -28,19 +30,13 @@ func (repoMedia *RepoMedia) SetMediaFile(
|
||||
size int64,
|
||||
collection string,
|
||||
) (model.FileID, error) {
|
||||
fileData, err := repoMedia.storage.Upload(
|
||||
file,
|
||||
filename,
|
||||
size,
|
||||
collection,
|
||||
)
|
||||
fileData, err := repoMedia.storage.Upload(file, filename, size, collection)
|
||||
if err != nil {
|
||||
slog.Error("repoMedia.storage.Upload: " + err.Error())
|
||||
return "", err
|
||||
}
|
||||
fileID := fileData.FileID
|
||||
|
||||
return model.FileID(fileID), nil
|
||||
return model.FileID(fileData.FileID), nil
|
||||
}
|
||||
|
||||
func (repoMedia *RepoMedia) GetMediaFile(
|
||||
@ -51,6 +47,7 @@ func (repoMedia *RepoMedia) GetMediaFile(
|
||||
slog.Error("repoMedia.storage.Download: " + err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return file, err
|
||||
}
|
||||
|
||||
@ -64,30 +61,18 @@ func (repoMedia *RepoMedia) UpdateMediaFile(
|
||||
collection string,
|
||||
mediaType model.MediaType,
|
||||
) error {
|
||||
err := repoMedia.storage.Update(
|
||||
file,
|
||||
fileID,
|
||||
filename,
|
||||
size,
|
||||
collection,
|
||||
)
|
||||
err := repoMedia.storage.Update(file, fileID, filename, size, collection)
|
||||
if err != nil {
|
||||
slog.Error("repoMedia.storage.Update: " + err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
mediaType = mediaType + "_url"
|
||||
query := fmt.Sprintf(`
|
||||
UPDATE widgets
|
||||
SET %s = (@%s)
|
||||
WHERE id = (@id)
|
||||
`, mediaType, mediaType)
|
||||
|
||||
args := pgx.NamedArgs{
|
||||
args := model.QueryArgs{
|
||||
string(mediaType): model.MediaUrl(fileID),
|
||||
"id": widgetID,
|
||||
}
|
||||
_, err = repoMedia.db.Query(ctx, query, args)
|
||||
_, err = repoMedia.db.Query(ctx, sql.UpdateMediaUrlQuery(mediaType), args)
|
||||
if err != nil {
|
||||
slog.Error("repoMedia.db.Query: " + err.Error())
|
||||
return err
|
||||
@ -103,17 +88,12 @@ func (repoMedia *RepoMedia) SetMediaUrl(
|
||||
mediaType model.MediaType,
|
||||
) error {
|
||||
mediaType = mediaType + "_url"
|
||||
query := fmt.Sprintf(`
|
||||
UPDATE widgets
|
||||
SET %s = (@%s)
|
||||
WHERE id = (@id)
|
||||
`, mediaType, mediaType)
|
||||
|
||||
args := pgx.NamedArgs{
|
||||
args := model.QueryArgs{
|
||||
string(mediaType): mediaUrl,
|
||||
"id": widgetID,
|
||||
}
|
||||
_, err := repoMedia.db.Query(ctx, query, args)
|
||||
_, err := repoMedia.db.Query(ctx, sql.UpdateMediaUrlQuery(mediaType), args)
|
||||
if err != nil {
|
||||
slog.Error("repoMedia.db.Query: " + err.Error())
|
||||
return err
|
||||
@ -127,22 +107,16 @@ func (repoMedia *RepoMedia) GetMediaUrl(
|
||||
mediaType model.MediaType,
|
||||
) (model.MediaUrl, error) {
|
||||
mediaType = mediaType + "_url"
|
||||
query := fmt.Sprintf(`
|
||||
SELECT %s
|
||||
FROM widgets
|
||||
WHERE id = (@id)
|
||||
`, mediaType)
|
||||
args := pgx.NamedArgs{
|
||||
args := model.QueryArgs{
|
||||
"id": widgetID,
|
||||
}
|
||||
|
||||
var widgets []*model.Widget
|
||||
rows, err := repoMedia.db.Query(ctx, query, args)
|
||||
rows, err := repoMedia.db.Query(ctx, sql.GetMediaUrl(mediaType), args)
|
||||
if err != nil {
|
||||
slog.Error("repoMedia.db.Query: " + err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
var widgets []*model.Widget
|
||||
err = pgxscan.ScanAll(&widgets, rows)
|
||||
if err != nil {
|
||||
slog.Error("repoMedia.pgxscan.ScanAll: " + err.Error())
|
||||
@ -155,15 +129,7 @@ func (repoMedia *RepoMedia) GetMediaUrl(
|
||||
}
|
||||
|
||||
widget := widgets[0]
|
||||
var mediaUrl model.MediaUrl
|
||||
|
||||
if mediaType == "background_url" {
|
||||
mediaUrl = widget.BackgroundUrl
|
||||
} else if mediaType == "image_url" {
|
||||
mediaUrl = widget.ImageUrl
|
||||
} else if mediaType == "audio_url" {
|
||||
mediaUrl = widget.AudioUrl
|
||||
}
|
||||
mediaUrl := widget.GetMediaUrl(mediaType)
|
||||
|
||||
return mediaUrl, nil
|
||||
}
|
||||
|
@ -3,22 +3,20 @@ package widget
|
||||
import (
|
||||
"context"
|
||||
"donat-widget/internal/model"
|
||||
"donat-widget/internal/model/sql"
|
||||
"errors"
|
||||
"github.com/georgysavva/scany/v2/pgxscan"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func New(
|
||||
db model.Db,
|
||||
) *RepoWidget {
|
||||
return &RepoWidget{db}
|
||||
func New(db model.Db) *RepoWidget {
|
||||
return &RepoWidget{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
type RepoWidget struct {
|
||||
model.Db
|
||||
db model.Db
|
||||
}
|
||||
|
||||
func (widgetRepo *RepoWidget) CreateWidget(
|
||||
@ -26,19 +24,13 @@ func (widgetRepo *RepoWidget) CreateWidget(
|
||||
streamerID model.StreamerID,
|
||||
templateID model.TemplateID,
|
||||
) (model.WidgetID, error) {
|
||||
query := `
|
||||
INSERT INTO widgets (streamer_id, template_id)
|
||||
VALUES (@streamer_id, @template_id);
|
||||
`
|
||||
|
||||
args := pgx.NamedArgs{
|
||||
args := model.QueryArgs{
|
||||
"streamer_id": streamerID,
|
||||
"template_id": templateID,
|
||||
}
|
||||
|
||||
_, err := widgetRepo.Query(ctx, query, args)
|
||||
_, err := widgetRepo.db.Query(ctx, sql.CreateWidgetQuery, args)
|
||||
if err != nil {
|
||||
slog.Error("widgetRepo.Query: " + err.Error())
|
||||
slog.Error("widgetRepo.db.Query: " + err.Error())
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@ -50,21 +42,16 @@ func (widgetRepo *RepoWidget) GetWidget(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
) (*model.Widget, error) {
|
||||
query := `
|
||||
SELECT * FROM widgets
|
||||
WHERE id = (@id);
|
||||
`
|
||||
args := pgx.NamedArgs{
|
||||
args := model.QueryArgs{
|
||||
"id": widgetID,
|
||||
}
|
||||
|
||||
var widgets []*model.Widget
|
||||
rows, err := widgetRepo.Query(ctx, query, args)
|
||||
rows, err := widgetRepo.db.Query(ctx, sql.GetWidgetQuery, args)
|
||||
if err != nil {
|
||||
slog.Error("widgetRepo.Query: " + err.Error())
|
||||
slog.Error("widgetRepo.db.Query: " + err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var widgets []*model.Widget
|
||||
err = pgxscan.ScanAll(&widgets, rows)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
@ -77,20 +64,7 @@ func (widgetRepo *RepoWidget) GetWidget(
|
||||
}
|
||||
|
||||
widget := widgets[0]
|
||||
|
||||
selfDomain := "http://localhost:8002/api/widget/media"
|
||||
strWidgetID := strconv.Itoa(int(widgetID))
|
||||
if !strings.Contains(string(widget.ImageUrl), "http") && widget.ImageUrl != "" {
|
||||
widget.ImageUrl = model.MediaUrl(selfDomain + "/image/get/" + strWidgetID)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(widget.BackgroundUrl), "http") && widget.BackgroundUrl != "" {
|
||||
widget.BackgroundUrl = model.MediaUrl(selfDomain + "/background/get/" + strWidgetID)
|
||||
}
|
||||
|
||||
if !strings.Contains(string(widget.AudioUrl), "http") && widget.AudioUrl != "" {
|
||||
widget.AudioUrl = model.MediaUrl(selfDomain + "/audio/get/" + strWidgetID)
|
||||
}
|
||||
widget.NormalizeUrl()
|
||||
|
||||
return widget, nil
|
||||
}
|
||||
@ -102,25 +76,18 @@ func (widgetRepo *RepoWidget) DeleteWidget(
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (widgetRepo *RepoWidget) UpdateWidgetDuration(
|
||||
func (widgetRepo *RepoWidget) UpdateDuration(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
duration model.Duration,
|
||||
) error {
|
||||
query := `
|
||||
UPDATE widgets
|
||||
SET duration = (@duration)
|
||||
WHERE id = (@id)
|
||||
`
|
||||
|
||||
args := pgx.NamedArgs{
|
||||
args := model.QueryArgs{
|
||||
"id": widgetID,
|
||||
"duration": duration,
|
||||
}
|
||||
|
||||
_, err := widgetRepo.Query(ctx, query, args)
|
||||
_, err := widgetRepo.db.Query(ctx, sql.UpdateDurationQuery, args)
|
||||
if err != nil {
|
||||
slog.Error("widgetRepo.Query: " + err.Error())
|
||||
slog.Error("widgetRepo.db.Query: " + err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package donat
|
||||
import (
|
||||
"context"
|
||||
"donat-widget/internal/model"
|
||||
mediaRepo "donat-widget/internal/repository/widget/donat"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
@ -12,10 +11,10 @@ type ServiceDonat struct {
|
||||
}
|
||||
|
||||
func New(
|
||||
db model.Db,
|
||||
donatRepo model.DonatRepo,
|
||||
) *ServiceDonat {
|
||||
return &ServiceDonat{
|
||||
donatRepo: mediaRepo.New(db),
|
||||
donatRepo: donatRepo,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,21 +3,17 @@ package media
|
||||
import (
|
||||
"context"
|
||||
"donat-widget/internal/model"
|
||||
mediaRepo "donat-widget/internal/repository/widget/media"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type ServiceMedia struct {
|
||||
mediaRepo model.MediaRepo
|
||||
func New(mediaRepo model.MediaRepo) *ServiceMedia {
|
||||
return &ServiceMedia{
|
||||
mediaRepo: mediaRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func New(
|
||||
db model.Db,
|
||||
storage model.Storage,
|
||||
) *ServiceMedia {
|
||||
return &ServiceMedia{
|
||||
mediaRepo: mediaRepo.New(db, storage),
|
||||
}
|
||||
type ServiceMedia struct {
|
||||
mediaRepo model.MediaRepo
|
||||
}
|
||||
|
||||
func (mediaService *ServiceMedia) SetMediaFile(
|
||||
|
@ -3,23 +3,24 @@ package widget
|
||||
import (
|
||||
"context"
|
||||
"donat-widget/internal/model"
|
||||
widgetRepo "donat-widget/internal/repository/widget"
|
||||
donatRepo "donat-widget/internal/repository/widget/donat"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
func New(
|
||||
widgetRepo model.WidgetRepo,
|
||||
donatRepo model.DonatRepo,
|
||||
) *ServiceWidget {
|
||||
return &ServiceWidget{
|
||||
widgetRepo: widgetRepo,
|
||||
donatRepo: donatRepo,
|
||||
}
|
||||
}
|
||||
|
||||
type ServiceWidget struct {
|
||||
widgetRepo model.WidgetRepo
|
||||
donatRepo model.DonatRepo
|
||||
}
|
||||
|
||||
func New(db model.Db) *ServiceWidget {
|
||||
return &ServiceWidget{
|
||||
widgetRepo: widgetRepo.New(db),
|
||||
donatRepo: donatRepo.New(db),
|
||||
}
|
||||
}
|
||||
|
||||
func (widgetService *ServiceWidget) CreateWidget(
|
||||
ctx context.Context,
|
||||
streamerID model.StreamerID,
|
||||
@ -45,6 +46,20 @@ func (widgetService *ServiceWidget) DeleteWidget(
|
||||
return nil
|
||||
}
|
||||
|
||||
func (widgetService *ServiceWidget) UpdateDuration(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
duration model.Duration,
|
||||
) error {
|
||||
err := widgetService.widgetRepo.UpdateDuration(ctx, widgetID, duration)
|
||||
if err != nil {
|
||||
slog.Error("widgetService.widgetRepo.UpdateDuration: " + err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (widgetService *ServiceWidget) GetWidgetHTML(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
@ -57,14 +72,10 @@ func (widgetService *ServiceWidget) GetWidgetHTML(
|
||||
return widgetHTML, err
|
||||
}
|
||||
|
||||
backgroundUrl := widget.BackgroundUrl
|
||||
|
||||
templateID := widget.TemplateID
|
||||
|
||||
if templateID == 1 {
|
||||
if widget.TemplateID == 1 {
|
||||
widgetHTML = model.GetTemplate1(
|
||||
widgetID,
|
||||
backgroundUrl,
|
||||
widget.BackgroundUrl,
|
||||
)
|
||||
}
|
||||
return widgetHTML, nil
|
||||
@ -102,21 +113,3 @@ func (widgetService *ServiceWidget) GetWidgetInfo(
|
||||
|
||||
return &donatAndWidget, nil
|
||||
}
|
||||
|
||||
func (widgetService *ServiceWidget) UpdateWidgetDuration(
|
||||
ctx context.Context,
|
||||
widgetID model.WidgetID,
|
||||
duration model.Duration,
|
||||
) error {
|
||||
err := widgetService.widgetRepo.UpdateWidgetDuration(
|
||||
ctx,
|
||||
widgetID,
|
||||
duration,
|
||||
)
|
||||
if err != nil {
|
||||
slog.Error("widgetService.widgetRepo.UpdateWidgetDuration: " + err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user