fix: preserve live streams on title edits
This commit is contained in:
@@ -8,7 +8,7 @@ CREATE TABLE IF NOT EXISTS `la_match_live` (
|
||||
`play_url_flv` varchar(1000) NOT NULL DEFAULT '' COMMENT '标清FLV播放地址',
|
||||
`play_url_hd_flv` varchar(1000) NOT NULL DEFAULT '' COMMENT '高清FLV播放地址',
|
||||
`fetch_status` tinyint UNSIGNED NOT NULL DEFAULT 0 COMMENT '抓取状态 0-待抓取 1-成功 2-失败',
|
||||
`fetch_error` varchar(255) NOT NULL DEFAULT '' COMMENT '抓取错误信息',
|
||||
`fetch_error` varchar(500) NOT NULL DEFAULT '' COMMENT '抓取错误信息',
|
||||
`last_fetch_at` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后抓取时间',
|
||||
`next_fetch_at` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '下次抓取时间',
|
||||
`create_time` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
INSERT INTO `la_system_menu` (`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
|
||||
SELECT COALESCE((SELECT `id` FROM `la_system_menu` WHERE `perms` = 'match.match/lists' LIMIT 1), 0), 'C', '直播线路管理', '', 0, 'match.matchLive/lists', 'match_live', 'match/lists/index', 'match/lists', '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM `la_system_menu`
|
||||
WHERE `perms` = 'match.matchLive/lists'
|
||||
);
|
||||
|
||||
INSERT INTO `la_system_menu` (`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
|
||||
SELECT (SELECT `id` FROM `la_system_menu` WHERE `perms` = 'match.matchLive/lists' LIMIT 1), 'A', '直播线路详情', '', 0, 'match.matchLive/detail', '', '', '', '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM `la_system_menu`
|
||||
WHERE `perms` = 'match.matchLive/detail'
|
||||
);
|
||||
|
||||
INSERT INTO `la_system_menu` (`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
|
||||
SELECT (SELECT `id` FROM `la_system_menu` WHERE `perms` = 'match.matchLive/lists' LIMIT 1), 'A', '直播线路新增', '', 0, 'match.matchLive/add', '', '', '', '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM `la_system_menu`
|
||||
WHERE `perms` = 'match.matchLive/add'
|
||||
);
|
||||
|
||||
INSERT INTO `la_system_menu` (`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
|
||||
SELECT (SELECT `id` FROM `la_system_menu` WHERE `perms` = 'match.matchLive/lists' LIMIT 1), 'A', '直播线路编辑', '', 0, 'match.matchLive/edit', '', '', '', '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM `la_system_menu`
|
||||
WHERE `perms` = 'match.matchLive/edit'
|
||||
);
|
||||
|
||||
INSERT INTO `la_system_menu` (`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
|
||||
SELECT (SELECT `id` FROM `la_system_menu` WHERE `perms` = 'match.matchLive/lists' LIMIT 1), 'A', '直播线路删除', '', 0, 'match.matchLive/delete', '', '', '', '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM `la_system_menu`
|
||||
WHERE `perms` = 'match.matchLive/delete'
|
||||
);
|
||||
|
||||
INSERT INTO `la_system_role_menu` (`role_id`, `menu_id`)
|
||||
SELECT 1, m.`id`
|
||||
FROM `la_system_menu` m
|
||||
WHERE m.`perms` IN (
|
||||
'match.matchLive/lists',
|
||||
'match.matchLive/detail',
|
||||
'match.matchLive/add',
|
||||
'match.matchLive/edit',
|
||||
'match.matchLive/delete'
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM `la_system_role_menu` rm
|
||||
WHERE rm.`role_id` = 1
|
||||
AND rm.`menu_id` = m.`id`
|
||||
);
|
||||
@@ -105,17 +105,64 @@ if (!is_file($matchLiveLogicPath)) {
|
||||
|
||||
$matchLiveLogic = file_get_contents($matchLiveLogicPath);
|
||||
foreach ([
|
||||
"'play_url_m3u8' => ''",
|
||||
"'play_url_hd_m3u8' => ''",
|
||||
"'play_url_flv' => ''",
|
||||
"'play_url_hd_flv' => ''",
|
||||
"'fetch_status' => 0",
|
||||
"'fetch_error' => ''",
|
||||
"'last_fetch_at' => 0",
|
||||
"'next_fetch_at' => \$now",
|
||||
'$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 reset token: {$needle}\n");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ $requiredSql = [
|
||||
'`play_url_flv` varchar(1000)',
|
||||
'`play_url_hd_flv` varchar(1000)',
|
||||
'`fetch_status` tinyint',
|
||||
'`fetch_error` varchar(255)',
|
||||
'`fetch_error` varchar(500)',
|
||||
'`last_fetch_at` int UNSIGNED NOT NULL',
|
||||
'`next_fetch_at` int UNSIGNED NOT NULL',
|
||||
'`create_time` int UNSIGNED NOT NULL',
|
||||
|
||||
@@ -2,9 +2,11 @@ from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(r"D:\www\sport-era\admin")
|
||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
MATCH_API = ROOT / "src" / "api" / "match.ts"
|
||||
MATCH_INDEX = ROOT / "src" / "views" / "match" / "lists" / "index.vue"
|
||||
MATCH_LIVE_TABLE = ROOT / "src" / "views" / "match" / "lists" / "components" / "MatchLiveTable.vue"
|
||||
MENU_SQL = REPO_ROOT / "docs" / "sql" / "insert_menu_match_live.sql"
|
||||
|
||||
|
||||
def assert_contains(path: Path, needle: str) -> None:
|
||||
@@ -15,6 +17,8 @@ def assert_contains(path: Path, needle: str) -> None:
|
||||
def main() -> None:
|
||||
match_api = MATCH_API.read_text(encoding="utf-8")
|
||||
match_live_table = MATCH_LIVE_TABLE.read_text(encoding="utf-8")
|
||||
assert MENU_SQL.is_file(), f"missing menu seed file: {MENU_SQL}"
|
||||
menu_sql = MENU_SQL.read_text(encoding="utf-8")
|
||||
|
||||
assert_contains(MATCH_INDEX, 'type="expand"')
|
||||
assert_contains(MATCH_INDEX, "MatchLiveTable")
|
||||
@@ -88,6 +92,15 @@ def main() -> None:
|
||||
):
|
||||
assert needle in match_live_table, f"{MATCH_LIVE_TABLE} missing fetch_status mapping: {needle}"
|
||||
|
||||
for needle in (
|
||||
"match.matchLive/lists",
|
||||
"match.matchLive/detail",
|
||||
"match.matchLive/add",
|
||||
"match.matchLive/edit",
|
||||
"match.matchLive/delete",
|
||||
):
|
||||
assert needle in menu_sql, f"{MENU_SQL} missing permission token: {needle}"
|
||||
|
||||
print("match live admin static checks passed")
|
||||
|
||||
|
||||
|
||||
@@ -49,21 +49,28 @@ class MatchLiveLogic extends BaseLogic
|
||||
$oldMatchId = (int) $live->match_id;
|
||||
$newMatchId = (int) $params['match_id'];
|
||||
$now = time();
|
||||
$sourceUrl = trim((string) $params['source_url']);
|
||||
$sourceUrlChanged = $sourceUrl !== trim((string) $live->source_url);
|
||||
|
||||
$live->save([
|
||||
$saveData = [
|
||||
'match_id' => $newMatchId,
|
||||
'title' => trim((string) $params['title']),
|
||||
'source_url' => trim((string) $params['source_url']),
|
||||
'play_url_m3u8' => '',
|
||||
'play_url_hd_m3u8' => '',
|
||||
'play_url_flv' => '',
|
||||
'play_url_hd_flv' => '',
|
||||
'fetch_status' => 0,
|
||||
'fetch_error' => '',
|
||||
'last_fetch_at' => 0,
|
||||
'next_fetch_at' => $now,
|
||||
'source_url' => $sourceUrl,
|
||||
'update_time' => $now,
|
||||
]);
|
||||
];
|
||||
|
||||
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);
|
||||
|
||||
if ($oldMatchId > 0 && $oldMatchId !== $newMatchId) {
|
||||
MatchLiveService::syncLegacyLiveUrl($oldMatchId);
|
||||
|
||||
Reference in New Issue
Block a user