From 7591b10219222f818d523f457fa6d01e1891260b Mon Sep 17 00:00:00 2001
From: sysadminstory
Date: Tue, 22 Aug 2023 20:44:36 +0200
Subject: [PATCH] [Core] New feature : User Interface to "Detect" Feed from an
URL (#3436)
* [Core] New feature : User Interface to "Detect" Feed from an URL
Detect Action has been expanded to support returning a Feed in a JSON
format instead of a Redirect. Existing usage of the Detect action will
keep working as usual.
Frontpage template has now a section to display the Feed detection
result, and a button to start the Feed Detection.
A new JS file contains the necessary JS (Ajax and Event management) to
fill the Feed Detection section.
* Coding policy fixes
* [Core] New feature : User Interface to "Detect" Feed from an URL
- Switch from old school XMLHttpRequest to fetch
- Enhance UX of search results
- Revert to it's original content
- Switch to a new Action : FindfeedAction.php
- Switch to template literals instead of string concatenation
- FindFeed action could retrun multiple feeds
- Results are sent with an absolute URL
- Switch to Json::encode() helper function
* [Core] New feature : User Interface to "Detect" Feed from an URL
- Move specific JS code to rss-bridge.js
- Change HTML tag for the button to have a consistant style with th rest
of the page
* [Core] New feature : User Interface to "Detect" Feed from an URL
- If no context is sent, assume there is only one unnamed context
- Find parameter name in global and currect context
* fix
* remove typo
---------
Co-authored-by: Dag
---
actions/FindfeedAction.php | 89 ++++++++++++++++++++++++++++++++++++
static/rss-bridge.js | 79 ++++++++++++++++++++++++++++++++
static/style.css | 35 ++++++++++++++
templates/frontpage.html.php | 9 ++++
4 files changed, 212 insertions(+)
create mode 100644 actions/FindfeedAction.php
diff --git a/actions/FindfeedAction.php b/actions/FindfeedAction.php
new file mode 100644
index 00000000..25fe4714
--- /dev/null
+++ b/actions/FindfeedAction.php
@@ -0,0 +1,89 @@
+getBridgeClassNames() as $bridgeClassName) {
+ if (!$bridgeFactory->isEnabled($bridgeClassName)) {
+ continue;
+ }
+
+ $bridge = $bridgeFactory->create($bridgeClassName);
+
+ $bridgeParams = $bridge->detectParameters($targetURL);
+
+ if ($bridgeParams === null) {
+ continue;
+ }
+
+ // It's allowed to have no 'context' in a bridge (only a default context without any name)
+ // In this case, the reference to the parameters are found in the first element of the PARAMETERS array
+
+ $context = $bridgeParams['context'] ?? 0;
+
+ $bridgeData = [];
+ // Construct the array of parameters
+ foreach ($bridgeParams as $key => $value) {
+ // 'context' is a special case : it's a bridge parameters, there is no "name" for this parameter
+ if ($key == 'context') {
+ $bridgeData[$key]['name'] = 'Context';
+ $bridgeData[$key]['value'] = $value;
+ } else {
+ $bridgeData[$key]['name'] = $this->getParameterName($bridge, $context, $key);
+ $bridgeData[$key]['value'] = $value;
+ }
+ }
+
+ $bridgeParams['bridge'] = $bridgeClassName;
+ $bridgeParams['format'] = $format;
+ $content = [
+ 'url' => get_home_page_url() . '?action=display&' . http_build_query($bridgeParams),
+ 'bridgeParams' => $bridgeParams,
+ 'bridgeData' => $bridgeData,
+ 'bridgeMeta' => [
+ 'name' => $bridge::NAME,
+ 'description' => $bridge::DESCRIPTION,
+ 'parameters' => $bridge::PARAMETERS,
+ 'icon' => $bridge->getIcon(),
+ ],
+ ];
+ $results[] = $content;
+ }
+ if ($results === []) {
+ return new Response(Json::encode(['message' => 'No bridge found for given url']), 404, ['content-type' => 'application/json']);
+ }
+ return new Response(Json::encode($results), 200, ['content-type' => 'application/json']);
+ }
+
+ // Get parameter name in the actual context, or in the global parameter
+ private function getParameterName($bridge, $context, $key)
+ {
+ if (isset($bridge::PARAMETERS[$context][$key]['name'])) {
+ $name = $bridge::PARAMETERS[$context][$key]['name'];
+ } else if (isset($bridge::PARAMETERS['global'][$key]['name'])) {
+ $name = $bridge::PARAMETERS['global'][$key]['name'];
+ } else {
+ $name = 'Variable "' . $key . '" (No name provided)';
+ }
+ return $name;
+ }
+}
diff --git a/static/rss-bridge.js b/static/rss-bridge.js
index 498acd37..82069d8c 100644
--- a/static/rss-bridge.js
+++ b/static/rss-bridge.js
@@ -47,3 +47,82 @@ function rssbridge_toggle_bridge(){
bridge.getElementsByClassName('showmore-box')[0].checked = true;
}
}
+
+var rssbridge_feed_finder = (function() {
+ /*
+ * Code for "Find feed by URL" feature
+ */
+
+ // Start the Feed search
+ async function rssbridge_feed_search(event) {
+ const input = document.getElementById('searchfield');
+ let content = input.value;
+ if (content) {
+ const findfeedresults = document.getElementById('findfeedresults');
+ findfeedresults.innerHTML = 'Searching for matching feeds ...';
+ let baseurl = window.location.protocol + window.location.pathname;
+ let url = baseurl + '?action=findfeed&format=Html&url=' + content;
+ const response = await fetch(url);
+ if (response.ok) {
+ const data = await response.json();
+ rss_bridge_feed_display_found_feed(data);
+ } else {
+ rss_bridge_feed_display_feed_search_fail();
+ }
+ } else {
+ rss_bridge_feed_display_find_feed_empty();
+ }
+ }
+
+ // Display the found feeds
+ function rss_bridge_feed_display_found_feed(obj) {
+ const findfeedresults = document.getElementById('findfeedresults');
+
+ let content = 'Found Feed(s) :';
+
+ // Let's go throug every Feed found
+ for (const element of obj) {
+ content += `
This feed may be only one of the possible feeds. You may find more feeds using one of the bridges with different parameters, for example.
';
+ findfeedresults.innerHTML = content;
+ }
+
+ // Display an error if no feed were found
+ function rss_bridge_feed_display_feed_search_fail() {
+ const findfeedresults = document.getElementById('findfeedresults');
+ findfeedresults.innerHTML = 'No Feed found !
Not every bridge supports feed detection. You can check below within the bridge parameters to create a feed.