feat(music-server): expose topn tracks endpoint
This commit is contained in:
@@ -26,6 +26,19 @@ class PlayerHistoryRouteTests(unittest.TestCase):
|
||||
playlist_id integer primary key,
|
||||
added_at text not null
|
||||
);
|
||||
|
||||
create table song_heat_summary (
|
||||
song_id integer primary key,
|
||||
play_count_total integer not null default 0,
|
||||
play_count_30d integer not null default 0,
|
||||
last_played_at text
|
||||
);
|
||||
|
||||
insert into song_heat_summary (
|
||||
song_id, play_count_total, play_count_30d, last_played_at
|
||||
) values
|
||||
(42, 8, 5, '2026-07-16T10:00:00+00:00'),
|
||||
(7, 12, 9, '2026-07-16T11:00:00+00:00');
|
||||
"""
|
||||
)
|
||||
conn.commit()
|
||||
@@ -66,6 +79,44 @@ class PlayerHistoryRouteTests(unittest.TestCase):
|
||||
1,
|
||||
),
|
||||
)
|
||||
conn.executescript(
|
||||
"""
|
||||
create table catalog_tracks (
|
||||
song_id integer primary key,
|
||||
platform text not null,
|
||||
remote_track_id text not null,
|
||||
name text not null,
|
||||
singers text,
|
||||
album text,
|
||||
cover_url text,
|
||||
duration_ms integer not null
|
||||
);
|
||||
|
||||
create table catalog_track_files (
|
||||
id integer primary key autoincrement,
|
||||
song_id integer not null,
|
||||
quality_label text,
|
||||
backend_type text not null,
|
||||
backend_name text,
|
||||
locator text not null,
|
||||
public_url text,
|
||||
status text not null,
|
||||
is_primary integer not null default 0
|
||||
);
|
||||
|
||||
insert into catalog_tracks (
|
||||
song_id, platform, remote_track_id, name, singers, album, cover_url, duration_ms
|
||||
) values
|
||||
(42, 'kuwo', '42', '热门歌曲二', '歌手乙', '专辑乙', 'https://img/42.jpg', 242000),
|
||||
(7, 'qq', '7', '热门歌曲一', '歌手甲', '专辑甲', 'https://img/7.jpg', 198000);
|
||||
|
||||
insert into catalog_track_files (
|
||||
song_id, quality_label, backend_type, backend_name, locator, public_url, status, is_primary
|
||||
) values
|
||||
(42, 'lossless', 'local_fs', 'default-local', 'kuwo/42.flac', null, 'active', 1),
|
||||
(7, 'high', 'local_fs', 'default-local', 'qq/7.mp3', null, 'active', 1);
|
||||
"""
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
@@ -140,6 +191,37 @@ class PlayerHistoryRouteTests(unittest.TestCase):
|
||||
self.assertEqual(400, invalid_track_id.status_code)
|
||||
self.assertEqual(400, invalid_progress.status_code)
|
||||
|
||||
def test_topn_returns_playable_tracks_in_heat_order(self):
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
player_db_path = Path(tmpdir) / "player.db"
|
||||
catalog_db_path = Path(tmpdir) / "catalog_read.db"
|
||||
self._prepare_player_db(player_db_path)
|
||||
self._prepare_catalog_db(catalog_db_path)
|
||||
|
||||
with patch.dict(
|
||||
"os.environ",
|
||||
{
|
||||
"PLAYER_DB_PATH": str(player_db_path),
|
||||
"CATALOG_DB_PATH": str(catalog_db_path),
|
||||
},
|
||||
clear=False,
|
||||
):
|
||||
response = TestClient(create_app()).get(
|
||||
"/player/v1/topn?limit=2",
|
||||
headers=auth_headers(player_db_path),
|
||||
)
|
||||
|
||||
self.assertEqual(200, response.status_code)
|
||||
payload = response.json()
|
||||
self.assertEqual(30, payload["periodDays"])
|
||||
self.assertEqual(
|
||||
["catalogsync:song:7", "catalogsync:song:42"],
|
||||
[item["id"] for item in payload["musicList"]],
|
||||
)
|
||||
self.assertEqual([1, 2], [item["rank"] for item in payload["musicList"]])
|
||||
self.assertEqual([9, 5], [item["playCount30d"] for item in payload["musicList"]])
|
||||
self.assertEqual("歌手甲", payload["musicList"][0]["artist"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user