From 73ddff1faa0f31d984502424c3013881cee153ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20B=C3=B6hning?=
<1497707+bohning@users.noreply.github.com>
Date: Sun, 17 Nov 2024 13:23:04 +0100
Subject: [PATCH 1/5] Remove parsing tags from usdb comments.
---
src/usdb_syncer/song_loader.py | 2 --
src/usdb_syncer/usdb_scraper.py | 16 +---------------
2 files changed, 1 insertion(+), 17 deletions(-)
diff --git a/src/usdb_syncer/song_loader.py b/src/usdb_syncer/song_loader.py
index 3891a9cd..c1067dc9 100644
--- a/src/usdb_syncer/song_loader.py
+++ b/src/usdb_syncer/song_loader.py
@@ -290,7 +290,6 @@ def _get_usdb_data(
txt = SongTxt.parse(txt_str, log)
txt.sanitize(txt_options)
txt.headers.creator = txt.headers.creator or details.uploader or None
- txt.headers.tags = ", ".join(details.comment_tags()) or None
return details, txt
@@ -310,7 +309,6 @@ def _update_song_with_usdb_data(
song.year = None
song.genre = txt.headers.genre or ""
song.creator = txt.headers.creator or ""
- song.tags = txt.headers.tags or ""
class _SongLoader(QtCore.QRunnable):
diff --git a/src/usdb_syncer/usdb_scraper.py b/src/usdb_syncer/usdb_scraper.py
index 2b3535f5..b80c60f3 100644
--- a/src/usdb_syncer/usdb_scraper.py
+++ b/src/usdb_syncer/usdb_scraper.py
@@ -44,7 +44,6 @@
WELCOME_REGEX = re.compile(
r"
\s*([^<]+) ([^<]+)"
)
-TAGS_LINE_REGEX = re.compile("#TAGS:(.+)")
def establish_usdb_login(session: Session) -> bool:
@@ -140,7 +139,6 @@ class CommentContents:
text: str
youtube_ids: list[str]
urls: list[str]
- tags: list[str]
class SongComment:
@@ -192,13 +190,6 @@ def all_comment_videos(self) -> Iterator[str]:
yield from comment.contents.youtube_ids
yield from comment.contents.urls
- def comment_tags(self) -> list[str]:
- """Return the first tags string sanitized, if any."""
- for comment in self.comments:
- if comment.contents.tags:
- return comment.contents.tags
- return []
-
def get_usdb_page(
rel_url: str,
@@ -495,12 +486,7 @@ def _parse_comment_contents(contents: BeautifulSoup, logger: Log) -> CommentCont
else:
urls.append(url)
- if match := TAGS_LINE_REGEX.search(text):
- tags = [t for tag in match.group(1).split(",") if (t := tag.strip())]
- else:
- tags = []
-
- return CommentContents(text=text, urls=urls, youtube_ids=youtube_ids, tags=tags)
+ return CommentContents(text=text, urls=urls, youtube_ids=youtube_ids)
def _all_urls_in_comment(
From 8e9d1369dc24e89c8968f0903f9a694627367d8a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20B=C3=B6hning?=
<1497707+bohning@users.noreply.github.com>
Date: Sun, 17 Nov 2024 13:23:50 +0100
Subject: [PATCH 2/5] Add parsing tags from meta tags.
---
src/usdb_syncer/meta_tags.py | 20 ++++++++++++--------
src/usdb_syncer/song_txt/tracks.py | 2 +-
2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/usdb_syncer/meta_tags.py b/src/usdb_syncer/meta_tags.py
index e7321951..8264a549 100644
--- a/src/usdb_syncer/meta_tags.py
+++ b/src/usdb_syncer/meta_tags.py
@@ -146,28 +146,29 @@ class MetaTags:
#VIDEO:a=example,co=foobar.jpg,bg=background.jpg
"""
- video: str | None = None
audio: str | None = None
+ video: str | None = None
cover: ImageMetaTags | None = None
background: ImageMetaTags | None = None
player1: str | None = None
player2: str | None = None
preview: float | None = None
medley: MedleyTag | None = None
+ tags: str | None = None
@classmethod
def parse(cls, video_tag: str, logger: Log) -> MetaTags:
- tags = cls()
+ meta_tags = cls()
if not "=" in video_tag:
# probably a regular video file name and not a meta tag
- return tags
+ return meta_tags
for pair in video_tag.split(","):
if "=" not in pair:
logger.warning(f"missing key or value for meta tag: '{pair}'")
continue
key, value = pair.split("=", maxsplit=1)
- tags._parse_key_value_pair(key, value, logger)
- return tags
+ meta_tags._parse_key_value_pair(key, value, logger)
+ return meta_tags
def _parse_key_value_pair(self, key: str, value: str, logger: Log) -> None:
value = decode_meta_tag_value(value)
@@ -202,6 +203,8 @@ def _parse_key_value_pair(self, key: str, value: str, logger: Log) -> None:
self.preview = _try_parse_float(value, logger)
case "medley":
self.medley = MedleyTag.try_parse(value, logger)
+ case "tags":
+ self.tags = value
case _:
logger.warning(f"unknown key for meta tag: '{key}={value}'")
@@ -211,14 +214,15 @@ def is_audio_only(self) -> bool:
def __str__(self) -> str:
return _join_tags(
- _key_value_str("v", self.video),
_key_value_str("a", self.audio),
+ _key_value_str("v", self.video),
self.cover.to_str("co") if self.cover else None,
self.background.to_str("bg") if self.background else None,
_key_value_str("p1", self.player1),
_key_value_str("p2", self.player2),
_key_value_str("preview", self.preview),
str(self.medley) if self.medley else None,
+ _key_value_str("tags", self.tags),
)
@@ -226,8 +230,8 @@ def _key_value_str(key: str, value: str | float | None) -> str | None:
return None if value is None else f"{key}={encode_meta_tag_value(str(value))}"
-def _join_tags(*tags: str | None) -> str:
- return ",".join(filter(None, tags))
+def _join_tags(*meta_tags: str | None) -> str:
+ return ",".join(filter(None, meta_tags))
def _try_parse_float(value: str, logger: Log) -> float | None:
diff --git a/src/usdb_syncer/song_txt/tracks.py b/src/usdb_syncer/song_txt/tracks.py
index 082cc2cb..9103b094 100644
--- a/src/usdb_syncer/song_txt/tracks.py
+++ b/src/usdb_syncer/song_txt/tracks.py
@@ -442,7 +442,7 @@ def fix_first_words_capitalization(self, logger: Log) -> None:
# capitalize first capitalizable character
# e.g. '"what time is it?"' -> '"What time is it?"'
for char in line.notes[0].text:
- if char.isalpha() or char == "’":
+ if char.isalpha():
if char.islower():
line.notes[0].text = line.notes[0].text.replace(
char, char.upper(), 1
From ac089bac3efc840888811015b4ea588201aa649b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20B=C3=B6hning?=
<1497707+bohning@users.noreply.github.com>
Date: Sun, 17 Nov 2024 13:24:49 +0100
Subject: [PATCH 3/5] Add support for tags in meta tags creation dialog.
Also: switch order of audio and video (as audio is more important than video).
---
src/usdb_syncer/gui/forms/MetaTagsDialog.ui | 126 ++++++++++++--------
src/usdb_syncer/gui/meta_tags_dialog.py | 4 +-
2 files changed, 82 insertions(+), 48 deletions(-)
diff --git a/src/usdb_syncer/gui/forms/MetaTagsDialog.ui b/src/usdb_syncer/gui/forms/MetaTagsDialog.ui
index 56b5663b..cf9821eb 100644
--- a/src/usdb_syncer/gui/forms/MetaTagsDialog.ui
+++ b/src/usdb_syncer/gui/forms/MetaTagsDialog.ui
@@ -69,11 +69,11 @@
QLayout::SizeConstraint::SetNoConstraint
-
-
+
- Video (v)
+ Audio (a)
-
+
4
@@ -87,16 +87,16 @@
4
-
-
+
-
-
+
URL:
-
-
+
@@ -104,11 +104,11 @@
-
-
+
- Audio (a)
+ Video (v)
-
+
4
@@ -122,16 +122,16 @@
4
-
-
+
-
-
+
URL:
-
-
+
@@ -139,7 +139,7 @@
-
-
+
Cover (co)
@@ -160,9 +160,9 @@
4
-
-
+
-
-
+
URL:
@@ -174,7 +174,7 @@
-
-
+
0
@@ -197,7 +197,7 @@
4
-
-
+
Angle (ccw):
@@ -254,7 +254,7 @@
4
-
-
+
Value:
@@ -316,7 +316,7 @@
4
-
-
+
Width/Height:
@@ -357,7 +357,7 @@
-
-
+
Crop (co-crop)
@@ -375,7 +375,7 @@
4
-
-
+
0
@@ -398,7 +398,7 @@
-
-
+
Top:
@@ -415,7 +415,7 @@
-
-
+
Width:
@@ -432,7 +432,7 @@
-
-
+
Height:
@@ -468,7 +468,7 @@
-
-
+
Background (bg)
@@ -486,9 +486,9 @@
4
-
-
+
-
-
+
URL:
@@ -500,7 +500,7 @@
-
-
+
Resize (bg-resize)
@@ -518,7 +518,7 @@
4
-
-
+
Width:
@@ -535,7 +535,7 @@
-
-
+
Height:
@@ -568,7 +568,7 @@
-
-
+
Crop (bg-crop)
@@ -586,7 +586,7 @@
4
-
-
+
0
@@ -609,7 +609,7 @@
-
-
+
Top:
@@ -626,7 +626,7 @@
-
-
+
Width:
@@ -643,7 +643,7 @@
-
-
+
Height:
@@ -709,7 +709,7 @@
4
-
-
+
0
@@ -735,7 +735,7 @@
-
-
+
0
@@ -777,15 +777,15 @@
-
-
+
-
-
+
Preview (preview)
-
-
+
Preview start:
@@ -824,13 +824,13 @@
-
-
+
Medley (medley)
-
-
+
Start:
@@ -850,7 +850,7 @@
-
-
+
End:
@@ -884,6 +884,41 @@
+ -
+
+
+ Tags (tags)
+
+
+
+ 4
+
+
+ 4
+
+
+ 4
+
+
+ 4
+
+
-
+
+
-
+
+
+ Tags:
+
+
+
+ -
+
+
+
+
+
+
+
-
@@ -901,7 +936,7 @@
-
-
+
-
@@ -921,9 +956,6 @@
- -
-
-
-
diff --git a/src/usdb_syncer/gui/meta_tags_dialog.py b/src/usdb_syncer/gui/meta_tags_dialog.py
index 8615864c..ab2dad35 100644
--- a/src/usdb_syncer/gui/meta_tags_dialog.py
+++ b/src/usdb_syncer/gui/meta_tags_dialog.py
@@ -55,6 +55,7 @@ def _connect_signals(self) -> None:
self.preview_start.valueChanged,
self.medley_start.valueChanged,
self.medley_end.valueChanged,
+ self.tags.textChanged,
):
signal.connect(lambda: self.output.setText(f"#VIDEO:{self._meta_tags()}"))
@@ -143,14 +144,15 @@ def _p2_meta_tag(self) -> str | None:
def _meta_tags(self) -> MetaTags:
return MetaTags(
- video=_sanitize_video_url(self.video_url.text()) or None,
audio=self._audio_source(),
+ video=_sanitize_video_url(self.video_url.text()) or None,
cover=self._cover_meta_tags(),
background=self._background_meta_tags(),
player1=self._p1_meta_tag(),
player2=self._p2_meta_tag(),
preview=round(self.preview_start.value(), 3) or None,
medley=self._medley_tag(),
+ tags=self.tags.text() or None,
)
def _toggle_auto_contrast(self) -> None:
From 18305d192f2f4bf6b55ca975502794f20bb76ab6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20B=C3=B6hning?=
<1497707+bohning@users.noreply.github.com>
Date: Sun, 17 Nov 2024 13:25:08 +0100
Subject: [PATCH 4/5] Add parsing of tags from meta tags instead of from
comments to changelog.
---
CHANGELOG.md | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cfadc7ca..a3b5be10 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,14 @@
+
+
+# Changes
+
+## Features
+
+- Song tags are no longer parsed from comments, but instead from meta tags
+ (Use `%2C` as separation, e.g. `tags=explicit%2C80s%2CSoundtrack).
+ See https://github.com/bohning/usdb_syncer/wiki/Meta-Tags for a full list of
+ supported tags.
+
# Changes
From 95315101ae757def87e9e40f158415d523192a6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20B=C3=B6hning?=
<1497707+bohning@users.noreply.github.com>
Date: Sun, 17 Nov 2024 14:10:39 +0100
Subject: [PATCH 5/5] Add tags to restore_missing_headers().
---
src/usdb_syncer/song_txt/__init__.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/usdb_syncer/song_txt/__init__.py b/src/usdb_syncer/song_txt/__init__.py
index 63c5f8b5..b5d0dd33 100644
--- a/src/usdb_syncer/song_txt/__init__.py
+++ b/src/usdb_syncer/song_txt/__init__.py
@@ -75,6 +75,8 @@ def restore_missing_headers(self) -> None:
if medley := self.meta_tags.medley:
self.headers.medleystartbeat = medley.start
self.headers.medleyendbeat = medley.end
+ if self.meta_tags.tags:
+ self.headers.tags = self.meta_tags.tags
def write_to_file(self, path: Path, encoding: str, newline: str) -> None:
with path.open(
|