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(