add router for get last moderation message

This commit is contained in:
harold 2025-03-10 11:02:47 +05:00
parent 8e91a17177
commit 5bebbd7521
11 changed files with 457 additions and 1 deletions

View File

@ -491,3 +491,38 @@ func GetDonationsStats(donatService model.DonatService) echo.HandlerFunc {
return request.JSON(http.StatusOK, stats)
}
}
// DonateModeration godoc
// @Summary Get the latest donation in moderation
// @Description Get the latest donation with status 'moderation' sorted by updated_at
// @Tags Donate
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} model.DonationModeration "Latest donation in moderation"
// @Failure 400 {object} echo.HTTPError "Bad request"
// @Failure 401 {object} echo.HTTPError "Unauthorized or expired token"
// @Failure 404 {object} echo.HTTPError "No donations in moderation found"
// @Failure 500 {object} echo.HTTPError "Internal server error"
// @Router /donat/latest-moderation [get]
func DonateModeration(donatService model.DonatService) echo.HandlerFunc {
return func(request echo.Context) error {
authData, err := donatService.CheckToken(request)
if err != nil {
slog.Error("Unauthorized")
return echo.NewHTTPError(http.StatusUnauthorized, err.Error())
}
ctx := context.Background()
donation, err := donatService.GetDonatModeration(ctx, authData.AccountID)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
if donation.ID == 0 { // Если донат не найден
return request.JSON(http.StatusOK, map[string]interface{}{})
}
return request.JSON(http.StatusOK, donation)
}
}

View File

