From 794f971b731f4fa875272bb6c81c3761d6e99ab5 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Mon, 16 Feb 2026 23:37:38 +0000 Subject: [PATCH] Autosave: 20260216-233738 --- api_v1_rss.php | 61 ++++++++++++++++++++++++++++++++++++++++++----- assets/js/main.js | 31 ++++++++++++++++++++++++ debug_reorder.log | 2 ++ index.php | 15 ++++++++++-- requests.log | 30 +++++++++++++++++++++++ 5 files changed, 131 insertions(+), 8 deletions(-) diff --git a/api_v1_rss.php b/api_v1_rss.php index 5871032..497df23 100644 --- a/api_v1_rss.php +++ b/api_v1_rss.php @@ -40,11 +40,29 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } if ($action === 'sync') { + // Cooldown check: only sync if last sync was > 5 minutes ago + // Or if it's a forced sync from the settings UI + $is_auto = isset($_POST['auto']) && $_POST['auto'] == 1; + // Fetch feeds for this channel $stmt = db()->prepare("SELECT * FROM channel_rss_feeds WHERE channel_id = ?"); $stmt->execute([$channel_id]); $feeds = $stmt->fetchAll(); + if ($is_auto) { + $last_fetch = 0; + foreach ($feeds as $f) { + if ($f['last_fetched_at']) { + $ts = strtotime($f['last_fetched_at']); + if ($ts > $last_fetch) $last_fetch = $ts; + } + } + if (time() - $last_fetch < 300) { // 5 minutes + echo json_encode(['success' => true, 'new_items' => 0, 'skipped' => true]); + exit; + } + } + $new_items_count = 0; foreach ($feeds as $feed) { $rss_content = @file_get_contents($feed['url']); @@ -66,31 +84,62 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $link = (string)($item->link['href'] ?? $item->link); $description = strip_tags((string)($item->description ?? $item->summary)); + // Extract additional fields + $category = (string)($item->category ?? ($item->category['term'] ?? '')); + $pubDate = (string)($item->pubDate ?? ($item->published ?? ($item->updated ?? ''))); + + // Format date nicely if possible + if ($pubDate) { + $timestamp = strtotime($pubDate); + if ($timestamp) { + $pubDate = date('d/m/Y H:i', $timestamp); + } + } + + $author = (string)($item->author->name ?? ($item->author ?? '')); + if (!$author) { + $dc = $item->children('http://purl.org/dc/elements/1.1/'); + if (isset($dc->creator)) { + $author = (string)$dc->creator; + } + } + // Check if already exists $stmt_check = db()->prepare("SELECT id FROM messages WHERE channel_id = ? AND rss_guid = ?"); $stmt_check->execute([$channel_id, $guid]); if ($stmt_check->fetch()) continue; // Insert as message from a special "RSS Bot" user or system - // Let's find or create an RSS Bot user $stmt_bot = db()->prepare("SELECT id FROM users WHERE username = 'RSS Bot' AND is_bot = 1"); $stmt_bot->execute(); $bot = $stmt_bot->fetch(); if (!$bot) { - $stmt_create_bot = db()->prepare("INSERT INTO users (username, is_bot, status) VALUES ('RSS Bot', 1, 'online')"); + $stmt_create_bot = db()->prepare("INSERT INTO users (username, is_bot, status, avatar_url, email, password_hash) VALUES ('RSS Bot', 1, 'online', 'https://cdn-icons-png.flaticon.com/512/3607/3607436.png', 'rss-bot@system.internal', 'bot-no-password')"); $stmt_create_bot->execute(); $bot_id = db()->lastInsertId(); } else { $bot_id = $bot['id']; } - $content = "**" . $title . "**\n" . $description . "\n" . $link; + // Format content for traditional view + $content = "[" . $title . "](" . $link . ")\n"; + if ($category || $pubDate || $author) { + $parts = []; + if ($category) $parts[] = $category; + if ($pubDate) $parts[] = $pubDate; + if ($author) $parts[] = $author; + $content .= implode(" · ", $parts) . "\n"; + } + $content .= $description; - // For announcements, we might want to use metadata for a rich embed $metadata = json_encode([ 'title' => $title, - 'description' => mb_substr($description, 0, 200) . (mb_strlen($description) > 200 ? '...' : ''), + 'description' => mb_substr($description, 0, 500) . (mb_strlen($description) > 500 ? '...' : ''), 'url' => $link, + 'category' => $category, + 'date' => $pubDate, + 'author' => $author, + 'is_rss' => true, 'site_name' => parse_url($feed['url'], PHP_URL_HOST) ]); @@ -103,7 +152,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $stmt_update_feed->execute([$feed['id']]); } - echo json_encode(['success' => true, 'new_items' => $new_items_count]); + echo json_encode(['success' => true, 'new_items' => $new_items_count, 'channel_id' => $channel_id]); exit; } } else { diff --git a/assets/js/main.js b/assets/js/main.js index 053a8e4..a531286 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1408,6 +1408,37 @@ document.addEventListener('DOMContentLoaded', () => { } }); + // Auto-sync for announcement channels + if (window.activeChannelId) { + const autoSyncRss = async () => { + // Check if we are in an announcement channel + // We can look for the bullhorn icon in the header + const headerIcon = document.querySelector('.main-header i.fa-bullhorn'); + if (headerIcon) { + const formData = new FormData(); + formData.append('action', 'sync'); + formData.append('channel_id', window.activeChannelId); + formData.append('auto', '1'); + try { + const resp = await fetch('api_v1_rss.php', { method: 'POST', body: formData }); + const data = await resp.json(); + if (data.success && data.new_items > 0) { + // If new items were found, we might want to refresh the message list + // but only if we are still on the same channel + if (window.activeChannelId == data.channel_id) { + // For now, we don't reload automatically to avoid interrupting the user + // The new messages will appear on next reload or polling if implemented + } + } + } catch (e) { } + } + }; + // Initial sync + setTimeout(autoSyncRss, 2000); + // Periodic sync every 2 minutes + setInterval(autoSyncRss, 120000); + } + // Clear Channel History const clearHistoryBtn = document.getElementById('clear-channel-history-btn'); clearHistoryBtn?.addEventListener('click', async () => { diff --git a/debug_reorder.log b/debug_reorder.log index 3ad33af..586fe4a 100644 --- a/debug_reorder.log +++ b/debug_reorder.log @@ -13,3 +13,5 @@ 2026-02-16 03:08:33 - Server: 1 - Orders: [{"id":"11","position":0,"category_id":null},{"id":"17","position":1,"category_id":null},{"id":"12","position":2,"category_id":null},{"id":"10","position":3,"category_id":null},{"id":"1","position":4,"category_id":"10"},{"id":"6","position":5,"category_id":"10"},{"id":"15","position":6,"category_id":"10"},{"id":"2","position":7,"category_id":"10"},{"id":"14","position":8,"category_id":null},{"id":"13","position":9,"category_id":null},{"id":"9","position":10,"category_id":null},{"id":"3","position":11,"category_id":null}] 2026-02-16 03:09:18 - Server: 1 - Orders: [{"id":"11","position":0,"category_id":null},{"id":"17","position":1,"category_id":null},{"id":"12","position":2,"category_id":null},{"id":"10","position":3,"category_id":null},{"id":"1","position":4,"category_id":"10"},{"id":"6","position":5,"category_id":"10"},{"id":"15","position":6,"category_id":"10"},{"id":"2","position":7,"category_id":"10"},{"id":"18","position":8,"category_id":"10"},{"id":"14","position":9,"category_id":null},{"id":"13","position":10,"category_id":null},{"id":"9","position":11,"category_id":null},{"id":"3","position":12,"category_id":null}] 2026-02-16 18:43:44 - Server: 1 - Orders: [{"id":"11","position":0,"category_id":null},{"id":"17","position":1,"category_id":null},{"id":"12","position":2,"category_id":null},{"id":"19","position":3,"category_id":null},{"id":"10","position":4,"category_id":null},{"id":"1","position":5,"category_id":"10"},{"id":"6","position":6,"category_id":"10"},{"id":"15","position":7,"category_id":"10"},{"id":"2","position":8,"category_id":"10"},{"id":"18","position":9,"category_id":"10"},{"id":"14","position":10,"category_id":null},{"id":"13","position":11,"category_id":null},{"id":"9","position":12,"category_id":null},{"id":"3","position":13,"category_id":null}] +2026-02-16 23:37:00 - Server: 1 - Orders: [{"id":"11","position":0,"category_id":null},{"id":"12","position":1,"category_id":null},{"id":"17","position":2,"category_id":null},{"id":"19","position":3,"category_id":null},{"id":"10","position":4,"category_id":null},{"id":"1","position":5,"category_id":"10"},{"id":"6","position":6,"category_id":"10"},{"id":"15","position":7,"category_id":"10"},{"id":"2","position":8,"category_id":"10"},{"id":"18","position":9,"category_id":"10"},{"id":"14","position":10,"category_id":null},{"id":"13","position":11,"category_id":null},{"id":"9","position":12,"category_id":null},{"id":"3","position":13,"category_id":null}] +2026-02-16 23:37:02 - Server: 1 - Orders: [{"id":"11","position":0,"category_id":null},{"id":"17","position":1,"category_id":null},{"id":"12","position":2,"category_id":null},{"id":"19","position":3,"category_id":null},{"id":"10","position":4,"category_id":null},{"id":"1","position":5,"category_id":"10"},{"id":"6","position":6,"category_id":"10"},{"id":"15","position":7,"category_id":"10"},{"id":"2","position":8,"category_id":"10"},{"id":"18","position":9,"category_id":"10"},{"id":"14","position":10,"category_id":null},{"id":"13","position":11,"category_id":null},{"id":"9","position":12,"category_id":null},{"id":"3","position":13,"category_id":null}] diff --git a/index.php b/index.php index d4fcae6..b263d37 100644 --- a/index.php +++ b/index.php @@ -867,11 +867,22 @@ $emote_html = '' . htmlspe
                                     $meta = json_decode($m['metadata'], true);
                                     if ($meta): ?>
                                     <div class= - +
- + + + +
+ +
diff --git a/requests.log b/requests.log index acf0581..fa08195 100644 --- a/requests.log +++ b/requests.log @@ -369,3 +369,33 @@ 2026-02-16 23:05:15 - GET /index.php?server_id=1&channel_id=6 - POST: [] 2026-02-16 23:05:29 - GET /index.php?server_id=1&channel_id=6 - POST: [] 2026-02-16 23:13:30 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:18:05 - GET /?fl_project=38443 - POST: [] +2026-02-16 23:18:47 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:26:02 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:26:50 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:27:48 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:28:42 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:28:44 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:30:14 - GET /?fl_project=38443 - POST: [] +2026-02-16 23:30:27 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:31:15 - GET /index.php?server_id=1&channel_id=17 - POST: [] +2026-02-16 23:31:17 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:31:45 - GET /index.php?server_id=1&channel_id=17 - POST: [] +2026-02-16 23:31:46 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:32:05 - GET /index.php?server_id=1&channel_id=17 - POST: [] +2026-02-16 23:32:07 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:32:49 - GET /index.php?server_id=1&channel_id=1 - POST: [] +2026-02-16 23:32:53 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:33:23 - GET /index.php?server_id=1&channel_id=17 - POST: [] +2026-02-16 23:33:24 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:33:50 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:34:25 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:34:50 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:34:54 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:35:43 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:35:58 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:36:07 - GET /index.php?server_id=1&channel_id=17 - POST: [] +2026-02-16 23:36:08 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:36:54 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:37:08 - GET /index.php?server_id=1&channel_id=12 - POST: [] +2026-02-16 23:37:26 - GET /index.php?server_id=1&channel_id=12 - POST: []