219 lines
6.9 KiB
PHP
219 lines
6.9 KiB
PHP
<?php
|
|
|
|
$root = dirname(__DIR__, 2);
|
|
$servicePath = $root . '/server/app/common/service/match/MatchLiveService.php';
|
|
$apiControllerPath = $root . '/server/app/api/controller/MatchController.php';
|
|
$adminLogicPath = $root . '/server/app/adminapi/logic/match/MatchLogic.php';
|
|
$listsPath = $root . '/server/app/adminapi/lists/match/MatchLiveLists.php';
|
|
$matchLiveLogicPath = $root . '/server/app/adminapi/logic/match/MatchLiveLogic.php';
|
|
$validatePath = $root . '/server/app/adminapi/validate/match/MatchLiveValidate.php';
|
|
$backendChecks = [
|
|
$root . '/server/app/adminapi/controller/match/MatchLiveController.php',
|
|
$listsPath,
|
|
$matchLiveLogicPath,
|
|
$validatePath,
|
|
];
|
|
|
|
if (!is_file($servicePath)) {
|
|
fwrite(STDERR, "missing service file\n");
|
|
exit(1);
|
|
}
|
|
|
|
foreach ($backendChecks as $path) {
|
|
if (!is_file($path)) {
|
|
fwrite(STDERR, "missing backend file: {$path}\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
$service = file_get_contents($servicePath);
|
|
$requiredSnippets = [
|
|
'class MatchLiveService',
|
|
'public static function syncLegacyLiveUrl',
|
|
'public static function getLiveListForApi',
|
|
'public static function buildStreamOptions',
|
|
"'live_url' => \$row ? (string) \$row->source_url : ''",
|
|
"'update_time' => time()",
|
|
"->whereNull('delete_time')",
|
|
"->order('create_time', 'asc')",
|
|
"->order('id', 'asc')",
|
|
"\$row['default_play_url'] = \$row['stream_options'][0]['url'] ?? '';",
|
|
"if (\$url === '')",
|
|
];
|
|
|
|
foreach ($requiredSnippets as $needle) {
|
|
if (strpos($service, $needle) === false) {
|
|
fwrite(STDERR, "missing service token: {$needle}\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
$whereNullCount = substr_count($service, "->whereNull('delete_time')");
|
|
if ($whereNullCount < 2) {
|
|
fwrite(STDERR, "missing explicit delete_time guard on both queries\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (!is_file($apiControllerPath)) {
|
|
fwrite(STDERR, "missing api controller file\n");
|
|
exit(1);
|
|
}
|
|
|
|
$apiController = file_get_contents($apiControllerPath);
|
|
foreach ([
|
|
"'live_list'",
|
|
'MatchLiveService::getLiveListForApi',
|
|
] as $needle) {
|
|
if (strpos($apiController, $needle) === false) {
|
|
fwrite(STDERR, "missing api controller token: {$needle}\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (!is_file($adminLogicPath)) {
|
|
fwrite(STDERR, "missing admin logic file\n");
|
|
exit(1);
|
|
}
|
|
|
|
$adminLogic = file_get_contents($adminLogicPath);
|
|
if (strpos($adminLogic, "'live_url'") !== false) {
|
|
fwrite(STDERR, "match admin logic still manually allows live_url\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (!is_file($listsPath)) {
|
|
fwrite(STDERR, "missing match live lists file\n");
|
|
exit(1);
|
|
}
|
|
|
|
$lists = file_get_contents($listsPath);
|
|
foreach ([
|
|
"\$matchId = (int) (\$this->params['match_id'] ?? 0);",
|
|
"if (\$matchId <= 0) {",
|
|
"\$query->where('match_id', 0);",
|
|
] as $needle) {
|
|
if (strpos($lists, $needle) === false) {
|
|
fwrite(STDERR, "missing lists guard token: {$needle}\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (!is_file($matchLiveLogicPath)) {
|
|
fwrite(STDERR, "missing match live logic file\n");
|
|
exit(1);
|
|
}
|
|
|
|
$matchLiveLogic = file_get_contents($matchLiveLogicPath);
|
|
foreach ([
|
|
'$sourceUrl = trim((string) $params[\'source_url\']);',
|
|
'$sourceUrlChanged = $sourceUrl !== trim((string) $live->source_url);',
|
|
"'source_url' => \$sourceUrl",
|
|
'if ($sourceUrlChanged) {',
|
|
"\$saveData['play_url_m3u8'] = '';",
|
|
"\$saveData['play_url_hd_m3u8'] = '';",
|
|
"\$saveData['play_url_flv'] = '';",
|
|
"\$saveData['play_url_hd_flv'] = '';",
|
|
"\$saveData['fetch_status'] = 0;",
|
|
"\$saveData['fetch_error'] = '';",
|
|
"\$saveData['last_fetch_at'] = 0;",
|
|
"\$saveData['next_fetch_at'] = \$now;",
|
|
'$live->save($saveData);',
|
|
] as $needle) {
|
|
if (strpos($matchLiveLogic, $needle) === false) {
|
|
fwrite(STDERR, "missing match live logic source-url reset guard token: {$needle}\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
$savePos = strpos($matchLiveLogic, '$live->save($saveData);');
|
|
$guardPos = strpos($matchLiveLogic, 'if ($sourceUrlChanged) {');
|
|
if ($savePos === false || $guardPos === false || $guardPos > $savePos) {
|
|
fwrite(STDERR, "match live logic must guard crawler resets inside source_url change branch\n");
|
|
exit(1);
|
|
}
|
|
|
|
$guardBody = substr($matchLiveLogic, $guardPos, $savePos - $guardPos);
|
|
|
|
foreach ([
|
|
"\$saveData['play_url_m3u8'] = '';",
|
|
"\$saveData['play_url_hd_m3u8'] = '';",
|
|
"\$saveData['play_url_flv'] = '';",
|
|
"\$saveData['play_url_hd_flv'] = '';",
|
|
"\$saveData['fetch_status'] = 0;",
|
|
"\$saveData['fetch_error'] = '';",
|
|
"\$saveData['last_fetch_at'] = 0;",
|
|
"\$saveData['next_fetch_at'] = \$now;",
|
|
] as $needle) {
|
|
if (strpos($guardBody, $needle) === false) {
|
|
fwrite(STDERR, "match live logic reset token not scoped to source_url change guard: {$needle}\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
$unconditionalSaveBody = preg_replace('/if \\(\\$sourceUrlChanged\\) \\{.*?\\}/s', '', $matchLiveLogic, 1);
|
|
foreach ([
|
|
"\$saveData['play_url_m3u8'] = '';",
|
|
"\$saveData['play_url_hd_m3u8'] = '';",
|
|
"\$saveData['play_url_flv'] = '';",
|
|
"\$saveData['play_url_hd_flv'] = '';",
|
|
"\$saveData['fetch_status'] = 0;",
|
|
"\$saveData['fetch_error'] = '';",
|
|
"\$saveData['last_fetch_at'] = 0;",
|
|
"\$saveData['next_fetch_at'] = \$now;",
|
|
] as $needle) {
|
|
if (strpos($unconditionalSaveBody, $needle) !== false) {
|
|
fwrite(STDERR, "match live logic still unconditionally resets crawler state: {$needle}\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (!is_file($validatePath)) {
|
|
fwrite(STDERR, "missing match live validate file\n");
|
|
exit(1);
|
|
}
|
|
|
|
$validate = file_get_contents($validatePath);
|
|
foreach ([
|
|
'checkTrimmedTitle',
|
|
'checkTrimmedSourceUrl',
|
|
"!is_scalar(\$value)",
|
|
"return '直播标题格式错误';",
|
|
"return '源地址格式错误';",
|
|
'$value = trim((string) $value);',
|
|
] as $needle) {
|
|
if (strpos($validate, $needle) === false) {
|
|
fwrite(STDERR, "missing trimmed validation token: {$needle}\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
$childLivePos = strpos($apiController, "!empty(\$data['live_list'][0]['source_url'])");
|
|
$worldCupFallbackPos = strpos($apiController, "if (empty(\$data['live_url']) && \$this->isWorldCupMatch(\$data))");
|
|
if ($childLivePos === false || $worldCupFallbackPos === false || $childLivePos >= $worldCupFallbackPos) {
|
|
fwrite(STDERR, "match detail live_url fallback order mismatch\n");
|
|
exit(1);
|
|
}
|
|
|
|
$orderedOptionSnippets = [
|
|
"['label' => 'M3U8', 'field' => 'play_url_m3u8']",
|
|
"['label' => 'HD M3U8', 'field' => 'play_url_hd_m3u8']",
|
|
"['label' => 'FLV', 'field' => 'play_url_flv']",
|
|
"['label' => 'HD FLV', 'field' => 'play_url_hd_flv']",
|
|
];
|
|
|
|
$lastPos = -1;
|
|
foreach ($orderedOptionSnippets as $snippet) {
|
|
$pos = strpos($service, $snippet);
|
|
if ($pos === false) {
|
|
fwrite(STDERR, "missing ordered stream option snippet: {$snippet}\n");
|
|
exit(1);
|
|
}
|
|
if ($pos <= $lastPos) {
|
|
fwrite(STDERR, "stream option order mismatch\n");
|
|
exit(1);
|
|
}
|
|
$lastPos = $pos;
|
|
}
|
|
|
|
echo "service static checks passed\n";
|