Skip to content

Commit

Permalink
feat: added publishing to LRClib
Browse files Browse the repository at this point in the history
  • Loading branch information
Dzheremi2 committed Dec 28, 2024
1 parent 4f68495 commit 6e8a1fb
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 2 deletions.
3 changes: 2 additions & 1 deletion chronograph/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ def do_activate(self) -> None: # pylint: disable=arguments-differ
("import_lyrics_lrclib_synced", (), shared.win),
("import_lyrics_lrclib_plain", (), shared.win),
("export_to_file", (), shared.win),
("export_to_clipboard", (), shared.win)
("export_to_clipboard", (), shared.win),
("export_to_lrclib", (), shared.win)
}
)

Expand Down
4 changes: 4 additions & 0 deletions chronograph/ui/SongCard.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,7 @@ def cover(self, data: bytes) -> None:
self._file.cover = data
else:
raise ValueError("Cover must be bytes")

@property
def duration(self) -> int:
return self._file.duration
6 changes: 6 additions & 0 deletions chronograph/utils/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class BaseFile:
_album: str = "Unknown"
_cover: Union[bytes, str] = None
_mutagen_file: dict = None
_duration: float = None

def __init__(self, path: str) -> None:
self._path: str = path
Expand All @@ -43,6 +44,7 @@ def load_from_file(self, path: str) -> None:
/path/to/file
"""
self._mutagen_file = mutagen.File(path)
self._duration = self._mutagen_file.info.length

def get_cover_texture(self) -> Union[Gdk.Texture, str]:
"""Prepares a Gdk.Texture for setting to SongCard.paintable
Expand Down Expand Up @@ -94,6 +96,10 @@ def cover(self, data: bytes) -> None:
@property
def path(self) -> str:
return self._path

@property
def duration(self) -> int:
return round(self._duration)

def load_str_data(self) -> None:
"""Should be implemenmted in file specific child classes"""
Expand Down
99 changes: 99 additions & 0 deletions chronograph/utils/publish.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import hashlib
import re
from binascii import unhexlify

import requests
from gi.repository import Adw

from chronograph import shared
from chronograph.utils.parsers import sync_lines_parser


def verify_nonce(result, target):
if len(result) != len(target):
return False

for i in range(len(result)):
if result[i] > target[i]:
return False
elif result[i] < target[i]:
break

return True

def solve_challenge(prefix, target_hex):
target = unhexlify(target_hex.upper())
nonce = 0

while True:
input_data = f"{prefix}{nonce}".encode()
hashed = hashlib.sha256(input_data).digest()

if verify_nonce(hashed, target):
break
else:
nonce += 1

return str(nonce)


def make_plain_lyrics() -> str:
pattern = r"\[.*?\] "
plain_lyrics = []
for child in shared.win.sync_lines:
plain_lyrics.append(re.sub(pattern, "", child.get_text()))
return "\n".join(plain_lyrics[:-1])


def do_publish() -> None:
if (
shared.win.loaded_card.title
or shared.win.loaded_card.artist
or shared.win.loaded_card.album
) == "Unknown":
shared.win.toast_overlay.add_toast(
Adw.Toast(title=_("Some of Title, Artist and/or Album fileds are Unknown!"))
)
shared.win.export_lyrics_button.set_icon_name("export-to-symbolic")
raise AttributeError('Some of Title, Artist and/or Album fields are "Unknown"')

challenge_data = requests.post(
url="https://lrclib.net/api/request-challenge"
)
challenge_data = challenge_data.json()
nonce = solve_challenge(
prefix=challenge_data["prefix"], target_hex=challenge_data["target"]
)
print(f"X-Publish-Token: {challenge_data['prefix']}:{nonce}")
response = requests.post(
url="https://lrclib.net/api/publish",
headers={
"X-Publish-Token": f"{challenge_data['prefix']}:{nonce}",
"Content-Type": "application/json",
},
params={"keep_headers": "true"},
json={
"trackName": shared.win.loaded_card.title,
"artistName": shared.win.loaded_card.artist,
"albumName": shared.win.loaded_card.album,
"duration": shared.win.loaded_card.duration,
"plainLyrics": make_plain_lyrics(),
"syncedLyrics": sync_lines_parser(),
},
)

print(response.status_code)
if response.status_code == 201:
shared.win.toast_overlay.add_toast(
Adw.Toast(title=_("Published successfully: ") + str(response.status_code))
)
elif response.status_code == 400:
shared.win.toast_overlay.add_toast(
Adw.Toast(title=_("Incorrect publish token: ") + str(response.status_code))
)
else:
shared.win.toast_overlay.add_toast(
Adw.Toast(title=_("Unknown error occured: ") + str(response.status_code))
)

shared.win.export_lyrics_button.set_icon_name("export-to-symbolic")
11 changes: 10 additions & 1 deletion chronograph/window.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
import threading

import requests
from gi.repository import Adw, Gio, GLib, Gtk # type: ignore
Expand All @@ -23,6 +24,7 @@
sync_lines_parser,
timing_parser,
)
from chronograph.utils.publish import do_publish
from chronograph.utils.select_data import select_dir, select_lyrics_file


Expand Down Expand Up @@ -65,6 +67,7 @@ class ChronographWindow(Adw.ApplicationWindow):
replay_line_button: Gtk.Button = Gtk.Template.Child()
rew100_button: Gtk.Button = Gtk.Template.Child()
forw100_button: Gtk.Button = Gtk.Template.Child()
export_lyrics_button: Gtk.MenuButton = Gtk.Template.Child()
info_button: Gtk.Button = Gtk.Template.Child()
sync_lines: Gtk.ListBox = Gtk.Template.Child()
add_line_button: Gtk.Button = Gtk.Template.Child()
Expand Down Expand Up @@ -425,5 +428,11 @@ def on_export_to_file_action(self, *_args) -> None:
export_file(sync_lines_parser())

def on_export_to_clipboard_action(self, *_args) -> None:
"""Exports current `se;f.sync_lines` lyrics to clipbaord"""
"""Exports current `self.sync_lines` lyrics to clipbaord"""
export_clipboard(sync_lines_parser())

def on_export_to_lrclib_action(self, *_args) -> None:
thread = threading.Thread(target=do_publish)
thread.daemon = True
thread.start()
shared.win.export_lyrics_button.set_child(Adw.Spinner())
1 change: 1 addition & 0 deletions chronograph/window.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ChronographWindow(Adw.ApplicationWindow):
replay_line_button: Gtk.Button
rew100_button: Gtk.Button
forw100_button: Gtk.Button
export_lyrics_button: Gtk.MenuButton
info_button: Gtk.Button
sync_lines: Gtk.ListBox
add_line_button: Gtk.Button
Expand Down

0 comments on commit 6e8a1fb

Please sign in to comment.