@ -90,6 +90,8 @@ func IncludeDonatHandlers(
server.POST(PREFIX+"/donat/paid", MarkDonatPaid(donatService))
server.GET(PREFIX+"/donat/period-stat", GetDonationsStats(donatService))
server.GET(PREFIX+"/donat/latest-moderation", DonateModeration(donatService))
}
func IncludeWidgetHandlers(

View File

@ -93,6 +93,58 @@ const docTemplate = `{
}
}
},
"/donat/latest-moderation": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"description": "Get the latest donation with status 'moderation' sorted by updated_at",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Donate"
],
"summary": "Get the latest donation in moderation",
"responses": {
"200": {
"description": "Latest donation in moderation",
"schema": {
"$ref": "#/definitions/donat-widget_internal_model.DonationModeration"
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
},
"401": {
"description": "Unauthorized or expired token",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
},
"404": {
"description": "No donations in moderation found",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
}
}
}
},
"/donat/period-stat": {
"get": {
"security": [
@ -1047,6 +1099,71 @@ const docTemplate = `{
}
}
},
"donat-widget_internal_model.DonationModeration": {
"type": "object",
"properties": {
"accepted": {
"description": "Донат принят на модерации",
"type": "boolean",
"example": false
},
"amount": {
"description": "Сумма доната",
"type": "integer",
"example": 2000
},
"created_at": {
"description": "Дата создания",
"type": "string",
"example": "2025-03-09T12:49:21.75005Z"
},
"donat_user": {
"description": "Имя пользователя, сделавшего донат",
"type": "string",
"example": "Петр"
},
"id": {
"description": "Уникальный идентификатор доната",
"type": "integer",
"example": 123
},
"play_content": {
"description": "Проигрывать контент",
"type": "boolean",
"example": true
},
"show_name": {
"description": "Показывать имя пользователя",
"type": "boolean",
"example": true
},
"show_text": {
"description": "Показывать текст доната",
"type": "boolean",
"example": true
},
"status": {
"description": "Статус доната (moderation, pending, viewed и т.д.)",
"type": "string",
"example": "moderation"
},
"target_id": {
"description": "ID цели (если есть)",
"type": "integer",
"example": 0
},
"text": {
"description": "Текст доната",
"type": "string",
"example": "Пиздатый стрим"
},
"updated_at": {
"description": "Дата последнего обновления",
"type": "string",
"example": "2025-03-09T12:49:21.75005Z"
}
}
},
"donat-widget_internal_model.DonationStatResponse": {
"type": "object",
"properties": {

View File

@ -86,6 +86,58 @@
}
}
},
"/donat/latest-moderation": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"description": "Get the latest donation with status 'moderation' sorted by updated_at",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Donate"
],
"summary": "Get the latest donation in moderation",
"responses": {
"200": {
"description": "Latest donation in moderation",
"schema": {
"$ref": "#/definitions/donat-widget_internal_model.DonationModeration"
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
},
"401": {
"description": "Unauthorized or expired token",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
},
"404": {
"description": "No donations in moderation found",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
}
}
}
},
"/donat/period-stat": {
"get": {
"security": [
@ -1040,6 +1092,71 @@
}
}
},
"donat-widget_internal_model.DonationModeration": {
"type": "object",
"properties": {
"accepted": {
"description": "Донат принят на модерации",
"type": "boolean",
"example": false
},
"amount": {
"description": "Сумма доната",
"type": "integer",
"example": 2000
},
"created_at": {
"description": "Дата создания",
"type": "string",
"example": "2025-03-09T12:49:21.75005Z"
},
"donat_user": {
"description": "Имя пользователя, сделавшего донат",
"type": "string",
"example": "Петр"
},
"id": {
"description": "Уникальный идентификатор доната",
"type": "integer",
"example": 123
},
"play_content": {
"description": "Проигрывать контент",
"type": "boolean",
"example": true
},
"show_name": {
"description": "Показывать имя пользователя",
"type": "boolean",
"example": true
},
"show_text": {
"description": "Показывать текст доната",
"type": "boolean",
"example": true
},
"status": {
"description": "Статус доната (moderation, pending, viewed и т.д.)",
"type": "string",
"example": "moderation"
},
"target_id": {
"description": "ID цели (если есть)",
"type": "integer",
"example": 0
},
"text": {
"description": "Текст доната",
"type": "string",
"example": "Пиздатый стрим"
},
"updated_at": {
"description": "Дата последнего обновления",
"type": "string",
"example": "2025-03-09T12:49:21.75005Z"
}
}
},
"donat-widget_internal_model.DonationStatResponse": {
"type": "object",
"properties": {

View File

@ -69,6 +69,57 @@ definitions:
streamer_id:
type: integer
type: object
donat-widget_internal_model.DonationModeration:
properties:
accepted:
description: Донат принят на модерации
example: false
type: boolean
amount:
description: Сумма доната
example: 2000
type: integer
created_at:
description: Дата создания
example: "2025-03-09T12:49:21.75005Z"
type: string
donat_user:
description: Имя пользователя, сделавшего донат
example: Петр
type: string
id:
description: Уникальный идентификатор доната
example: 123
type: integer
play_content:
description: Проигрывать контент
example: true
type: boolean
show_name:
description: Показывать имя пользователя
example: true
type: boolean
show_text:
description: Показывать текст доната
example: true
type: boolean
status:
description: Статус доната (moderation, pending, viewed и т.д.)
example: moderation
type: string
target_id:
description: ID цели (если есть)
example: 0
type: integer
text:
description: Текст доната
example: Пиздатый стрим
type: string
updated_at:
description: Дата последнего обновления
example: "2025-03-09T12:49:21.75005Z"
type: string
type: object
donat-widget_internal_model.DonationStatResponse:
properties:
amount_collected:
@ -454,6 +505,39 @@ paths:
summary: Create donat
tags:
- Donate
/donat/latest-moderation:
get:
consumes:
- application/json
description: Get the latest donation with status 'moderation' sorted by updated_at
produces:
- application/json
responses:
"200":
description: Latest donation in moderation
schema:
$ref: '#/definitions/donat-widget_internal_model.DonationModeration'
"400":
description: Bad request
schema:
$ref: '#/definitions/echo.HTTPError'
"401":
description: Unauthorized or expired token
schema:
$ref: '#/definitions/echo.HTTPError'
"404":
description: No donations in moderation found
schema:
$ref: '#/definitions/echo.HTTPError'
"500":
description: Internal server error
schema:
$ref: '#/definitions/echo.HTTPError'
security:
- BearerAuth: []
summary: Get the latest donation in moderation
tags:
- Donate
/donat/period-stat:
get:
consumes:

View File

@ -102,6 +102,8 @@ type DonatService interface {
UpdateModerationSettings(ctx context.Context, streamerID int, updateModel UpdateModeration) error
GetDonationsStats(ctx context.Context, streamerID int, period string) (DonationSummaryResponse, error)
GetDonatModeration(ctx context.Context, streamerID int) (DonationModeration, error)
}
type DonatRepo interface {
@ -154,6 +156,8 @@ type DonatRepo interface {
GetDonationsStats(ctx context.Context, streamerID int, period string) ([]DonationStat, error)
GetDonationsSummary(ctx context.Context, streamerID int, period string) (DonationSummary, error)
GetDonatModeration(ctx context.Context, streamerID int) (DonationModeration, error)
}
type TargetService interface {

View File

@ -278,6 +278,21 @@ type DonationSummaryResponse struct {
Donations []DonationStatResponse `json:"donations"`
}
type DonationModeration struct {
ID int `db:"id" json:"id" example:"123"` // Уникальный идентификатор доната
TargetID int `db:"target_id" json:"target_id" example:"0"` // ID цели (если есть)
Status string `db:"status" json:"status" example:"moderation"` // Статус доната (moderation, pending, viewed и т.д.)
Text string `db:"text" json:"text" example:"Пиздатый стрим"` // Текст доната
Amount int `db:"amount" json:"amount" example:"2000"` // Сумма доната
DonatUser string `db:"donat_user" json:"donat_user" example:"Петр"` // Имя пользователя, сделавшего донат
Accepted bool `db:"accepted" json:"accepted" example:"false"` // Донат принят на модерации
ShowName bool `db:"show_name" json:"show_name" example:"true"` // Показывать имя пользователя
ShowText bool `db:"show_text" json:"show_text" example:"true"` // Показывать текст доната
PlayContent bool `db:"play_content" json:"play_content" example:"true"` // Проигрывать контент
CreatedAt time.Time `db:"created_at" json:"created_at" example:"2025-03-09T12:49:21.75005Z"` // Дата создания
UpdatedAt time.Time `db:"updated_at" json:"updated_at" example:"2025-03-09T12:49:21.75005Z"` // Дата последнего обновления
}
//func (widget *GetWidgetDb) GetMediaUrl(mediaType MediaType) MediaUrl {
// var mediaUrl MediaUrl
// if mediaType == "background_url" {

View File

@ -43,7 +43,14 @@ CREATE TABLE IF NOT EXISTS donats (
text TEXT NOT NULL,
amount INTEGER NOT NULL,
donat_user TEXT NOT NULL,
accepted BOOLEAN NOT NULL DEFAULT 'false',
show_name BOOLEAN NOT NULL DEFAULT 'true',
show_text BOOLEAN NOT NULL DEFAULT 'true',
play_content BOOLEAN NOT NULL DEFAULT 'true',
showed BOOLEAN NOT NULL DEFAULT 'false',
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

View File

@ -421,3 +421,27 @@ WHERE
streamer_id = @streamer_id
AND created_at >= NOW() - INTERVAL '1 year';
`
const GetLastModeration = `
SELECT
id,
target_id,
status,
text,
amount,
donat_user,
accepted,
show_name,
show_text,
play_content,
created_at,
updated_at
FROM
public.donats
WHERE
status = 'moderation' AND
streamer_id = @streamer_id
ORDER BY
updated_at DESC
LIMIT 1;
`

View File

@ -681,3 +681,41 @@ func (repoDonat *RepoDonat) GetDonationsSummary(
return summary, nil
}
func (repoDonat *RepoDonat) GetDonatModeration(
ctx context.Context,
streamerID int,
) (model.DonationModeration, error) {
var donation model.DonationModeration
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
row, err := repoDonat.db.SelectOne(ctx, sql.GetLastModeration, args)
if err != nil {
slog.Error("Failed to get donation", "error", err)
return model.DonationModeration{}, err
}
if row == nil {
return model.DonationModeration{}, nil
}
err = row.Scan(
&donation.ID,
&donation.TargetID,
&donation.Status,
&donation.Text,
&donation.Amount,
&donation.DonatUser,
&donation.Accepted,
&donation.ShowName,
&donation.ShowText,
&donation.PlayContent,
&donation.CreatedAt,
&donation.UpdatedAt,
)
if err != nil {
slog.Error("Failed to get latest donation in moderation", "error", err)
return model.DonationModeration{}, err
}
return donation, nil
}

View File

@ -492,3 +492,16 @@ func (donatService *ServiceDonat) GetDonationsStats(
return response, nil
}
func (donatService *ServiceDonat) GetDonatModeration(
ctx context.Context,
streamerID int,
) (model.DonationModeration, error) {
donation, err := donatService.donatRepo.GetDonatModeration(ctx, streamerID)
if err != nil {
slog.Error("Failed to get latest donation in moderation", "error", err)
return model.DonationModeration{}, err
}
return donation, nil
}