diff --git a/.restyled.yaml b/.restyled.yaml
index ad90851f3a..30cb332137 100644
--- a/.restyled.yaml
+++ b/.restyled.yaml
@@ -10,4 +10,14 @@ restylers:
enabled: false
- clazy:
enabled: false
+ # Disable conflicting python linters.
+ # Conflicts with "isort"
+ - reorder-python-imports:
+ enabled: false
+ # Conflicts with "black"
+ - yapf:
+ enabled: false
+ # Fix compatibilitry with "black" for "autopep8"
+ - autopep8:
+ arguments: ["--max-line-length", "88"]
- "*"
diff --git a/smileys/EmojiOne/emoticons.xml b/smileys/EmojiOne/emoticons.xml
index 51b0d47e42..7f6afaa465 100644
--- a/smileys/EmojiOne/emoticons.xml
+++ b/smileys/EmojiOne/emoticons.xml
@@ -2358,11 +2358,9 @@
㊗
- 祝
㊙
- 秘
©
diff --git a/smileys/blocked_smileys.json b/smileys/blocked_smileys.json
new file mode 100644
index 0000000000..74a65caea5
--- /dev/null
+++ b/smileys/blocked_smileys.json
@@ -0,0 +1,6 @@
+{
+ "EmojiOne": {
+ "3297": ["祝"],
+ "3299": ["秘"]
+ }
+}
diff --git a/smileys/update_smileys.py b/smileys/update_smileys.py
index afe0285a60..387b3fefee 100755
--- a/smileys/update_smileys.py
+++ b/smileys/update_smileys.py
@@ -1,19 +1,22 @@
#!/usr/bin/env python3
+import argparse
+import json
import os
-import sys
from xml.dom import minidom # nosec
-def load_smileys(path: str) -> dict[str, list[str]]:
+def load_smileys(path: str) -> dict[str, list[str]]: # noqa: D213
"""Load smileys from emoticons.xml file.
Args:
path: Path to the emoticons.xml file.
- Returns:
- A dictionary where the keys are the filenames (without suffix) of the
+ Returns
+ -------
+ smileys: A dictionary where the keys are the filenames (without suffix) of the
smileys and the values are the strings that will be replaced by the
file when sent in a message.
+
"""
smileys: dict[str, list[str]] = {}
dom = minidom.parse(path) # nosec
@@ -27,18 +30,18 @@ def load_smileys(path: str) -> dict[str, list[str]]:
return smileys
-def save_smileys(path: str, smileys: dict[str, list[str]]) -> None:
+def save_smileys(path: str, smileys: dict[str, list[str]]) -> None: # noqa: D213,D407
"""Save smileys to emoticons.xml file.
Args:
path: Path to the emoticons.xml file.
smileys: The same format as the return value of load_smileys.
+
"""
doc = minidom.Document()
root = doc.createElement("messaging-emoticon-map")
root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
- root.setAttribute("xsi:noNamespaceSchemaLocation",
- "../messaging-emoticon-map.xsd")
+ root.setAttribute("xsi:noNamespaceSchemaLocation", "../messaging-emoticon-map.xsd")
doc.appendChild(root)
for file, strings in smileys.items():
emoticon = doc.createElement("emoticon")
@@ -69,11 +72,13 @@ def emoji_to_string(emoji: tuple[int, ...]) -> str:
def add_missing_smileys(path: str, smileys: dict[str, list[str]]) -> None:
"""Add smileys that exist in the path but not in the smileys dict."""
- for emoji_str in sorted(filter_svgs(os.listdir(path)),
- key=parse_emoji_sequence):
+ for emoji_str in sorted(filter_svgs(os.listdir(path)), key=parse_emoji_sequence):
emoji = emoji_to_string(parse_emoji_sequence(emoji_str))
- if (emoji_str not in smileys or len(smileys[emoji_str]) == 1
- and smileys[emoji_str][0] == emoji):
+ if (
+ emoji_str not in smileys
+ or len(smileys[emoji_str]) == 1
+ and smileys[emoji_str][0] == emoji
+ ):
smileys[emoji_str] = [emoji]
if emoji not in smileys[emoji_str]:
smileys[emoji_str].append(emoji)
@@ -94,7 +99,7 @@ def prefer_emoji(emoji: str, string: str) -> str:
return string
-def sort_strings(smileys: dict[str, list[str]]) -> None:
+def sort_strings(smileys: dict[str, list[str]]) -> None: # noqa: D213
"""Sort the strings in the smileys dict.
We put the emoji string first.
@@ -104,15 +109,181 @@ def sort_strings(smileys: dict[str, list[str]]) -> None:
strings.sort(key=lambda s: prefer_emoji(emoji, s))
+def block_smiley_maybe(
+ smileys: dict[str, list[str]],
+ blocked_smileys_in_pack: dict[str, list[str]],
+ block: str | None,
+) -> bool: # noqa: D213
+ """Block smiley defined in block and return True if blocked smiley list was modified.
+
+ Args
+ ----
+ smileys: The loaded set of smileys.
+ blocked_smileys_in_pack: the list of currently blocked smileys.
+ block: The smiley to be blocked.
+
+ Returns
+ -------
+ True if blocked_smileys_in_pack was modified, False otherwise.
+
+ """
+ is_dirty = False
+ if not block:
+ return is_dirty
+ block_name = None
+ for name, strings in smileys.items():
+ smiley_set = set(strings)
+ if block in smiley_set:
+ block_name = name
+ block_list = blocked_smileys_in_pack.get(block_name, [])
+ if block not in block_list:
+ # Add blocked smiley.
+ block_list.append(block)
+ blocked_smileys_in_pack[block_name] = block_list
+ is_dirty = True
+ else:
+ print(f'The smiley "{block}" is already blocked.')
+ break
+ if not block_name:
+ is_blocked = False
+ for name, strings in blocked_smileys_in_pack.items():
+ if block in strings:
+ print(f'The smiley "{block}" is already blocked.')
+ break
+ if is_blocked:
+ print(f'The smiley to block "{block}" was not found.')
+ return is_dirty
+
+
+def unblock_smiley_maybe(
+ smileys: dict[str, list[str]],
+ blocked_smileys_in_pack: dict[str, list[str]],
+ unblock: str | None,
+) -> bool: # noqa: D213
+ """Unblock smiley defined in unblock and return True if blocked smiley list was modified.
+
+ Args:
+ smileys: The loaded set of smileys.
+ blocked_smileys_in_pack: the list of currently blocked smileys.
+ unblock: The smiley to be unblocked.
+
+ Returns
+ -------
+ True if blocked_smileys_in_pack was modified, False otherwise.
+
+ """
+ is_dirty = False
+ unblock_name = None
+ if not unblock:
+ return is_dirty
+ for name, strings in blocked_smileys_in_pack.items():
+ smiley_set = set(strings)
+ if unblock in smiley_set:
+ # Unblock smiley.
+ unblock_name = name
+ blocked_smileys_in_pack[unblock_name].remove(unblock)
+ smiley_list = smileys.get(unblock_name, [])
+ smiley_list.append(unblock)
+ smileys[unblock_name] = list(set(smiley_list))
+ is_dirty = True
+ break
+ if not unblock_name:
+ print(f'The smiley to unblock "{unblock}" was not found in the blocklist.')
+ return is_dirty
+
+
+def load_and_update_blocklist(
+ smileypack: str,
+ smileys: dict[str, list[str]],
+ block: str | None,
+ unblock: str | None,
+) -> dict[str, list[str]]: # noqa: D213
+ """Load the smiley block list, update and save it.
+
+ We also add unblocked smileys to the smileys dictionary.
+
+ Args:
+ smileypack: The name of a smiley pack to update/load.
+ smileys: The loaded set of smileys.
+ block: The smiley to be blocked.
+ unblock: The smiley to be unblocked.
+
+ Returns
+ -------
+ The dictionary, containing where the keys are the filenames (without suffix) of the
+ smileys and the values are strings that will be replaced by the
+ file when sent in a message.
+
+ """
+ if block == unblock:
+ raise ValueError("The smiley cannot be blocked and unblocked simultaneously.")
+ block_list_file = os.path.join(os.path.dirname(__file__), "blocked_smileys.json")
+ blocked_smileys: dict[str, dict[str, list[str]]] = {}
+ if os.path.isfile(block_list_file):
+ with open(block_list_file, "r") as f:
+ blocked_smileys = json.load(f)
+ blocked_smileys_in_pack = blocked_smileys.get(smileypack, {})
+ # Update the dictionary of blocked smileys if needed.
+ is_dirty = block_smiley_maybe(smileys, blocked_smileys_in_pack, block)
+ # Search for the smiley to unblock in the block list and remove it.
+ is_dirty = (
+ unblock_smiley_maybe(smileys, blocked_smileys_in_pack, unblock) or is_dirty
+ )
+
+ if is_dirty:
+ sort_strings(blocked_smileys_in_pack)
+ blocked_smileys[smileypack] = blocked_smileys_in_pack
+ with open(block_list_file, "w") as f:
+ json.dump(blocked_smileys, f, ensure_ascii=False, indent=2)
+ return blocked_smileys.get(smileypack, {})
+
+
+def remove_blocked_smileys(
+ smileys: dict[str, list[str]], blocked_smileys: dict[str, list[str]]
+) -> None: # noqa: D213, D407
+ """Remove all blocked_smileys from smileys.
+
+ Args:
+ smileys: The loaded set of smileys.
+ blocked_smileys: The loaded smileys to be blocked.
+
+ """
+ for fname, strings in blocked_smileys.items():
+ if fname in smileys:
+ smileys[fname] = list(set(smileys[fname]).difference(set(strings)))
+
+
def main() -> None:
- if len(sys.argv) != 2:
- print(f"Usage: {sys.argv[0]} ")
- sys.exit(1)
- smileys = load_smileys(os.path.join(sys.argv[1], "emoticons.xml"))
- add_missing_smileys(sys.argv[1], smileys)
- remove_missing_smileys(sys.argv[1], smileys)
+ parser = argparse.ArgumentParser(
+ description="The script to parse and fix smileys directories."
+ )
+ parser.add_argument("smileypack", help="The folder with smileys.")
+ parser.add_argument(
+ "-b",
+ "--block-smiley",
+ help="The smiley to be added to blocklist.",
+ required=False,
+ default=None,
+ )
+ parser.add_argument(
+ "-u",
+ "--unblock-smiley",
+ help="The smiley to be removed from blocklist.",
+ required=False,
+ default=None,
+ )
+ args = parser.parse_args()
+ smileys = load_smileys(
+ os.path.join(os.path.dirname(__file__), args.smileypack, "emoticons.xml")
+ )
+ add_missing_smileys(args.smileypack, smileys)
+ remove_missing_smileys(args.smileypack, smileys)
+ blocked_smileys = load_and_update_blocklist(
+ args.smileypack, smileys, args.block_smiley, args.unblock_smiley
+ )
+ remove_blocked_smileys(smileys, blocked_smileys)
sort_strings(smileys)
- save_smileys(os.path.join(sys.argv[1], "emoticons.xml"), smileys)
+ save_smileys(os.path.join(args.smileypack, "emoticons.xml"), smileys)
if __name__ == "__main__":