605 lines
13 KiB
Go

package donat
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"
"strings"
)
func New(db model.Db) *RepoDonat {
return &RepoDonat{
db: db,
}
}
type RepoDonat struct {
db model.Db
}
func (repoDonat *RepoDonat) CreateDonat(
ctx context.Context,
streamerID model.StreamerID,
widgetID model.WidgetID,
orderID model.OrderID,
targetID model.TargetID,
amount model.DonatAmount,
text string,
donatUser string,
) error {
args := pgx.NamedArgs{
"streamer_id": streamerID,
"widget_id": widgetID,
"order_id": orderID,
"target_id": targetID,
"text": text,
"amount": amount,
"donat_user": donatUser,
}
_, err := repoDonat.db.Insert(ctx, sql.CreateDonat, args)
if err != nil {
slog.Error(err.Error())
return err
}
return nil
}
func (repoDonat *RepoDonat) GetDonatByStreamerID(
ctx context.Context,
streamerID model.StreamerID,
) ([]*model.Donat, error) {
args := pgx.NamedArgs{
"streamer_id": streamerID,
"paid": true,
"view": false,
}
rows, err := repoDonat.db.Select(ctx, sql.GetDonatByStreamerID, args)
if err != nil {
slog.Error(err.Error())
return nil, err
}
var donats []*model.Donat
err = pgxscan.ScanAll(&donats, rows)
if err != nil {
slog.Error(err.Error())
return nil, err
}
return donats, nil
}
func (repoDonat *RepoDonat) GetDonatByOrderID(
ctx context.Context,
orderID model.OrderID,
) (*model.Donat, error) {
args := pgx.NamedArgs{
"order_id": orderID,
}
rows, err := repoDonat.db.Select(ctx, sql.GetDonatByOrderID, args)
if err != nil {
slog.Error(err.Error())
return nil, err
}
var donats []*model.Donat
err = pgxscan.ScanAll(&donats, rows)
if err != nil {
slog.Error(err.Error())
return nil, err
}
if len(donats) == 0 {
return nil, errors.New("donat not found")
}
return donats[0], nil
}
func (repoDonat *RepoDonat) MarkDonatView(
ctx context.Context,
donatID model.DonatID,
) error {
args := pgx.NamedArgs{
"id": donatID,
"view": true,
}
err := repoDonat.db.Update(ctx, sql.MarkDonatView, args)
if err != nil {
slog.Error(err.Error())
return err
}
return nil
}
func (repoDonat *RepoDonat) MarkDonatPaid(
ctx context.Context,
orderID model.OrderID,
) error {
args := pgx.NamedArgs{
"order_id": orderID,
"paid": true,
}
err := repoDonat.db.Update(ctx, sql.MarkDonatPaid, args)
if err != nil {
slog.Error(err.Error())
return err
}
return nil
}
func (repoDonat *RepoDonat) GetDonatPage(
ctx context.Context,
streamerID model.StreamerID,
) (model.DonatePage, error) {
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
rows, err := repoDonat.db.Select(ctx, sql.GetDonationPage, args)
if err != nil {
slog.Error(err.Error())
return model.DonatePage{}, err
}
var donatePage []*model.DonatePage
err = pgxscan.ScanAll(&donatePage, rows)
if err != nil {
slog.Error(err.Error())
return model.DonatePage{}, err
}
if len(donatePage) == 0 {
return model.DonatePage{}, errors.New("donat not found")
}
return *donatePage[0], nil
}
func (repoDonat *RepoDonat) GetDonatPageByLogin(
ctx context.Context,
streamerLogin string,
) (model.DonatePage, error) {
args := pgx.NamedArgs{
"streamer_login": streamerLogin,
}
rows, err := repoDonat.db.Select(ctx, sql.GetDonationPageByLogin, args)
if err != nil {
slog.Error(err.Error())
return model.DonatePage{}, err
}
var donatePage []*model.DonatePage
err = pgxscan.ScanAll(&donatePage, rows)
if err != nil {
slog.Error(err.Error())
return model.DonatePage{}, err
}
if len(donatePage) == 0 {
return model.DonatePage{}, errors.New("donat not found")
}
return *donatePage[0], nil
}
func (repoDonat *RepoDonat) UpdateDonatePage(
ctx context.Context,
streamerID int,
backgroundFileID *string,
headImgFileID *string,
description *string,
textAfterDonation *string,
) error {
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
if backgroundFileID != nil {
args["background_img"] = *backgroundFileID
}
if headImgFileID != nil {
args["head_img"] = *headImgFileID
}
if description != nil {
args["description"] = *description
}
if textAfterDonation != nil {
args["text_after_donat"] = *textAfterDonation
}
err := repoDonat.db.Update(ctx, sql.UpdateDonatePage, args)
if err != nil {
slog.Error(err.Error())
return err
}
return nil
}
func (repoDonat *RepoDonat) GetLanguagesByStreamerID(ctx context.Context, streamerID int) ([]model.Language, error) {
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
// Выполняем SQL-запрос
rows, err := repoDonat.db.Select(ctx, sql.GetLanguagesByStreamerID, args)
if err != nil {
slog.Error("Failed to execute query", "error", err)
return nil, err
}
// Сканируем результаты в структуру Language
var languages []*model.Language
err = pgxscan.ScanAll(&languages, rows)
if err != nil {
slog.Error("Failed to scan rows", "error", err)
return nil, err
}
// Проверяем ошибки, которые могли возникнуть при итерации по строкам
if err := rows.Err(); err != nil {
slog.Error("Error during rows iteration", "error", err)
return nil, err
}
// Преобразуем []*model.Language в []model.Language
result := make([]model.Language, len(languages))
for i, lang := range languages {
result[i] = *lang
}
return result, nil
}
func (repoDonat *RepoDonat) GetVoiceSettingsByStreamerID(
ctx context.Context,
streamerID int,
) (model.VoiceSettingsResponse, error) {
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
rows, err := repoDonat.db.Select(ctx, sql.GetVoiceSettingsByStreamerID, args)
if err != nil {
slog.Error(err.Error())
return model.VoiceSettingsResponse{}, err
}
var voiceSettings []*model.VoiceSettingsResponse
err = pgxscan.ScanAll(&voiceSettings, rows)
if err != nil {
slog.Error(err.Error())
return model.VoiceSettingsResponse{}, err
}
if len(voiceSettings) == 0 {
return model.VoiceSettingsResponse{}, errors.New("voice settings not found")
}
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
}
func (repoDonat *RepoDonat) GetFilterSettingsByStreamerID(
ctx context.Context,
streamerID int,
) (int, bool, error) {
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
row, err := repoDonat.db.SelectOne(ctx, sql.GetFilterSettings, args)
if err != nil {
slog.Error("Failed to get filter settings", "error", err)
return 0, false, err
}
var filterSettingID int
var enableLinks bool
err = row.Scan(&filterSettingID, &enableLinks)
if err != nil {
slog.Error("Failed to scan filter settings", "error", err)
return 0, false, err
}
return filterSettingID, enableLinks, nil
}
func (repoDonat *RepoDonat) GetFilteredWords(
ctx context.Context,
filterId int,
) ([]string, error) {
args := pgx.NamedArgs{
"donat_filter_id": filterId,
}
rows, err := repoDonat.db.Select(ctx, sql.GetFilterWords, args)
if err != nil {
slog.Error("Failed to get filter settings", "error", err)
return nil, err
}
var filterWords []string
err = pgxscan.ScanAll(&filterWords, rows)
if err != nil {
slog.Error("Failed to scan filter settings", "error", err)
return nil, err
}
return filterWords, nil
}
func (repoDonat RepoDonat) UpdateFilterSettings(
ctx context.Context,
streamerID int,
enableLinks *bool,
) error {
if enableLinks != nil {
args := pgx.NamedArgs{
"streamer_id": streamerID,
"enable_links": enableLinks,
}
err := repoDonat.db.Exec(ctx, sql.UpdateFilterSettings, args)
if err != nil {
slog.Error("Failed to update filter settings", "error", err)
return err
}
}
return nil
}
func (repoDonat *RepoDonat) GetFilterIDByStreamer(
ctx context.Context,
streamerID int,
) (int, error) {
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
row, err := repoDonat.db.SelectOne(ctx, sql.GetFilterIdByStreamerID, args)
if err != nil {
slog.Error("Failed to get filter settings", "error", err)
return 0, err
}
var filterID int
err = row.Scan(&filterID)
if err != nil {
slog.Error("Failed to scan filter settings", "error", err)
return 0, err
}
return filterID, nil
}
func (repoDonat *RepoDonat) AddFilteredWords(
ctx context.Context,
filterID int,
words []string,
) error {
if len(words) == 0 {
return nil
}
var valueStrings []string
var valueArgs []interface{}
for i, word := range words {
valueStrings = append(valueStrings, fmt.Sprintf("($%d, $%d)", i*2+1, i*2+2))
valueArgs = append(valueArgs, filterID, word)
}
query := fmt.Sprintf(sql.InsertFilteredWordsBatch, strings.Join(valueStrings, ","))
err := repoDonat.db.Exec(ctx, query, valueArgs...)
if err != nil {
slog.Error("Failed to add filtered words", "error", err)
return err
}
return nil
}
func (repoDonat *RepoDonat) RemoveFilteredWords(
ctx context.Context,
filterID int,
words []string,
) error {
if len(words) == 0 {
return nil // Нет слов для удаления
}
args := pgx.NamedArgs{
"donat_filter_id": filterID,
"words": words,
}
err := repoDonat.db.Exec(ctx, sql.DeleteFilteredWordsBatch, args)
if err != nil {
slog.Error("Failed to remove filtered words", "error", err)
return err
}
return nil
}
func (repoDonat *RepoDonat) GetModeration(ctx context.Context, streamerID int) (model.ModerationResponse, error) {
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
row, err := repoDonat.db.SelectOne(ctx, sql.GetModeration, args)
if err != nil {
slog.Error("Failed to get moderation state", "error", err)
return model.ModerationResponse{}, err
}
var response model.ModerationResponse
err = row.Scan(&response.Enable, &response.Duration)
if err != nil {
slog.Error("Failed to get moderation state", "error", err)
return model.ModerationResponse{}, err
}
return response, nil
}
func (repoDonat *RepoDonat) UpdateModeration(
ctx context.Context,
streamerID int,
enable *bool,
duration *int,
) error {
args := pgx.NamedArgs{
"streamer_id": streamerID,
}
if enable != nil {
args["enable"] = enable
}
if duration != nil {
args["duration"] = duration
}
err := repoDonat.db.Exec(ctx, sql.UpdateModeration, args)
if err != nil {
slog.Error("Failed to update moderation state", "error", err)
return err
}
return nil
}