Vibe generated documentation
Build LinkLog Development Image / development-image (push) Successful in 38s

This commit is contained in:
2026-09-04 16:10:34 +02:00
parent 4bf2da218c
commit 495d5c3907
4 changed files with 40 additions and 0 deletions
+6
View File
@@ -2,18 +2,24 @@
## SPDX-License-Identifier: GPL-3.0-or-later
class BasePlugin:
"""Define the interface shared by LinkLog event plugins."""
name = 'base'
version = '1.0.0'
enabled = True
def initialize(self, config=None):
"""Apply plugin configuration and report whether initialization succeeded."""
return True
def validate_config(self, config):
"""Validate configuration and return a ``(valid, message)`` pair."""
return True, 'ok'
def handle_event(self, event):
"""Handle a LinkLog event; subclasses must provide the implementation."""
raise NotImplementedError
def health_check(self):
"""Return the plugin name and basic health status."""
return {'name': self.name, 'status': 'ok'}
+20
View File
@@ -17,24 +17,36 @@ logger = logging.getLogger(__name__)
class DefaultFrontendPlugin(BasePlugin):
"""Accept events for the built-in frontend plugin."""
name = 'default_frontend'
version = '1.0.0'
def handle_event(self, event):
"""Acknowledge an event without performing an external side effect."""
return {'status': 'accepted', 'plugin': self.name, 'event': event.get('type')}
class MastodonPlugin(BasePlugin):
"""Publish and remove LinkLog entries through a Mastodon instance."""
name = 'mastodon'
version = '1.0.0'
enabled = False
config = {}
def initialize(self, config=None):
"""Store the administrator-provided defaults for later event handling."""
self.config = config or {}
return True
def handle_event(self, event):
"""Publish a link event, returning a structured status result.
Per-user plugin settings override global settings. The access token is
decrypted only for the duration of the outbound request, and the
instance is validated before any network connection is opened.
"""
if not event.get('post_to_mastodon', True):
return {'status': 'skipped', 'plugin': self.name, 'reason': 'not_requested'}
@@ -145,6 +157,7 @@ class MastodonPlugin(BasePlugin):
}
def delete_posts(self, event):
"""Delete all Mastodon statuses recorded for a link event."""
config = dict(self.config)
user_id = event.get('user_id')
if user_id:
@@ -188,10 +201,14 @@ class MastodonPlugin(BasePlugin):
class PluginManager:
"""Load enabled plugins and route LinkLog events to them."""
def __init__(self):
"""Create the built-in plugin registry."""
self.plugins = [DefaultFrontendPlugin(), MastodonPlugin()]
def refresh_from_db(self):
"""Refresh enabled flags and configuration from the plugin table."""
from backend.app.database import get_connection
with get_connection() as conn:
@@ -205,6 +222,7 @@ class PluginManager:
return enabled_names
def dispatch(self, event):
"""Send an event to every currently enabled plugin."""
self.refresh_from_db()
results = []
for plugin in self.plugins:
@@ -215,6 +233,7 @@ class PluginManager:
return results
def post_to_mastodon(self, event):
"""Publish one event through Mastodon when that plugin is enabled."""
self.refresh_from_db()
plugin = next(plugin for plugin in self.plugins if plugin.name == 'mastodon')
if not plugin.enabled:
@@ -222,6 +241,7 @@ class PluginManager:
return plugin.handle_event(event)
def delete_mastodon_posts(self, event):
"""Delete the Mastodon statuses associated with an event."""
self.refresh_from_db()
plugin = next(plugin for plugin in self.plugins if plugin.name == 'mastodon')
return plugin.delete_posts(event)