diff --git a/cmd/main.go b/cmd/main.go index 4f25a79..a0f0c70 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -52,7 +52,7 @@ func main() { targetRepo := TargetRepo.New(db) // SERVICES - widgetService := WidgetService.New(widgetRepo) + widgetService := WidgetService.New(widgetRepo, authClient) donatService := DonatService.New(donatRepo, widgetRepo, paymentClient, authClient) targetService := TargetService.New(targetRepo, authClient) diff --git a/internal/api/http/handlers/widget/widget.go b/internal/api/http/handlers/widget/widget.go index ac44e2d..16679bc 100644 --- a/internal/api/http/handlers/widget/widget.go +++ b/internal/api/http/handlers/widget/widget.go @@ -1,226 +1,209 @@ -//package widget -// -//import ( -// "context" -// "donat-widget/internal/model" -// "github.com/labstack/echo/v4" -// "log/slog" -// "net/http" -// "strconv" -//) -// -//func CreateWidget(widgetService model.WidgetService, authClient model.AuthClient) echo.HandlerFunc { -// type CreateWidgetBody struct { -// TemplateID model.TemplateID `json:"templateID"` -// MinAmount model.DonatAmount `json:"minAmount"` -// Duration model.Duration `json:"duration"` -// } -// -// type CreateWidgetResponse struct { -// WidgetID model.WidgetID `json:"widgetID"` -// } -// return func(request echo.Context) error { -// ctx := context.Background() -// var body CreateWidgetBody -// if err := request.Bind(&body); err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// if err := request.Validate(&body); err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// authData, err := authClient.CheckToken(request) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// if authData.StreamerID == 0 { -// slog.Error("Unauthorized account") -// return request.JSON(http.StatusUnauthorized, "Unauthorized") -// } -// if authData.StreamerID == -1 { -// slog.Error("Expired token") -// return request.JSON(http.StatusUnauthorized, "Expired token") -// } -// -// widgetID, err := widgetService.CreateWidget( -// ctx, -// model.StreamerID(authData.StreamerID), -// body.TemplateID, -// body.Duration, -// body.MinAmount, -// ) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// response := CreateWidgetResponse{ -// WidgetID: widgetID, -// } -// -// return request.JSON(200, response) -// } -//} -// -//func GetWidgetHTML(widgetService model.WidgetService) echo.HandlerFunc { -// return func(request echo.Context) error { -// ctx := context.Background() -// -// streamerID, err := strconv.Atoi(request.Param("streamerID")) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// widgetHTML, err := widgetService.GetWidgetHTML( -// ctx, -// model.StreamerID(streamerID), -// ) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// slog.Info("Get widget HTML successfully") -// return request.HTML(200, string(widgetHTML)) -// } -//} -// -//func GetWidgetInfo(widgetService model.WidgetService) echo.HandlerFunc { -// type Response struct { -// AudioUrl model.MediaUrl `json:"audioUrl"` -// ImageUrl model.MediaUrl `json:"imageUrl"` -// Duration model.Duration `json:"duration"` -// } -// return func(request echo.Context) error { -// ctx := context.Background() -// -// widgetID, err := strconv.Atoi(request.Param("widgetID")) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// widget, err := widgetService.GetWidgetByID(ctx, model.WidgetID(widgetID)) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// if len(widget) == 0 { -// return request.JSON(http.StatusNotFound, "widget not found") -// } -// -// return request.JSON(200, widget) -// } -//} -// -//func SetMediaFile(widgetService model.WidgetService) echo.HandlerFunc { -// return func(request echo.Context) error { -// ctx := context.Background() -// -// widgetID, err := strconv.Atoi(request.FormValue("widgetID")) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// mediaType := request.Param("mediaType") -// -// file, err := request.FormFile("file") -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// src, err := file.Open() -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// err = widgetService.SetMediaFile( -// ctx, -// model.MediaType(mediaType), -// model.WidgetID(widgetID), -// &src, -// file.Filename, -// file.Size, -// "", -// ) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// slog.Info("set " + mediaType + " file successfully") -// return request.String(200, "File successfully uploaded") -// } -//} -// -//func GetMediaFile(widgetService model.WidgetService) echo.HandlerFunc { -// return func(request echo.Context) error { -// ctx := context.Background() -// -// mediaType := request.Param("mediaType") -// if mediaType != "background" && mediaType != "image" && mediaType != "audio" { -// slog.Error("Path parameter 'mediaType' is invalid") -// return echo.NewHTTPError(400, "Path parameter 'mediaType' is invalid") -// } -// -// widgetID, err := strconv.Atoi(request.Param("widgetID")) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// file, err := widgetService.GetMediaFile( -// ctx, -// model.WidgetID(widgetID), -// model.MediaType(mediaType), -// ) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// slog.Info("get " + mediaType + " file successfully") -// return request.Blob(200, "application/octet-stream", file) -// } -//} -// -//func SetMediaUrl(widgetService model.WidgetService) echo.HandlerFunc { -// type Body struct { -// WidgetID model.WidgetID `json:"widgetID" validate:"required"` -// MediaUrl model.MediaUrl `json:"mediaUrl" validate:"required"` -// } -// return func(request echo.Context) error { -// ctx := context.Background() -// var body Body -// if err := request.Bind(&body); err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// if err := request.Validate(&body); err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// mediaType := request.Param("mediaType") -// -// err := widgetService.SetMediaUrl( -// ctx, -// model.MediaType(mediaType), -// body.WidgetID, -// body.MediaUrl, -// ) -// if err != nil { -// slog.Error(err.Error()) -// return request.JSON(http.StatusInternalServerError, err.Error()) -// } -// -// return request.String(200, "Media URL successfully set") -// } -//} +package widget + +import ( + "context" + "donat-widget/internal/model" + "github.com/labstack/echo/v4" + "log/slog" + "net/http" + "strconv" +) + +func CreateWidget(widgetService model.WidgetService, authClient model.AuthClient) echo.HandlerFunc { + return func(request echo.Context) error { + ctx := context.Background() + var body model.CreateWidgetBody + if err := request.Bind(&body); err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + if err := request.Validate(&body); err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + authData, err := widgetService.CheckToken(request) + if err != nil { + slog.Error(err.Error()) + return echo.NewHTTPError(http.StatusUnauthorized, err.Error()) + } + + widgetID, err := widgetService.CreateWidget( + ctx, + model.StreamerID(authData.AccountID), + body.TemplateID, + body.Duration, + body.MinAmount, + ) + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + response := model.CreateWidgetResponse{ + WidgetID: widgetID, + } + + return request.JSON(http.StatusOK, response) + } +} + +func GetWidgetHTML(widgetService model.WidgetService) echo.HandlerFunc { + return func(request echo.Context) error { + ctx := context.Background() + + streamerID, err := strconv.Atoi(request.Param("streamerID")) + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + widgetHTML, err := widgetService.GetWidgetHTML( + ctx, + model.StreamerID(streamerID), + ) + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + slog.Info("Get widget HTML successfully") + return request.HTML(200, string(widgetHTML)) + } +} + +func GetWidgetInfo(widgetService model.WidgetService) echo.HandlerFunc { + return func(request echo.Context) error { + ctx := context.Background() + + widgetID, err := strconv.Atoi(request.Param("widgetID")) + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + widget, err := widgetService.GetWidgetByID(ctx, model.WidgetID(widgetID)) + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + if len(widget) == 0 { + return request.JSON(http.StatusNotFound, "widget not found") + } + + var ResponseWidget = model.WidgetInfoResponse{ + AudioUrl: widget[0].AudioUrl, + ImageUrl: widget[0].ImageUrl, + Duration: widget[0].Duration, + } + + return request.JSON(http.StatusOK, ResponseWidget) + } +} + +func SetMediaFile(widgetService model.WidgetService) echo.HandlerFunc { + return func(request echo.Context) error { + ctx := context.Background() + + widgetID, err := strconv.Atoi(request.FormValue("widgetID")) + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + mediaType := request.Param("mediaType") + + file, err := request.FormFile("file") + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + src, err := file.Open() + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + err = widgetService.SetMediaFile( + ctx, + model.MediaType(mediaType), + model.WidgetID(widgetID), + &src, + file.Filename, + file.Size, + "", + ) + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + slog.Info("set " + mediaType + " file successfully") + return request.String(200, "File successfully uploaded") + } +} + +func GetMediaFile(widgetService model.WidgetService) echo.HandlerFunc { + return func(request echo.Context) error { + ctx := context.Background() + + mediaType := request.Param("mediaType") + if mediaType != "background" && mediaType != "image" && mediaType != "audio" { + slog.Error("Path parameter 'mediaType' is invalid") + return echo.NewHTTPError(400, "Path parameter 'mediaType' is invalid") + } + + widgetID, err := strconv.Atoi(request.Param("widgetID")) + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + file, err := widgetService.GetMediaFile( + ctx, + model.WidgetID(widgetID), + model.MediaType(mediaType), + ) + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + slog.Info("get " + mediaType + " file successfully") + return request.Blob(200, "application/octet-stream", file) + } +} + +func SetMediaUrl(widgetService model.WidgetService) echo.HandlerFunc { + type Body struct { + WidgetID model.WidgetID `json:"widgetID" validate:"required"` + MediaUrl model.MediaUrl `json:"mediaUrl" validate:"required"` + } + return func(request echo.Context) error { + ctx := context.Background() + var body Body + if err := request.Bind(&body); err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + if err := request.Validate(&body); err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + mediaType := request.Param("mediaType") + + err := widgetService.SetMediaUrl( + ctx, + model.MediaType(mediaType), + body.WidgetID, + body.MediaUrl, + ) + if err != nil { + slog.Error(err.Error()) + return request.JSON(http.StatusInternalServerError, err.Error()) + } + + return request.String(200, "Media URL successfully set") + } +} diff --git a/internal/docs/docs.go b/internal/docs/docs.go index 8c4e852..eb49dd7 100644 --- a/internal/docs/docs.go +++ b/internal/docs/docs.go @@ -595,7 +595,7 @@ const docTemplate = `{ var SwaggerInfo = &swag.Spec{ Version: "3.0", Host: "", - BasePath: "/api/donat-wiget", + BasePath: "/api/widget", Schemes: []string{}, Title: "Donate Auth Documentation", Description: "Donate auth service docs.", diff --git a/internal/docs/swagger.json b/internal/docs/swagger.json index 584171a..9abfd06 100644 --- a/internal/docs/swagger.json +++ b/internal/docs/swagger.json @@ -6,7 +6,7 @@ "contact": {}, "version": "3.0" }, - "basePath": "/api/donat-wiget", + "basePath": "/api/widget", "paths": { "/donat-page": { "patch": { diff --git a/internal/docs/swagger.yaml b/internal/docs/swagger.yaml index 29d528e..82d3bd4 100644 --- a/internal/docs/swagger.yaml +++ b/internal/docs/swagger.yaml @@ -1,4 +1,4 @@ -basePath: /api/donat-wiget +basePath: /api/widget definitions: donat-widget_internal_model.FilterSettingResponse: properties: diff --git a/internal/model/interfaces.go b/internal/model/interfaces.go index 8c40596..feb62d2 100644 --- a/internal/model/interfaces.go +++ b/internal/model/interfaces.go @@ -8,6 +8,8 @@ import ( ) type WidgetService interface { + CheckToken(request echo.Context) (api.CheckTokenResponse, error) + CreateWidget(ctx context.Context, streamerID StreamerID, templateId TemplateID, duration Duration, minAmount DonatAmount) (WidgetID, error) GetWidgetByID(ctx context.Context, widgetID WidgetID) ([]*Widget, error) diff --git a/internal/model/models.go b/internal/model/models.go index 28e51fc..ad3838a 100644 --- a/internal/model/models.go +++ b/internal/model/models.go @@ -160,6 +160,22 @@ type UpdateModeration struct { Duration int `json:"duration"` } +type CreateWidgetBody struct { + TemplateID TemplateID `json:"templateID"` + MinAmount DonatAmount `json:"minAmount"` + Duration Duration `json:"duration"` +} + +type CreateWidgetResponse struct { + WidgetID WidgetID `json:"widgetID"` +} + +type WidgetInfoResponse struct { + AudioUrl MediaUrl `json:"audioUrl"` + ImageUrl MediaUrl `json:"imageUrl"` + Duration Duration `json:"duration"` +} + type DonatAndWidget struct { Widget *Widget Donat *Donat diff --git a/internal/service/widget/widget.go b/internal/service/widget/widget.go index f493d8e..768f143 100644 --- a/internal/service/widget/widget.go +++ b/internal/service/widget/widget.go @@ -3,20 +3,26 @@ package widget import ( "context" "donat-widget/internal/model" + "donat-widget/internal/model/api" "errors" + "github.com/labstack/echo/v4" "log/slog" + "net/http" ) func New( widgetRepo model.WidgetRepo, + authClient model.AuthClient, ) *ServiceWidget { return &ServiceWidget{ widgetRepo: widgetRepo, + authClient: authClient, } } type ServiceWidget struct { widgetRepo model.WidgetRepo + authClient model.AuthClient } func (widgetService *ServiceWidget) CreateWidget( @@ -157,3 +163,27 @@ func (widgetService *ServiceWidget) SetMediaUrl( } return nil } + +func (widgetService *ServiceWidget) CheckToken( + request echo.Context, +) (api.CheckTokenResponse, error) { + accessToken := model.Token(request.Request().Header.Get("Authorization")) + + checkTokenResponse, err := widgetService.authClient.CheckToken(accessToken) + if err != nil { + slog.Error("Failed to check token", "error", err.Error()) + return api.CheckTokenResponse{}, echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + } + + if checkTokenResponse.AccountID == 0 { + slog.Error("Unauthorized account") + return api.CheckTokenResponse{}, echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized account") + } + + if checkTokenResponse.AccountID == -1 { + slog.Error("Expired token") + return api.CheckTokenResponse{}, echo.NewHTTPError(http.StatusUnauthorized, "Expired token") + } + + return checkTokenResponse, nil +}