where('id', $messageId)->find(); if (empty($row)) { return false; } $update = self::buildMessageArchiveUpdate($row); if (empty($update)) { return false; } Db::table('s2_wechat_message')->where('id', $messageId)->update($update); return true; } public static function archiveMomentById($momentId) { $momentId = (int)$momentId; if ($momentId <= 0) { return false; } $row = Db::table('s2_wechat_moments')->where('id', $momentId)->find(); if (empty($row)) { return false; } $displayUrls = self::decodeJsonArray($row['resUrls'] ?? ''); $rawUrls = self::decodeJsonArray($row['urls'] ?? ''); $candidateUrls = !empty($displayUrls) ? $displayUrls : $rawUrls; if (empty($candidateUrls)) { return false; } $ossUrls = []; foreach ($candidateUrls as $index => $url) { if (!MediaOssArchiveService::isRemoteHttpUrl($url)) { continue; } $resourceType = self::isVideoUrl($url) ? 'video' : 'image'; $result = MediaOssArchiveService::archiveRemoteUrl($url, 'moments', $resourceType, (string)($row['snsId'] ?? $momentId), [ 'index' => $index, ]); if (!empty($result['success']) && !empty($result['url'])) { $ossUrls[] = $result['url']; } } if (empty($ossUrls)) { return false; } Db::table('s2_wechat_moments')->where('id', $momentId)->update([ 'ossUrls' => json_encode($ossUrls, JSON_UNESCAPED_UNICODE), 'isOssUploaded' => 1, 'update_time' => time(), ]); return true; } public static function updateDownloadedMessageMedia($messageId, $downloadUrl) { $messageId = (int)$messageId; $downloadUrl = trim((string)$downloadUrl); if ($messageId <= 0 || empty($downloadUrl)) { return false; } $row = Db::table('s2_wechat_message')->where('id', $messageId)->find(); if (empty($row)) { return false; } $content = (string)($row['content'] ?? ''); $originalContent = (string)($row['originalContent'] ?? ''); $msgType = (int)($row['msgType'] ?? 0); $update = []; if (empty($originalContent)) { $update['originalContent'] = $content; } if ($msgType === 43) { $payload = self::decodeJsonObject($content); if (empty($payload)) { $payload = []; } $payload['videoUrl'] = $downloadUrl; $payload['isLoading'] = false; $update['content'] = self::encodeJson($payload); } elseif ($msgType === 49) { $payload = self::decodeJsonObject($content); if (empty($payload) || strtolower((string)($payload['type'] ?? '')) !== 'file') { $payload = [ 'type' => 'file', 'title' => self::extractFileTitle($content), ]; } $payload['url'] = $downloadUrl; $payload['isDownloading'] = false; $update['content'] = self::encodeJson($payload); } else { return false; } Db::table('s2_wechat_message')->where('id', $messageId)->update($update); return true; } protected static function buildMessageArchiveUpdate(array $row) { $msgType = (int)($row['msgType'] ?? 0); $content = (string)($row['content'] ?? ''); $originalContent = (string)($row['originalContent'] ?? ''); $sourceOriginalContent = $originalContent !== '' ? $originalContent : $content; $update = []; switch ($msgType) { case 3: case 47: $imageUpdate = self::archiveImageLikeContent($content, $msgType, $row['id']); if (!empty($imageUpdate)) { $update = array_merge($update, $imageUpdate); } break; case 34: $audioUpdate = self::archiveAudioContent($content, $row['id']); if (!empty($audioUpdate)) { $update = array_merge($update, $audioUpdate); } break; case 43: $videoUpdate = self::archiveVideoContent($content, $row['id']); if (!empty($videoUpdate)) { $update = array_merge($update, $videoUpdate); } break; case 49: $fileUpdate = self::archiveFileContent($content, $row['id']); if (!empty($fileUpdate)) { $update = array_merge($update, $fileUpdate); } break; default: break; } if (!empty($update) && empty($originalContent) && !empty($sourceOriginalContent)) { $update['originalContent'] = $sourceOriginalContent; } return $update; } protected static function archiveImageLikeContent($content, $msgType, $messageId) { $payload = self::decodeJsonObject($content); if (!empty($payload) && !empty($payload['url'])) { $sourceUrl = (string)($payload['originUrl'] ?? $payload['url']); $result = MediaOssArchiveService::archiveRemoteUrl( $sourceUrl, 'messages', $msgType == 47 ? 'emoji' : 'image', (string)$messageId ); if (empty($result['success']) || empty($result['url'])) { return []; } $payload['originUrl'] = $payload['originUrl'] ?? $sourceUrl; $payload['ossUrl'] = $result['url']; $payload['url'] = $result['url']; return ['content' => self::encodeJson($payload)]; } if (!MediaOssArchiveService::isRemoteHttpUrl($content)) { return []; } $result = MediaOssArchiveService::archiveRemoteUrl( $content, 'messages', $msgType == 47 ? 'emoji' : 'image', (string)$messageId ); if (empty($result['success']) || empty($result['url'])) { return []; } return ['content' => $result['url']]; } protected static function archiveAudioContent($content, $messageId) { $payload = self::decodeJsonObject($content); if (!empty($payload) && !empty($payload['url'])) { $sourceUrl = (string)($payload['originUrl'] ?? $payload['url']); $result = MediaOssArchiveService::archiveRemoteUrl($sourceUrl, 'messages', 'audio', (string)$messageId); if (empty($result['success']) || empty($result['url'])) { return []; } $payload['originUrl'] = $payload['originUrl'] ?? $sourceUrl; $payload['ossUrl'] = $result['url']; $payload['url'] = $result['url']; return ['content' => self::encodeJson($payload)]; } if (!MediaOssArchiveService::isRemoteHttpUrl($content)) { return []; } $result = MediaOssArchiveService::archiveRemoteUrl($content, 'messages', 'audio', (string)$messageId); if (empty($result['success']) || empty($result['url'])) { return []; } return ['content' => $result['url']]; } protected static function archiveVideoContent($content, $messageId) { $payload = self::decodeJsonObject($content); if (empty($payload)) { if (!MediaOssArchiveService::isRemoteHttpUrl($content)) { return []; } $result = MediaOssArchiveService::archiveRemoteUrl($content, 'messages', 'video', (string)$messageId); if (empty($result['success']) || empty($result['url'])) { return []; } return ['content' => $result['url']]; } $changed = false; $previewSource = (string)($payload['previewImageOriginUrl'] ?? $payload['previewImage'] ?? ''); if (MediaOssArchiveService::isRemoteHttpUrl($previewSource)) { $previewResult = MediaOssArchiveService::archiveRemoteUrl($previewSource, 'messages', 'video_cover', (string)$messageId); if (!empty($previewResult['success']) && !empty($previewResult['url'])) { $payload['previewImageOriginUrl'] = $payload['previewImageOriginUrl'] ?? $previewSource; $payload['previewImageOssUrl'] = $previewResult['url']; $payload['previewImage'] = $previewResult['url']; $changed = true; } } $videoSource = (string)($payload['originUrl'] ?? $payload['videoUrl'] ?? $payload['ossUrl'] ?? $payload['tencentUrl'] ?? $payload['url'] ?? ''); if (MediaOssArchiveService::isRemoteHttpUrl($videoSource)) { $videoResult = MediaOssArchiveService::archiveRemoteUrl($videoSource, 'messages', 'video', (string)$messageId); if (!empty($videoResult['success']) && !empty($videoResult['url'])) { $payload['originUrl'] = $payload['originUrl'] ?? $videoSource; $payload['ossUrl'] = $videoResult['url']; $payload['videoUrl'] = $videoResult['url']; $payload['url'] = $videoResult['url']; $payload['isLoading'] = false; $changed = true; } } if (!$changed) { return []; } return ['content' => self::encodeJson($payload)]; } protected static function archiveFileContent($content, $messageId) { $payload = self::decodeJsonObject($content); if (empty($payload) || strtolower((string)($payload['type'] ?? '')) !== 'file') { return []; } $sourceUrl = (string)($payload['originUrl'] ?? $payload['url'] ?? ''); if (!MediaOssArchiveService::isRemoteHttpUrl($sourceUrl)) { return []; } $result = MediaOssArchiveService::archiveRemoteUrl( $sourceUrl, 'messages', 'file', (string)$messageId, [ 'extension' => $payload['fileext'] ?? '', ] ); if (empty($result['success']) || empty($result['url'])) { return []; } $payload['originUrl'] = $payload['originUrl'] ?? $sourceUrl; $payload['ossUrl'] = $result['url']; $payload['url'] = $result['url']; $payload['isDownloading'] = false; return ['content' => self::encodeJson($payload)]; } protected static function decodeJsonObject($value) { if (!is_string($value)) { return []; } $decoded = json_decode(trim($value), true); return is_array($decoded) ? $decoded : []; } protected static function decodeJsonArray($value) { if (is_array($value)) { return $value; } if (!is_string($value) || trim($value) === '') { return []; } $decoded = json_decode($value, true); return is_array($decoded) ? $decoded : []; } protected static function encodeJson(array $payload) { return json_encode($payload, JSON_UNESCAPED_UNICODE); } protected static function extractFileTitle($rawContent) { if (!is_string($rawContent) || trim($rawContent) === '') { return '文件'; } if (preg_match('/<!\[CDATA\[(.*?)\]\]><\/title>/i', $rawContent, $matches) && !empty($matches[1])) { return trim($matches[1]); } if (preg_match('/<title>([^<]+)<\/title>/i', $rawContent, $matches) && !empty($matches[1])) { return trim($matches[1]); } return '文件'; } protected static function isVideoUrl($url) { if (!is_string($url)) { return false; } return (bool)preg_match('/\.(mp4|mov|avi|webm|mkv)(\?.*)?$/i', $url); } }