*/ public static function purgableRetentionTypes(): array { return [ self::RETENTION_GAME_NOTICE, self::RETENTION_EPHEMERAL_NOTICE, ]; } /** * 根据广播消息载荷推断数据库保留类型。 * * @param array $messageData 聊天室消息载荷 */ public static function resolveRetentionType(array $messageData): string { $explicitType = (string) ($messageData['retention_type'] ?? ''); if (in_array($explicitType, [ self::RETENTION_USER_CHAT, self::RETENTION_SYSTEM_NOTICE, self::RETENTION_GAME_NOTICE, self::RETENTION_EPHEMERAL_NOTICE, ], true)) { return $explicitType; } $fromUser = (string) ($messageData['from_user'] ?? ''); $action = (string) ($messageData['action'] ?? ''); $messageType = (string) ($messageData['message_type'] ?? 'text'); if (self::isEphemeralNotice($fromUser, $action)) { return self::RETENTION_EPHEMERAL_NOTICE; } if (self::isGameNotice($fromUser, $action, $messageType, $messageData)) { return self::RETENTION_GAME_NOTICE; } if (self::isSystemNotice($fromUser)) { return self::RETENTION_SYSTEM_NOTICE; } return self::RETENTION_USER_CHAT; } /** * 判断消息是否属于可短期保留的进出场类通知。 */ public static function isEphemeralNotice(string $fromUser, string $action = ''): bool { return in_array($fromUser, ['进出播报', '座驾播报'], true) || in_array($action, ['system_welcome', 'vip_presence', 'ride_presence', 'auto_save_exp'], true); } /** * 判断消息是否属于游戏或玩法通知。 * * @param array $messageData 聊天室消息载荷 */ public static function isGameNotice(string $fromUser, string $action, string $messageType = 'text', array $messageData = []): bool { $gameSenders = ['钓鱼播报', '星海小博士']; $gameActions = [ 'fishing_result', 'idiom_result', 'riddle_result', 'ride_purchase', ]; if (in_array($fromUser, $gameSenders, true) || in_array($action, $gameActions, true)) { return true; } if (isset($messageData['toast_notification'])) { $title = (string) data_get($messageData, 'toast_notification.title', ''); return str_contains($title, '下注') || str_contains($title, '赛马') || str_contains($title, '百家乐') || str_contains($title, '双色球') || str_contains($title, '红包') || str_contains($title, '结算'); } return in_array($messageType, ['game_notice'], true); } /** * 判断消息是否来自系统发送者。 */ public static function isSystemNotice(string $fromUser): bool { return in_array($fromUser, [ '系统', '系统公告', '系统传音', '系统播报', '送花播报', 'AI小班长', ], true); } /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'room_id', 'from_user', 'to_user', 'content', 'is_secret', 'font_color', 'action', 'message_type', 'image_path', 'image_thumb_path', 'image_original_name', 'retention_type', 'sent_at', ]; /** * 返回模型字段的类型转换配置。 * * @return array */ protected function casts(): array { return [ 'sent_at' => 'datetime', 'is_secret' => 'boolean', ]; } }