add voice settings update and get router

This commit is contained in:
harold 2025-03-08 23:51:29 +05:00
parent 9f8bf11a82
commit 3a51c42061
11 changed files with 281 additions and 27 deletions

View File

@ -78,6 +78,14 @@ func (pg *Postgres) Delete(ctx context.Context, query string, args ...interface{
return nil
}
func (pg *Postgres) Exec(ctx context.Context, query string, args ...interface{}) error {
_, err := pg.db.Exec(ctx, query, args...)
if err != nil {
return err
}
return nil
}
func (pg *Postgres) CreateTable(ctx context.Context, query string) error {
_, err := pg.db.Exec(ctx, query)
if err != nil {

View File

@ -256,12 +256,13 @@ func UpdateDonatePage(donatService model.DonatService, fileService model.FileSer
// @Router /voice-settings [get]
func GetVoiceSettings(donatService model.DonatService) echo.HandlerFunc {
return func(request echo.Context) error {
ctx := context.Background()
authData, err := donatService.CheckToken(request)
if err != nil {
slog.Error("Unauthorized")
return echo.NewHTTPError(http.StatusUnauthorized, err.Error())
}
ctx := context.Background()
voiceSettings, err := donatService.GetVoiceSettings(ctx, authData.AccountID)
if err != nil {
@ -280,16 +281,36 @@ func GetVoiceSettings(donatService model.DonatService) echo.HandlerFunc {
// @Tags Donate
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body model.UpdateVoiceSettings true "Update fields"
// @Param background formData file false "Background image"
// @Success 200 {string} string "Voice settings updated successfully"
// @Failure 400 {object} echo.HTTPError "Bad request"
// @Failure 401 {object} echo.HTTPError "Unauthorized or expired token"
// @Failure 422 {object} echo.HTTPError "Validation error"
// @Router /voice-settings [patch]
func UpdateVoiceSettings(donatService model.DonatService) echo.HandlerFunc {
return func(c echo.Context) error {
return nil
return func(request echo.Context) error {
ctx := context.Background()
authData, err := donatService.CheckToken(request)
if err != nil {
slog.Error("Unauthorized")
return echo.NewHTTPError(http.StatusUnauthorized, err.Error())
}
var body model.UpdateVoiceSettings
err = validator.ParseAndValidate(&body, request)
if err != nil {
slog.Error(err.Error())
return echo.NewHTTPError(http.StatusUnprocessableEntity, "Unprocessable Entity")
}
err = donatService.UpdateVoiceSettings(ctx, authData.AccountID, body)
if err != nil {
slog.Error("Failed to update voice settings", "error", err)
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to update voice settings")
}
return request.JSON(http.StatusOK, "Voice settings updated successfully")
}
}

View File

@ -74,7 +74,9 @@ func IncludeDonatHandlers(
server.GET(PREFIX+"/inner-donate-page", GetInnerDonatePage(donatService))
server.GET(PREFIX+"/outer-donate-page/:streamer-login", GetOuterDonatePage(donatService))
server.PATCH(PREFIX+"/donat-page", UpdateDonatePage(donatService, fileService))
server.GET(PREFIX+"/voice-settings", GetVoiceSettings(donatService))
server.PATCH(PREFIX+"/voice-settings", UpdateVoiceSettings(donatService))
server.GET(PREFIX+"/donat/get/:streamerID", GetDonat(donatService))

View File

@ -571,6 +571,11 @@ const docTemplate = `{
}
},
"patch": {
"security": [
{
"BearerAuth": []
}
],
"description": "Update donat voice settings.",
"consumes": [
"application/json"
@ -591,12 +596,6 @@ const docTemplate = `{
"schema": {
"$ref": "#/definitions/donat-widget_internal_model.UpdateVoiceSettings"
}
},
{
"type": "file",
"description": "Background image",
"name": "background",
"in": "formData"
}
],
"responses": {
@ -1122,6 +1121,12 @@ const docTemplate = `{
"enable": {
"type": "boolean"
},
"languages": {
"type": "array",
"items": {
"type": "string"
}
},
"min_price": {
"type": "integer"
},

View File

@ -564,6 +564,11 @@
}
},
"patch": {
"security": [
{
"BearerAuth": []
}
],
"description": "Update donat voice settings.",
"consumes": [
"application/json"
@ -584,12 +589,6 @@
"schema": {
"$ref": "#/definitions/donat-widget_internal_model.UpdateVoiceSettings"
}
},
{
"type": "file",
"description": "Background image",
"name": "background",
"in": "formData"
}
],
"responses": {
@ -1115,6 +1114,12 @@
"enable": {
"type": "boolean"
},
"languages": {
"type": "array",
"items": {
"type": "string"
}
},
"min_price": {
"type": "integer"
},

View File

@ -228,6 +228,10 @@ definitions:
properties:
enable:
type: boolean
languages:
items:
type: string
type: array
min_price:
type: integer
scenery:
@ -659,10 +663,6 @@ paths:
required: true
schema:
$ref: '#/definitions/donat-widget_internal_model.UpdateVoiceSettings'
- description: Background image
in: formData
name: background
type: file
produces:
- application/json
responses:
@ -682,6 +682,8 @@ paths:
description: Validation error
schema:
$ref: '#/definitions/echo.HTTPError'
security:
- BearerAuth: []
summary: Update donat voice settings.
tags:
- Donate

View File

@ -91,7 +91,7 @@ type DonatService interface {
headImg multipart.FileHeader,
) error
GetVoiceSettings(ctx context.Context, streamerID int) (VoiceSettingsResponse, error)
UpdateVoiceSettings(ctx context.Context, streamerID StreamerID, updateModel UpdateVoiceSettings) error
UpdateVoiceSettings(ctx context.Context, streamerID int, updateModel UpdateVoiceSettings) error
GetFiltersSettings(ctx context.Context, streamerID StreamerID) (FilterSettingResponse, error)
UpdateFiltersSettings(ctx context.Context, streamerID StreamerID, updateModel UpdateFilterSettings) error
@ -121,7 +121,13 @@ type DonatRepo interface {
textAfterDonation *string,
) error
GetVoiceSettingsByStreamerID(ctx context.Context, streamerID int) (VoiceSettingsResponse, error)
UpdateVoiceSettings(ctx context.Context, streamerID int, updateModel UpdateVoiceSettings) error
GetLanguagesByStreamerID(ctx context.Context, streamerID int) ([]Language, error)
DeleteLanguagesByVoiceSettingID(ctx context.Context, voiceSettingID int) error
InsertLanguagesForVoiceSetting(ctx context.Context, voiceSettingID int, languageIDs []int) error
GetLanguageIDsByISOCodes(ctx context.Context, isoCodes []string) ([]int, error)
GetVoiceSettingIDByStreamerID(ctx context.Context, streamerID int) (int, error)
}
type TargetService interface {
@ -158,6 +164,7 @@ type Db interface {
SelectOne(ctx context.Context, query string, args ...interface{}) (pgx.Row, error)
Delete(ctx context.Context, query string, args ...interface{}) error
Update(ctx context.Context, query string, args ...interface{}) error
Exec(ctx context.Context, query string, args ...interface{}) error
CreateTable(ctx context.Context, query string) error
DropTable(ctx context.Context, query string) error

View File

@ -199,11 +199,12 @@ type VoiceSettingsResponse struct {
}
type UpdateVoiceSettings struct {
Enable bool `json:"enable"`
VoiceSpeed int `json:"voice_speed"`
Scenery string `json:"scenery"`
VoiceSoundPercent int `json:"voice_sound_percent"`
MinPrice int `json:"min_price"`
Enable *bool `json:"enable"`
VoiceSpeed *int `json:"voice_speed"`
Scenery *string `json:"scenery"`
VoiceSoundPercent *int `json:"voice_sound_percent"`
MinPrice *int `json:"min_price"`
Languages []string `json:"languages"`
}
type FilterSettingResponse struct {

View File

@ -248,3 +248,33 @@ var GetLanguagesByStreamerID = `
JOIN voice_settings vs ON vl.voice_setting_id = vs.id
WHERE vs.streamer_id = (@streamer_id);
`
var DeleteLanguage = `
DELETE FROM voices_languages
WHERE voice_setting_id = @voice_setting_id;
`
var InsertLanguagesForVoiceSetting = `
INSERT INTO voices_languages (voice_setting_id, language_id)
VALUES %s;
`
const GetLangByISO = `
SELECT id FROM languages WHERE iso_code = ANY(@iso_codes);
`
var VoiceIDByStreamer = `
SELECT id FROM voice_settings WHERE streamer_id = @streamer_id;
`
const UpdateVoiceSettings = `
UPDATE voice_settings
SET
enable = COALESCE(@enable, enable),
voice_speed = COALESCE(@voice_speed, voice_speed),
scenery = COALESCE(@scenery, scenery),
voice_sound_percent = COALESCE(@voice_sound_percent, voice_sound_percent),
min_price = COALESCE(@min_price, min_price)
WHERE streamer_id = @streamer_id;
`

View File

@ -5,9 +5,11 @@ import (
"donat-widget/internal/model"
"donat-widget/internal/model/sql"
"errors"
"fmt"
"github.com/georgysavva/scany/v2/pgxscan"
"github.com/jackc/pgx/v5"
"log/slog"
"strings"
)
func New(db model.Db) *RepoDonat {
@ -279,3 +281,140 @@ func (repoDonat *RepoDonat) GetVoiceSettingsByStreamerID(
return *voiceSettings[0], nil
}
func (repoDonat *RepoDonat) DeleteLanguagesByVoiceSettingID(
ctx context.Context,
voiceSettingID int,
) error {
args := pgx.NamedArgs{
"voice_setting_id": voiceSettingID,
}
err := repoDonat.db.Exec(ctx, sql.DeleteLanguage, args)
if err != nil {
slog.Error("Failed to delete languages", "error", err)
return err
}
return nil
}
func (repoDonat *RepoDonat) InsertLanguagesForVoiceSetting(
ctx context.Context,
voiceSettingID int,
languageIDs []int,
) error {
if len(languageIDs) == 0 {
return nil // Нет языков для вставки
}
// Формируем список значений для вставки
var valueStrings []string
var valueArgs []interface{}
for i, languageID := range languageIDs {
valueStrings = append(valueStrings, fmt.Sprintf("($%d, $%d)", i*2+1, i*2+2))
valueArgs = append(valueArgs, voiceSettingID, languageID)
}
query := fmt.Sprintf(sql.InsertLanguagesForVoiceSetting, strings.Join(valueStrings, ","))
err := repoDonat.db.Exec(ctx, query, valueArgs...)
if err != nil {
slog.Error("Failed to insert languages", "error", err)
return err
}
return nil
}
func (repoDonat *RepoDonat) GetLanguageIDsByISOCodes(
ctx context.Context,
isoCodes []string,
) ([]int, error) {
args := pgx.NamedArgs{
"iso_codes": isoCodes,
}
rows, err := repoDonat.db.Select(ctx, sql.GetLangByISO, args)
if err != nil {
slog.Error("Failed to get language IDs by ISO codes", "error", err)
return nil, err
}
var languageIDs []int
for rows.Next() {
var languageID int
err := rows.Scan(&languageID)
if err != nil {
slog.Error("Failed to scan language ID", "error", err)
return nil, err
}
languageIDs = append(languageIDs, languageID)
}
if err := rows.Err(); err != nil {
slog.Error("Error during rows iteration", "error", err)
return nil, err
}
return languageIDs, nil
}
func (repoDonat *RepoDonat) GetVoiceSettingIDByStreamerID(
ctx context.Context,
streamerID int,
) (int, error) {
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
var voiceSettingID int
row, err := repoDonat.db.SelectOne(ctx, sql.VoiceIDByStreamer, args)
if err != nil {
slog.Error("Failed to get voice setting ID by streamer ID", "error", err)
return 0, err
}
err = row.Scan(&voiceSettingID)
if err != nil {
slog.Error(err.Error())
return 0, err
}
return voiceSettingID, nil
}
func (repoDonat *RepoDonat) UpdateVoiceSettings(
ctx context.Context,
streamerID int,
settings model.UpdateVoiceSettings,
) error {
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
// Добавляем только те поля, которые не nil
if settings.Enable != nil {
args["enable"] = *settings.Enable
}
if settings.VoiceSpeed != nil {
args["voice_speed"] = *settings.VoiceSpeed
}
if settings.Scenery != nil {
args["scenery"] = *settings.Scenery
}
if settings.VoiceSoundPercent != nil {
args["voice_sound_percent"] = *settings.VoiceSoundPercent
}
if settings.MinPrice != nil {
args["min_price"] = *settings.MinPrice
}
// Выполняем SQL-запрос
err := repoDonat.db.Update(ctx, sql.UpdateVoiceSettings, args)
if err != nil {
slog.Error("Failed to update voice settings", "error", err)
return err
}
return nil
}

View File

@ -310,9 +310,43 @@ func (donatService *ServiceDonat) GetVoiceSettings(
func (donatService *ServiceDonat) UpdateVoiceSettings(
ctx context.Context,
streamerID model.StreamerID,
streamerID int,
updateModel model.UpdateVoiceSettings,
) error {
// Получаем voice_setting_id для streamerID
voiceSettingID, err := donatService.donatRepo.GetVoiceSettingIDByStreamerID(ctx, streamerID)
if err != nil {
slog.Error("Failed to get voice setting ID", "error", err)
return err
}
// Удаляем старые языки
err = donatService.donatRepo.DeleteLanguagesByVoiceSettingID(ctx, voiceSettingID)
if err != nil {
slog.Error("Failed to delete old languages", "error", err)
return err
}
// Получаем ID всех языков по их ISO-кодам
languageIDs, err := donatService.donatRepo.GetLanguageIDsByISOCodes(ctx, updateModel.Languages)
if err != nil {
slog.Error("Failed to get language IDs by ISO codes", "error", err)
return err
}
// Добавляем новые языки (пакетная вставка)
err = donatService.donatRepo.InsertLanguagesForVoiceSetting(ctx, voiceSettingID, languageIDs)
if err != nil {
slog.Error("Failed to insert new languages", "error", err)
return err
}
err = donatService.donatRepo.UpdateVoiceSettings(ctx, streamerID, updateModel)
if err != nil {
slog.Error("Failed to update voice settings", "error", err)
return err
}
return nil
}