118 lines
3.9 KiB
Go
118 lines
3.9 KiB
Go
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
|
||
}
|