From a6d8f3c2ee360cd297427fa625b6527c6d80d602 Mon Sep 17 00:00:00 2001 From: Theenoro Date: Thu, 26 Feb 2026 09:34:55 +0100 Subject: [PATCH] 0.0.1 --- __init__.py | 0 manager.py | 349 +++++++++++++++++++++++++++++++++++++++++++ providers/base.py | 34 +++++ providers/coub.py | 18 +++ providers/reddit.py | 15 ++ providers/youtube.py | 19 +++ 6 files changed, 435 insertions(+) create mode 100644 __init__.py create mode 100644 manager.py create mode 100644 providers/base.py create mode 100644 providers/coub.py create mode 100644 providers/reddit.py create mode 100644 providers/youtube.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/manager.py b/manager.py new file mode 100644 index 0000000..35310d5 --- /dev/null +++ b/manager.py @@ -0,0 +1,349 @@ +import importlib +import pkgutil +import re +from engine.plugin import Plugin +from plugins.embed.providers.base import EmbedProvider + +class EmbedConsentManager(Plugin): + name = "embed" + priority = 45 + + def __init__(self, config): + super().__init__(config) + self.providers = [] + self.load_providers() + + def load_providers(self): + package = "plugins.embed.providers" + pkg = importlib.import_module(package) + + for _, name, _ in pkgutil.iter_modules(pkg.__path__): + module = importlib.import_module(f"{package}.{name}") + for attr in dir(module): + cls = getattr(module, attr) + if isinstance(cls, type) and issubclass(cls, EmbedProvider) and cls is not EmbedProvider: + if hasattr(cls, "pattern") and hasattr(cls, "name"): + provider_config = self.config.get(cls.name, {}) + self.providers.append(cls(provider_config)) + + def after_markdown(self, builder, html): + for provider in self.providers: + html = provider.match(html) + return html + + return super().after_markdown(builder, html) + def after_page_render(self, builder, page, content): + pattern = r"<\/body>" + content = re.sub(pattern, self.inject_assets() + "BLAAA", content, 0, re.MULTILINE) + return content + + def after_build(self, builder): + settings_path = builder.config.output_dir / "privacy-settings.html" + settings_path.write_text(self.generate_settings_page(), encoding="utf-8") + + def inject_assets(self): + return self.css() + self.script() + + def generate_settings_page(self): + + cards = "" + + for p in self.providers: + cards += f""" +
+
+ {p.name.title()} +
+ External content provider +
+
+ + +
+ """ + + return f""" + + + + + Privacy Settings + {self.css()} + + + +
+

Privacy Settings

+

Control which external providers may load content on this site.

+ + {cards} + + + +
+ + {self.script()} + + + + + + """ + + def css(self): + return """ + +""" + + + # --------------------------------- + # JavaScript + # --------------------------------- + def script(self): + return """ + +""" + + def revocation_script(self): + return ''' + +''' \ No newline at end of file diff --git a/providers/base.py b/providers/base.py new file mode 100644 index 0000000..b73b041 --- /dev/null +++ b/providers/base.py @@ -0,0 +1,34 @@ +import re + +class EmbedProvider: + name = "base" + pattern = None + + def __init__(self, config=None): + self.config = config or {} + + def match(self, content): + if not self.pattern: + return content + return re.sub(self.pattern, self.replace, content) + + def replace(self, match): + raise NotImplementedError("Provider replace() missing!") + + def wrap_template(self, provider, embed_html): + return f''' + +''' \ No newline at end of file diff --git a/providers/coub.py b/providers/coub.py new file mode 100644 index 0000000..cbb3b24 --- /dev/null +++ b/providers/coub.py @@ -0,0 +1,18 @@ +from .base import EmbedProvider + +class CoubProvider(EmbedProvider): + name = "coub" + pattern = r"\{\{COUB:([A-Za-z0-9]+)\}\}" + + def replace(self, match): + coub_id = match.group(1) + + embed_html = f''' + +''' + return self.wrap_template("coub", embed_html) \ No newline at end of file diff --git a/providers/reddit.py b/providers/reddit.py new file mode 100644 index 0000000..eb05048 --- /dev/null +++ b/providers/reddit.py @@ -0,0 +1,15 @@ +from .base import EmbedProvider + +class RedditProvider(EmbedProvider): + name = "reddit" + pattern = r"\{\{REDDIT:(https?://[^\}]+)\}\}" + + def replace(self, match): + url = match.group(1) + + embed_html = f''' +
+ +
+''' + return self.wrap_template("reddit", embed_html) \ No newline at end of file diff --git a/providers/youtube.py b/providers/youtube.py new file mode 100644 index 0000000..ad91dc2 --- /dev/null +++ b/providers/youtube.py @@ -0,0 +1,19 @@ +from .base import EmbedProvider + +class YouTubeProvider(EmbedProvider): + name = "youtube" + pattern = r"\{\{YOUTUBE:([A-Za-z0-9_-]+)\}\}" + + def replace(self, match): + video_id = match.group(1) + nocookie = self.config.get("nocookie", True) + domain = "www.youtube-nocookie.com" if nocookie else "www.youtube.com" + + embed_html = f''' + +''' + return self.wrap_template("youtube", embed_html) \ No newline at end of file