package moderation import ( "errors" "log" "strings" "time" "gorm.io/gorm" ) // ModerationService handles business logic for content moderation type ModerationService struct { db *gorm.DB } // NewModerationService creates a new moderation service func NewModerationService(db *gorm.DB) *ModerationService { // Auto-migrate the schema db.AutoMigrate(&ContentFlag{}, &ModerationQueueItem{}) return &ModerationService{ db: db, } } // FlagContent flags content for moderation func (s *ModerationService) FlagContent(contentID, reason, flaggerAddress string) (*ContentFlag, error) { // Create a new flag flag := &ContentFlag{ ContentID: contentID, Reason: reason, FlaggerAddress: flaggerAddress, Timestamp: time.Now(), } // Save the flag to the database if err := s.db.Create(flag).Error; err != nil { log.Printf("Error creating flag: %v", err) return nil, err } // Count how many flags this content has var flagCount int64 if err := s.db.Model(&ContentFlag{}).Where("content_id = ?", contentID).Count(&flagCount).Error; err != nil { log.Printf("Error counting flags: %v", err) return nil, err } // If content is flagged 3 or more times, add to moderation queue if flagCount >= 3 { // Check if already in queue var existingItem ModerationQueueItem result := s.db.Where("content_id = ?", contentID).First(&existingItem) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { // Add to queue queueItem := &ModerationQueueItem{ ContentID: contentID, FlagCount: int(flagCount), Reason: "User flagged", Status: "pending", AIFlagged: false, } if err := s.db.Create(queueItem).Error; err != nil { log.Printf("Error adding to moderation queue: %v", err) return nil, err } } else { log.Printf("Error checking moderation queue: %v", result.Error) return nil, result.Error } } else { // Update flag count existingItem.FlagCount = int(flagCount) if err := s.db.Save(&existingItem).Error; err != nil { log.Printf("Error updating moderation queue item: %v", err) return nil, err } } } return flag, nil } // ModerateContent approves or rejects content in the moderation queue func (s *ModerationService) ModerateContent(contentID, decision string) error { var queueItem ModerationQueueItem if err := s.db.Where("content_id = ?", contentID).First(&queueItem).Error; err != nil { log.Printf("Error finding queue item: %v", err) return err } // Update status based on decision if decision == "approve" { queueItem.Status = "approved" } else if decision == "reject" { queueItem.Status = "rejected" } else { return errors.New("invalid decision: must be 'approve' or 'reject'") } // Save the updated queue item if err := s.db.Save(&queueItem).Error; err != nil { log.Printf("Error updating queue item: %v", err) return err } return nil } // GetModerationQueue returns all pending items in the moderation queue func (s *ModerationService) GetModerationQueue() ([]ModerationQueueItem, error) { var queueItems []ModerationQueueItem if err := s.db.Where("status = ?", "pending").Find(&queueItems).Error; err != nil { log.Printf("Error getting moderation queue: %v", err) return nil, err } return queueItems, nil } // RunAIModeration runs AI moderation on content (mock implementation) func (s *ModerationService) RunAIModeration(content *ContentToModerate) (bool, string, error) { if content.IsVerified { // Skip AI moderation for verified users return false, "", nil } // Mock implementation of content moderation // In a real implementation, this would call an AI moderation service text := strings.ToLower(content.Text) // Simple keyword check for demonstration spamKeywords := []string{"spam", "viagra", "casino", "xxx", "lottery", "prize", "winner", "free money"} for _, keyword := range spamKeywords { if strings.Contains(text, keyword) { // Add to moderation queue queueItem := &ModerationQueueItem{ ContentID: content.ContentID, FlagCount: 1, // AI counts as one flag Reason: "AI-flagged: potential spam", Status: "pending", AIFlagged: true, } // Check if already in queue var existingItem ModerationQueueItem result := s.db.Where("content_id = ?", content.ContentID).First(&existingItem) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { // Add to queue if err := s.db.Create(queueItem).Error; err != nil { log.Printf("Error adding AI-flagged content to moderation queue: %v", err) return true, "AI-flagged: potential spam", err } } else { log.Printf("Error checking moderation queue: %v", result.Error) return true, "AI-flagged: potential spam", result.Error } } else { // Update reason and AI flag existingItem.Reason = "AI-flagged: potential spam" existingItem.AIFlagged = true if err := s.db.Save(&existingItem).Error; err != nil { log.Printf("Error updating moderation queue item: %v", err) return true, "AI-flagged: potential spam", err } } return true, "AI-flagged: potential spam", nil } } // Check for harmful content harmfulKeywords := []string{"kill", "die", "hate", "attack", "bomb", "threat", "hack"} for _, keyword := range harmfulKeywords { if strings.Contains(text, keyword) { // Add to moderation queue queueItem := &ModerationQueueItem{ ContentID: content.ContentID, FlagCount: 1, // AI counts as one flag Reason: "AI-flagged: potential harmful content", Status: "pending", AIFlagged: true, } // Check if already in queue var existingItem ModerationQueueItem result := s.db.Where("content_id = ?", content.ContentID).First(&existingItem) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { // Add to queue if err := s.db.Create(queueItem).Error; err != nil { log.Printf("Error adding AI-flagged content to moderation queue: %v", err) return true, "AI-flagged: potential harmful content", err } } else { log.Printf("Error checking moderation queue: %v", result.Error) return true, "AI-flagged: potential harmful content", result.Error } } else { // Update reason and AI flag existingItem.Reason = "AI-flagged: potential harmful content" existingItem.AIFlagged = true if err := s.db.Save(&existingItem).Error; err != nil { log.Printf("Error updating moderation queue item: %v", err) return true, "AI-flagged: potential harmful content", err } } return true, "AI-flagged: potential harmful content", nil } } return false, "", nil } // CheckEconomicBarrier checks if the user has paid the required fee (mock implementation) func (s *ModerationService) CheckEconomicBarrier(userAddress string, isVerified bool) (bool, error) { if isVerified { // Verified users don't need to pay a fee return true, nil } // Mock implementation - always return true // In a real implementation, this would check the blockchain return true, nil }