diff --git a/py3status/constants.py b/py3status/constants.py index 0a03a9b75a..67beb97b58 100644 --- a/py3status/constants.py +++ b/py3status/constants.py @@ -270,3 +270,31 @@ MARKUP_LANGUAGES = ["pango", "none"] ON_ERROR_VALUES = ["hide", "show"] + +SANITIZE_TITLES = "|".join( + [ + "bonus", + "demo", + "edit", + "explicit", + "extended", + "feat", + "mono", + "remaster", + "stereo", + "version", + ] +) + +SANITIZE_PATTERNS = { + # Match brackets with their content containing any metadata word. + # (Remastered 2017) + # [Single] + # (Bonus Track) + "inside_brackets": r"([\(\[][^)\]]*?({})[^)\]]*?[\)\]])".format(SANITIZE_TITLES), + # Match string after hyphen, comma, semicolon or slash containing any metadata word. + # - Remastered 2012 + # / Radio Edit + # ; Remastered + "after_delimiter": r"([\-,;/])([^\-,;/])*({}).*".format(SANITIZE_TITLES), +} diff --git a/py3status/formatter.py b/py3status/formatter.py index a732fe65d5..0a812aa7fb 100644 --- a/py3status/formatter.py +++ b/py3status/formatter.py @@ -5,7 +5,7 @@ from urllib.parse import parse_qsl from py3status.composite import Composite -from py3status.constants import COLOR_NAMES, COLOR_NAMES_EXCLUDED +from py3status.constants import COLOR_NAMES, COLOR_NAMES_EXCLUDED, SANITIZE_PATTERNS def expand_color(color, default=None, passthrough=False, block=None): @@ -296,10 +296,35 @@ class Placeholder: Class representing a {placeholder} """ + sanitized_regex_cache = {} + sanitized_string_cache = {} + def __init__(self, key, format): self.key = key self.format = format + def _sanitize(self, string): + """ + Remove redundant metadata from string and return it + """ + try: + return self.sanitized_string_cache[string] + except KeyError: + cache_key = string + + # add compiled sanitized regexes to the cache + if not self.sanitized_regex_cache: + for sanitize_key, sanitize_value in SANITIZE_PATTERNS.items(): + self.sanitized_regex_cache[sanitize_key] = re.compile(sanitize_value, re.IGNORECASE) + + # sanitize the strings + for pattern in self.sanitized_regex_cache.values(): + string = re.sub(pattern, "", string).strip() + + # add sanitized strings to the cache + self.sanitized_string_cache[cache_key] = string + return string + def get(self, get_params, block): """ return the correct value for the placeholder @@ -327,6 +352,8 @@ def get(self, get_params, block): value = float(value) if "d" in self.format: value = int(float(value)) + if "sanitize" in self.format: + value = self._sanitize(value) output = f"{{[{self.key}]{self.format}}}" value = output.format({self.key: value}) value_ = float(value) diff --git a/py3status/modules/spotify.py b/py3status/modules/spotify.py index 29b87e7a8a..034434b01f 100644 --- a/py3status/modules/spotify.py +++ b/py3status/modules/spotify.py @@ -15,11 +15,6 @@ (default 'Spotify not running') format_stopped: define output if spotify is not playing (default 'Spotify stopped') - sanitize_titles: whether to remove meta data from album/track title - (default True) - sanitize_words: which meta data to remove - *(default ['bonus', 'demo', 'edit', 'explicit', 'extended', - 'feat', 'mono', 'remaster', 'stereo', 'version'])* Format placeholders: {album} album name @@ -60,7 +55,6 @@ {'color': '#FF0000', 'full_text': 'Spotify stopped'} """ -import re from datetime import timedelta from time import sleep @@ -82,47 +76,10 @@ class Py3status: format = "{artist} : {title}" format_down = "Spotify not running" format_stopped = "Spotify stopped" - sanitize_titles = True - sanitize_words = [ - "bonus", - "demo", - "edit", - "explicit", - "extended", - "feat", - "mono", - "remaster", - "stereo", - "version", - ] def _spotify_cmd(self, action): return SPOTIFY_CMD.format(dbus_client=self.dbus_client, cmd=action) - def post_config_hook(self): - """ """ - # Match string after hyphen, comma, semicolon or slash containing any metadata word - # examples: - # - Remastered 2012 - # / Radio Edit - # ; Remastered - self.after_delimiter = self._compile_re(r"([\-,;/])([^\-,;/])*(META_WORDS_HERE).*") - - # Match brackets with their content containing any metadata word - # examples: - # (Remastered 2017) - # [Single] - # (Bonus Track) - self.inside_brackets = self._compile_re(r"([\(\[][^)\]]*?(META_WORDS_HERE)[^)\]]*?[\)\]])") - - def _compile_re(self, expression): - """ - Compile given regular expression for current sanitize words - """ - meta_words = "|".join(self.sanitize_words) - expression = expression.replace("META_WORDS_HERE", meta_words) - return re.compile(expression, re.IGNORECASE) - def _get_playback_status(self): """ Get the playback status. One of: "Playing", "Paused" or "Stopped". @@ -145,9 +102,6 @@ def _get_text(self): microtime = metadata.get("mpris:length") rtime = str(timedelta(seconds=microtime // 1_000_000)) title = metadata.get("xesam:title") - if self.sanitize_titles: - album = self._sanitize_title(album) - title = self._sanitize_title(title) playback_status = self._get_playback_status() if playback_status == "Playing": @@ -176,14 +130,6 @@ def _get_text(self): except Exception: return (self.format_down, self.py3.COLOR_OFFLINE or self.py3.COLOR_BAD) - def _sanitize_title(self, title): - """ - Remove redundant metadata from title and return it - """ - title = re.sub(self.inside_brackets, "", title) - title = re.sub(self.after_delimiter, "", title) - return title.strip() - def spotify(self): """ Get the current "artist - title" and return it.