-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlyrics.py
123 lines (89 loc) · 4.02 KB
/
lyrics.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import requests as req
from system_utils import get_current_song_meta_data
current_song_data = None
current_song_lyrics = None
async def _update_song():
"""
This function updates the current song data and lyrics (the global variables).
"""
global current_song_lyrics, current_song_data
new_song_data = await get_current_song_meta_data()
should_fetch_lyrics = new_song_data is not None and (
current_song_data is None or (
current_song_data["artist"] != new_song_data["artist"] or
current_song_data["title"] != new_song_data["title"]
))
if should_fetch_lyrics:
current_song_lyrics = _get_lyrics(new_song_data["artist"], new_song_data["title"])
current_song_data = new_song_data
def _get_lyrics(artist: str, title: str) -> list[tuple[float, str]]:
"""
This function returns the lyrics of the given song by using the lrclib.net API.
Args:
artist (str): The artist of the song.
title (str): The title of the song.
Returns:
list[tuple[float, str]]: The lyrics of the song.
"""
artist_title= f"{artist} {title}"
song_id = req.request("GET", f"https://lrclib.net/api/search?q={artist_title}").json()
if len(song_id) == 0: return None
song_id = song_id[0]["id"]
lyrics = req.request("GET", f"https://lrclib.net/api/get/{song_id}").json()["syncedLyrics"]
if lyrics is None: return None
processed_lyrics = []
for lyric in lyrics.split("\n"):
time = lyric[1: lyric.find("]") -1]
m, s = time.split(":")
seconds = float(m) * 60 + float(s)
processed_lyrics.append((seconds, lyric[lyric.find("]") + 1:].strip()))
return processed_lyrics
def _find_current_lyric_index(delta: float = 0.1) -> int:
"""
This function returns the index of the current lyric in the current_song_lyrics list.
Args:
delta (float, optional): A delay to take into account when calculating the index. Defaults to 0.1.
Returns:
int: The index of the current lyric in the current_song_lyrics list. If a lyric is not found, -1 is returned.
"""
if current_song_lyrics is not None and current_song_data is not None:
time = current_song_data["position"]
for i in range(len(current_song_lyrics) - 1):
if current_song_lyrics[i][0] <= time + delta < current_song_lyrics[i + 1][0]:
return i
return -1
async def get_timed_lyrics(delta: int = 0) -> str:
"""
This function returns the current lyric of the song.
Args:
delta (int, optional): The delay to take into account when calculating the lyric. Defaults to 0.
Returns:
str: The current lyric of the song. If a lyric is not found, "Lyrics not found" is returned.
"""
await _update_song()
lyric_index = _find_current_lyric_index(delta)
if lyric_index == -1: return "Lyrics not found"
return current_song_lyrics[lyric_index][1]
async def get_timed_lyrics_previous_and_next() -> tuple[str, str, str]:
"""
This function returns the previous, current and next lyrics of the song.
Returns:
tuple[str, str, str]: The previous, current and next lyrics of the song. If a lyric is not found, "-" is returned.
"""
def _lyric_representation(lyric_index: int) -> str:
"""
This function returns the lyric representation of the given lyric index.
Args:
lyric_index (int): The index of the lyric in the current_song_lyrics list.
Returns:
str: The lyric representation of the given lyric index.
"""
return current_song_lyrics[lyric_index][1] or "-"
await _update_song()
lyric_index = _find_current_lyric_index()
if lyric_index == -1: return "Lyrics not found"
previous = _lyric_representation(lyric_index-1) if lyric_index > 0 else "-"
current = _lyric_representation(lyric_index)
next = (_lyric_representation(lyric_index+1)
if lyric_index + 1 < len(current_song_lyrics) - 1 else "-")
return previous, current, next