add fix for inner outer donate page during set head as default avatar

This commit is contained in:
harold 2025-04-09 10:15:29 +05:00
parent 5e8c433d36
commit d0742f49dd
7 changed files with 215 additions and 14 deletions

View File

@ -14,6 +14,7 @@ import (
//"donat-widget/infrastructure/weed"
AuthClient "donat-widget/pkg/api/auth"
PaymentClient "donat-widget/pkg/api/payment"
StreamerClient "donat-widget/pkg/api/streamer"
)
import (
@ -47,6 +48,7 @@ func main() {
// CLIENTS
paymentClient := PaymentClient.New(cfg.PaymentService.Host, cfg.PaymentService.Port)
authClient := AuthClient.New(cfg.AuthService.Host, cfg.AuthService.Port)
streamerClient := StreamerClient.New(cfg.StreamerService.Host, cfg.StreamerService.Port)
// REPOSITORIES
widgetRepo := WidgetRepo.New(db, storage)
@ -65,6 +67,7 @@ func main() {
widgetRepo,
paymentClient,
authClient,
streamerClient,
fileRepo,
fileService,
storage,

View File

@ -192,7 +192,10 @@ func GetInnerDonatePage(donatService model.DonatService) echo.HandlerFunc {
ctx := context.Background()
var innerPage model.InnerDonatePageResponse
innerPage, err = donatService.GetInnerDonatPage(ctx, authData.AccountID)
accessToken := model.Token(request.Request().Header.Get("Authorization"))
innerPage, err = donatService.GetInnerDonatPage(ctx, authData.AccountID, string(accessToken))
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
@ -217,8 +220,10 @@ func GetOuterDonatePage(donatService model.DonatService) echo.HandlerFunc {
ctx := context.Background()
streamerLogin := request.Param("streamer-login")
accessToken := model.Token(request.Request().Header.Get("Authorization"))
outerPageResponse, err := donatService.GetOuterDonatPage(
ctx, streamerLogin,
ctx, streamerLogin, string(accessToken),
)
if outerPageResponse.Login == "" {
return echo.NewHTTPError(http.StatusNotFound, "Пользователь не найден!")
@ -283,14 +288,13 @@ func UpdateDonatePage(donatService model.DonatService, fileService model.FileSer
avatarFile, err := request.FormFile("avatar")
if err != nil {
headImgFile = &multipart.FileHeader{
avatarFile = &multipart.FileHeader{
Filename: "",
Size: 0,
Header: nil,
}
}
// Передаем файлы только если они были переданы
err = donatService.UpdateDonatePage(
ctx,
authData.AccountID,

View File

@ -6,12 +6,13 @@ import (
)
type Config struct {
Db Database `yaml:"db"`
Storage Storage `yaml:"storage"`
PaymentService PaymentService `yaml:"paymentService"`
AuthService AuthService `yaml:"authService"`
TtsHost string `yaml:"ttsHost"`
HOST string `yaml:"host"`
Db Database `yaml:"db"`
Storage Storage `yaml:"storage"`
PaymentService PaymentService `yaml:"paymentService"`
AuthService AuthService `yaml:"authService"`
StreamerService StreamerService `yaml:"streamerService"`
TtsHost string `yaml:"ttsHost"`
HOST string `yaml:"host"`
}
type Database struct {
@ -40,6 +41,11 @@ type AuthService struct {
Port string `yaml:"port"`
}
type StreamerService struct {
Host string `yaml:"host"`
Port string `yaml:"port"`
}
func Init() *Config {
data, err := os.ReadFile("internal/config/config.yaml")
if err != nil {

View File

@ -80,8 +80,8 @@ type DonatService interface {
MarkDonatPaid(ctx context.Context, orderID string) error
MarkDonatView(ctx context.Context, orderID string) error
GetInnerDonatPage(ctx context.Context, streamerID int) (InnerDonatePageResponse, error)
GetOuterDonatPage(ctx context.Context, streamerLogin string) (OuterDonatePageResponse, error)
GetInnerDonatPage(ctx context.Context, streamerID int, token string) (InnerDonatePageResponse, error)
GetOuterDonatPage(ctx context.Context, streamerLogin string, token string) (OuterDonatePageResponse, error)
UpdateDonatePage(
ctx context.Context,
streamerID int,
@ -249,3 +249,7 @@ type FileService interface {
WidgetsFiles(ctx context.Context, fileType string, streamerID int) ([]*DataFile, error)
GetFileInfo(ctx context.Context, fileID string) (DataFile, error)
}
type StreamerClient interface {
GetAvatarID(token string) (string, error)
}

View File

@ -338,3 +338,11 @@ type UpdateLoginBody struct {
AccountID int `json:"account_id"`
Login string `json:"login"`
}
type StreamerInfo struct {
Login string `json:"login"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Email string `json:"email"`
Avatar string `json:"avatar"`
}

View File

@ -16,6 +16,7 @@ type ServiceDonat struct {
widgetRepo model.WidgetRepo
authClient model.AuthClient
paymentClient model.PaymentClient
streamerClient model.StreamerClient
fileRepo model.FileRepo
fileService model.FileService
storage model.Storage
@ -29,6 +30,7 @@ func New(
widgetRepo model.WidgetRepo,
paymentClient model.PaymentClient,
authClient model.AuthClient,
streamerClient model.StreamerClient,
fileRepo model.FileRepo,
fileService model.FileService,
storage model.Storage,
@ -41,6 +43,7 @@ func New(
widgetRepo: widgetRepo,
paymentClient: paymentClient,
authClient: authClient,
streamerClient: streamerClient,
fileRepo: fileRepo,
fileService: fileService,
storage: storage,
@ -187,6 +190,7 @@ func (donatService *ServiceDonat) MarkDonatView(
func (donatService *ServiceDonat) GetInnerDonatPage(
ctx context.Context,
streamerID int,
token string,
) (model.InnerDonatePageResponse, error) {
// Получаем данные страницы доната из репозитория
donatePage, err := donatService.donatRepo.GetDonatPage(ctx, streamerID)
@ -212,6 +216,26 @@ func (donatService *ServiceDonat) GetInnerDonatPage(
FileSize: donatePage.AvatarImgSize,
}
if donatePage.ProfileAvatar == true {
fileId, err := donatService.streamerClient.GetAvatarID(token)
if err != nil {
slog.Error(err.Error())
}
fileInfo, err := donatService.fileRepo.GetFileInfoById(ctx, fileId)
if err != nil {
slog.Error(err.Error())
}
if err == nil {
avatarFile = model.InnerFile{
FileID: fileInfo.ID,
FileName: fileInfo.FileName,
FileType: fileInfo.FileType,
FileLink: donatService.storage.DownloadLink(fileInfo.ID),
FileSize: int(fileInfo.Size),
}
}
}
backgroundImgFile := model.InnerFile{
FileID: donatePage.BackgroundImgFileId,
FileName: donatePage.BackgroundImgFileName,
@ -220,7 +244,6 @@ func (donatService *ServiceDonat) GetInnerDonatPage(
FileSize: donatePage.BackgroundImgSize,
}
// Создаем объект InnerDonatePageResponse
innerDonatePageResponse := model.InnerDonatePageResponse{
Description: donatePage.Description,
TextAfterDonat: donatePage.TextAfterDonat,
@ -237,6 +260,7 @@ func (donatService *ServiceDonat) GetInnerDonatPage(
func (donatService *ServiceDonat) GetOuterDonatPage(
ctx context.Context,
streamerLogin string,
token string,
) (model.OuterDonatePageResponse, error) {
donatePage, err := donatService.donatRepo.GetDonatPageByLogin(ctx, streamerLogin)
if err != nil {
@ -244,13 +268,28 @@ func (donatService *ServiceDonat) GetOuterDonatPage(
return model.OuterDonatePageResponse{}, err
}
avatarFileId := donatePage.AvatarFileId
if donatePage.ProfileAvatar == true {
fileId, err := donatService.streamerClient.GetAvatarID(token)
if err != nil {
slog.Error(err.Error())
avatarFileId = donatePage.AvatarFileId
}
avatarFileId, err = uuid.Parse(fileId)
if err != nil {
slog.Error(err.Error())
avatarFileId = donatePage.AvatarFileId
}
}
var outerDonatePageResponse = model.OuterDonatePageResponse{
Description: donatePage.Description,
Login: donatePage.StreamerLogin,
OnLine: "online",
BackgroundImg: donatService.storage.DownloadLink(donatePage.BackgroundImgFileId),
HeadImg: donatService.storage.DownloadLink(donatePage.HeadImgFileId),
AvatarImg: donatService.storage.DownloadLink(donatePage.AvatarFileId),
AvatarImg: donatService.storage.DownloadLink(avatarFileId),
}
return outerDonatePageResponse, nil
}

View File

@ -0,0 +1,137 @@
package streamer
import (
"bytes"
"donat-widget/internal/model"
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"strings"
)
func New(host, port string) *ClientStreamer {
return &ClientStreamer{
client: &http.Client{},
baseURL: "http://" + host + ":" + port + "/api/streamer",
}
}
type ClientStreamer struct {
client *http.Client
baseURL string
}
func (c *ClientStreamer) GetAvatarID(token string) (string, error) {
const endpoint = "/info"
var result model.StreamerInfo
req, err := http.NewRequest("GET", c.baseURL+endpoint, nil)
if err != nil {
slog.Error("create request failed", "error", err)
return "", fmt.Errorf("request creation error: %w", err)
}
req.Header.Set("Authorization", token)
req.Header.Set("Accept", "application/json")
resp, err := c.client.Do(req)
if err != nil {
slog.Error("request failed", "error", err)
return "", fmt.Errorf("HTTP request error: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
slog.Error("unexpected status code",
"status", resp.Status,
"response", string(body))
return "", fmt.Errorf("HTTP %d: %s", resp.StatusCode, resp.Status)
}
rawBody, err := io.ReadAll(resp.Body)
if err != nil {
slog.Error("read body failed", "error", err)
return "", fmt.Errorf("read body error: %w", err)
}
if err := json.Unmarshal(rawBody, &result); err != nil {
slog.Error("JSON parse error",
"error", err,
"response", string(rawBody))
return "", fmt.Errorf("JSON unmarshal error: %w", err)
}
return extractFileID(result.Avatar), nil
}
// extractFileID извлекает последний сегмент URL (fileId)
func extractFileID(avatarURL string) string {
if avatarURL == "" {
return ""
}
// Удаляем возможный завершающий слэш
avatarURL = strings.TrimSuffix(avatarURL, "/")
// Разделяем URL по слэшам
parts := strings.Split(avatarURL, "/")
if len(parts) == 0 {
return ""
}
// Берём последнюю часть
return parts[len(parts)-1]
}
func (c *ClientStreamer) post(
path string,
body map[string]any,
token string,
) ([]byte, error) {
bytesBody, err := json.Marshal(body)
if err != nil {
slog.Error("json.Marshal error", "error", err)
return nil, fmt.Errorf("marshal error: %w", err)
}
// Создаем новый запрос
req, err := http.NewRequest(
"POST",
c.baseURL+path,
bytes.NewReader(bytesBody),
)
if err != nil {
slog.Error("request creation failed", "error", err)
return nil, fmt.Errorf("request error: %w", err)
}
req.Header.Set("Content-Type", "application/json")
if token != "" {
req.Header.Set("Authorization", "Bearer "+token)
}
resp, err := c.client.Do(req)
if err != nil {
slog.Error("request failed", "error", err)
return nil, fmt.Errorf("HTTP error: %w", err)
}
defer resp.Body.Close()
// Проверяем статус
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body) // Попробуем прочитать тело ошибки
slog.Error("unexpected status",
"status", resp.Status,
"body", string(body))
return nil, fmt.Errorf("status %d: %s", resp.StatusCode, resp.Status)
}
// Читаем ответ
response, err := io.ReadAll(resp.Body)
if err != nil {
slog.Error("read body failed", "error", err)
return nil, fmt.Errorf("read error: %w", err)
}
return response, nil
}