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 }