• jmiller released this 2026-06-06 11:31:14 +00:00 | 11 commits to dev since this release

    Fixed

    • C-1 OauthController: Added CSRF nonce validation to OAuth callback — session-based nonce is generated during authorize(), embedded in the state parameter, and verified in callback() to prevent CSRF attacks

    • C-2 DispatchController: Added POST method enforcement — rejects non-POST requests with 405 status

    • C-5 ServiceModel: Credential form fields (cred_*) are now collected into the credentials JSON column on save, and expanded back into individual fields on load — previously these fields were silently discarded

    • H-1 Event pattern: Fixed Joomla 5 SubscriberInterface incompatibility where onMokoJoomCrossGetServices by-reference pattern silently lost all service plugins — dispatchers now read plugin instances from Event ArrayAccess indices after dispatch

    • H-4 ServiceTable: Added check() method with alias generation, required field validation (title, service_type), timestamp management, and JSON defaults for credentials/params

    • H-9 WebhookService: Fixed credential key mismatch — publish() and validateCredentials() now use keys matching the service.xml form fields (url, method, auth_type, bearer_token, basic_username, basic_password, content_type) and properly apply Bearer/Basic auth headers

    • M-4 ServiceIconHelper: Escaped $extraClass parameter in renderIcon() with htmlspecialchars() to prevent XSS

    • M-5 Content plugin: Fixed double-escaped HTML in cross-post history panel — uses setFieldAttribute() to inject history HTML into the note field description after XML load, avoiding XML attribute encoding

    • Content plugin: Fixed onContentBeforeDisplay signature for Joomla 5/6 — now accepts BeforeDisplayEvent object instead of individual parameters

    • QueueProcessor: Replaced read-then-write DB lock with MySQL advisory locks (GET_LOCK/RELEASE_LOCK) to eliminate race condition

    • Twitter/X: Replaced Bearer token auth with OAuth 1.0a (HMAC-SHA1) — Bearer tokens are app-only and cannot create tweets

    • service.xml: Fixed missing closing </field> tag on webhook method field

    • Views: Added missing Toolbar and Route imports in Logs, Posts, Services, Template, Templates HtmlView files

    • 13 service plugins: Fixed broken publish() methods that had literal placeholder URLs instead of using credential values — ActivityPub, Blogger, Ghost, Google Business, Hashnode, Matrix, Medium, Nostr, RSS Feed, Threads, Tumblr, WhatsApp, WordPress

    • Ghost: Proper JWT auth from {id}:{secret} admin API key format

    • WordPress: Correct Basic Auth (not Bearer) with Application Passwords

    • Medium: 2-step flow — fetch user ID via /v1/me, then post

    • Matrix: PUT with transaction ID for idempotent message sending

    • Hashnode: GraphQL mutation with proper query structure

    • Threads: 2-step container creation + publish flow

    • WhatsApp: Meta Cloud API with messaging_product payload

    • Nostr: Stub with clear "not yet implemented" message (requires WebSocket)

    • RSS Feed: Local service — no external API, always succeeds

    Added

    • ServiceIconHelper: Centralised icon mapping for all 34 service types — replaces per-template icon arrays with ServiceIconHelper::getIcon() / ::renderIcon()

    • Service Stats drill-down: New servicestats view with per-service analytics — post counts, success rate, daily trend chart, recent posts table, and top articles list

    • Dashboard service links: Service breakdown table rows now link to the per-service stats view with service type icons

    • Posts list icons: Service type column in the posts list now shows the service icon

    • Category routing rules: New #__mokojoomcross_category_rules table to whitelist services per Joomla category — if rules exist for a category, only those services receive posts; no rules = all services (backward compatible)

    • CrossPostDispatcher: Category rule filtering integrated before per-article service filter in the dispatch loop

    • Template editor: Live character counter below template body textarea with platform-aware limits (green/yellow/red badges)

    • Template editor: Added {tags}, {hashtags}, and {field:xxx} rows to the placeholder reference table

    • Content plugin: Cross-post history panel in article editor showing last 10 posts with status badges, service names, timestamps, and error messages

    • Config: New "Category Rules" fieldset with explanatory note about the feature

    • CrossPostDispatcher: New static helper (com_mokojoomcross/Helper/CrossPostDispatcher) centralising dispatch logic for reuse by all source plugins

    • Content plugin: Added onContentAfterSave and onContentChangeState handlers with Joomla 5/6 event compatibility, dispatching via CrossPostDispatcher

    • plg_system_mokojoomcross_events: New source plugin for MokoJoomCalendar — cross-posts calendar events when published

    • plg_system_mokojoomcross_gallery: New source plugin for MokoJoomGallery — cross-posts galleries and images when published

    • Credential fields: Added fields for 19 previously missing services (Pinterest, Tumblr, TikTok, Nostr, ActivityPub, Brevo, ConvertKit, Constant Contact, Hashnode, Blogger, Google Business, RSS Feed config)

    • Twitter: Access Token and Access Token Secret fields for OAuth 1.0a

    • LinkedIn: Refresh token field for automatic token renewal

    • Bluesky: PDS URL field for self-hosted instances

    • Discord: Username and avatar URL override fields

    • Mailchimp: From name and from email fields

    • SendGrid: From email and from name fields

    • Reddit: Account password field for script-type OAuth

    • WordPress: Default post status selector (draft/publish)

    • Dev.to: Organization ID field

    • Ghost: Default post status selector (draft/published)

    • Webhook: Auth type selector (none/bearer/basic), auth token field, content type selector (JSON/form)

    • RSS Feed: Feed title and max items config fields

    • OAuth services: Added Pinterest, Tumblr, TikTok, Constant Contact, Blogger, Google Business to OAuth authorize flow

    • Developer Guide: Comprehensive wiki page for building new service plugins

    • Help articles: 42 KB articles on mokoconsulting.tech (overview, installation, 34 per-service guides, templates, queue, troubleshooting)

    • Service help link: Per-service "Setup Guide" button in service edit sidebar links to the matching KB article

    • Evergreen re-sharing: Articles can be marked as evergreen for automatic recurring cross-posts on a configurable interval (default 30 days)

    • Post edit form: Full CRUD for queue posts — edit message, reschedule, change status, re-queue failed posts

    • Manual post creator: New button in Post Queue toolbar to create manual cross-posts with article/service selection, custom message, and optional scheduling

    • Scheduled posts: Calendar picker for scheduling posts to specific date/time; scheduled_at shown in queue list

    • Dashboard trend chart: Chart.js line chart showing daily posted vs failed counts between stat cards and service breakdown

    • Dashboard date range filter: Period selector (7/30/90 days, all time) filters service breakdown, top articles, and trend chart

    • Hashtag placeholders: {tags} (comma-separated) and {hashtags} (#-prefixed space-separated) template placeholders from article tags

    • Posts service filter: SQL-driven service dropdown filter in posts list, plus search filter by article title or message content

    • CSV export: "Export CSV" toolbar button on posts list to download filtered post data as CSV

    • WordPress canonical URL: WordPress cross-posts now include an "Originally published at" source link appended to content with the Joomla article URL

    • REST API dispatch endpoint: POST /api/v1/mokojoomcross/dispatch — trigger cross-posts for an article via API with optional service filtering, duplicate guard, and template rendering

    Added (original)

    Core Engine

    • Cross-posting engine dispatches articles to service plugins on publish
    • System plugin hooks onContentAfterSave and onContentChangeState
    • Duplicate guard prevents re-posting to services that already received an article
    • Message template rendering with 8 placeholders: {title}, {url}, {introtext}, {fulltext}, {image}, {category}, {author}, {date}
    • Custom mokojoomcross plugin group for extensible service architecture
    • MokoJoomCrossServiceInterface contract for all service plugins

    Admin Component (5 views)

    • Dashboard — summary cards, posts-by-service analytics with success rates, top cross-posted articles, recent activity feed, PP Pro migration banner, page-load processing warning
    • Post Queue — list with color-coded status badges, error messages, retry counts, platform post IDs, article/service columns, date filters
    • Services — CRUD with service type selector (34 platforms organized by category), default/custom mode badges, publish toggle, credential editor
    • Templates — CRUD for message templates, per-platform assignment, placeholder reference panel, template body preview
    • Activity Logs — list with level badges (info/warning/error), service column, context data, level and search filters

    Queue Processing (3 methods)

    • Joomla Scheduled Task plugin (plg_task_mokojoomcross) — preferred, processes 20 posts per run
    • Page-load fallback via system plugin onAfterRender — configurable throttle interval, backend/frontend/both
    • Shared QueueProcessor helper with DB lock to prevent concurrent execution
    • Failed post retry with configurable max retries and exponential delay
    • Scheduled post support (scheduled_at column)
    • Automatic log cleanup based on configurable retention period

    Per-Article Controls

    • "Cross-Posting" fieldset injected into article editor via onContentPrepareForm
    • Skip cross-posting toggle per article
    • Service selection checkboxes (unchecked = post to all enabled services)

    OAuth 2.0

    • OAuthHelper with authorization URL generation, code-to-token exchange, token storage
    • Twitter PKCE flow support
    • OauthController with authorize and callback endpoints
    • Reads client ID/secret from service plugin params

    Perfect Publisher Pro Migration

    • Reads #__autotweet_channels table with per-platform credential mapping
    • Fallback extraction from component params when channel table missing
    • Maps Facebook, Twitter, LinkedIn, Telegram, Discord, Slack, Mastodon
    • Creates services in disabled state for manual verification
    • One-click migration from dashboard

    Service Plugins (34 platforms)

    Social Media (12)

    • Facebook / Meta — Graph API v19.0, default MokoWaaS app mode, page feed posting
    • X / Twitter — API v2, OAuth 2.0 Bearer Token, 280 char limit
    • LinkedIn — Share API v2, organization + personal profile, 3000 char limit
    • Mastodon — API v1, multi-instance, hashtags, 500 char limit
    • Bluesky — AT Protocol, session auth, app passwords, 300 char limit
    • Threads (Meta) — Threads Publishing API, default app mode, 500 char limit
    • Pinterest — Pins API v5, board selection, image-focused
    • Reddit — OAuth2 link submission, subreddit selection
    • Tumblr — API v2, link/text posts, OAuth 1.0a
    • TikTok — Content Posting API, photo slideshows
    • Nostr — NIP-01 event publishing, configurable relays
    • ActivityPub — generic Fediverse (Pleroma, Akkoma, Misskey, Pixelfed)

    Chat / Messaging (8)

    • Telegram — Bot API, default @MokoWaaSBot + custom bot, HTML/Markdown, 4096 chars
    • Discord — Webhooks, default MokoWaaS webhook mode, embeds, 2000 chars
    • Slack — Incoming Webhooks, default MokoWaaS webhook mode, Block Kit
    • Microsoft Teams — Incoming Webhooks, default mode, Adaptive Cards
    • Google Chat — Webhook API, card formatting
    • WhatsApp Business — Meta Cloud API, template + free-form messages
    • Matrix / Element — Client-Server API, self-hosted homeserver support
    • Ntfy — Push notifications, priority levels, action buttons

    Email / Newsletter (5)

    • Mailchimp — Campaigns API, audience selection, send/draft modes
    • SendGrid — Marketing Campaigns API v3, Single Send creation
    • Brevo (Sendinblue) — API v3, campaign creation
    • ConvertKit — API v3, broadcast creation
    • Constant Contact — API v3, campaign creation

    Publishing / Blogging (6)

    • Medium — Publishing API, full HTML, canonical URL, tags
    • WordPress — REST API v2, Application Passwords, category mapping
    • Dev.to — Forem API, markdown, series support
    • Ghost — Admin API v5, JWT auth, full HTML
    • Hashnode — GraphQL API, cover image, tags
    • Google Blogger — Blogger API v3, labels from categories

    Business (1)

    • Google Business Profile — API v1, local posts (UPDATE/EVENT/OFFER)

    Universal (2)

    • Generic Webhook — POST/PUT to any URL, JSON/form body, custom headers (IFTTT, Zapier, n8n, Make)
    • RSS Feed — dedicated cross-post feed generation

    Plugin Configuration

    • Telegram: default bot token, parse mode, link preview toggle
    • Facebook: default page access token, default page ID
    • Discord: default webhook URL, embed color
    • Slack: default webhook URL
    • LinkedIn: OAuth client ID/secret, redirect URI
    • Mastodon: default instance URL, visibility, hashtags
    • Bluesky: default PDS URL, auto link cards
    • Mailchimp: default sender name/email, auto-send toggle
    • Microsoft Teams: default webhook URL
    • Threads: default webhook URL

    Infrastructure

    • 7 CI/CD workflows: CI, auto-release, pre-release, auto-bump, update-server, cascade-dev, issue-branch
    • Joomla update server (updates.xml) with development channel
    • WebServices REST API plugin with CRUD routes for posts and services
    • Database: 4 tables (services, posts, templates, logs) with default templates
    • Package installer with auto-enable for core + task + service plugins
    • 9 wiki documentation pages
    • Windows Terminal profile in Joomla dropdown
    Downloads