2026-05-29 16:48:00 +08:00

118 lines
3.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package user
import (
"context"
"net/url"
"strings"
"unicode/utf8"
"hyapp/pkg/idgen"
"hyapp/pkg/roomid"
"hyapp/pkg/xerr"
userdomain "hyapp/services/user-service/internal/domain/user"
)
const (
maxReportReasonRunes = 512
maxReportImages = 9
maxReportImageURLLen = 1024
)
var validReportTypes = map[string]struct{}{
"politics": {},
"pornography": {},
"graphic_violence": {},
"verbal_abuse": {},
"fraud": {},
"illegal_content": {},
"minors": {},
"in_person_transactions": {},
"other": {},
}
// SubmitReport 校验 App 举报目标和证据 URL并把不可变举报事实交给 user repository 持久化。
func (s *Service) SubmitReport(ctx context.Context, reporterUserID int64, userID int64, roomID string, reportType string, reason string, imageURLs []string, requestID string) (userdomain.Report, error) {
if s.userRepository == nil {
return userdomain.Report{}, xerr.New(xerr.Unavailable, "user repository is not configured")
}
reporterUserID, userID, roomID, reportType, reason, imageURLs, targetType, err := normalizeReportInput(reporterUserID, userID, roomID, reportType, reason, imageURLs)
if err != nil {
return userdomain.Report{}, err
}
nowMs := s.now().UnixMilli()
report := userdomain.Report{
ReportID: idgen.New("rpt"),
ReporterUserID: reporterUserID,
TargetType: targetType,
UserID: userID,
RoomID: roomID,
ReportType: reportType,
Reason: reason,
ImageURLs: imageURLs,
Status: userdomain.ReportStatusSubmitted,
RequestID: strings.TrimSpace(requestID),
CreatedAtMs: nowMs,
UpdatedAtMs: nowMs,
}
return s.userRepository.SubmitReport(ctx, report)
}
func normalizeReportInput(reporterUserID int64, userID int64, roomID string, reportType string, reason string, imageURLs []string) (int64, int64, string, string, string, []string, string, error) {
roomID = strings.TrimSpace(roomID)
reportType = strings.ToLower(strings.TrimSpace(reportType))
reason = strings.TrimSpace(reason)
if reporterUserID <= 0 {
return 0, 0, "", "", "", nil, "", xerr.New(xerr.InvalidArgument, "reporter_user_id is required")
}
hasUser := userID > 0
hasRoom := roomID != ""
if hasUser == hasRoom {
return 0, 0, "", "", "", nil, "", xerr.New(xerr.InvalidArgument, "user_id and room_id must be exactly one")
}
if hasUser && userID == reporterUserID {
return 0, 0, "", "", "", nil, "", xerr.New(xerr.InvalidArgument, "cannot report self")
}
targetType := userdomain.ReportTargetUser
if hasRoom {
if !roomid.ValidStringID(roomID) {
return 0, 0, "", "", "", nil, "", xerr.New(xerr.InvalidArgument, "room_id is invalid")
}
targetType = userdomain.ReportTargetRoom
}
if _, ok := validReportTypes[reportType]; !ok {
return 0, 0, "", "", "", nil, "", xerr.New(xerr.InvalidArgument, "report_type is invalid")
}
if utf8.RuneCountInString(reason) > maxReportReasonRunes {
return 0, 0, "", "", "", nil, "", xerr.New(xerr.InvalidArgument, "reason is too long")
}
normalizedImages, err := normalizeReportImageURLs(imageURLs)
if err != nil {
return 0, 0, "", "", "", nil, "", err
}
return reporterUserID, userID, roomID, reportType, reason, normalizedImages, targetType, nil
}
func normalizeReportImageURLs(imageURLs []string) ([]string, error) {
if len(imageURLs) > maxReportImages {
return nil, xerr.New(xerr.InvalidArgument, "too many report images")
}
normalized := make([]string, 0, len(imageURLs))
for _, raw := range imageURLs {
value := strings.TrimSpace(raw)
if value == "" {
continue
}
if len(value) > maxReportImageURLLen {
return nil, xerr.New(xerr.InvalidArgument, "image url is too long")
}
parsed, err := url.Parse(value)
if err != nil || parsed.Host == "" || (parsed.Scheme != "http" && parsed.Scheme != "https") {
return nil, xerr.New(xerr.InvalidArgument, "image url is invalid")
}
normalized = append(normalized, value)
}
return normalized, nil
}