/** * Pleroma to Mastodon API Response Adapter * * This script intercepts fetch requests to Pleroma instances and adapts * the responses to match the structure expected by mastodon-timeline.umd.js */ (function() { 'use strict'; // Store original fetch const originalFetch = window.fetch; // Override fetch globally window.fetch = async function(...args) { const response = await originalFetch.apply(this, args); // Only intercept Pleroma API timeline and emoji requests const url = args[0]; if (typeof url === 'string' && (url.includes('/api/v1/timelines/') || url.includes('/api/v1/accounts/') && url.includes('/statuses'))) { // Clone the response so we can modify it const clonedResponse = response.clone(); try { const data = await clonedResponse.json(); // Adapt the response structure const adaptedData = Array.isArray(data) ? data.map(adaptPost) : adaptPost(data); // Create a new response with adapted data return new Response(JSON.stringify(adaptedData), { status: response.status, statusText: response.statusText, headers: response.headers }); } catch (error) { console.warn('Pleroma adapter: Failed to parse response, returning original', error); return response; } } return response; }; /** * Adapt a single Pleroma post to Mastodon format */ function adaptPost(post) { if (!post || typeof post !== 'object') { return post; } // Create a copy to avoid mutating the original const adapted = { ...post }; // Adapt media attachments if (adapted.media_attachments && Array.isArray(adapted.media_attachments)) { adapted.media_attachments = adapted.media_attachments.map(adaptMediaAttachment); } // Adapt reblog if present if (adapted.reblog) { adapted.reblog = adaptPost(adapted.reblog); } return adapted; } /** * Adapt media attachment to include missing meta fields */ function adaptMediaAttachment(attachment) { if (!attachment || typeof attachment !== 'object') { return attachment; } // If meta already exists and has required fields, return as-is if (attachment.meta?.original?.width && attachment.meta?.small?.aspect) { return attachment; } // Create adapted attachment const adapted = { ...attachment }; // Default dimensions (will work for most cases) const defaultWidth = 1280; const defaultHeight = 720; const defaultAspect = defaultWidth / defaultHeight; // Try to extract dimensions from Pleroma's meta if available let width = defaultWidth; let height = defaultHeight; if (attachment.pleroma?.mime_type) { // For videos, use 16:9 ratio if (attachment.pleroma.mime_type.startsWith('video/')) { width = 1920; height = 1080; } // For images, use standard web dimensions else if (attachment.pleroma.mime_type.startsWith('image/')) { width = 1200; height = 800; } } // Ensure meta structure exists adapted.meta = adapted.meta || {}; // Add original dimensions adapted.meta.original = adapted.meta.original || { width: width, height: height, aspect: width / height }; // Add small (preview) dimensions adapted.meta.small = adapted.meta.small || { width: Math.floor(width / 2), height: Math.floor(height / 2), aspect: width / height }; return adapted; } console.log('Pleroma adapter initialized: API responses will be adapted for Mastodon compatibility'); })();