- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_API/FeedExpander.html b/Bridge_API/FeedExpander.html
index 7ca146063ff..f7f67c7e376 100644
--- a/Bridge_API/FeedExpander.html
+++ b/Bridge_API/FeedExpander.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_API/How_to_create_a_new_bridge.html b/Bridge_API/How_to_create_a_new_bridge.html
index fa404a1ae88..4e8bf9ad7ae 100644
--- a/Bridge_API/How_to_create_a_new_bridge.html
+++ b/Bridge_API/How_to_create_a_new_bridge.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_API/WebDriverAbstract.html b/Bridge_API/WebDriverAbstract.html
index 5831e8d8ee7..8bf5566cb7e 100644
--- a/Bridge_API/WebDriverAbstract.html
+++ b/Bridge_API/WebDriverAbstract.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_API/XPathAbstract.html b/Bridge_API/XPathAbstract.html
index 6a18b4c3fe8..f80e578b5a7 100644
--- a/Bridge_API/XPathAbstract.html
+++ b/Bridge_API/XPathAbstract.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_API/index.html b/Bridge_API/index.html
index f7c620a3a5d..507007c3bbd 100644
--- a/Bridge_API/index.html
+++ b/Bridge_API/index.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_Specific/ActivityPub_(Mastodon).html b/Bridge_Specific/ActivityPub_(Mastodon).html
index 5da34a0f4c9..7404db57549 100644
--- a/Bridge_Specific/ActivityPub_(Mastodon).html
+++ b/Bridge_Specific/ActivityPub_(Mastodon).html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_Specific/FacebookBridge.html b/Bridge_Specific/FacebookBridge.html
index 3992095318f..0e579a397b2 100644
--- a/Bridge_Specific/FacebookBridge.html
+++ b/Bridge_Specific/FacebookBridge.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_Specific/FurAffinityBridge.html b/Bridge_Specific/FurAffinityBridge.html
index ba5283eefeb..fb316dbc92f 100644
--- a/Bridge_Specific/FurAffinityBridge.html
+++ b/Bridge_Specific/FurAffinityBridge.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_Specific/Furaffinityuser.html b/Bridge_Specific/Furaffinityuser.html
index c3f83fcc2c7..bf03053d37f 100644
--- a/Bridge_Specific/Furaffinityuser.html
+++ b/Bridge_Specific/Furaffinityuser.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_Specific/Instagram.html b/Bridge_Specific/Instagram.html
index fb0bf6e54c2..f9f894a73c2 100644
--- a/Bridge_Specific/Instagram.html
+++ b/Bridge_Specific/Instagram.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_Specific/PixivBridge.html b/Bridge_Specific/PixivBridge.html
index 9036fa15c04..15ad86dafa0 100644
--- a/Bridge_Specific/PixivBridge.html
+++ b/Bridge_Specific/PixivBridge.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_Specific/TwitterV2.html b/Bridge_Specific/TwitterV2.html
index 23776c0a7e7..c3c85f392cc 100644
--- a/Bridge_Specific/TwitterV2.html
+++ b/Bridge_Specific/TwitterV2.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Bridge_Specific/Vk2.html b/Bridge_Specific/Vk2.html
index d6272bd2f05..8e168b5577f 100644
--- a/Bridge_Specific/Vk2.html
+++ b/Bridge_Specific/Vk2.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/CLI/index.html b/CLI/index.html
index a7128a7a49f..ddf4f039f99 100644
--- a/CLI/index.html
+++ b/CLI/index.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Cache_API/CacheInterface.html b/Cache_API/CacheInterface.html
index 1cc78045763..10c26a74014 100644
--- a/Cache_API/CacheInterface.html
+++ b/Cache_API/CacheInterface.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Cache_API/How_to_create_a_new_cache.html b/Cache_API/How_to_create_a_new_cache.html
index 031b9319d96..7cb31bdf0c5 100644
--- a/Cache_API/How_to_create_a_new_cache.html
+++ b/Cache_API/How_to_create_a_new_cache.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Cache_API/index.html b/Cache_API/index.html
index ece36e956c7..ef71c839630 100644
--- a/Cache_API/index.html
+++ b/Cache_API/index.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Developers/Actions.html b/For_Developers/Actions.html
index b19e4376b77..d00f7508281 100644
--- a/For_Developers/Actions.html
+++ b/For_Developers/Actions.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Developers/Coding_style_policy.html b/For_Developers/Coding_style_policy.html
index e6e2dd95e4b..cea8dc26cb7 100644
--- a/For_Developers/Coding_style_policy.html
+++ b/For_Developers/Coding_style_policy.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Developers/Debug_mode.html b/For_Developers/Debug_mode.html
index e83d6db275d..f274ba6e0f9 100644
--- a/For_Developers/Debug_mode.html
+++ b/For_Developers/Debug_mode.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Developers/Development_Environment_Setup.html b/For_Developers/Development_Environment_Setup.html
index abe4cc42349..60c6b765d59 100644
--- a/For_Developers/Development_Environment_Setup.html
+++ b/For_Developers/Development_Environment_Setup.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Developers/Folder_structure.html b/For_Developers/Folder_structure.html
index b375673e20f..202b890c473 100644
--- a/For_Developers/Folder_structure.html
+++ b/For_Developers/Folder_structure.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Developers/Github_Codespaces_Tutorial.html b/For_Developers/Github_Codespaces_Tutorial.html
index a4e784bf2bc..aaf8e30a602 100644
--- a/For_Developers/Github_Codespaces_Tutorial.html
+++ b/For_Developers/Github_Codespaces_Tutorial.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Developers/Pull_Request_policy.html b/For_Developers/Pull_Request_policy.html
index 96705535b30..50ad3036313 100644
--- a/For_Developers/Pull_Request_policy.html
+++ b/For_Developers/Pull_Request_policy.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Developers/index.html b/For_Developers/index.html
index 5e6ea81e997..6638791038d 100644
--- a/For_Developers/index.html
+++ b/For_Developers/index.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Hosts/Authentication.html b/For_Hosts/Authentication.html
index ca455028b62..674e52277f6 100644
--- a/For_Hosts/Authentication.html
+++ b/For_Hosts/Authentication.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Hosts/Custom_Configuration.html b/For_Hosts/Custom_Configuration.html
index d0e48d3aa69..2197ed2cd7e 100644
--- a/For_Hosts/Custom_Configuration.html
+++ b/For_Hosts/Custom_Configuration.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Hosts/Customizations.html b/For_Hosts/Customizations.html
index c16505405a8..0c82c8316ed 100644
--- a/For_Hosts/Customizations.html
+++ b/For_Hosts/Customizations.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Hosts/Docker_Installation.html b/For_Hosts/Docker_Installation.html
index 7ca83ffff86..211fdf75664 100644
--- a/For_Hosts/Docker_Installation.html
+++ b/For_Hosts/Docker_Installation.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Hosts/Heroku_Installation.html b/For_Hosts/Heroku_Installation.html
index 344ad8059f1..71a6fa87ed7 100644
--- a/For_Hosts/Heroku_Installation.html
+++ b/For_Hosts/Heroku_Installation.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Hosts/Installation.html b/For_Hosts/Installation.html
index 73a5576dabb..689b061390b 100644
--- a/For_Hosts/Installation.html
+++ b/For_Hosts/Installation.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Hosts/Updating.html b/For_Hosts/Updating.html
index ef9d7779c57..c1cab547b06 100644
--- a/For_Hosts/Updating.html
+++ b/For_Hosts/Updating.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Hosts/Whitelisting.html b/For_Hosts/Whitelisting.html
index 5ed900e649b..b513085bd10 100644
--- a/For_Hosts/Whitelisting.html
+++ b/For_Hosts/Whitelisting.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/For_Hosts/index.html b/For_Hosts/index.html
index 982663f4db3..55f7c65ca83 100644
--- a/For_Hosts/index.html
+++ b/For_Hosts/index.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/General/Contribute.html b/General/Contribute.html
index 7f4444d6b54..40642de4b1d 100644
--- a/General/Contribute.html
+++ b/General/Contribute.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/General/FAQ.html b/General/FAQ.html
index 53cfde77d1e..8e327d5e950 100644
--- a/General/FAQ.html
+++ b/General/FAQ.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/General/Project_goals.html b/General/Project_goals.html
index b782f697f74..cda69939b85 100644
--- a/General/Project_goals.html
+++ b/General/Project_goals.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/General/Public_Hosts.html b/General/Public_Hosts.html
index 8a0736b151e..814da8e210c 100644
--- a/General/Public_Hosts.html
+++ b/General/Public_Hosts.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/General/Screenshots.html b/General/Screenshots.html
index 212e32fd443..e1f5ad579b9 100644
--- a/General/Screenshots.html
+++ b/General/Screenshots.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Helper_functions/index.html b/Helper_functions/index.html
index e44c54742f3..5c306e87a32 100644
--- a/Helper_functions/index.html
+++ b/Helper_functions/index.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/Technical_recommendations/index.html b/Technical_recommendations/index.html
index a58066e10bb..3d934bdb7cd 100644
--- a/Technical_recommendations/index.html
+++ b/Technical_recommendations/index.html
@@ -100,7 +100,7 @@
- April 4, 2024 at 10:29 AM
+ April 13, 2024 at 6:59 AM
Edit on GitHub
diff --git a/daux_search_index.js b/daux_search_index.js
index 66c2468da7b..61e749ebf6f 100644
--- a/daux_search_index.js
+++ b/daux_search_index.js
@@ -1 +1 @@
-load_search_index({"pages":[{"title":"RSS-Bridge","text":"RSS-Bridge is a web application. It generates web feeds for websites that don\u2019t have one. Officially hosted instance: https:\/\/rss-bridge.org\/bridge01\/ You want to know more about RSS-Bridge? Check out our project goals. You want to contribute and don\u2019t know how? Check out our How can I contribute? section. You are a developer and searching for more details? Check out our For developers section. You want to know what is required to host RSS-Bridge? Check out the Requirements section. You want to host RSS-Bridge? Check out the For hosts section. You have questions? Check out the FAQ.","tags":"","url":"index.html"},{"title":"Project-goals","text":"RSS-Bridge aims at sites that: don\u2019t provide public accessible Atom or RSS feeds force their users to subscribe to e-mail notifications force their users to use their own proprietary APIs require their users to come back on a regular basis in order to check for new content RSS-Bridge will generate feeds based on \u201cbridges\u201d that are developed for any site. Those bridges will collect data and extract all necessary information which is then converted into various feed formats like Atom or RSS.","tags":"","url":"General\/Project_goals.html"},{"title":"Contribute","text":"There are many things you can do to contribute to RSS-Bridge as developer or as user without any knowledge in PHP or (web) development. Here are a few things: Share RSS-Bridge with your friends (Twitter, Facebook, \u2026you name it\u2026) Report broken bridges or bugs here Request new features or propose ideas (via Issues) Discuss bugs, features, ideas or issues Add new bridges or improve the API Improve this documentation Host RSS-Bridge","tags":"","url":"General\/Contribute.html"},{"title":"Requirements","text":"RSS-Bridge requires either of the following: #A Web server* with: PHP 7.4 (or higher) openssl extension libxml extension (enabled by default, see PHP Manual) mbstring extension simplexml extension curl extension json extension filter extension zip (for some bridges) sqlite3 extension (only when using SQLiteCache) Enable extensions by un-commenting the corresponding line in your PHP configuration (php.ini). #A Linux server with: Docker server configured (Any recent version should do) 100MB of disk space To setup RSS Bridge using Docker, see the Docker Guide on installing RSS Bridge.","tags":"","url":"General\/Requirements.html"},{"title":"Screenshots","text":"#Welcome screen: #rss-bridge hashtag (#rss-bridge) search on Twitter: in Atom format (as displayed by Firefox)","tags":"","url":"General\/Screenshots.html"},{"title":"FAQ","text":"This page provides a collection of frequently asked questions and their answers. Please check this page before opening a new Issue :revolving_hearts: Why doesn\u2019t my bridge show new contents? How can I make a bridge update more frequently? Firefox doesn\u2019t show feeds anymore, what can I do? #Why doesn\u2019t my bridge show new contents? RSS-Bridge creates a cached version of your feed in order to reduce traffic and respond faster. The cached version is created on the first request and served for all subsequent requests. On every request RSS-Bridge checks if the cache timeout has elapsed. If the timeout has elapsed, it loads new contents and updates the cached version. Notice: RSS-Bridge only updates feeds if you actively request it, for example by pressing F5 in your browser or using a feed reader. The cache duration is bridge specific and can last anywhere between five minutes and 24 hours. You can specify a custom cache timeout for each bridge if this option has been enabled on the server. #How can I make a bridge update more frequently? You can only do that if you are hosting the RSS-Bridge instance: Enable custom_timeout Alternatively, change the default timeout for your bridge by modifying the CACHE_TIMEOUT constant in the relevant bridge file (e.g here for the Filter Bridge). #Firefox doesn\u2019t show feeds anymore, what can I do? As of version 64, Firefox removed support for viewing Atom and RSS feeds in the browser. This results in the browser downloading the pages instead of showing contents. Further reading: https:\/\/support.mozilla.org\/en-US\/kb\/feed-reader-replacements-firefox https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=1477667 To restore the original behavior in Firefox 64 or higher you can use following Add-on which attempts to recreate the original behavior (with some sugar on top): https:\/\/addons.mozilla.org\/en-US\/firefox\/addon\/rsspreview\/","tags":"","url":"General\/FAQ.html"},{"title":"Public Hosts","text":"#Public instances Country Address Status Contact Comment https:\/\/rss-bridge.org\/bridge01 @dvikan London, Digital Ocean https:\/\/rssbridge.flossboxin.org.in\/ @vdbhb59 Hosted with OVH SAS (Maintained in India) https:\/\/rss-bridge.cheredeprince.net\/ @La_B\u00e9casse Self-Hosted at home in France https:\/\/rss-bridge.sans-nuage.fr @Alsace R\u00e9seau Neutre Hosted in Alsace, France https:\/\/rss-bridge.lewd.tech @Erisa Hosted in London, protected by Cloudflare Rate Limiting https:\/\/bridge.easter.fr @chatainsim Hosted in Is\u00e8re, France https:\/\/wtf.roflcopter.fr\/rss-bridge\/ roflcopter.fr Hosted in France https:\/\/rss.nixnet.services @amolith Hosted in Wunstorf, Germany https:\/\/rss-bridge.ggc-project.de @ggc-project.de Hosted in Steyr, Austria https:\/\/rssbridge.bus-hit.me @austinhuang0131 Hosted with Oracle in Qu\u00e9bec, Canada https:\/\/feeds.proxeuse.com Proxeuse Hosted in Germany https:\/\/rssbridge.boldair.dev @Boldairdev Latest Github release, Hosted on PHP 8.0 in Roubaix, France https:\/\/rss-bridge.bb8.fun @captn3m0 Hosted in Bengaluru, India https:\/\/ololbu.ru\/rss-bridge @Ololbu Hosted in Moscow, Russia https:\/\/tools.bheil.net\/rss-bridge\/ @bheil Hosted in Germany https:\/\/bridge.suumitsu.eu @mitsukarenai Hosted in Paris, France https:\/\/feed.eugenemolotov.ru @em92 Hosted in Amsterdam, Netherlands https:\/\/rss-bridge.mediani.de @sokai Hosted with Netcup, Germany https:\/\/rss.foxhaven.cyou @Aysilu Hosted with Timeweb (Maintained in Poland) https:\/\/rss.m3wz.su @m3oweezed Poland, Hosted with Timeweb Cloud https:\/\/rb.ash.fail @ash Hosted with Hostaris, Germany https:\/\/rss.noleron.com @ihor Hosted with Hosting Ukraine, Ukraine #Inactive instances Country Address Status Contact Comment https:\/\/rss-bridge.snopyta.org @Perflyst Hosted in Helsinki, Finland http:\/\/rb.vern.cc\/ @vern.cc Hosted with Hetzner, US","tags":"","url":"General\/Public_Hosts.html"},{"title":"CLI","text":"RSS-Bridge supports calls via CLI. You can use the same parameters as you would normally use via the URI. Example: php index.php action=display bridge=DansTonChat format=Json #Required parameters RSS-Bridge requires a few parameters that must be specified on every call. Omitting these parameters will result in error messages: #action Defines how RSS-Bridge responds to the request. Value Description action=list Returns a JSON formatted list of bridges. Other parameters are ignored. action=display Returns (displays) a feed. #bridge This parameter specifies the name of the bridge RSS-Bridge should return feeds from. The name of the bridge equals the class name of the bridges in the .\/bridges\/ folder without the \u2018Bridge\u2019 prefix. For example: DansTonChatBridge => DansTonChat. #format This parameter specifies the format in which RSS-Bridge returns the contents. RSS-Bridge currently supports five formats: Atom, Html, Json, Mrssand Plaintext. #Optional parameters RSS-Bridge supports optional parameters. These parameters are only valid if the options have been enabled in the index.php script. #_noproxy This parameter is only available if a proxy server has been specified via proxy.url and proxy.by_bridge has been enabled. This is a Boolean parameter that can be set to true or false. #Bridge parameters Each bridge can specify its own set of parameters. As in the example above, some bridges don\u2019t specify any parameters or only optional parameters that can be neglected. For more details read the PARAMETERS definition for your bridge.","tags":"","url":"CLI\/index.html"},{"title":"For Hosts","text":"This section is directed at hosts and server administrators. To install RSS-Bridge, please follow the installation instructions. You must have access to a web server with a working PHP environment! RSS-Bridge comes with a large amount of bridges. Only few bridges are enabled by default. Unlock more bridges by adding them to the whitelist. Some bridges could be implemented more efficiently by actually using proprietary APIs, but there are reasons against it: RSS-Bridge exists in the first place to NOT use APIs. See the rant APIs require private keys that could be stored on servers running RSS-Bridge, which is a security concern, involves complex authorizations for inexperienced users and could cause harm (when using paid services for example). In a closed environment (a server only you use for yourself) however you might be interested in using them anyway. So, check this possible implementation of an anti-captcha solution.","tags":"","url":"For_Hosts\/index.html"},{"title":"Installation","text":"In order to install RSS-Bridge on your own web server* do as follows: Make sure your web server meets all requirements Download the ZIP file of the last stable release Place all files on your web server For linux hosts: Grant read-write-access for www-data to the .\/cache directory (chown -R www-data .\/cache) You have successfully installed RSS-Bridge. Instructions for Docker setups are at Docker Installation","tags":"","url":"For_Hosts\/Installation.html"},{"title":"Updating","text":"Updating an existing installation is very simple, depending on your type of installation. #Release Build Download latest version Extract all files Replace existing files This will update all core files to the latest version. Your custom configuration and bridges are left untouched. Keep in mind that changes to any core file of RSS-Bridge will be replaced. #Docker Simply get the latest Docker build via :latest or specific builds via :<tag-name>. #Heroku #If you didn\u2019t fork the repo before Fork the repo by clicking the Fork button at the top right of this page (must be on desktop site). Then on your Heroku account, go to the application. Click on the Deploy tab and connect the repo named yourusername\/rss-bridge. Do a manual deploy of the master branch. #If you forked the repo before Click here to create a new pull request to your fork. Select compare across forks, make the base repository yourusername\/rss-bridge and ensure the branch is set to master. Put any title you want and create the pull request. On the page that comes after this, merge the pull request. You then want to go to your application in Heroku, connect your fork via the Deploy tab and deploy the master branch. You can turn on auto-deploy for the master branch if you don\u2019t want to go through the process of logging into Heroku and deploying the branch every time changes to the repo are made in the future. #Git To get the latest changes from the master branch git pull To use a specific tag git fetch --all git checkout tags\/<tag-name>","tags":"","url":"For_Hosts\/Updating.html"},{"title":"Docker Installation","text":"This guide is for people who want to run RSS Bridge using Docker. If you want to run it a simple PHP Webhost environment, see Installation instead. #Setup #Create the container docker create \\ --name=rss-bridge \\ --volume <\/local\/custom\/path>:\/config \\ --publish 3000:80 \\ rssbridge\/rss-bridge:latest #Run it docker start rss-bridge Access it using http:\/\/IP_Address:3000. If you\u2019d like to run a specific version, you can run it by changing the \u2018:latest\u2019 on the image to a tag listed here The server runs on port 80 internally, map any port of your choice (in this example 3000). You can run it using a docker-compose.yml as well: version: '2' services: rss-bridge: image: rssbridge\/rss-bridge:latest volumes: - <\/local\/custom\/path>:\/config ports: - 3000:80 restart: unless-stopped #Container access and information Function Command Shell access (live container) docker exec -it rss-bridge \/bin\/sh Realtime container logs docker logs -f rss-bridge #Adding custom bridges and configurations If you want to add a bridge that is not part of \/bridges, you can map a folder to the \/config folder of the rss-bridge container. Create a folder in the location of your docker-compose.yml or your general docker working area (in this example it will be \/home\/docker\/rssbridge\/config ). Copy your custom bridges to the \/home\/docker\/rssbridge\/config folder. Applies also to config.ini.php. Map the folder to \/config inside the container. To do that, replace the <\/local\/custom\/path> from the previous examples with \/home\/docker\/rssbridge\/config","tags":"","url":"For_Hosts\/Docker_Installation.html"},{"title":"Heroku Installation","text":"This guide is for people who want to run RSS Bridge on Heroku. You can run it on Heroku for free, however make sure your RSS reader interval is not set to a fast rate, otherwise your Heroku hours will use up quicker. Heroku puts the app to sleep after 30 mins of no activity. When the app is asleep no Heroku hours are used. So choose an interval that won\u2019t make the app exceed the limit! You can increase your Heroku hours to 1000 a month from 550 a month by simply verifying your account with a credit card. #Deploy button You can simply press the button below to easily deploy RSS Bridge on Heroku and use the default bridges. Or you can follow the manual instructions given below. #Manual deploy Fork this repo by clicking the Fork button at the top right of this page (only on desktop site) To customise what bridges can be used if need, see here. You don\u2019t need to do this if you\u2019re fine with the default bridges. Log in to Heroku and create a new app. The app name will be the URL of the RSS Bridge (appname.herokuapp.com) Go to Deploy, select the GitHub option and connect your GitHub account. Search for the repo named yourusername\/rss-bridge Deploy the master branch.","tags":"","url":"For_Hosts\/Heroku_Installation.html"},{"title":"Whitelisting","text":"Modify config.ini.php to limit available bridges. Those changes should be applied in the [system] section. #Enable all bridges [system] enabled_bridges[] = * #Enable some bridges [system] enabled_bridges[] = TwitchBridge enabled_bridges[] = GettrBridge #Enable all bridges (legacy shortcut) echo '*' > whitelist.txt #Enable some bridges (legacy shortcut) echo -e "TwitchBridge\\nTwitterBridge" > whitelist.txt","tags":"","url":"For_Hosts\/Whitelisting.html"},{"title":"Authentication","text":"Depending on your servers abilities you can choose between two types of authentication: .htaccess RSS-Bridge Authentication General advice: Make sure to use a strong password, no matter which solution you choose! Enable HTTPS on your server to ensure your connection is encrypted and secure! #.htaccess .htaccess files are commonly used to restrict access to files on a web server. One of the features of .htaccess files is the ability to password protect specific (or all) directories. If setup correctly, a password is required to access the files. The usage of .htaccess files requires three basic steps: Enable .htaccess Create a .htpasswd file Create a .htaccess file #Enable .htaccess This process depends on the server you are using. Some providers may require you to change some settings, or place\/change some file. Here are some helpful links for your server (please add your own if missing :sparkling_heart:) Apache: http:\/\/ask.xmodulo.com\/enable-htaccess-apache.html #Create a .htpasswd file The .htpasswd file contains the user name and password used for login to your web server. Please notice that the password is stored in encrypted form, which requires you to encrypt your password before creating the .htpasswd file! Here are three ways of creating your own .htpasswd file: 1) Example file Example .htpasswd file (user name: \u201ctest\u201d, password: \u201ctest\u201d): test:$apr1$a52u9ILP$XTNG8qMJiEXSm1zD0lQcR0 Just copy and paste the contents to your .htpasswd file. 2) Online generator (read warning!) You can create your own .htpasswd file online using a .htpasswd generator like this: https:\/\/www.htaccesstools.com\/htpasswd-generator\/ WARNING! Never insert real passwords to an online generator! 3) Generate your own password Another way to create your own .htpasswd file is to run this script on your server (it\u2019ll output the data for you, you just have to paste it int a .htpasswd file): <?php \/\/ Password to be encrypted for a .htpasswd file $clearTextPassword = 'some password'; \/\/ Encrypt password $password = crypt($clearTextPassword, base64_encode($clearTextPassword)); \/\/ Print encrypted password echo $password; ?> source: https:\/\/www.htaccesstools.com\/articles\/create-password-for-htpasswd-file-using-php\/ #Create a .htaccess file The .htaccess file is used to specify which directories are password protected. For that purpose you should place the file in whatever directory you want to restrict access. If you want to restrict access to RSS-Bridge in general, you should place the file in the root directory (where index.php is located). Two parameters must be specified in the .htaccess file: AuthName AuthUserFile AuthName specifies the name of the authentication (i.e. \u201cRSS-Bridge\u201d). AuthUserFile defines the absolute path to a .htpasswd file. Here are two ways of creating your own .htaccess file: 1) Example file AuthType Basic AuthName "My Protected Area" AuthUserFile \/path\/to\/.htpasswd Require valid-user Notice: You must change the AuthUserFile location to fit your own server (i.e. \/var\/www\/html\/rss-bridge\/.htpasswd) 2) Online generator You can use an online generator to create the file for you and copy-paste it to your .htaccess file: https:\/\/www.htaccesstools.com\/htaccess-authentication\/ #RSS-Bridge Authentication RSS-Bridge ships with an authentication module designed for single user environments. You can enable authentication and specify the username & password in the configuration file. Please notice that the password is stored in plain text and thus is readable to anyone who can access the file. Make sure to restrict access to the file, so that it cannot be read remotely!","tags":"","url":"For_Hosts\/Authentication.html"},{"title":"Customizations","text":"RSS-Bridge ships a few options the host may or may not activate. All options are listed in the config.default.ini.php file, see Custom Configuration section for more information. #Customizable cache timeout Sometimes it is necessary to specify custom timeouts to update contents more frequently than the bridge maintainer intended. In these cases the client may specify a custom cache timeout to prevent loading contents from cache earlier (or later). This option can be activated by setting the cache.custom_timeout option to true. When enabled each bridge receives an additional parameter Cache timeout in seconds that can be set to any value between 1 and 86400 (24 hours). If the value is not within the limits the default settings apply (as specified by the bridge maintainer). The cache timeout is send to RSS-Bridge using the _cache_timeout parameter. RSS-Bridge will return an error message if the parameter is received and the option is disabled.","tags":"","url":"For_Hosts\/Customizations.html"},{"title":"Custom Configuration","text":"RSS-Bridge supports custom configurations for common parameters on the server side! A default configuration file (config.default.ini.php) is shipped with RSS-Bridge. Please do not edit this file, as it gets replaced when upgrading RSS-Bridge! You should, however, use this file as template to create your own configuration (or leave it as is, to keep the default settings). In order to create your own configuration perform following actions: Create the file config.ini.php in the RSS-Bridge root folder (next to config.default.ini.php) Copy the contents from config.default.ini.php to your configuration file Change the parameters to satisfy your requirements RSS-Bridge will automatically detect the config.ini.php and use it. If the file doesn\u2019t exist it will default to config.default.ini.php automatically. Notice: If a parameter is not specified in your config.ini.php RSS-Bridge will automatically use the default settings from config.default.ini.php. #Available parameters The configuration file is split into sections: system http client cache proxy authentication admin error System: This section specifies system specific parameters Http client: This section has http client options Cache: This section is all about the caching behavior of RSS-Bridge Proxy: This section can be used to specify a proxy server for RSS-Bridge to utilize for fetching contents Authentication: This section defines parameters to require authentication to use RSS-Bridge Admin: This section specifies parameters related to the administrator of your instance of RSS-Bridge #System This section provides following parameters: timezone #Timezone Defines the timezone used by RSS-Bridge. This parameter can be set to any value of the values defined at https:\/\/www.php.net\/manual\/en\/timezones.php The default value is UTC. #Cache This section provides following parameters: type custom_timeout #type Defines the cache type used by RSS-Bridge. Type Description file File based (default) sqlite SQLite database memcached Memcached service #custom_timeout Allow users to specify custom timeout for specific requests. true = enabled false = disabled (default) #Proxy This section provides following parameters: url name by_bridge #url Sets the proxy url (i.e. \u201ctcp:\/\/192.168.0.0:32\u201d) "" = Proxy disabled (default) #name Sets the proxy name that is shown on the bridge instead of the proxy url. "" = Show proxy url (default: \u201cHidden proxy name\u201d) #by_bridge Allow users to disable proxy usage for specific requests. true = enabled false = disabled (default) #Http client This section provides the following parameters: timeout useragent #timeout Default network timeout. #useragent Default user agent. #Authentication This section provides following parameters: enable username password #enable Enables authentication for RSS-Bridge. Notice: Login is required for all requests when enabled! Make sure to update feed subscriptions accordingly. true = enabled false = disabled (default) #username Defines the user name used for login. #password Defines the password used for login. Use a strong password to prevent others from guessing your login! #Admin This section provides following parameters: email #email Advertises an email address where people can reach the administrator. Notice: This address is displayed on the main page, visible to everyone! "" = Disabled (default) Example: email = "admin@instance.rss-bridge.com" #error This section provides following parameters: output report_limit #output Defines how error messages are returned by RSS-Bridge feed: As part of the feed (default) http: As HTTP error message none: No errors are reported #report_limit Defines how often an error must occur before it is reported to the user report_limit: 1 (default)","tags":"","url":"For_Hosts\/Custom_Configuration.html"},{"title":"For Developers","text":"This area is intended for developers who decide to contribute to RSS-Bridge. It is written in PHP. If you are new to RSS-Bridge you should make yourself familiar with some general aspects: Coding style policy Folder structure Debug mode Bridge API Cache API Technical recommendations","tags":"","url":"For_Developers\/index.html"},{"title":"Coding style policy","text":"This section explains the coding style policy for RSS-Bridge with examples and references to external resources. Please make sure your code is compliant before opening a pull request. You will automatically be notified if issues were found in your pull request. You must fix those issues before the pull request will be merged. Refer to phpcs.xml for a complete list of policies enforced by Travis-CI. If you want to run the checks locally, make sure you have phpcs and phpunit installed on your machine and run following commands in the root directory of RSS-Bridge (tested on Debian): .\/vendor\/bin\/phpcs --standard=phpcs.xml --warning-severity=0 --extensions=php -p .\/ .\/vendor\/bin\/phpunit The following list provides an overview of all policies applied to RSS-Bridge. #Whitespace #Add a new line at the end of a file Each PHP\/CSS\/HTML file must end with a new line at the end of a file. Example Bad { \/\/ code here } \/\/ This is the end of the file Good { \/\/ code here } \/\/ This is the end of the file Reference: PSR2.Files.EndFileNewline #Do not add a whitespace before a semicolon A semicolon indicates the end of a line of code. Spaces before the semicolon is unnecessary and must be removed. Example Bad echo 'Hello World!' ; Good echo 'Hello World!'; Reference: Squiz.WhiteSpace.SemicolonSpacing #Do not add whitespace at start or end of a file or end of a line Whitespace at the end of lines or at the start or end of a file is invisible to the reader and absolutely unnecessary. Thus it must be removed. Reference: Squiz.WhiteSpace.SuperfluousWhitespace #Indentation #Use spaces indentation #Maximum Line Length 180 #Strings #Whenever possible use single quote strings PHP supports both single quote strings and double quote strings. For pure text you must use single quote strings for consistency. Double quote strings are only allowed for special characters (i.e. "\\n") or inlined variables (i.e. "My name is {$name}"); Example Bad echo "Hello World!"; Good echo 'Hello World!'; Reference: Squiz.Strings.DoubleQuoteUsage #Add spaces around the concatenation operator The concatenation operator should have one space on both sides in order to improve readability. Example Bad $text = $greeting.' '.$name.'!'; Good (add spaces) $text = $greeting . ' ' . $name . '!'; You may break long lines into multiple lines using the concatenation operator. That way readability can improve considerable when combining lots of variables. Example Bad $text = $greeting.' '.$name.'!'; Good (split into multiple lines) $text = $greeting . ' ' . $name . '!'; Reference: Squiz.Strings.ConcatenationSpacing #Use a single string instead of concatenating While concatenation is useful for combining variables with other variables or static text. It should not be used to combine two sets of static text. See also: Maximum line length Example Bad $text = 'This is' . 'a bad idea!'; Good $text = 'This is a good idea!'; Reference: Generic.Strings.UnnecessaryStringConcat #Constants #Use UPPERCASE for constants As in most languages, constants should be written in UPPERCASE. Notice: This does not apply to keywords! Example Bad const pi = 3.14; Good const PI = 3.14; Reference: Generic.NamingConventions.UpperCaseConstantName #Keywords #Use lowercase for true, false and null true, false and null must be written in lower case letters. Example Bad if($condition === TRUE && $error === FALSE) { return NULL; } Good if($condition === true && $error === false) { return null; } Reference: Generic.PHP.LowerCaseConstant #Operators #Operators must have a space around them Operators must be readable and therefore should have spaces around them. Example Bad $text='Hello '.$name.'!'; Good $text = 'Hello ' . $name . '!'; Reference: Squiz.WhiteSpace.OperatorSpacing #Functions #Parameters with default values must appear last in functions It is considered good practice to make parameters with default values last in function declarations. Example Bad function showTitle($duration = 60000, $title) { ... } Good function showTitle($title, $duration = 60000) { ... } Reference: PEAR.Functions.ValidDefaultValue #Calling functions Function calls must follow a few rules in order to maintain readability throughout the project: Do not add whitespace before the opening parenthesis Example Bad $result = my_function ($param); Good $result = my_function($param); Do not add whitespace after the opening parenthesis Example Bad $result = my_function( $param); Good $result = my_function($param); Do not add a space before the closing parenthesis Example Bad $result = my_function($param ); Good $result = my_function($param); Do not add a space before a comma Example Bad $result = my_function($param1 ,$param2); Good $result = my_function($param1, $param2); Add a space after a comma Example Bad $result = my_function($param1,$param2); Good $result = my_function($param1, $param2); Reference: Generic.Functions.FunctionCallArgumentSpacing #Do not add spaces after opening or before closing bracket Parenthesis must tightly enclose parameters. Example Bad if( $condition ) { ... } Good if($condition) { ... } Reference: PSR2.ControlStructures.ControlStructureSpacing #Structures #Structures must always be formatted as multi-line blocks A structure should always be treated as if it contains a multi-line block. Add a space after closing parenthesis Example Bad if($condition){ ... } Good if($condition) { ... } Add body into new line Example Bad if($condition){ ... } Good if($condition) { ... } Close body in new line Example Bad if($condition){ ... } Good if($condition) { ... } Reference: Squiz.ControlStructures.ControlSignature #If-Statements #Use elseif instead of else if For sake of consistency else if is considered bad practice. Example Bad if($conditionA) { } else if($conditionB) { } Good if($conditionA) { } elseif($conditionB) { } Reference: PSR2.ControlStructures.ElseIfDeclaration #Do not write empty statements Empty statements are considered bad practice and must be avoided. Example Bad if($condition) { \/\/ empty statement } else { \/\/ do something here } Good (invert condition) if(!$condition) { \/\/ do something } Reference: Generic.CodeAnalysis.EmptyStatement #Do not write unconditional if-statements If-statements without conditions are considered bad practice and must be avoided. Example if(true) { } Reference: Generic.CodeAnalysis.UnconditionalIfStatement #Classes #Use PascalCase for class names Class names must be written in PascalCase. Example Bad class mySUPERclass { ... } Good class MySuperClass { ... } Reference: PEAR.NamingConventions.ValidClassName #Do not use final statements inside final classes Final classes cannot be extended, so it doesn\u2019t make sense to add the final keyword to class members. Example Bad final class MyClass { final public function MyFunction() { } } Good (remove the final keyword from class members) final class MyClass { public function MyFunction() { } } Reference: Generic.CodeAnalysis.UnnecessaryFinalModifier #Do not override methods to call their parent It doesn\u2019t make sense to override a method only to call their parent. When overriding methods, make sure to add some functionality to it. Example Bad class MyClass extends BaseClass { public function BaseFunction() { parent::BaseFunction(); } } Good (don\u2019t override the function) class MyClass extends BaseClass { } Reference: Generic.CodeAnalysis.UselessOverridingMethod #abstract and final declarations MUST precede the visibility declaration When declaring abstract and final functions, the visibility (scope) must follow after abstract or final. Example Bad class MyClass extends BaseClass { public abstract function AbstractFunction() { } public final function FinalFunction() { } } Good (abstract and final before public) class MyClass extends BaseClass { abstract public function AbstractFunction() { } final public function FinalFunction() { } } Reference: PSR2.Methods.MethodDeclaration #static declaration MUST come after the visibility declaration The static keyword must come after the visibility (scope) parameter. Example Bad class MyClass extends BaseClass { static public function StaticFunction() { } } Good (static after public) class MyClass extends BaseClass { public static function StaticFunction() { } } Reference: PSR2.Methods.MethodDeclaration #Casting #Do not add spaces when casting The casting type should be put into parenthesis without spaces. Example Bad $text = ( string )$number; Good $text = (string)$number; Reference: Squiz.WhiteSpace.CastSpacing #Arrays #Always use the short array syntax","tags":"","url":"For_Developers\/Coding_style_policy.html"},{"title":"Pull Request policy","text":"Pull requests allow you to improve RSS-Bridge. Maintainers will have to understand your changes before merging. In order to make this process as efficient as possible, please follow the policies explained below. Maintainers will merge your pull request much faster that way. #Fix one issue per pull request It is considered good practice to fix one specific (or a specific set of) error(s). You can open multiple pull requests if you need to address multiple subjects. The same applies to adding features to RSS-Bridge. Maintainers must be able to comprehend your pull request for it to be merged quickly. #Respect the coding style policy The coding style policy requires you to write your code in certain ways. If you plan to get it merged into RSS-Bridge, please make sure your code follows the policy. Maintainers will only merge pull requests that pass all tests. #Properly name your commits Commits are not only for show, they do help maintainers understand what you did in your pull request, just like a table of contents in a well formed book (or Wiki). Here are a few rules you should follow: When fixing a bridge (located in the bridges directory), write [BridgeName] Feature (i.e. [YoutubeBridge] Fix typo in video titles). When fixing other files, use [FileName] Feature (i.e. [index.php] Add multilingual support). When fixing a general problem that applies to multiple files, write category: feature (i.e. bridges: Fix various typos).","tags":"","url":"For_Developers\/Pull_Request_policy.html"},{"title":"Folder structure","text":"The repository contains a few folders that make up RSS-Bridge. Here is a brief description of what you can expect to find where: Folder Description actions\/ Contains all \u201ccontrollers\u201d for the web front-end. bridges\/ Contains all bridges that are currently supported. Each file represents one Bridge that is displayed on the Welcome screen of RSS-Bridge caches\/ Contains implementation for different cache back-ends supported. contrib\/ Contains various helpers for development and release process. docs\/ Contains this documentation. formats\/ Contains all export formats. lib\/ Contains the core API and helper functions. static\/ Contains all static assets for the web front-end, including images, style sheets and JavaScript code. templates\/ Contains templates for producing the HTML of the web front-end. tests\/ Contains the test suite and fixtures. vendor\/ Contains third-party libraries used by RSS-Bridge. Development of all files in this folder must be done in the vendor specific repository (not part of RSS-Bridge)","tags":"","url":"For_Developers\/Folder_structure.html"},{"title":"Actions","text":"RSS-Bridge currently supports four \u2018actions\u2019 which it can operate: Display (?action=display) Detect (?action=detect) List (?action=list) FindFeed (?action=findfeed) #Display The display action returns feeds generated by bridges. It requires additional parameter, some of which are specific to each bridge (see implementation details for your specific bridge). The following list contains mandatory parameter applicable to all bridges, excluding parameters that require additional options. Errors are returned for missing mandatory parameters: Parameter Required Description bridge yes Specifies the name of the bridge to display. Possible values are determined from the bridges available to the current instance of RSS-Bridge and the whitelist. format yes Specifies the name of the format to use for displaying the feed. Possible values are determined from the formats available to the current instance of RSS-Bridge. #Detect The detect action attempts to redirect the user to an appropriate display action for a feed based on a supplied URL. As bridges have to individually implement this it may not work for every bridge. If an appropriate bridge is found, a 301 Moved Permanently HTTP status code is returned with a relative location for a display action. If no appropriate bridge is found or a required parameter is missing, a 400 Bad Request status code is returned. The parameters for this action are listed below: Parameter Required Description url yes Specifies the URL to attempt to find a feed from. The value of this should be URL encoded. format yes Specifies the name of the format to use for displaying the feed. This is passed to the detected display action. Possible values are determined from the formats available to the current instance of RSS-Bridge. #List The list action returns a JSON formatted text containing information on all bridges available to the current instance of RSS-Bridge. Inactive bridges (not whitelisted) are included as well. Broken bridges are also included, but with limited parameters (only "status": "inactive"). This example shows JSON data for a single bridge: { "bridges": { "ABCTabs": { "status": "active", "uri": "https:\\\/\\\/www.abc-tabs.com\\\/", "name": "ABC Tabs Bridge", "parameters": [], "maintainer": "kranack", "description": "Returns 22 newest tabs" } }, "total": 1 } The top-level JSON object contains two parameters: bridges: A collection of bridges total: The total number of bridges { "bridges": { }, "total": 0 } #bridges The bridges parameter is a collection of bridge objects. The name of each object represents the name of the bridge as needed for the display action. Each object contains parameters, most of which are optional. The following table summarizes the parameters: Parameter Optional Description status No Indicates the status of the bridge. Possible values are \u2018active\u2019 and \u2018inactive\u2019. Only active bridges can be used for the display action. uri Yes Returns the URI of the bridge, as returned by the getURI function of the bridge. name Yes Returns the name of the bridge, as returned by the getName function of the bridge. parameters Yes Returns the PARAMETERS object of the bridge maintainer Yes Returns the name(s) of maintainer(s) for the bridge description Yes Returns the description of the bridge #total This parameter represents the total number of bridges available to the current instance of RSS-Bridge. #FindFeed The findfeed action attempts to list all available feeds based on a supplied URL for the active bridges of this instance. As bridges have to individually implement detectParameters, this it may not work for every bridge. If one or more bridges return a feed, a JSON data array structure is returned. If no feeds were found, a 404 Not Found status code is returned. If a required parameter is missing, a 400 Bad Request status code is returned. For each feed, the whole feed URL is sent in the url member, the feed specific bridge parameters metadata in the bridgeData member and the Bridge metadata in the bridgeMeta member. This example shows JSON data for the NASA Instagram account URL (https:\/\/www.instagram.com\/nasa\/) using the Html format : [ { "url": "https:\/\/rssbridge.host\/?action=display&context=Username&u=nasa&bridge=InstagramBridge&format=Html", "bridgeParams": { "context": "Username", "u": "nasa", "bridge": "InstagramBridge", "format": "Html" }, "bridgeData": { "context": { "name": "Context", "value": "Username" }, "u": { "name": "username", "value": "nasa" } }, "bridgeMeta": { "name": "Instagram Bridge", "description": "Returns the newest images", "parameters": { "Username": { "u": { "name": "username", "exampleValue": "aesoprockwins", "required": true } }, "Hashtag": { "h": { "name": "hashtag", "exampleValue": "beautifulday", "required": true } }, "Location": { "l": { "name": "location", "exampleValue": "london", "required": true } }, "global": { "media_type": { "name": "Media type", "type": "list", "required": false, "values": { "All": "all", "Video": "video", "Picture": "picture", "Multiple": "multiple" }, "defaultValue": "all" }, "direct_links": { "name": "Use direct media links", "type": "checkbox" } } }, "icon": "https:\/\/www.instagram.com\/\/favicon.ico" } } ] The parameters for this action are listed below: Parameter Required Description url yes Specifies the URL to attempt to find a feed from. The value of this should be URL encoded. format yes Specifies the name of the format to use for the URL of the feeds. This is passed to the detected display action. Possible values are determined from the formats available to the current instance of RSS-Bridge.","tags":"","url":"For_Developers\/Actions.html"},{"title":"Debug mode","text":"Warning! Enabling debug mode on a public server may result in malicious clients retrieving sensitive data about your server and possibly gaining access to it. Do not enable debug mode on a public server, unless you understand the implications of your doing! Debug mode enables error reporting and prevents loading data from the cache (data is still written to the cache). To enable debug mode, set in config.ini.php: enable_debug_mode = true Allow only explicit ip addresses: debug_mode_whitelist[] = 127.0.0.1 debug_mode_whitelist[] = 192.168.1.10 Notice: An empty file enables debug mode for anyone! The bridge whitelist still applies! (debug mode does not enable all bridges) RSS-Bridge will give you a visual feedback when debug mode is enabled. While debug mode is active, RSS-Bridge will write additional data to your servers error.log. Debug mode is controlled by the static class Debug. It provides three core functions: Debug::isEnabled(): Returns true if debug mode is enabled. Debug::log($message): Adds a message to error.log. It takes one parameter, which can be anything. Example: Debug::log('Hello World!'); Notice: Debug::log($message) calls Debug::isEnabled() internally. You don\u2019t have to do that manually.","tags":"","url":"For_Developers\/Debug_mode.html"},{"title":"Github Codespaces Tutorial","text":"Github Codespaces lets you develop RSS-Bridge right from within your browser in an online hosted environment without the need to install anything. Github Codespaces is free, check out this for more info. #How to get started You must enable Codespaces for your account here . After you are enabled to use Codespaces, you will get the additional functionality that you can see in the screenshots below. #How to develop for RSS-Bridge This will give you an example workflow of how to create a bridge for RSS-Bridge using codespaces Fork the main RSS-Bridge repo On your own repo, click the \u201ccode\u201d icon on the top on your repo and select \u201cCreate codespace on master\u201d A new window will open and show this screen. This means that your dev environment is being prepared When the window has loaded, give it some time to run all the preparation scripts. You will see that it is done when you see a \u201cListen for Xdebug (rss-bridge)\u201d line in the bottom row At this point, there is a running instance of RSS-Bridge active that you can open by clicking on the \u201cPORTS\u201d tab and then on the icon to open the website for port 3100 Xdebug is already started so you can set breakpoints and check out the variables in the debug pane You can now create a new branch for your new bridge by clicking on the \u201cmaster\u201d entry in the bottom left and select \u201ccreate new branch\u201d from the menu. You can commit straight from the IDE as your github credentials are already included in the Codespace. To open a PR, either go back to the Github website and open it there or do it right from the Codespaces instance using the github integration (when you push a new branch, it will ask you if you want to open a new PR). #How-Tos This guide assumes that you already know the basics of php development, some basics in VScode and some basics in working with git. If you want to know more about any of these steps, check out these How-Tos Check How to create a new Bridge on how to do that. Check This Youtube Tutorial for a quick introduction to using VSCode with Git (ignore the initial git setup, Codespaces does that for you)","tags":"","url":"For_Developers\/Github_Codespaces_Tutorial.html"},{"title":"Development Environment Setup","text":"These are examples of how to setup a local development environment to add bridges, improve the docs, etc. #Docker The following can serve as an example for using docker: # create a new directory mkdir rss-bridge-contribution cd rss-bridge-contribution # clone the project into a subfolder git clone https:\/\/github.com\/RSS-Bridge\/rss-bridge Then add a docker-compose.yml file: version: '3' services: rss-bridge: build: context: .\/rss-bridge ports: - 3000:80 volumes: - .\/config:\/config - .\/rss-bridge\/bridges:\/app\/bridges You can then access RSS-Bridge at localhost:3000 and add your bridge to the rss-bridge\/bridges folder. If you need to edit any other files, like from the lib folder add this to the volumes section: .\/rss-bridge\/lib:\/app\/lib. #Docs with Docker If you want to edit the docs add this to your docker-compose.yml: services: [...] daux: image: daux\/daux.io ports: - 8085:8085 working_dir: \/build volumes: - .\/rss-bridge\/docs:\/build\/docs network_mode: host and run for example the daux serve command with docker-compose run --rm daux daux serve. After that you can access the docs at localhost:8085 and edit the files in rss-bridge\/docs.","tags":"","url":"For_Developers\/Development_Environment_Setup.html"},{"title":"Bridge API","text":"A Bridge is a class that allows RSS-Bridge to create an RSS-feed from a website. A Bridge represents one element on the Welcome screen and covers one or more sites to return feeds for. It is developed in a PHP file located in the bridges\/ folder (see Folder structure) and extends one of the base classes of RSS-Bridge: Base class Description BridgeAbstract This class is intended for standard Bridges that need to filter HTML pages for content. FeedExpander Expand\/modify existing feed urls WebDriverAbstract XPathAbstract This class is meant as an alternative base class for bridge implementations. It offers preliminary functionality for generating feeds based on XPath expressions. For more information about how to create a new Bridge, read How to create a new Bridge?","tags":"","url":"Bridge_API\/index.html"},{"title":"How to create a new bridge","text":"Create a new file in the bridges\/ folder (see Folder structure). The file name must be named according to following specification: It starts with the full name of the site All white-space must be removed The first letter of a word is written in upper-case, unless the site name is specified otherwise (example: Freenews, not FreeNews, because the site is named \u2018Freenews\u2019) The first character must be upper-case The file name must end with \u2018Bridge\u2019 The file type must be PHP, written in small letters (seriously!) \u201c.php\u201d Examples: Site Filename Wikipedia WikipediaBridge.php Facebook FacebookBridge.php GitHub GitHubBridge.php Freenews FreenewsBridge.php The file must start with the PHP tags and end with an empty line. The closing tag ?> is omitted. Example: <?php \/\/ PHP code here \/\/ This line is empty (just imagine it!) The next step is to extend one of the base classes. Refer to one of an base classes listed on the Bridge API page.","tags":"","url":"Bridge_API\/How_to_create_a_new_bridge.html"},{"title":"BridgeAbstract","text":"BridgeAbstract is a base class for standard bridges. It implements the most common functions to simplify the process of adding new bridges. #Creating a new bridge You need four basic steps in order to create a new bridge: Step 1 - Create a new file Step 2 - Add a class, extending BridgeAbstract Step 3 - Add general constants to the class Step 4 - Implement a function to collect feed data These steps are described in more detail below. At the end of this document you\u2019ll find a complete template based on these instructions. The pictures below show an example based on these instructions: Show pictures Make sure to read these instructions carefully. Please don\u2019t hesitate to open an Issue if you have further questions (or suggestions). Once your bridge is finished, please open a Pull Request, in order to get your bridge merge into RSS-Bridge. #Step 1 - Create a new file Please read these instructions on how to create a new file for RSS-Bridge. #Step 2 - Add a class, extending BridgeAbstract Your bridge needs to be a class, which extends BridgeAbstract. The class name must exactly match the name of the file, without the file extension. For example: MyBridge.php => MyBridge Show example <?PHP class MyBridge extends BridgeAbstract { } \/\/ This line is empty (just imagine it!) #Step 3 - Add general constants to the class In order to present your bridge on the front page, RSS-Bridge requires a few constants: const NAME \/\/ Name of the Bridge (default: "Unnamed Bridge") const URI \/\/ URI to the target website of the bridge (default: empty) const DESCRIPTION \/\/ A brief description of the Bridge (default: "No description provided") const MAINTAINER \/\/ Name of the maintainer, i.e. your name on GitHub (default: "No maintainer") const PARAMETERS \/\/ (optional) Definition of additional parameters (default: empty) const CACHE_TIMEOUT \/\/ (optional) Defines the maximum duration for the cache in seconds (default: 3600) Show example <?PHP class MyBridge extends BridgeAbstract { const NAME = 'My Bridge'; const URI = 'https:\/\/rss-bridge.github.io\/rss-bridge\/Bridge_API\/BridgeAbstract.html'; const DESCRIPTION = 'Returns "Hello World!"'; const MAINTAINER = 'ghost'; } \/\/ This line is empty (just imagine it!) Notice: const PARAMETERS can be used to request information from the user. Refer to these instructions for more information. #Step 4 - Implement a function to collect feed data In order for RSS-Bridge to collect data, you must implement the public function collectData. This function takes no arguments and returns nothing. It generates a list of feed elements, which must be placed into the variable $this->items. Show example <?PHP class MyBridge extends BridgeAbstract { const NAME = 'My Bridge'; const URI = 'https:\/\/rss-bridge.github.io\/rss-bridge\/Bridge_API\/BridgeAbstract.html'; const DESCRIPTION = 'Returns "Hello World!"'; const MAINTAINER = 'ghost'; public function collectData() { $item = []; \/\/ Create an empty item $item['title'] = 'Hello World!'; $this->items[] = $item; \/\/ Add item to the list } } \/\/ This line is empty (just imagine it!) For more details on the collectData function refer to these instructions. #Template Use this template to create your own bridge. Please remove any unnecessary comments and parameters. <?php class MyBridge extends BridgeAbstract { const NAME = 'Unnamed bridge'; const URI = ''; const DESCRIPTION = 'No description provided'; const MAINTAINER = 'No maintainer'; const PARAMETERS = []; \/\/ Can be omitted! const CACHE_TIMEOUT = 3600; \/\/ Can be omitted! public function collectData() { $item = []; \/\/ Create an empty item $item['title'] = 'Hello World!'; $this->items[] = $item; \/\/ Add item to the list } } \/\/ This line is empty (just imagine it!) #PARAMETERS You can specify additional parameters in order to customize the bridge (i.e. to specify how many items to return). This document explains how to specify those parameters and which options are available to you. For information on how to read parameter values during execution, please refer to the getInput function. #Adding parameters to a bridge Parameters are specified as part of the bridge class. An empty list of parameters is defined as const PARAMETERS = []; Show example <?PHP class MyBridge extends BridgeAbstract { \/* ... *\/ const PARAMETERS = []; \/\/ Empty list of parameters (can be omitted) \/* ... *\/ } Parameters are organized in two levels: Level 1 - Context Level 2 - Parameter #Level 1 - Context A context is defined as a associative array of parameters. The name of a context is displayed by RSS-Bridge. Show example const PARAMETERS = [ 'My Context 1' => [], 'My Context 2' => [], ]; Output Notice: The name of a context can be left empty if only one context is needed! Show example const PARAMETERS = [ [] ]; You can also define a set of parameters that will be applied to every possible context of your bridge. To do this, specify a context named global. Show example const PARAMETERS = [ 'global' => [] \/\/ Applies to all contexts! ]; #Level 2 - Parameter Parameters are placed inside a context. They are defined as associative array of parameter specifications. Each parameter is defined by it\u2019s internal input name, a definition in the form 'n' => [];, where n is the name with which the bridge can access the parameter during execution. Show example const PARAMETERS = [ 'My Context' => [ 'n' => [] ] ]; The parameter specification consists of various fields, listed in the table below. Show example const PARAMETERS = array( 'My Context' => array( 'n' => array( 'name' => 'Limit', 'type' => 'number', 'required' => false, 'title' => 'Maximum number of items to return', 'defaultValue' => 10 ) ) ); Output Parameter Name Required Type Supported values Description name yes Text Input name as displayed to the user type no Text text, number, list, checkbox Type of the input (default: text) required no Boolean true, false Specifies if the parameter is required or not (default: false). Not supported for lists and checkboxes. values no associative array name\/value pairs used by the HTML option tag, required for type \u2018list\u2019 title no Text Used as tool-tip when mouse-hovering over the input box pattern no Text Defines a pattern for an element of type text. The pattern should be mentioned in the title attribute! exampleValue no Text Defines an example value displayed for elements of type text and number when no data has been entered yet defaultValue no Defines the default value if left blank by the user #List values List values are defined in an associative array where keys are the string displayed in the combo list of the RSS-Bridge web interface, and values are the content of the <option> HTML tag value attribute. ... 'type' => 'list', 'values' => array( 'Item A' => 'itemA' 'Item B' => 'itemB' ) ... If a more complex organization is required to display the values, the above key\/value can be used to set a title as a key and another array as a value: ... 'type' => 'list', 'values' => array( 'Item A' => 'itemA', 'List 1' => array( 'Item C' => 'itemC', 'Item D' => 'itemD' ), 'List 2' => array( 'Item E' => 'itemE', 'Item F' => 'itemF' ), 'Item B' => 'itemB' ) ... #defaultValue This attribute defines the default value for your parameter. Its behavior depends on the type: text: Allows any text number: Allows any number list: Must match either name or value of one element checkbox: Must be \u201cchecked\u201d to activate the checkbox #queriedContext The queried context is defined via PARAMETERS and can be accessed via $this->queriedContext. It provides a way to identify which context the bridge is called with. Example: ... const PARAMETERS = array( 'By user name' => array( 'u' => array('name' => 'Username') ), 'By user ID' => array( 'id' => array('name' => 'User ID') ) ); ... In this example $this->queriedContext will either return By user name or By user ID. The queried context might return no value, so the best way to handle it is by using a case-structure: switch($this->queriedContext){ case 'By user name': break; case 'By user ID': break; default: \/\/ Return default value } #collectData The collectData function is responsible for collecting data and adding items to generate feeds from. If you are unsure how to solve a specific problem, please don\u2019t hesitate to open an Issue on GitHub. Existing bridges are also a good source to learn implementing your own bridge. #Implementing the collectData function Implementation for the collectData function is specific to each bridge. However, there are certain reoccurring elements, described below. RSS-Bridge also provides functions to simplify the process of collecting and parsing HTML data (see \u201cHelper Functions\u201d on the sidebar) Elements collected by this function must be stored in $this->items. The items variable is an array of item elements, each of which is an associative array that may contain arbitrary keys. RSS-Bridge specifies common keys which are used to generate most common feed formats. Show example $item = []; \/\/ Create a new item $item['title'] = 'Hello World!'; $this->items[] = $item; \/\/ Add item to the list Additional keys may be added for custom APIs (ignored by RSS-Bridge). #Item parameters The item array should provide as much information as possible for RSS-Bridge to generate feature rich feeds. Find below list of keys supported by RSS-Bridge. $item['uri'] \/\/ URI to reach the subject ("https:\/\/...") $item['title'] \/\/ Title of the item $item['timestamp'] \/\/ Timestamp of the item in numeric or text format (compatible for strtotime()) $item['author'] \/\/ Name of the author for this item $item['content'] \/\/ Content in HTML format $item['enclosures'] \/\/ Array of URIs to an attachments (pictures, files, etc...) $item['categories'] \/\/ Array of categories \/ tags \/ topics $item['uid'] \/\/ A unique ID to identify the current item All formats support these parameters. The formats Plaintext and JSON also support custom parameters. #getDescription The getDescription function returns the description for a bridge. Notice: By default RSS-Bridge returns the contents of const DESCRIPTION, so you only have to implement this function if you require different behavior! public function getDescription(){ return self::DESCRIPTION; } #getMaintainer The getMaintainer function returns the name of the maintainer for a bridge. Notice: By default RSS-Bridge returns const MAINTAINER, so you only have to implement this function if you require different behavior! public function getMaintainer(){ return self::MAINTAINER; } #getName The getName function returns the name of a bridge. Notice: By default RSS-Bridge returns const NAME, so you only have to implement this function if you require different behavior! public function getName(){ return self::NAME; } #getURI The getURI function returns the base URI for a bridge. Notice: By default RSS-Bridge returns const URI, so you only have to implement this function if you require different behavior! public function getURI(){ return self::URI; } #getIcon The getIcon function returns the URI for an icon, used as favicon in feeds. If no icon is specified by the bridge, RSS-Bridge will use a default location: static::URI . '\/favicon.ico' (i.e. \u201chttps:\/\/github.com\/favicon.ico\u201d) which may or may not exist. public function getIcon(){ return static::URI . '\/favicon.ico'; } #detectParameters The detectParameters function takes a URL and attempts to extract a valid set of parameters for the current bridge. If the passed URL is valid for this bridge, the function should return an array of parameter -> value pairs that can be used by this bridge, including context if available, or an empty array if the bridge requires no parameters. If the URL is not relevant for this bridge, the function should return null. Notice: Implementing this function is optional. By default, RSS-Bridge tries to match the supplied URL to the URI constant defined in the bridge, which may be enough for bridges without any parameters defined. public function detectParameters($url){ $regex = '\/^(https?:\\\/\\\/)?(www\\.)?(.+?)(\\\/)?$\/'; if(empty(static::PARAMETERS) && preg_match($regex, $url, $urlMatches) > 0 && preg_match($regex, static::URI, $bridgeUriMatches) > 0 && $urlMatches[3] === $bridgeUriMatches[3]) { return []; } else { return null; } } Notice: This function is also used by the findFeed action. This action allows an user to get a list of all feeds corresponding to an URL. You can implement automated tests for the detectParameters function by adding the TEST_DETECT_PARAMETERS constant to your bridge class constant. TEST_DETECT_PARAMETERS is an array, with as key the URL passed to the detectParametersfunction and as value, the array of parameters returned by detectParameters const TEST_DETECT_PARAMETERS = [ 'https:\/\/www.instagram.com\/metaverse' => ['context' => 'Username', 'u' => 'metaverse'], 'https:\/\/instagram.com\/metaverse' => ['context' => 'Username', 'u' => 'metaverse'], 'http:\/\/www.instagram.com\/metaverse' => ['context' => 'Username', 'u' => 'metaverse'], ]; Notice: Adding this constant is optional. If the constant is not present, no automated test will be executed. #Helper Methods BridgeAbstract implements helper methods to make it easier for bridge maintainers to create bridges. Use these methods whenever possible instead of writing your own. saveCacheValue loadCacheValue #saveCacheValue Within the context of the current bridge, stores a value by key in the cache. The value can later be retrieved with loadCacheValue. protected function saveCacheValue($key, $value) $key - the name under which the value is stored in the cache. $value - the value to store in the cache. Usage example: const MY_KEY = 'MyKey'; public function collectData() { $value = 'my value'; $this->saveCacheValue(MY_KEY, $value); } #loadCacheValue Within the context of the current bridge, loads a value by key from cache. Optionally specifies the cache duration for the key. Returns null if the key doesn\u2019t exist or the value is expired. protected function loadCacheValue($key, $duration = null) $key - the name under which the value is stored in the cache. $duration - the maximum time in seconds after which the value expires. Usage example: const MY_KEY = 'MyKey'; public function collectData() { $value = $this->loadCacheValue(MY_KEY, 1800 \/* 30 minutes *\/); if (!isset($value)){ \/\/ load value $this->saveCacheValue(MY_KEY, $value); } \/\/ ... }","tags":"","url":"Bridge_API\/BridgeAbstract.html"},{"title":"FeedExpander","text":"Usage example: You have discovered a site that provides feeds which are hidden and inaccessible by normal means. You want your bridge to directly read the feeds and provide them via RSS-Bridge Find a template at the end of this file. Notice: For a standard feed only collectData need to be implemented. collectData should call $this->collectExpandableDatas('your URI here'); to automatically load feed items and header data (will subsequently call parseItem for each item in the feed). You can limit the number of items to fetch by specifying an additional parameter for: $this->collectExpandableDatas('your URI here', 10) (limited to 10 items). #The parseItem method This method receives one item from the current feed and should return one RSS-Bridge item. The default function does all the work to get the item data from the feed, whether it is RSS 1.0, RSS 2.0 or Atom 1.0. Notice: The following code sample is just an example. Implementation depends on your requirements! protected function parseItem(array $item) { $item['content'] = str_replace('rssbridge','RSS-Bridge',$item['content']); return $item; } #Feed parsing How rss-bridge processes xml feeds: Function uri title timestamp author content atom id title updated author content rss 0.91 link title description rss 1.0 link title dc:date dc:creator description rss 2.0 link, guid title pubDate, dc:date author, dc:creator description #Template This is the template for a new bridge: <?php class MySiteBridge extends FeedExpander { const MAINTAINER = 'No maintainer'; const NAME = 'Unnamed bridge'; const URI = ''; const DESCRIPTION = 'No description provided'; const PARAMETERS = []; const CACHE_TIMEOUT = 3600; public function collectData() { $this->collectExpandableDatas('your feed URI'); } }","tags":"","url":"Bridge_API\/FeedExpander.html"},{"title":"WebDriverAbstract","text":"WebDriverAbstract extends BridgeAbstract and adds functionality for generating feeds from active websites that use XMLHttpRequest (XHR) to load content and \/ or JavaScript to modify content. It highly depends on the php-webdriver library which offers Selenium WebDriver bindings for PHP. https:\/\/github.com\/php-webdriver\/php-webdriver (Project Repository) https:\/\/php-webdriver.github.io\/php-webdriver\/latest\/ (API) Please note that this class is intended as a solution for websites that cannot be covered by the other classes. The WebDriver starts a browser and is therefore very resource-intensive. #Configuration You need a running WebDriver to use bridges that depend on WebDriverAbstract. The easiest way is to start the Selenium server from the project of the same name: docker run -d -p 4444:4444 --shm-size="2g" docker.io\/selenium\/standalone-chrome:latest https:\/\/github.com\/SeleniumHQ\/docker-selenium With these parameters only one browser window can be started at a time. On a multi-user site, Selenium Grid should be used and the number of sessions should be adjusted to the number of processor cores. Finally, the config.ini.php file must be adjusted so that the WebDriver can find the Selenium server: [webdriver] selenium_server_url = "http:\/\/localhost:4444" #Development While you are programming a new bridge, it is easier to start a local WebDriver because then you can see what is happening and where the errors are. I\u2019ve also had good experience recording the process with a screen video to find any timing problems. chromedriver --port=4444 https:\/\/chromedriver.chromium.org\/ If you start rss-bridge from a container, then Chrome driver is only accessible if you call it with the --allowed-ips option so that it binds to all network interfaces. chromedriver --port=4444 --allowed-ips=192.168.1.42 The most important rule is that after an event such as loading the web page or pressing a button, you often have to explicitly wait for the desired elements to appear. A simple example is the bridge ScalableCapitalBlogBridge.php. A more complex and relatively complete example is the bridge GULPProjekteBridge.php. #Template Use this template to create your own bridge. <?php class MyBridge extends WebDriverAbstract { const NAME = 'My Bridge'; const URI = 'https:\/\/www.example.org'; const DESCRIPTION = 'Further description'; const MAINTAINER = 'your name'; public function collectData() { parent::collectData(); try { \/\/ TODO } finally { $this->cleanUp(); } } }","tags":"","url":"Bridge_API\/WebDriverAbstract.html"},{"title":"XPathAbstract","text":"XPathAbstract extends BridgeAbstract and adds functionality for generating feeds based on XPath expressions. It makes creation of new bridges easy and if you\u2019re familiar with XPath expressions this class is probably the right point for you to start with. At the end of this document you\u2019ll find a complete template based on these instructions. #Required constants To create a new Bridge based on XPathAbstract your inheriting class should specify a set of constants describing the feed and the XPath expressions. It is advised to override constants inherited from BridgeAbstract aswell. #Class constant FEED_SOURCE_URL Source Web page URL (should provide either HTML or XML content). You can specify any website URL which serves data suited for display in RSS feeds #Class constant XPATH_EXPRESSION_FEED_TITLE XPath expression for extracting the feed title from the source page. If this is left blank or does not provide any data BridgeAbstract::getName() is used instead as the feed\u2019s title. #Class constant XPATH_EXPRESSION_FEED_ICON XPath expression for extracting the feed favicon URL from the source page. If this is left blank or does not provide any data BridgeAbstract::getIcon() is used instead as the feed\u2019s favicon URL. #Class constant XPATH_EXPRESSION_ITEM XPath expression for extracting the feed items from the source page. Enter an XPath expression matching a list of dom nodes, each node containing one feed article item in total (usually a surrounding <div> or <span> tag). This will be the context nodes for all of the following expressions. This expression usually starts with a single forward slash. #Class constant XPATH_EXPRESSION_ITEM_TITLE XPath expression for extracting an item title from the item context. This expression should match a node contained within each article item node containing the article headline. It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. #Class constant XPATH_EXPRESSION_ITEM_CONTENT XPath expression for extracting an item\u2019s content from the item context. This expression should match a node contained within each article item node containing the article content or description. It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. #Class constant XPATH_EXPRESSION_ITEM_URI XPath expression for extracting an item link from the item context. This expression should match a node\u2019s attribute containing the article URL (usually the href attribute of an <a> tag). It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. Attributes can be selected by prepending an @ char before the attributes name. #Class constant XPATH_EXPRESSION_ITEM_AUTHOR XPath expression for extracting an item author from the item context. This expression should match a node contained within each article item node containing the article author\u2019s name. It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. #Class constant XPATH_EXPRESSION_ITEM_TIMESTAMP XPath expression for extracting an item timestamp from the item context. This expression should match a node or node\u2019s attribute containing the article timestamp or date (parsable by PHP\u2019s strtotime function). It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. Attributes can be selected by prepending an @ char before the attributes name. #Class constant XPATH_EXPRESSION_ITEM_ENCLOSURES XPath expression for extracting item enclosures (media content like images or movies) from the item context. This expression should match a node\u2019s attribute containing an article image URL (usually the src attribute of an tag or a style attribute). It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. Attributes can be selected by prepending an @ char before the attributes name. #Class constant XPATH_EXPRESSION_ITEM_CATEGORIES XPath expression for extracting an item category from the item context. This expression should match a node or node\u2019s attribute contained within each article item node containing the article category. This could be inside or tags or sometimes be hidden in a data attribute. It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. Attributes can be selected by prepending an @ char before the attributes name. #Class constant SETTING_FIX_ENCODING Turns on automatic fixing of encoding errors. Set this to true for fixing feed encoding by invoking PHP\u2019s utf8_decode function on all extracted texts. Try this in case you see \u201cbroken\u201d or \u201cweird\u201d characters in your feed where you\u2019d normally expect umlauts or any other non-ascii characters. #Optional methods XPathAbstract offers a set of methods which can be overridden by derived classes for fine tuning and customization. This is optional. The methods provided for overriding can be grouped into three categories. #Methods for providing XPath expressions Usually XPath expressions are defined in the class constants described above. By default the following base methods just return the value of its corresponding class constant. However deriving classed can override them in case if XPath expressions need to be formed dynamically or based on conditions. In case any of these methods is defined, the method\u2019s return value is used instead of the corresponding constant for providing the value. #Method getSourceUrl() Should return the source Web page URL used as a base for applying the XPath expressions. #Method getExpressionTitle() Should return the XPath expression for extracting the feed title from the source page. #Method getExpressionIcon() Should return the XPath expression for extracting the feed favicon from the source page. #Method getExpressionItem() Should return the XPath expression for extracting the feed items from the source page. #Method getExpressionItemTitle() Should return the XPath expression for extracting an item title from the item context. #Method getExpressionItemContent() Should return the XPath expression for extracting an item\u2019s content from the item context. #Method getSettingUseRawItemContent() Should return the \u2018Use raw item content\u2019 setting value (bool true or false). #Method getExpressionItemUri() Should return the XPath expression for extracting an item link from the item context. #Method getExpressionItemAuthor() Should return the XPath expression for extracting an item author from the item context. #Method getExpressionItemTimestamp() Should return the XPath expression for extracting an item timestamp from the item context. #Method getExpressionItemEnclosures() Should return the XPath expression for extracting item enclosures (media content like images or movies) from the item context. #Method getExpressionItemCategories() Should return the XPath expression for extracting an item category from the item context. #Method getSettingFixEncoding() Should return the Fix encoding setting value (bool true or false). #Methods for providing feed data Those methods are invoked for providing the HTML source as a base for applying the XPath expressions as well as feed meta data as the title and icon. #Method provideWebsiteContent() This method should return the HTML source as a base for the XPath expressions. Usually it merely returns the HTML content of the URL specified in the constant FEED_SOURCE_URL retrieved by curl. Some sites however require user authentication mechanisms, the use of special cookies and\/or headers, where the direct retrival using standard curl would not suffice. In that case this method should be overridden and take care of the page retrival. #Method provideFeedTitle() This method should provide the feed title. Usually the XPath expression defined in XPATH_EXPRESSION_FEED_TITLE is used for extracting the title directly from the page source. #Method provideFeedIcon() This method should provide the feed title. Usually the XPath expression defined in XPATH_EXPRESSION_FEED_ICON is used for extracting the title directly from the page source. #Method provideFeedItems() This method should provide the feed items. Usually the XPath expression defined in XPATH_EXPRESSION_ITEM is used for extracting the items from the page source. All other XPath expressions are applied on a per-item basis, item by item, and only on the item\u2019s contents. #Methods for formatting and filtering feed item attributes The following methods are invoked after extraction of the feed items from the source. Each of them expect one parameter, the value of the corresponding field, which then can be processed and transformed by the method. You can override these methods in order to format or filter parts of the feed output. #Method formatItemTitle() Accepts the items title values as parameter, processes and returns it. Should return a string. #Method formatItemContent() Accepts the items content as parameter, processes and returns it. Should return a string. #Method formatItemUri() Accepts the items link URL as parameter, processes and returns it. Should return a string. #Method formatItemAuthor() Accepts the items author as parameter, processes and returns it. Should return a string. #Method formatItemTimestamp() Accepts the items creation timestamp as parameter, processes and returns it. Should return a unix timestamp as integer. #Method cleanImageUrl() Method invoked for cleaning feed icon and item image URL\u2019s. Extracts the image URL from the passed parameter, stripping any additional content. Furthermore makes sure that relative image URL\u2019s get transformed to absolute ones. #Method fixEncoding() Only invoked when class constant SETTING_FIX_ENCODING is set to true. It then passes all extracted string values through PHP\u2019s utf8_decode function. #Method generateItemId() This method plays in important role for generating feed item ids for all extracted items. Every feed item needs an unique identifier (Uid), so that your feed reader updates the original item instead of adding a duplicate in case an items content is updated on the source site. Usually the items link URL is a good candidate the the Uid. #Template Use this template to create your own bridge. Please remove any unnecessary comments and parameters. <?php class TestBridge extends XPathAbstract { const NAME = 'Test'; const URI = 'https:\/\/www.unbemerkt.eu\/de\/blog\/'; const DESCRIPTION = 'Test'; const MAINTAINER = 'your name'; const CACHE_TIMEOUT = 3600; const FEED_SOURCE_URL = 'https:\/\/www.unbemerkt.eu\/de\/blog\/'; const XPATH_EXPRESSION_ITEM = '\/html[1]\/body[1]\/section[1]\/section[1]\/div[1]\/div[1]\/div[1]\/div[1]\/div[1]\/div[*]\/article[1]'; const XPATH_EXPRESSION_ITEM_TITLE = '.\/\/a[@target="_self"]'; const XPATH_EXPRESSION_ITEM_CONTENT = '.\/\/div[@class="post-content"]'; const XPATH_EXPRESSION_ITEM_URI = '.\/\/a[@class="more-btn"]\/@href'; const XPATH_EXPRESSION_ITEM_AUTHOR = '\/html[1]\/body[1]\/section[1]\/div[2]\/div[1]\/div[1]\/h1[1]'; const XPATH_EXPRESSION_ITEM_TIMESTAMP = '.\/\/time\/@datetime'; const XPATH_EXPRESSION_ITEM_ENCLOSURES = '.\/\/img\/@data-src'; const SETTING_FIX_ENCODING = false; }","tags":"","url":"Bridge_API\/XPathAbstract.html"},{"title":"Helper functions","text":"#getInput The getInput function is used to receive a value for a parameter, specified in const PARAMETERS $this->getInput('your input name here'); getInput will either return the value for your parameter or null if the parameter is unknown or not specified. Defined in lib\/BridgeAbstract.php #getKey The getKey function is used to receive the key name to a selected list value given the name of the list, specified in const PARAMETERS Is able to work with multidimensional list arrays. \/\/ Given a multidimensional array like this const PARAMETERS = [[ 'country' => [ 'name' => 'Country', 'type' => 'list', 'values' => [ 'North America' => [ 'Mexico' => 'mx', 'United States' => 'us' ], 'South America' => [ 'Uruguay' => 'uy', 'Venezuela' => 've' ], ] ] ]], \/\/ Provide the list name to the function $this->getKey('country'); \/\/ if the selected value was "ve", this function will return "Venezuela" getKey will either return the key name for your parameter or null if the parameter is unknown or not specified. Defined in lib\/BridgeAbstract.php #getContents The getContents function uses cURL to acquire data from the specified URI while respecting the various settings defined at a global level by RSS-Bridge (i.e., proxy host, user agent, etc.). This function accepts a few parameters: Parameter Type Optional Description url string required The URL of the contents to acquire header array optional An array of HTTP header fields to set, in the format array('Content-type: text\/plain', 'Content-length: 100'), see CURLOPT_HTTPHEADER opts array optional An array of cURL options in the format array(CURLOPT_POST => 1);, see curl_setopt for a complete list of options. returnFull boolean optional Specifies whether to return the response body from cURL (default) or the response body, code, headers, etc. $header = array('Content-type:text\/plain', 'Content-length: 100'); $opts = array(CURLOPT_POST => 1); $html = getContents($url, $header, $opts); Defined in lib\/contents.php #getSimpleHTMLDOM The getSimpleHTMLDOM function is a wrapper for the simple_html_dom file_get_html function in order to provide context by design. $html = getSimpleHTMLDOM('your URI'); Defined in lib\/contents.php #getSimpleHTMLDOMCached The getSimpleHTMLDOMCached function does the same as the getSimpleHTMLDOM function, except that the content received for the given URI is stored in a cache and loaded from cache on the next request if the specified cache duration was not reached. Use this function for data that is very unlikely to change between consecutive requests to RSS-Bridge. This function allows to specify the cache duration with the second parameter. $html = getSimpleHTMLDOMCached('your URI', 86400); \/\/ Duration 24h Defined in lib\/contents.php #returnClientError The returnClientError function aborts execution of the current bridge and returns the given error message with error code 400: returnClientError('Your error message') Use this function when the user provided invalid parameter or a required parameter is missing. Defined in lib\/utils.php #returnServerError The returnServerError function aborts execution of the current bridge and returns the given error message with error code 500: returnServerError('Your error message') Use this function when a problem occurs that has nothing to do with the parameters provided by the user. (like: Host service gone missing, empty data received, etc\u2026) Defined in lib\/utils.php #defaultLinkTo Automatically replaces any relative URL in a given string or DOM object (i.e. the one returned by getSimpleHTMLDOM) with an absolute URL. defaultLinkTo ( mixed $content, string $server ) : object Returns a DOM object (even if provided a string). Remarks Only handles <a> and <img> tags. Example $html = '<img src=\"\/blob\/master\/README.md\">'; $html = defaultLinkTo($html, 'https:\/\/www.github.com\/rss-bridge\/rss-bridge'); \/\/ Using custom server $html = defaultLinkTo($html, $this->getURI()); \/\/ Using bridge URL \/\/ Output \/\/ <img src=\"https:\/\/www.github.com\/rss-bridge\/rss-bridge\/blob\/master\/README.md\"> Defined in lib\/html.php #backgroundToImg Replaces tags with styles of backgroud-image by <img \/> tags. backgroundToImg(mixed $htmlContent) : object Returns a DOM object (even if provided a string). Defined in lib\/html.php #extractFromDelimiters Extract the first part of a string matching the specified start and end delimiters. function extractFromDelimiters(string $string, string $start, string $end) : mixed Returns the extracted string if delimiters were found and false otherwise. Example $string = '<div>Post author: John Doe<\/div>'; $start = 'author: '; $end = '<'; $extracted = extractFromDelimiters($string, $start, $end); \/\/ Output \/\/ 'John Doe' Defined in lib\/html.php #stripWithDelimiters Remove one or more part(s) of a string using a start and end delimiter. It is the inverse of extractFromDelimiters. function stripWithDelimiters(string $string, string $start, string $end) : string Returns the cleaned string, even if no delimiters were found. Example $string = 'foo<script>superscript()<\/script>bar'; $start = '<script>'; $end = '<\/script>'; $cleaned = stripWithDelimiters($string, $start, $end); \/\/ Output \/\/ 'foobar' Defined in lib\/html.php #stripRecursiveHTMLSection Remove HTML sections containing one or more sections using the same HTML tag. function stripRecursiveHTMLSection(string $string, string $tag_name, string $tag_start) : string Example $string = 'foo<div class=\"ads\"><div>ads<\/div>ads<\/div>bar'; $tag_name = 'div'; $tag_start = '<div class=\"ads\">'; $cleaned = stripRecursiveHTMLSection($string, $tag_name, $tag_start); \/\/ Output \/\/ 'foobar' Defined in lib\/html.php #markdownToHtml Converts markdown input to HTML using Parsedown. Parameter Type Optional Description string string required The URL of the contents to acquire config array optional An array of Parsedown options in the format ['breaksEnabled' => true] Valid options: Option Default Description breaksEnabled false Enable automatic line breaks markupEscaped false Escape inline markup (HTML) urlsLinked true Automatically convert URLs to links function markdownToHtml(string $string, array $config = []) : string Example $input = <<<EOD RELEASE-2.8 * Share QR code of a token * Dark mode improvemnet * Fix some layout issues * Add shortcut to launch the app with screenshot mode on * Translation improvements EOD; $html = markdownToHtml($input); \/\/ Output: \/\/ <p>RELEASE-2.8<\/p> \/\/ <ul> \/\/ <li>Share QR code of a token<\/li> \/\/ <li>Dark mode improvemnet<\/li> \/\/ <li>Fix some layout issues<\/li> \/\/ <li>Add shortcut to launch the app with screenshot mode on<\/li> \/\/ <li>Translation improvements<\/li> \/\/ <\/ul> Defined in lib\/html.php #e The e function is used to convert special characters to HTML entities e('0 < 1 and 2 > 1'); e will return the content of the string escape that can be rendered as is in HTML Defined in lib\/html.php #truncate The truncate function is used to shorten a string if exceeds a certain length, and add a string indicating that the string has been shortened. truncate('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a neque nunc. Nam nibh sem.', 20 , '...'); Defined in lib\/html.php #sanitize The sanitize function is used to remove some tags from a given HTML text. $html = '<head><title>Sample Page<\/title><\/head> <body><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...<\/p> <iframe src="https:\/\/www.example.com" width="600" height="400" frameborder="0" allowfullscreen><\/iframe> <\/body> <\/html>'; $tags_to_remove = ['script', 'iframe', 'input', 'form']; $attributes_to_keep = ['title', 'href', 'src']; $text_to_keep = []; sanitize($html, $tags_to_remove, $attributes_to_keep, $text_to_keep); This function returns a simplehtmldom object of the remaining contents. Defined in lib\/html.php #convertLazyLoading The convertLazyLoading function is used to convert onvert lazy-loading images and frames (video embeds) into static elements. It accepts the HTML content as HTML objects or string objects. It returns the HTML content with fixed image\/frame URLs (same type as input). $html = '<html> <body style="background-image: url('bgimage.jpg');"> <h1>Hello world!<\/h1> <\/body> <\/html> backgroundToImg($html); Defined in lib\/html.php #Json::encode The Json::encode function is used to encode a value as \u00e0 JSON string. $array = [ "foo" => "bar", "bar" => "foo", ]; Json::encode($array, true, true); Defined in lib\/utils.php #Json::decode The Json::decode function is used to decode a JSON string into \u00e0 PHP variable. $json = '{ "foo": "bar", "bar": "foo" }'; Json::decode($json); Defined in lib\/utils.php","tags":"","url":"Helper_functions\/index.html"},{"title":"Cache API","text":"A Cache is a class that allows RSS-Bridge to store fetched data in a local storage area on the server. Cache imlementations are placed in the caches\/ folder (see Folder structure). A cache must implement the CacheInterface interface. For more information about how to create a new Cache, read How to create a new cache?","tags":"","url":"Cache_API\/index.html"},{"title":"How to create a new cache","text":"Create a new file in the caches\/ folder (see Folder structure). See NullCache and SQLiteCache for examples.","tags":"","url":"Cache_API\/How_to_create_a_new_cache.html"},{"title":"CacheInterface","text":"See CacheInterface. interface CacheInterface { public function get(string $key, $default = null); public function set(string $key, $value, int $ttl = null): void; public function delete(string $key): void; public function clear(): void; public function prune(): void; }","tags":"","url":"Cache_API\/CacheInterface.html"},{"title":"Technical recommendations","text":"#General recommendations Use HTTPS (https:\/\/...) over HTTP (http:\/\/...) whenever possible #Test a site before building a bridge Some sites make use of anti-bot mechanisms (e.g.: by using JavaScript) in which case they work fine in regular browsers, but not in the PHP environment. To check if a site works with RSS-Bridge, create a new bridge using the template and load a valid URL (not the base URL!). Example (using github.com) <?php class TestBridge extends BridgeAbstract { const NAME = 'Unnamed bridge'; const URI = ''; const DESCRIPTION = 'No description provided'; const MAINTAINER = 'No maintainer'; const PARAMETERS = []; const CACHE_TIMEOUT = 3600; public function collectData(){ $html = getSimpleHTMLDOM('https:\/\/github.com\/rss-bridge\/rss-bridge') or returnServerError('No contents received!'); } } This bridge should return an empty page (HTML format)","tags":"","url":"Technical_recommendations\/index.html"},{"title":"ActivityPub (Mastodon)","text":"#MastodonBridge (aka. ActivityPub Bridge) Certain ActivityPub implementations, such as Mastodon and Pleroma, allow instances to require requests to ActivityPub endpoints to be signed. RSS-Bridge can handle the HTTP signature header if a private key is provided, while the ActivityPub instance must be able to know the corresponding public key. You do not need to configure this if the usage on your RSS-Bridge instance is limited to accessing ActivityPub instances that do not have such requirements. While the majority of ActivityPub instances don\u2019t have them at the time of writing, the situation may change in the future. #Configuration This article is referenced. Select a domain. It may, but does not need to, be the one RSS-Bridge is on. For all subsequent steps, replace DOMAIN with this domain. Run the following commands on your machine: $ openssl genrsa -out private.pem 2048 $ openssl rsa -in private.pem -outform PEM -pubout -out public.pem Place private.pem in an appropriate location and note down its absolute path. Serve the following page at https:\/\/DOMAIN\/.well-known\/webfinger: { \"subject\": \"acct:DOMAIN@DOMAIN\", \"aliases\": [\"https:\/\/DOMAIN\/actor\"], \"links\": [{ \"rel\": \"self\", \"type\": \"application\/activity+json\", \"href\": \"https:\/\/DOMAIN\/actor\" }] } Serve the following page at https:\/\/DOMAIN\/actor, replacing the value of publicKeyPem with the contents of the public.pem file in step 2, with all line breaks substituted with \\n: { \"@context\": [ \"https:\/\/www.w3.org\/ns\/activitystreams\", \"https:\/\/w3id.org\/security\/v1\" ], \"id\": \"https:\/\/DOMAIN\/actor\", \"type\": \"Application\", \"inbox\": \"https:\/\/DOMAIN\/actor\/inbox\", \"preferredUsername\": \"DOMAIN\", \"publicKey\": { \"id\": \"https:\/\/DOMAIN\/actor#main-key\", \"owner\": \"https:\/\/DOMAIN\/actor\", \"publicKeyPem\": \"-----BEGIN PUBLIC KEY-----\\n...\\n-----END PUBLIC KEY-----\\n\" } } Add the following configuration in config.ini.php in your RSS-Bridge folder, replacing the path with the one from step 3: [MastodonBridge] private_key = \"\/absolute\/path\/to\/your\/private.pem\" key_id = \"https:\/\/DOMAIN\/actor#main-key\" #Considerations Any ActivityPub instance your users requested content from will be able to identify requests from your RSS-Bridge instance by the domain you specified in the configuration. This also means that an ActivityPub instance may choose to block this domain should they judge your instance\u2019s usage excessive. Therefore, public instance operators should monitor for abuse and prepare to communicate with ActivityPub instance admins when necessary. You may also leave contact information as the summary value in the actor JSON (step 5).","tags":"","url":"Bridge_Specific\/ActivityPub_(Mastodon).html"},{"title":"FacebookBridge","text":"#FacebookBridge State of this bridge: Facebook Groups (and probably other sections too) do not work at all No maintainer Needs cookie consent support for public pages Needs login support see this example for Instagram) for private groups Due to the 2020 Facebook redesign and the requirement to accept cookies users are getting problems with Facebook on public RSS-Bridge instances. #Relevant Info Facebook Cookies \u201cDatr\u201d is a unique identifier for your browser and it has a lifespan of two years. \u201cc_user\u201d and \u201cxs\u201d cookies to verify the account and have a lifespan of 365 days","tags":"","url":"Bridge_Specific\/FacebookBridge.html"},{"title":"FurAffinityBridge","text":"#FurAffinityBridge By default this bridge will only return submissions that are rated \u201cGeneral\u201d and are public. To unlock the ability to load submissions that require an account to view or are rated \u201cMature\u201d and higher, you must set the following in config.ini.php with cookies from an existing FurAffinity account with the desired maturity ratings enabled in Account Settings. [FurAffinityBridge] aCookie = "your-a-cookie-value-here" ; from cookie "a" bCookie = "your-b-cookie-value-here" ; from cookie "b" To confirm the bridge is authenticated, the name of the authenticating account will be shown in the bridge\u2019s name once the bridge has been used at least once. (Example: user's FurAffinity Bridge)","tags":"","url":"Bridge_Specific\/FurAffinityBridge.html"},{"title":"Furaffinityuser","text":"#FuraffinityuserBridge #How to retrieve and use cookie values The following steps describe how to get the session cookies using a Chromium-based browser. Other browser may require slightly different steps. Keyword search \u201chow to find cookie values\u201d in your favorite search engine. #Retreiving session cookies. Login to Furaffinity Open DevTools by pressing F12 Open \u201cApplication\u201d On the left side, select \u201cCookies\u201d -> \u201cFuraffinity.net\u201d There will be (at least) two cookie informations in the main window. You need the values of the \u201ca\u201d key and \u201cb\u201d key #Configuring RSS-Bridge Copy\/Paste the values from cookies \u201ca\u201d and \u201cb\u201d into their respective fields in the bridge config and generate the feed","tags":"","url":"Bridge_Specific\/Furaffinityuser.html"},{"title":"Instagram","text":"#InstagramBridge To somehow bypass the rate limiting issue it is suggested to deploy a private RSS-Bridge instance that uses a working Instagram account. NOTE: There exists alternative bridges (e.g. PicukiBridge and PicnobBridge) for viewing posts without a working account. #Configuration Retreiving session id and ds_user_id. The following steps describe how to get the session id and ds user id using a Chromium-based browser. Create an Instagram account, that you will use for your RSS-Bridge instance. It is NOT recommended to use your existing account that is used for common interaction with Instagram services. Login to Instagram Open DevTools by pressing F12 Open \u201cNetworks tab\u201d In the \u201cFilter\u201d field input \u201ci.instagram.com\u201d Click on \u201cFetch\/XHR\u201d Refresh web page Click on any item from the table of http requests In the new frame open the \u201cHeaders\u201d tab and scroll to \u201cRequest Headers\u201d There will be a cookie param will lots of <key>=<value>; text. You need the value of the \u201csessionid\u201d and \u201cds_user_id\u201d keys. Copy them. Configuring RSS-Bridge In config.ini.php add following configuration: [InstagramBridge] session_id = %sessionid from step 1% ds_user_id = %ds_user_id from step 1% cache_timeout = %cache timeout in seconds% The bigger the cache_timeout value, the smaller the chance for RSS-Bridge to throw 429 errors. Default cache_timeout is 3600 seconds (1 hour).","tags":"","url":"Bridge_Specific\/Instagram.html"},{"title":"PixivBridge","text":"#PixivBridge #Image proxy As Pixiv requires images to be loaded with the Referer "https:\/\/www.pixiv.net\/" header set, caching or image proxy is required to use this bridge. To turn off image caching, set the proxy_url value in this bridge\u2019s configuration section of config.ini.php to the url of the proxy. The bridge will then use the proxy in this format (essentially replacing https:\/\/i.pximg.net with the proxy): Before: https:\/\/i.pximg.net\/img-original\/img\/0000\/00\/00\/00\/00\/00\/12345678_p0.png After: https:\/\/proxy.example.com\/img-original\/img\/0000\/00\/00\/00\/00\/00\/12345678_p0.png proxy_url = "https:\/\/proxy.example.com" #Authentication Authentication is required to view and search R-18+ and non-public images. To enable this, set the following in this bridge\u2019s configuration in config.ini.php. ; from cookie \"PHPSESSID\". Recommend to get in incognito browser. cookie = \"00000000_hashedsessionidhere\"","tags":"","url":"Bridge_Specific\/PixivBridge.html"},{"title":"TwitterV2","text":"#TwitterV2Bridge To automatically retrieve Tweets containing potentially sensitive\/age-restricted content, you\u2019ll need to acquire your own unique API Bearer token, which will be used by this Bridge to query Twitter\u2019s API v2. #Configuration Make a Twitter Developer account Developer Portal: https:\/\/dev.twitter.com I will not detail exactly how to do this, as the specific process will likely change over time. You should easily be able to find guides using your search engine of choice. Note: as of April 2023, the \u201cFree\u201d access level no longer allows read access. The cheapest access level with read access is called \u201cBasic\u201d. Create a Twitter Project and App, get Bearer Token Once you have an active Twitter Developer account, sign in to the dev portal Create a new Project (name doesn\u2019t matter) Create an App within the Project (again, name doesn\u2019t matter) Go to the Keys and tokens tab Generate a Bearer Token (you don\u2019t want the API Key and Secret, or the Access Token and Secret) Configure RSS-Bridge In config.ini.php (in rss-bridge root directory) add following lines at the end: [TwitterV2Bridge] twitterv2apitoken = %Bearer Token from step 2% If you don\u2019t have a config.ini.php, create one by making a copy of config.default.ini.php","tags":"","url":"Bridge_Specific\/TwitterV2.html"},{"title":"Vk2","text":"#Vk2Bridge \u0420\u0430\u0431\u043e\u0442\u0430 \u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 VK API. \u041f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 VkBridge \u0443 \u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u0440\u0438\u0435\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438. #\u041f\u0440\u0438\u0435\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0421\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u0421\u043a\u0440\u0438\u043f\u0442 \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 HTML-\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b VK \u0433\u0440\u0443\u043f\u043f \u0438\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. #\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438 \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u0412\u041a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c access_token, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u201c\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u201d \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u0440\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u043c \u043a\u044d\u0448\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e - 5000 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0441\u0443\u0442\u043a\u0438 #\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 my_personal_app \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u0441\u0441\u044b\u043b\u043a\u0443 \u0432\u0438\u0434\u0430 https:\/\/oauth.vk.com\/blank.html#access_token=MNOGO_BUKAV&expires_in=0&user_id=123456. \u0418\u0437 \u044d\u0442\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 MNOGO_BUKAV. \u0412 config.ini.php \u0432 \u0440\u0430\u0437\u0434\u0435\u043b Vk2Bridge \u0432\u0441\u0442\u0430\u0432\u044c\u0442\u0435 access_token [Vk2Bridge] access_token = "MNOGO_BUKAV" \u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f @em92. \u0414\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u043e \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0432\u043e\u0435\u0433\u043e standalone-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0434\u043e \u0432 \u0441\u0441\u044b\u043b\u043a\u0435 \u0438\u0437 \u043f.1. \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 client_id \u043d\u0430 \u0441\u0432\u043e\u0439.","tags":"","url":"Bridge_Specific\/Vk2.html"}]});
\ No newline at end of file
+load_search_index({"pages":[{"title":"RSS-Bridge","text":"RSS-Bridge is a web application. It generates web feeds for websites that don\u2019t have one. Officially hosted instance: https:\/\/rss-bridge.org\/bridge01\/ You want to know more about RSS-Bridge? Check out our project goals. You want to contribute and don\u2019t know how? Check out our How can I contribute? section. You are a developer and searching for more details? Check out our For developers section. You want to know what is required to host RSS-Bridge? Check out the Requirements section. You want to host RSS-Bridge? Check out the For hosts section. You have questions? Check out the FAQ.","tags":"","url":"index.html"},{"title":"Project-goals","text":"RSS-Bridge aims at sites that: don\u2019t provide public accessible Atom or RSS feeds force their users to subscribe to e-mail notifications force their users to use their own proprietary APIs require their users to come back on a regular basis in order to check for new content RSS-Bridge will generate feeds based on \u201cbridges\u201d that are developed for any site. Those bridges will collect data and extract all necessary information which is then converted into various feed formats like Atom or RSS.","tags":"","url":"General\/Project_goals.html"},{"title":"Contribute","text":"There are many things you can do to contribute to RSS-Bridge as developer or as user without any knowledge in PHP or (web) development. Here are a few things: Share RSS-Bridge with your friends (Twitter, Facebook, \u2026you name it\u2026) Report broken bridges or bugs here Request new features or propose ideas (via Issues) Discuss bugs, features, ideas or issues Add new bridges or improve the API Improve this documentation Host RSS-Bridge","tags":"","url":"General\/Contribute.html"},{"title":"Requirements","text":"RSS-Bridge requires either of the following: #A Web server* with: PHP 7.4 (or higher) openssl extension libxml extension (enabled by default, see PHP Manual) mbstring extension simplexml extension curl extension json extension filter extension zip (for some bridges) sqlite3 extension (only when using SQLiteCache) Enable extensions by un-commenting the corresponding line in your PHP configuration (php.ini). #A Linux server with: Docker server configured (Any recent version should do) 100MB of disk space To setup RSS Bridge using Docker, see the Docker Guide on installing RSS Bridge.","tags":"","url":"General\/Requirements.html"},{"title":"Screenshots","text":"#Welcome screen: #rss-bridge hashtag (#rss-bridge) search on Twitter: in Atom format (as displayed by Firefox)","tags":"","url":"General\/Screenshots.html"},{"title":"FAQ","text":"This page provides a collection of frequently asked questions and their answers. Please check this page before opening a new Issue :revolving_hearts: Why doesn\u2019t my bridge show new contents? How can I make a bridge update more frequently? Firefox doesn\u2019t show feeds anymore, what can I do? #Why doesn\u2019t my bridge show new contents? RSS-Bridge creates a cached version of your feed in order to reduce traffic and respond faster. The cached version is created on the first request and served for all subsequent requests. On every request RSS-Bridge checks if the cache timeout has elapsed. If the timeout has elapsed, it loads new contents and updates the cached version. Notice: RSS-Bridge only updates feeds if you actively request it, for example by pressing F5 in your browser or using a feed reader. The cache duration is bridge specific and can last anywhere between five minutes and 24 hours. You can specify a custom cache timeout for each bridge if this option has been enabled on the server. #How can I make a bridge update more frequently? You can only do that if you are hosting the RSS-Bridge instance: Enable custom_timeout Alternatively, change the default timeout for your bridge by modifying the CACHE_TIMEOUT constant in the relevant bridge file (e.g here for the Filter Bridge). #Firefox doesn\u2019t show feeds anymore, what can I do? As of version 64, Firefox removed support for viewing Atom and RSS feeds in the browser. This results in the browser downloading the pages instead of showing contents. Further reading: https:\/\/support.mozilla.org\/en-US\/kb\/feed-reader-replacements-firefox https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=1477667 To restore the original behavior in Firefox 64 or higher you can use following Add-on which attempts to recreate the original behavior (with some sugar on top): https:\/\/addons.mozilla.org\/en-US\/firefox\/addon\/rsspreview\/","tags":"","url":"General\/FAQ.html"},{"title":"Public Hosts","text":"#Public instances Country Address Status Contact Comment https:\/\/rss-bridge.org\/bridge01 @dvikan London, Digital Ocean https:\/\/rssbridge.flossboxin.org.in\/ @vdbhb59 Hosted with OVH SAS (Maintained in India) https:\/\/rss-bridge.cheredeprince.net\/ @La_B\u00e9casse Self-Hosted at home in France https:\/\/rss-bridge.sans-nuage.fr @Alsace R\u00e9seau Neutre Hosted in Alsace, France https:\/\/rss-bridge.lewd.tech @Erisa Hosted in London, protected by Cloudflare Rate Limiting https:\/\/bridge.easter.fr @chatainsim Hosted in Is\u00e8re, France https:\/\/wtf.roflcopter.fr\/rss-bridge\/ roflcopter.fr Hosted in France https:\/\/rss.nixnet.services @amolith Hosted in Wunstorf, Germany https:\/\/rss-bridge.ggc-project.de @ggc-project.de Hosted in Steyr, Austria https:\/\/rssbridge.bus-hit.me @austinhuang0131 Hosted with Oracle in Qu\u00e9bec, Canada https:\/\/feeds.proxeuse.com Proxeuse Hosted in Germany https:\/\/rssbridge.boldair.dev @Boldairdev Latest Github release, Hosted on PHP 8.0 in Roubaix, France https:\/\/rss-bridge.bb8.fun @captn3m0 Hosted in Bengaluru, India https:\/\/ololbu.ru\/rss-bridge @Ololbu Hosted in Moscow, Russia https:\/\/tools.bheil.net\/rss-bridge\/ @bheil Hosted in Germany https:\/\/bridge.suumitsu.eu @mitsukarenai Hosted in Paris, France https:\/\/feed.eugenemolotov.ru @em92 Hosted in Amsterdam, Netherlands https:\/\/rss-bridge.mediani.de @sokai Hosted with Netcup, Germany https:\/\/rss.foxhaven.cyou @Aysilu Hosted with Timeweb (Maintained in Poland) https:\/\/rss.m3wz.su @m3oweezed Poland, Hosted with Timeweb Cloud https:\/\/rb.ash.fail @ash Hosted with Hostaris, Germany https:\/\/rss.noleron.com @ihor Hosted with Hosting Ukraine, Ukraine https:\/\/rssbridge.projectsegfau.lt @gi-yt Self-Hosted at Mumbai, India with Airtel (ISP) #Inactive instances Country Address Status Contact Comment https:\/\/rss-bridge.snopyta.org @Perflyst Hosted in Helsinki, Finland http:\/\/rb.vern.cc\/ @vern.cc Hosted with Hetzner, US","tags":"","url":"General\/Public_Hosts.html"},{"title":"CLI","text":"RSS-Bridge supports calls via CLI. You can use the same parameters as you would normally use via the URI. Example: php index.php action=display bridge=DansTonChat format=Json #Required parameters RSS-Bridge requires a few parameters that must be specified on every call. Omitting these parameters will result in error messages: #action Defines how RSS-Bridge responds to the request. Value Description action=list Returns a JSON formatted list of bridges. Other parameters are ignored. action=display Returns (displays) a feed. #bridge This parameter specifies the name of the bridge RSS-Bridge should return feeds from. The name of the bridge equals the class name of the bridges in the .\/bridges\/ folder without the \u2018Bridge\u2019 prefix. For example: DansTonChatBridge => DansTonChat. #format This parameter specifies the format in which RSS-Bridge returns the contents. RSS-Bridge currently supports five formats: Atom, Html, Json, Mrssand Plaintext. #Optional parameters RSS-Bridge supports optional parameters. These parameters are only valid if the options have been enabled in the index.php script. #_noproxy This parameter is only available if a proxy server has been specified via proxy.url and proxy.by_bridge has been enabled. This is a Boolean parameter that can be set to true or false. #Bridge parameters Each bridge can specify its own set of parameters. As in the example above, some bridges don\u2019t specify any parameters or only optional parameters that can be neglected. For more details read the PARAMETERS definition for your bridge.","tags":"","url":"CLI\/index.html"},{"title":"For Hosts","text":"This section is directed at hosts and server administrators. To install RSS-Bridge, please follow the installation instructions. You must have access to a web server with a working PHP environment! RSS-Bridge comes with a large amount of bridges. Only few bridges are enabled by default. Unlock more bridges by adding them to the whitelist. Some bridges could be implemented more efficiently by actually using proprietary APIs, but there are reasons against it: RSS-Bridge exists in the first place to NOT use APIs. See the rant APIs require private keys that could be stored on servers running RSS-Bridge, which is a security concern, involves complex authorizations for inexperienced users and could cause harm (when using paid services for example). In a closed environment (a server only you use for yourself) however you might be interested in using them anyway. So, check this possible implementation of an anti-captcha solution.","tags":"","url":"For_Hosts\/index.html"},{"title":"Installation","text":"In order to install RSS-Bridge on your own web server* do as follows: Make sure your web server meets all requirements Download the ZIP file of the last stable release Place all files on your web server For linux hosts: Grant read-write-access for www-data to the .\/cache directory (chown -R www-data .\/cache) You have successfully installed RSS-Bridge. Instructions for Docker setups are at Docker Installation","tags":"","url":"For_Hosts\/Installation.html"},{"title":"Updating","text":"Updating an existing installation is very simple, depending on your type of installation. #Release Build Download latest version Extract all files Replace existing files This will update all core files to the latest version. Your custom configuration and bridges are left untouched. Keep in mind that changes to any core file of RSS-Bridge will be replaced. #Docker Simply get the latest Docker build via :latest or specific builds via :<tag-name>. #Heroku #If you didn\u2019t fork the repo before Fork the repo by clicking the Fork button at the top right of this page (must be on desktop site). Then on your Heroku account, go to the application. Click on the Deploy tab and connect the repo named yourusername\/rss-bridge. Do a manual deploy of the master branch. #If you forked the repo before Click here to create a new pull request to your fork. Select compare across forks, make the base repository yourusername\/rss-bridge and ensure the branch is set to master. Put any title you want and create the pull request. On the page that comes after this, merge the pull request. You then want to go to your application in Heroku, connect your fork via the Deploy tab and deploy the master branch. You can turn on auto-deploy for the master branch if you don\u2019t want to go through the process of logging into Heroku and deploying the branch every time changes to the repo are made in the future. #Git To get the latest changes from the master branch git pull To use a specific tag git fetch --all git checkout tags\/<tag-name>","tags":"","url":"For_Hosts\/Updating.html"},{"title":"Docker Installation","text":"This guide is for people who want to run RSS Bridge using Docker. If you want to run it a simple PHP Webhost environment, see Installation instead. #Setup #Create the container docker create \\ --name=rss-bridge \\ --volume <\/local\/custom\/path>:\/config \\ --publish 3000:80 \\ rssbridge\/rss-bridge:latest #Run it docker start rss-bridge Access it using http:\/\/IP_Address:3000. If you\u2019d like to run a specific version, you can run it by changing the \u2018:latest\u2019 on the image to a tag listed here The server runs on port 80 internally, map any port of your choice (in this example 3000). You can run it using a docker-compose.yml as well: version: '2' services: rss-bridge: image: rssbridge\/rss-bridge:latest volumes: - <\/local\/custom\/path>:\/config ports: - 3000:80 restart: unless-stopped #Container access and information Function Command Shell access (live container) docker exec -it rss-bridge \/bin\/sh Realtime container logs docker logs -f rss-bridge #Adding custom bridges and configurations If you want to add a bridge that is not part of \/bridges, you can map a folder to the \/config folder of the rss-bridge container. Create a folder in the location of your docker-compose.yml or your general docker working area (in this example it will be \/home\/docker\/rssbridge\/config ). Copy your custom bridges to the \/home\/docker\/rssbridge\/config folder. Applies also to config.ini.php. Map the folder to \/config inside the container. To do that, replace the <\/local\/custom\/path> from the previous examples with \/home\/docker\/rssbridge\/config","tags":"","url":"For_Hosts\/Docker_Installation.html"},{"title":"Heroku Installation","text":"This guide is for people who want to run RSS Bridge on Heroku. You can run it on Heroku for free, however make sure your RSS reader interval is not set to a fast rate, otherwise your Heroku hours will use up quicker. Heroku puts the app to sleep after 30 mins of no activity. When the app is asleep no Heroku hours are used. So choose an interval that won\u2019t make the app exceed the limit! You can increase your Heroku hours to 1000 a month from 550 a month by simply verifying your account with a credit card. #Deploy button You can simply press the button below to easily deploy RSS Bridge on Heroku and use the default bridges. Or you can follow the manual instructions given below. #Manual deploy Fork this repo by clicking the Fork button at the top right of this page (only on desktop site) To customise what bridges can be used if need, see here. You don\u2019t need to do this if you\u2019re fine with the default bridges. Log in to Heroku and create a new app. The app name will be the URL of the RSS Bridge (appname.herokuapp.com) Go to Deploy, select the GitHub option and connect your GitHub account. Search for the repo named yourusername\/rss-bridge Deploy the master branch.","tags":"","url":"For_Hosts\/Heroku_Installation.html"},{"title":"Whitelisting","text":"Modify config.ini.php to limit available bridges. Those changes should be applied in the [system] section. #Enable all bridges [system] enabled_bridges[] = * #Enable some bridges [system] enabled_bridges[] = TwitchBridge enabled_bridges[] = GettrBridge #Enable all bridges (legacy shortcut) echo '*' > whitelist.txt #Enable some bridges (legacy shortcut) echo -e "TwitchBridge\\nTwitterBridge" > whitelist.txt","tags":"","url":"For_Hosts\/Whitelisting.html"},{"title":"Authentication","text":"Depending on your servers abilities you can choose between two types of authentication: .htaccess RSS-Bridge Authentication General advice: Make sure to use a strong password, no matter which solution you choose! Enable HTTPS on your server to ensure your connection is encrypted and secure! #.htaccess .htaccess files are commonly used to restrict access to files on a web server. One of the features of .htaccess files is the ability to password protect specific (or all) directories. If setup correctly, a password is required to access the files. The usage of .htaccess files requires three basic steps: Enable .htaccess Create a .htpasswd file Create a .htaccess file #Enable .htaccess This process depends on the server you are using. Some providers may require you to change some settings, or place\/change some file. Here are some helpful links for your server (please add your own if missing :sparkling_heart:) Apache: http:\/\/ask.xmodulo.com\/enable-htaccess-apache.html #Create a .htpasswd file The .htpasswd file contains the user name and password used for login to your web server. Please notice that the password is stored in encrypted form, which requires you to encrypt your password before creating the .htpasswd file! Here are three ways of creating your own .htpasswd file: 1) Example file Example .htpasswd file (user name: \u201ctest\u201d, password: \u201ctest\u201d): test:$apr1$a52u9ILP$XTNG8qMJiEXSm1zD0lQcR0 Just copy and paste the contents to your .htpasswd file. 2) Online generator (read warning!) You can create your own .htpasswd file online using a .htpasswd generator like this: https:\/\/www.htaccesstools.com\/htpasswd-generator\/ WARNING! Never insert real passwords to an online generator! 3) Generate your own password Another way to create your own .htpasswd file is to run this script on your server (it\u2019ll output the data for you, you just have to paste it int a .htpasswd file): <?php \/\/ Password to be encrypted for a .htpasswd file $clearTextPassword = 'some password'; \/\/ Encrypt password $password = crypt($clearTextPassword, base64_encode($clearTextPassword)); \/\/ Print encrypted password echo $password; ?> source: https:\/\/www.htaccesstools.com\/articles\/create-password-for-htpasswd-file-using-php\/ #Create a .htaccess file The .htaccess file is used to specify which directories are password protected. For that purpose you should place the file in whatever directory you want to restrict access. If you want to restrict access to RSS-Bridge in general, you should place the file in the root directory (where index.php is located). Two parameters must be specified in the .htaccess file: AuthName AuthUserFile AuthName specifies the name of the authentication (i.e. \u201cRSS-Bridge\u201d). AuthUserFile defines the absolute path to a .htpasswd file. Here are two ways of creating your own .htaccess file: 1) Example file AuthType Basic AuthName "My Protected Area" AuthUserFile \/path\/to\/.htpasswd Require valid-user Notice: You must change the AuthUserFile location to fit your own server (i.e. \/var\/www\/html\/rss-bridge\/.htpasswd) 2) Online generator You can use an online generator to create the file for you and copy-paste it to your .htaccess file: https:\/\/www.htaccesstools.com\/htaccess-authentication\/ #RSS-Bridge Authentication RSS-Bridge ships with an authentication module designed for single user environments. You can enable authentication and specify the username & password in the configuration file. Please notice that the password is stored in plain text and thus is readable to anyone who can access the file. Make sure to restrict access to the file, so that it cannot be read remotely!","tags":"","url":"For_Hosts\/Authentication.html"},{"title":"Customizations","text":"RSS-Bridge ships a few options the host may or may not activate. All options are listed in the config.default.ini.php file, see Custom Configuration section for more information. #Customizable cache timeout Sometimes it is necessary to specify custom timeouts to update contents more frequently than the bridge maintainer intended. In these cases the client may specify a custom cache timeout to prevent loading contents from cache earlier (or later). This option can be activated by setting the cache.custom_timeout option to true. When enabled each bridge receives an additional parameter Cache timeout in seconds that can be set to any value between 1 and 86400 (24 hours). If the value is not within the limits the default settings apply (as specified by the bridge maintainer). The cache timeout is send to RSS-Bridge using the _cache_timeout parameter. RSS-Bridge will return an error message if the parameter is received and the option is disabled.","tags":"","url":"For_Hosts\/Customizations.html"},{"title":"Custom Configuration","text":"RSS-Bridge supports custom configurations for common parameters on the server side! A default configuration file (config.default.ini.php) is shipped with RSS-Bridge. Please do not edit this file, as it gets replaced when upgrading RSS-Bridge! You should, however, use this file as template to create your own configuration (or leave it as is, to keep the default settings). In order to create your own configuration perform following actions: Create the file config.ini.php in the RSS-Bridge root folder (next to config.default.ini.php) Copy the contents from config.default.ini.php to your configuration file Change the parameters to satisfy your requirements RSS-Bridge will automatically detect the config.ini.php and use it. If the file doesn\u2019t exist it will default to config.default.ini.php automatically. Notice: If a parameter is not specified in your config.ini.php RSS-Bridge will automatically use the default settings from config.default.ini.php. #Available parameters The configuration file is split into sections: system http client cache proxy authentication admin error System: This section specifies system specific parameters Http client: This section has http client options Cache: This section is all about the caching behavior of RSS-Bridge Proxy: This section can be used to specify a proxy server for RSS-Bridge to utilize for fetching contents Authentication: This section defines parameters to require authentication to use RSS-Bridge Admin: This section specifies parameters related to the administrator of your instance of RSS-Bridge #System This section provides following parameters: timezone #Timezone Defines the timezone used by RSS-Bridge. This parameter can be set to any value of the values defined at https:\/\/www.php.net\/manual\/en\/timezones.php The default value is UTC. #Cache This section provides following parameters: type custom_timeout #type Defines the cache type used by RSS-Bridge. Type Description file File based (default) sqlite SQLite database memcached Memcached service #custom_timeout Allow users to specify custom timeout for specific requests. true = enabled false = disabled (default) #Proxy This section provides following parameters: url name by_bridge #url Sets the proxy url (i.e. \u201ctcp:\/\/192.168.0.0:32\u201d) "" = Proxy disabled (default) #name Sets the proxy name that is shown on the bridge instead of the proxy url. "" = Show proxy url (default: \u201cHidden proxy name\u201d) #by_bridge Allow users to disable proxy usage for specific requests. true = enabled false = disabled (default) #Http client This section provides the following parameters: timeout useragent #timeout Default network timeout. #useragent Default user agent. #Authentication This section provides following parameters: enable username password #enable Enables authentication for RSS-Bridge. Notice: Login is required for all requests when enabled! Make sure to update feed subscriptions accordingly. true = enabled false = disabled (default) #username Defines the user name used for login. #password Defines the password used for login. Use a strong password to prevent others from guessing your login! #Admin This section provides following parameters: email #email Advertises an email address where people can reach the administrator. Notice: This address is displayed on the main page, visible to everyone! "" = Disabled (default) Example: email = "admin@instance.rss-bridge.com" #error This section provides following parameters: output report_limit #output Defines how error messages are returned by RSS-Bridge feed: As part of the feed (default) http: As HTTP error message none: No errors are reported #report_limit Defines how often an error must occur before it is reported to the user report_limit: 1 (default)","tags":"","url":"For_Hosts\/Custom_Configuration.html"},{"title":"For Developers","text":"This area is intended for developers who decide to contribute to RSS-Bridge. It is written in PHP. If you are new to RSS-Bridge you should make yourself familiar with some general aspects: Coding style policy Folder structure Debug mode Bridge API Cache API Technical recommendations","tags":"","url":"For_Developers\/index.html"},{"title":"Coding style policy","text":"This section explains the coding style policy for RSS-Bridge with examples and references to external resources. Please make sure your code is compliant before opening a pull request. You will automatically be notified if issues were found in your pull request. You must fix those issues before the pull request will be merged. Refer to phpcs.xml for a complete list of policies enforced by Travis-CI. If you want to run the checks locally, make sure you have phpcs and phpunit installed on your machine and run following commands in the root directory of RSS-Bridge (tested on Debian): .\/vendor\/bin\/phpcs --standard=phpcs.xml --warning-severity=0 --extensions=php -p .\/ .\/vendor\/bin\/phpunit The following list provides an overview of all policies applied to RSS-Bridge. #Whitespace #Add a new line at the end of a file Each PHP\/CSS\/HTML file must end with a new line at the end of a file. Example Bad { \/\/ code here } \/\/ This is the end of the file Good { \/\/ code here } \/\/ This is the end of the file Reference: PSR2.Files.EndFileNewline #Do not add a whitespace before a semicolon A semicolon indicates the end of a line of code. Spaces before the semicolon is unnecessary and must be removed. Example Bad echo 'Hello World!' ; Good echo 'Hello World!'; Reference: Squiz.WhiteSpace.SemicolonSpacing #Do not add whitespace at start or end of a file or end of a line Whitespace at the end of lines or at the start or end of a file is invisible to the reader and absolutely unnecessary. Thus it must be removed. Reference: Squiz.WhiteSpace.SuperfluousWhitespace #Indentation #Use spaces indentation #Maximum Line Length 180 #Strings #Whenever possible use single quote strings PHP supports both single quote strings and double quote strings. For pure text you must use single quote strings for consistency. Double quote strings are only allowed for special characters (i.e. "\\n") or inlined variables (i.e. "My name is {$name}"); Example Bad echo "Hello World!"; Good echo 'Hello World!'; Reference: Squiz.Strings.DoubleQuoteUsage #Add spaces around the concatenation operator The concatenation operator should have one space on both sides in order to improve readability. Example Bad $text = $greeting.' '.$name.'!'; Good (add spaces) $text = $greeting . ' ' . $name . '!'; You may break long lines into multiple lines using the concatenation operator. That way readability can improve considerable when combining lots of variables. Example Bad $text = $greeting.' '.$name.'!'; Good (split into multiple lines) $text = $greeting . ' ' . $name . '!'; Reference: Squiz.Strings.ConcatenationSpacing #Use a single string instead of concatenating While concatenation is useful for combining variables with other variables or static text. It should not be used to combine two sets of static text. See also: Maximum line length Example Bad $text = 'This is' . 'a bad idea!'; Good $text = 'This is a good idea!'; Reference: Generic.Strings.UnnecessaryStringConcat #Constants #Use UPPERCASE for constants As in most languages, constants should be written in UPPERCASE. Notice: This does not apply to keywords! Example Bad const pi = 3.14; Good const PI = 3.14; Reference: Generic.NamingConventions.UpperCaseConstantName #Keywords #Use lowercase for true, false and null true, false and null must be written in lower case letters. Example Bad if($condition === TRUE && $error === FALSE) { return NULL; } Good if($condition === true && $error === false) { return null; } Reference: Generic.PHP.LowerCaseConstant #Operators #Operators must have a space around them Operators must be readable and therefore should have spaces around them. Example Bad $text='Hello '.$name.'!'; Good $text = 'Hello ' . $name . '!'; Reference: Squiz.WhiteSpace.OperatorSpacing #Functions #Parameters with default values must appear last in functions It is considered good practice to make parameters with default values last in function declarations. Example Bad function showTitle($duration = 60000, $title) { ... } Good function showTitle($title, $duration = 60000) { ... } Reference: PEAR.Functions.ValidDefaultValue #Calling functions Function calls must follow a few rules in order to maintain readability throughout the project: Do not add whitespace before the opening parenthesis Example Bad $result = my_function ($param); Good $result = my_function($param); Do not add whitespace after the opening parenthesis Example Bad $result = my_function( $param); Good $result = my_function($param); Do not add a space before the closing parenthesis Example Bad $result = my_function($param ); Good $result = my_function($param); Do not add a space before a comma Example Bad $result = my_function($param1 ,$param2); Good $result = my_function($param1, $param2); Add a space after a comma Example Bad $result = my_function($param1,$param2); Good $result = my_function($param1, $param2); Reference: Generic.Functions.FunctionCallArgumentSpacing #Do not add spaces after opening or before closing bracket Parenthesis must tightly enclose parameters. Example Bad if( $condition ) { ... } Good if($condition) { ... } Reference: PSR2.ControlStructures.ControlStructureSpacing #Structures #Structures must always be formatted as multi-line blocks A structure should always be treated as if it contains a multi-line block. Add a space after closing parenthesis Example Bad if($condition){ ... } Good if($condition) { ... } Add body into new line Example Bad if($condition){ ... } Good if($condition) { ... } Close body in new line Example Bad if($condition){ ... } Good if($condition) { ... } Reference: Squiz.ControlStructures.ControlSignature #If-Statements #Use elseif instead of else if For sake of consistency else if is considered bad practice. Example Bad if($conditionA) { } else if($conditionB) { } Good if($conditionA) { } elseif($conditionB) { } Reference: PSR2.ControlStructures.ElseIfDeclaration #Do not write empty statements Empty statements are considered bad practice and must be avoided. Example Bad if($condition) { \/\/ empty statement } else { \/\/ do something here } Good (invert condition) if(!$condition) { \/\/ do something } Reference: Generic.CodeAnalysis.EmptyStatement #Do not write unconditional if-statements If-statements without conditions are considered bad practice and must be avoided. Example if(true) { } Reference: Generic.CodeAnalysis.UnconditionalIfStatement #Classes #Use PascalCase for class names Class names must be written in PascalCase. Example Bad class mySUPERclass { ... } Good class MySuperClass { ... } Reference: PEAR.NamingConventions.ValidClassName #Do not use final statements inside final classes Final classes cannot be extended, so it doesn\u2019t make sense to add the final keyword to class members. Example Bad final class MyClass { final public function MyFunction() { } } Good (remove the final keyword from class members) final class MyClass { public function MyFunction() { } } Reference: Generic.CodeAnalysis.UnnecessaryFinalModifier #Do not override methods to call their parent It doesn\u2019t make sense to override a method only to call their parent. When overriding methods, make sure to add some functionality to it. Example Bad class MyClass extends BaseClass { public function BaseFunction() { parent::BaseFunction(); } } Good (don\u2019t override the function) class MyClass extends BaseClass { } Reference: Generic.CodeAnalysis.UselessOverridingMethod #abstract and final declarations MUST precede the visibility declaration When declaring abstract and final functions, the visibility (scope) must follow after abstract or final. Example Bad class MyClass extends BaseClass { public abstract function AbstractFunction() { } public final function FinalFunction() { } } Good (abstract and final before public) class MyClass extends BaseClass { abstract public function AbstractFunction() { } final public function FinalFunction() { } } Reference: PSR2.Methods.MethodDeclaration #static declaration MUST come after the visibility declaration The static keyword must come after the visibility (scope) parameter. Example Bad class MyClass extends BaseClass { static public function StaticFunction() { } } Good (static after public) class MyClass extends BaseClass { public static function StaticFunction() { } } Reference: PSR2.Methods.MethodDeclaration #Casting #Do not add spaces when casting The casting type should be put into parenthesis without spaces. Example Bad $text = ( string )$number; Good $text = (string)$number; Reference: Squiz.WhiteSpace.CastSpacing #Arrays #Always use the short array syntax","tags":"","url":"For_Developers\/Coding_style_policy.html"},{"title":"Pull Request policy","text":"Pull requests allow you to improve RSS-Bridge. Maintainers will have to understand your changes before merging. In order to make this process as efficient as possible, please follow the policies explained below. Maintainers will merge your pull request much faster that way. #Fix one issue per pull request It is considered good practice to fix one specific (or a specific set of) error(s). You can open multiple pull requests if you need to address multiple subjects. The same applies to adding features to RSS-Bridge. Maintainers must be able to comprehend your pull request for it to be merged quickly. #Respect the coding style policy The coding style policy requires you to write your code in certain ways. If you plan to get it merged into RSS-Bridge, please make sure your code follows the policy. Maintainers will only merge pull requests that pass all tests. #Properly name your commits Commits are not only for show, they do help maintainers understand what you did in your pull request, just like a table of contents in a well formed book (or Wiki). Here are a few rules you should follow: When fixing a bridge (located in the bridges directory), write [BridgeName] Feature (i.e. [YoutubeBridge] Fix typo in video titles). When fixing other files, use [FileName] Feature (i.e. [index.php] Add multilingual support). When fixing a general problem that applies to multiple files, write category: feature (i.e. bridges: Fix various typos).","tags":"","url":"For_Developers\/Pull_Request_policy.html"},{"title":"Folder structure","text":"The repository contains a few folders that make up RSS-Bridge. Here is a brief description of what you can expect to find where: Folder Description actions\/ Contains all \u201ccontrollers\u201d for the web front-end. bridges\/ Contains all bridges that are currently supported. Each file represents one Bridge that is displayed on the Welcome screen of RSS-Bridge caches\/ Contains implementation for different cache back-ends supported. contrib\/ Contains various helpers for development and release process. docs\/ Contains this documentation. formats\/ Contains all export formats. lib\/ Contains the core API and helper functions. static\/ Contains all static assets for the web front-end, including images, style sheets and JavaScript code. templates\/ Contains templates for producing the HTML of the web front-end. tests\/ Contains the test suite and fixtures. vendor\/ Contains third-party libraries used by RSS-Bridge. Development of all files in this folder must be done in the vendor specific repository (not part of RSS-Bridge)","tags":"","url":"For_Developers\/Folder_structure.html"},{"title":"Actions","text":"RSS-Bridge currently supports four \u2018actions\u2019 which it can operate: Display (?action=display) Detect (?action=detect) List (?action=list) FindFeed (?action=findfeed) #Display The display action returns feeds generated by bridges. It requires additional parameter, some of which are specific to each bridge (see implementation details for your specific bridge). The following list contains mandatory parameter applicable to all bridges, excluding parameters that require additional options. Errors are returned for missing mandatory parameters: Parameter Required Description bridge yes Specifies the name of the bridge to display. Possible values are determined from the bridges available to the current instance of RSS-Bridge and the whitelist. format yes Specifies the name of the format to use for displaying the feed. Possible values are determined from the formats available to the current instance of RSS-Bridge. #Detect The detect action attempts to redirect the user to an appropriate display action for a feed based on a supplied URL. As bridges have to individually implement this it may not work for every bridge. If an appropriate bridge is found, a 301 Moved Permanently HTTP status code is returned with a relative location for a display action. If no appropriate bridge is found or a required parameter is missing, a 400 Bad Request status code is returned. The parameters for this action are listed below: Parameter Required Description url yes Specifies the URL to attempt to find a feed from. The value of this should be URL encoded. format yes Specifies the name of the format to use for displaying the feed. This is passed to the detected display action. Possible values are determined from the formats available to the current instance of RSS-Bridge. #List The list action returns a JSON formatted text containing information on all bridges available to the current instance of RSS-Bridge. Inactive bridges (not whitelisted) are included as well. Broken bridges are also included, but with limited parameters (only "status": "inactive"). This example shows JSON data for a single bridge: { "bridges": { "ABCTabs": { "status": "active", "uri": "https:\\\/\\\/www.abc-tabs.com\\\/", "name": "ABC Tabs Bridge", "parameters": [], "maintainer": "kranack", "description": "Returns 22 newest tabs" } }, "total": 1 } The top-level JSON object contains two parameters: bridges: A collection of bridges total: The total number of bridges { "bridges": { }, "total": 0 } #bridges The bridges parameter is a collection of bridge objects. The name of each object represents the name of the bridge as needed for the display action. Each object contains parameters, most of which are optional. The following table summarizes the parameters: Parameter Optional Description status No Indicates the status of the bridge. Possible values are \u2018active\u2019 and \u2018inactive\u2019. Only active bridges can be used for the display action. uri Yes Returns the URI of the bridge, as returned by the getURI function of the bridge. name Yes Returns the name of the bridge, as returned by the getName function of the bridge. parameters Yes Returns the PARAMETERS object of the bridge maintainer Yes Returns the name(s) of maintainer(s) for the bridge description Yes Returns the description of the bridge #total This parameter represents the total number of bridges available to the current instance of RSS-Bridge. #FindFeed The findfeed action attempts to list all available feeds based on a supplied URL for the active bridges of this instance. As bridges have to individually implement detectParameters, this it may not work for every bridge. If one or more bridges return a feed, a JSON data array structure is returned. If no feeds were found, a 404 Not Found status code is returned. If a required parameter is missing, a 400 Bad Request status code is returned. For each feed, the whole feed URL is sent in the url member, the feed specific bridge parameters metadata in the bridgeData member and the Bridge metadata in the bridgeMeta member. This example shows JSON data for the NASA Instagram account URL (https:\/\/www.instagram.com\/nasa\/) using the Html format : [ { "url": "https:\/\/rssbridge.host\/?action=display&context=Username&u=nasa&bridge=InstagramBridge&format=Html", "bridgeParams": { "context": "Username", "u": "nasa", "bridge": "InstagramBridge", "format": "Html" }, "bridgeData": { "context": { "name": "Context", "value": "Username" }, "u": { "name": "username", "value": "nasa" } }, "bridgeMeta": { "name": "Instagram Bridge", "description": "Returns the newest images", "parameters": { "Username": { "u": { "name": "username", "exampleValue": "aesoprockwins", "required": true } }, "Hashtag": { "h": { "name": "hashtag", "exampleValue": "beautifulday", "required": true } }, "Location": { "l": { "name": "location", "exampleValue": "london", "required": true } }, "global": { "media_type": { "name": "Media type", "type": "list", "required": false, "values": { "All": "all", "Video": "video", "Picture": "picture", "Multiple": "multiple" }, "defaultValue": "all" }, "direct_links": { "name": "Use direct media links", "type": "checkbox" } } }, "icon": "https:\/\/www.instagram.com\/\/favicon.ico" } } ] The parameters for this action are listed below: Parameter Required Description url yes Specifies the URL to attempt to find a feed from. The value of this should be URL encoded. format yes Specifies the name of the format to use for the URL of the feeds. This is passed to the detected display action. Possible values are determined from the formats available to the current instance of RSS-Bridge.","tags":"","url":"For_Developers\/Actions.html"},{"title":"Debug mode","text":"Warning! Enabling debug mode on a public server may result in malicious clients retrieving sensitive data about your server and possibly gaining access to it. Do not enable debug mode on a public server, unless you understand the implications of your doing! Debug mode enables error reporting and prevents loading data from the cache (data is still written to the cache). To enable debug mode, set in config.ini.php: enable_debug_mode = true Allow only explicit ip addresses: debug_mode_whitelist[] = 127.0.0.1 debug_mode_whitelist[] = 192.168.1.10 Notice: An empty file enables debug mode for anyone! The bridge whitelist still applies! (debug mode does not enable all bridges) RSS-Bridge will give you a visual feedback when debug mode is enabled. While debug mode is active, RSS-Bridge will write additional data to your servers error.log. Debug mode is controlled by the static class Debug. It provides three core functions: Debug::isEnabled(): Returns true if debug mode is enabled. Debug::log($message): Adds a message to error.log. It takes one parameter, which can be anything. Example: Debug::log('Hello World!'); Notice: Debug::log($message) calls Debug::isEnabled() internally. You don\u2019t have to do that manually.","tags":"","url":"For_Developers\/Debug_mode.html"},{"title":"Github Codespaces Tutorial","text":"Github Codespaces lets you develop RSS-Bridge right from within your browser in an online hosted environment without the need to install anything. Github Codespaces is free, check out this for more info. #How to get started You must enable Codespaces for your account here . After you are enabled to use Codespaces, you will get the additional functionality that you can see in the screenshots below. #How to develop for RSS-Bridge This will give you an example workflow of how to create a bridge for RSS-Bridge using codespaces Fork the main RSS-Bridge repo On your own repo, click the \u201ccode\u201d icon on the top on your repo and select \u201cCreate codespace on master\u201d A new window will open and show this screen. This means that your dev environment is being prepared When the window has loaded, give it some time to run all the preparation scripts. You will see that it is done when you see a \u201cListen for Xdebug (rss-bridge)\u201d line in the bottom row At this point, there is a running instance of RSS-Bridge active that you can open by clicking on the \u201cPORTS\u201d tab and then on the icon to open the website for port 3100 Xdebug is already started so you can set breakpoints and check out the variables in the debug pane You can now create a new branch for your new bridge by clicking on the \u201cmaster\u201d entry in the bottom left and select \u201ccreate new branch\u201d from the menu. You can commit straight from the IDE as your github credentials are already included in the Codespace. To open a PR, either go back to the Github website and open it there or do it right from the Codespaces instance using the github integration (when you push a new branch, it will ask you if you want to open a new PR). #How-Tos This guide assumes that you already know the basics of php development, some basics in VScode and some basics in working with git. If you want to know more about any of these steps, check out these How-Tos Check How to create a new Bridge on how to do that. Check This Youtube Tutorial for a quick introduction to using VSCode with Git (ignore the initial git setup, Codespaces does that for you)","tags":"","url":"For_Developers\/Github_Codespaces_Tutorial.html"},{"title":"Development Environment Setup","text":"These are examples of how to setup a local development environment to add bridges, improve the docs, etc. #Docker The following can serve as an example for using docker: # create a new directory mkdir rss-bridge-contribution cd rss-bridge-contribution # clone the project into a subfolder git clone https:\/\/github.com\/RSS-Bridge\/rss-bridge Then add a docker-compose.yml file: version: '3' services: rss-bridge: build: context: .\/rss-bridge ports: - 3000:80 volumes: - .\/config:\/config - .\/rss-bridge\/bridges:\/app\/bridges You can then access RSS-Bridge at localhost:3000 and add your bridge to the rss-bridge\/bridges folder. If you need to edit any other files, like from the lib folder add this to the volumes section: .\/rss-bridge\/lib:\/app\/lib. #Docs with Docker If you want to edit the docs add this to your docker-compose.yml: services: [...] daux: image: daux\/daux.io ports: - 8085:8085 working_dir: \/build volumes: - .\/rss-bridge\/docs:\/build\/docs network_mode: host and run for example the daux serve command with docker-compose run --rm daux daux serve. After that you can access the docs at localhost:8085 and edit the files in rss-bridge\/docs.","tags":"","url":"For_Developers\/Development_Environment_Setup.html"},{"title":"Bridge API","text":"A Bridge is a class that allows RSS-Bridge to create an RSS-feed from a website. A Bridge represents one element on the Welcome screen and covers one or more sites to return feeds for. It is developed in a PHP file located in the bridges\/ folder (see Folder structure) and extends one of the base classes of RSS-Bridge: Base class Description BridgeAbstract This class is intended for standard Bridges that need to filter HTML pages for content. FeedExpander Expand\/modify existing feed urls WebDriverAbstract XPathAbstract This class is meant as an alternative base class for bridge implementations. It offers preliminary functionality for generating feeds based on XPath expressions. For more information about how to create a new Bridge, read How to create a new Bridge?","tags":"","url":"Bridge_API\/index.html"},{"title":"How to create a new bridge","text":"Create a new file in the bridges\/ folder (see Folder structure). The file name must be named according to following specification: It starts with the full name of the site All white-space must be removed The first letter of a word is written in upper-case, unless the site name is specified otherwise (example: Freenews, not FreeNews, because the site is named \u2018Freenews\u2019) The first character must be upper-case The file name must end with \u2018Bridge\u2019 The file type must be PHP, written in small letters (seriously!) \u201c.php\u201d Examples: Site Filename Wikipedia WikipediaBridge.php Facebook FacebookBridge.php GitHub GitHubBridge.php Freenews FreenewsBridge.php The file must start with the PHP tags and end with an empty line. The closing tag ?> is omitted. Example: <?php \/\/ PHP code here \/\/ This line is empty (just imagine it!) The next step is to extend one of the base classes. Refer to one of an base classes listed on the Bridge API page.","tags":"","url":"Bridge_API\/How_to_create_a_new_bridge.html"},{"title":"BridgeAbstract","text":"BridgeAbstract is a base class for standard bridges. It implements the most common functions to simplify the process of adding new bridges. #Creating a new bridge You need four basic steps in order to create a new bridge: Step 1 - Create a new file Step 2 - Add a class, extending BridgeAbstract Step 3 - Add general constants to the class Step 4 - Implement a function to collect feed data These steps are described in more detail below. At the end of this document you\u2019ll find a complete template based on these instructions. The pictures below show an example based on these instructions: Show pictures Make sure to read these instructions carefully. Please don\u2019t hesitate to open an Issue if you have further questions (or suggestions). Once your bridge is finished, please open a Pull Request, in order to get your bridge merge into RSS-Bridge. #Step 1 - Create a new file Please read these instructions on how to create a new file for RSS-Bridge. #Step 2 - Add a class, extending BridgeAbstract Your bridge needs to be a class, which extends BridgeAbstract. The class name must exactly match the name of the file, without the file extension. For example: MyBridge.php => MyBridge Show example <?PHP class MyBridge extends BridgeAbstract { } \/\/ This line is empty (just imagine it!) #Step 3 - Add general constants to the class In order to present your bridge on the front page, RSS-Bridge requires a few constants: const NAME \/\/ Name of the Bridge (default: "Unnamed Bridge") const URI \/\/ URI to the target website of the bridge (default: empty) const DESCRIPTION \/\/ A brief description of the Bridge (default: "No description provided") const MAINTAINER \/\/ Name of the maintainer, i.e. your name on GitHub (default: "No maintainer") const PARAMETERS \/\/ (optional) Definition of additional parameters (default: empty) const CACHE_TIMEOUT \/\/ (optional) Defines the maximum duration for the cache in seconds (default: 3600) Show example <?PHP class MyBridge extends BridgeAbstract { const NAME = 'My Bridge'; const URI = 'https:\/\/rss-bridge.github.io\/rss-bridge\/Bridge_API\/BridgeAbstract.html'; const DESCRIPTION = 'Returns "Hello World!"'; const MAINTAINER = 'ghost'; } \/\/ This line is empty (just imagine it!) Notice: const PARAMETERS can be used to request information from the user. Refer to these instructions for more information. #Step 4 - Implement a function to collect feed data In order for RSS-Bridge to collect data, you must implement the public function collectData. This function takes no arguments and returns nothing. It generates a list of feed elements, which must be placed into the variable $this->items. Show example <?PHP class MyBridge extends BridgeAbstract { const NAME = 'My Bridge'; const URI = 'https:\/\/rss-bridge.github.io\/rss-bridge\/Bridge_API\/BridgeAbstract.html'; const DESCRIPTION = 'Returns "Hello World!"'; const MAINTAINER = 'ghost'; public function collectData() { $item = []; \/\/ Create an empty item $item['title'] = 'Hello World!'; $this->items[] = $item; \/\/ Add item to the list } } \/\/ This line is empty (just imagine it!) For more details on the collectData function refer to these instructions. #Template Use this template to create your own bridge. Please remove any unnecessary comments and parameters. <?php class MyBridge extends BridgeAbstract { const NAME = 'Unnamed bridge'; const URI = ''; const DESCRIPTION = 'No description provided'; const MAINTAINER = 'No maintainer'; const PARAMETERS = []; \/\/ Can be omitted! const CACHE_TIMEOUT = 3600; \/\/ Can be omitted! public function collectData() { $item = []; \/\/ Create an empty item $item['title'] = 'Hello World!'; $this->items[] = $item; \/\/ Add item to the list } } \/\/ This line is empty (just imagine it!) #PARAMETERS You can specify additional parameters in order to customize the bridge (i.e. to specify how many items to return). This document explains how to specify those parameters and which options are available to you. For information on how to read parameter values during execution, please refer to the getInput function. #Adding parameters to a bridge Parameters are specified as part of the bridge class. An empty list of parameters is defined as const PARAMETERS = []; Show example <?PHP class MyBridge extends BridgeAbstract { \/* ... *\/ const PARAMETERS = []; \/\/ Empty list of parameters (can be omitted) \/* ... *\/ } Parameters are organized in two levels: Level 1 - Context Level 2 - Parameter #Level 1 - Context A context is defined as a associative array of parameters. The name of a context is displayed by RSS-Bridge. Show example const PARAMETERS = [ 'My Context 1' => [], 'My Context 2' => [], ]; Output Notice: The name of a context can be left empty if only one context is needed! Show example const PARAMETERS = [ [] ]; You can also define a set of parameters that will be applied to every possible context of your bridge. To do this, specify a context named global. Show example const PARAMETERS = [ 'global' => [] \/\/ Applies to all contexts! ]; #Level 2 - Parameter Parameters are placed inside a context. They are defined as associative array of parameter specifications. Each parameter is defined by it\u2019s internal input name, a definition in the form 'n' => [];, where n is the name with which the bridge can access the parameter during execution. Show example const PARAMETERS = [ 'My Context' => [ 'n' => [] ] ]; The parameter specification consists of various fields, listed in the table below. Show example const PARAMETERS = array( 'My Context' => array( 'n' => array( 'name' => 'Limit', 'type' => 'number', 'required' => false, 'title' => 'Maximum number of items to return', 'defaultValue' => 10 ) ) ); Output Parameter Name Required Type Supported values Description name yes Text Input name as displayed to the user type no Text text, number, list, checkbox Type of the input (default: text) required no Boolean true, false Specifies if the parameter is required or not (default: false). Not supported for lists and checkboxes. values no associative array name\/value pairs used by the HTML option tag, required for type \u2018list\u2019 title no Text Used as tool-tip when mouse-hovering over the input box pattern no Text Defines a pattern for an element of type text. The pattern should be mentioned in the title attribute! exampleValue no Text Defines an example value displayed for elements of type text and number when no data has been entered yet defaultValue no Defines the default value if left blank by the user #List values List values are defined in an associative array where keys are the string displayed in the combo list of the RSS-Bridge web interface, and values are the content of the <option> HTML tag value attribute. ... 'type' => 'list', 'values' => array( 'Item A' => 'itemA' 'Item B' => 'itemB' ) ... If a more complex organization is required to display the values, the above key\/value can be used to set a title as a key and another array as a value: ... 'type' => 'list', 'values' => array( 'Item A' => 'itemA', 'List 1' => array( 'Item C' => 'itemC', 'Item D' => 'itemD' ), 'List 2' => array( 'Item E' => 'itemE', 'Item F' => 'itemF' ), 'Item B' => 'itemB' ) ... #defaultValue This attribute defines the default value for your parameter. Its behavior depends on the type: text: Allows any text number: Allows any number list: Must match either name or value of one element checkbox: Must be \u201cchecked\u201d to activate the checkbox #queriedContext The queried context is defined via PARAMETERS and can be accessed via $this->queriedContext. It provides a way to identify which context the bridge is called with. Example: ... const PARAMETERS = array( 'By user name' => array( 'u' => array('name' => 'Username') ), 'By user ID' => array( 'id' => array('name' => 'User ID') ) ); ... In this example $this->queriedContext will either return By user name or By user ID. The queried context might return no value, so the best way to handle it is by using a case-structure: switch($this->queriedContext){ case 'By user name': break; case 'By user ID': break; default: \/\/ Return default value } #collectData The collectData function is responsible for collecting data and adding items to generate feeds from. If you are unsure how to solve a specific problem, please don\u2019t hesitate to open an Issue on GitHub. Existing bridges are also a good source to learn implementing your own bridge. #Implementing the collectData function Implementation for the collectData function is specific to each bridge. However, there are certain reoccurring elements, described below. RSS-Bridge also provides functions to simplify the process of collecting and parsing HTML data (see \u201cHelper Functions\u201d on the sidebar) Elements collected by this function must be stored in $this->items. The items variable is an array of item elements, each of which is an associative array that may contain arbitrary keys. RSS-Bridge specifies common keys which are used to generate most common feed formats. Show example $item = []; \/\/ Create a new item $item['title'] = 'Hello World!'; $this->items[] = $item; \/\/ Add item to the list Additional keys may be added for custom APIs (ignored by RSS-Bridge). #Item parameters The item array should provide as much information as possible for RSS-Bridge to generate feature rich feeds. Find below list of keys supported by RSS-Bridge. $item['uri'] \/\/ URI to reach the subject ("https:\/\/...") $item['title'] \/\/ Title of the item $item['timestamp'] \/\/ Timestamp of the item in numeric or text format (compatible for strtotime()) $item['author'] \/\/ Name of the author for this item $item['content'] \/\/ Content in HTML format $item['enclosures'] \/\/ Array of URIs to an attachments (pictures, files, etc...) $item['categories'] \/\/ Array of categories \/ tags \/ topics $item['uid'] \/\/ A unique ID to identify the current item All formats support these parameters. The formats Plaintext and JSON also support custom parameters. #getDescription The getDescription function returns the description for a bridge. Notice: By default RSS-Bridge returns the contents of const DESCRIPTION, so you only have to implement this function if you require different behavior! public function getDescription(){ return self::DESCRIPTION; } #getMaintainer The getMaintainer function returns the name of the maintainer for a bridge. Notice: By default RSS-Bridge returns const MAINTAINER, so you only have to implement this function if you require different behavior! public function getMaintainer(){ return self::MAINTAINER; } #getName The getName function returns the name of a bridge. Notice: By default RSS-Bridge returns const NAME, so you only have to implement this function if you require different behavior! public function getName(){ return self::NAME; } #getURI The getURI function returns the base URI for a bridge. Notice: By default RSS-Bridge returns const URI, so you only have to implement this function if you require different behavior! public function getURI(){ return self::URI; } #getIcon The getIcon function returns the URI for an icon, used as favicon in feeds. If no icon is specified by the bridge, RSS-Bridge will use a default location: static::URI . '\/favicon.ico' (i.e. \u201chttps:\/\/github.com\/favicon.ico\u201d) which may or may not exist. public function getIcon(){ return static::URI . '\/favicon.ico'; } #detectParameters The detectParameters function takes a URL and attempts to extract a valid set of parameters for the current bridge. If the passed URL is valid for this bridge, the function should return an array of parameter -> value pairs that can be used by this bridge, including context if available, or an empty array if the bridge requires no parameters. If the URL is not relevant for this bridge, the function should return null. Notice: Implementing this function is optional. By default, RSS-Bridge tries to match the supplied URL to the URI constant defined in the bridge, which may be enough for bridges without any parameters defined. public function detectParameters($url){ $regex = '\/^(https?:\\\/\\\/)?(www\\.)?(.+?)(\\\/)?$\/'; if(empty(static::PARAMETERS) && preg_match($regex, $url, $urlMatches) > 0 && preg_match($regex, static::URI, $bridgeUriMatches) > 0 && $urlMatches[3] === $bridgeUriMatches[3]) { return []; } else { return null; } } Notice: This function is also used by the findFeed action. This action allows an user to get a list of all feeds corresponding to an URL. You can implement automated tests for the detectParameters function by adding the TEST_DETECT_PARAMETERS constant to your bridge class constant. TEST_DETECT_PARAMETERS is an array, with as key the URL passed to the detectParametersfunction and as value, the array of parameters returned by detectParameters const TEST_DETECT_PARAMETERS = [ 'https:\/\/www.instagram.com\/metaverse' => ['context' => 'Username', 'u' => 'metaverse'], 'https:\/\/instagram.com\/metaverse' => ['context' => 'Username', 'u' => 'metaverse'], 'http:\/\/www.instagram.com\/metaverse' => ['context' => 'Username', 'u' => 'metaverse'], ]; Notice: Adding this constant is optional. If the constant is not present, no automated test will be executed. #Helper Methods BridgeAbstract implements helper methods to make it easier for bridge maintainers to create bridges. Use these methods whenever possible instead of writing your own. saveCacheValue loadCacheValue #saveCacheValue Within the context of the current bridge, stores a value by key in the cache. The value can later be retrieved with loadCacheValue. protected function saveCacheValue($key, $value) $key - the name under which the value is stored in the cache. $value - the value to store in the cache. Usage example: const MY_KEY = 'MyKey'; public function collectData() { $value = 'my value'; $this->saveCacheValue(MY_KEY, $value); } #loadCacheValue Within the context of the current bridge, loads a value by key from cache. Optionally specifies the cache duration for the key. Returns null if the key doesn\u2019t exist or the value is expired. protected function loadCacheValue($key, $duration = null) $key - the name under which the value is stored in the cache. $duration - the maximum time in seconds after which the value expires. Usage example: const MY_KEY = 'MyKey'; public function collectData() { $value = $this->loadCacheValue(MY_KEY, 1800 \/* 30 minutes *\/); if (!isset($value)){ \/\/ load value $this->saveCacheValue(MY_KEY, $value); } \/\/ ... }","tags":"","url":"Bridge_API\/BridgeAbstract.html"},{"title":"FeedExpander","text":"Usage example: You have discovered a site that provides feeds which are hidden and inaccessible by normal means. You want your bridge to directly read the feeds and provide them via RSS-Bridge Find a template at the end of this file. Notice: For a standard feed only collectData need to be implemented. collectData should call $this->collectExpandableDatas('your URI here'); to automatically load feed items and header data (will subsequently call parseItem for each item in the feed). You can limit the number of items to fetch by specifying an additional parameter for: $this->collectExpandableDatas('your URI here', 10) (limited to 10 items). #The parseItem method This method receives one item from the current feed and should return one RSS-Bridge item. The default function does all the work to get the item data from the feed, whether it is RSS 1.0, RSS 2.0 or Atom 1.0. Notice: The following code sample is just an example. Implementation depends on your requirements! protected function parseItem(array $item) { $item['content'] = str_replace('rssbridge','RSS-Bridge',$item['content']); return $item; } #Feed parsing How rss-bridge processes xml feeds: Function uri title timestamp author content atom id title updated author content rss 0.91 link title description rss 1.0 link title dc:date dc:creator description rss 2.0 link, guid title pubDate, dc:date author, dc:creator description #Template This is the template for a new bridge: <?php class MySiteBridge extends FeedExpander { const MAINTAINER = 'No maintainer'; const NAME = 'Unnamed bridge'; const URI = ''; const DESCRIPTION = 'No description provided'; const PARAMETERS = []; const CACHE_TIMEOUT = 3600; public function collectData() { $this->collectExpandableDatas('your feed URI'); } }","tags":"","url":"Bridge_API\/FeedExpander.html"},{"title":"WebDriverAbstract","text":"WebDriverAbstract extends BridgeAbstract and adds functionality for generating feeds from active websites that use XMLHttpRequest (XHR) to load content and \/ or JavaScript to modify content. It highly depends on the php-webdriver library which offers Selenium WebDriver bindings for PHP. https:\/\/github.com\/php-webdriver\/php-webdriver (Project Repository) https:\/\/php-webdriver.github.io\/php-webdriver\/latest\/ (API) Please note that this class is intended as a solution for websites that cannot be covered by the other classes. The WebDriver starts a browser and is therefore very resource-intensive. #Configuration You need a running WebDriver to use bridges that depend on WebDriverAbstract. The easiest way is to start the Selenium server from the project of the same name: docker run -d -p 4444:4444 --shm-size="2g" docker.io\/selenium\/standalone-chrome:latest https:\/\/github.com\/SeleniumHQ\/docker-selenium With these parameters only one browser window can be started at a time. On a multi-user site, Selenium Grid should be used and the number of sessions should be adjusted to the number of processor cores. Finally, the config.ini.php file must be adjusted so that the WebDriver can find the Selenium server: [webdriver] selenium_server_url = "http:\/\/localhost:4444" #Development While you are programming a new bridge, it is easier to start a local WebDriver because then you can see what is happening and where the errors are. I\u2019ve also had good experience recording the process with a screen video to find any timing problems. chromedriver --port=4444 https:\/\/chromedriver.chromium.org\/ If you start rss-bridge from a container, then Chrome driver is only accessible if you call it with the --allowed-ips option so that it binds to all network interfaces. chromedriver --port=4444 --allowed-ips=192.168.1.42 The most important rule is that after an event such as loading the web page or pressing a button, you often have to explicitly wait for the desired elements to appear. A simple example is the bridge ScalableCapitalBlogBridge.php. A more complex and relatively complete example is the bridge GULPProjekteBridge.php. #Template Use this template to create your own bridge. <?php class MyBridge extends WebDriverAbstract { const NAME = 'My Bridge'; const URI = 'https:\/\/www.example.org'; const DESCRIPTION = 'Further description'; const MAINTAINER = 'your name'; public function collectData() { parent::collectData(); try { \/\/ TODO } finally { $this->cleanUp(); } } }","tags":"","url":"Bridge_API\/WebDriverAbstract.html"},{"title":"XPathAbstract","text":"XPathAbstract extends BridgeAbstract and adds functionality for generating feeds based on XPath expressions. It makes creation of new bridges easy and if you\u2019re familiar with XPath expressions this class is probably the right point for you to start with. At the end of this document you\u2019ll find a complete template based on these instructions. #Required constants To create a new Bridge based on XPathAbstract your inheriting class should specify a set of constants describing the feed and the XPath expressions. It is advised to override constants inherited from BridgeAbstract aswell. #Class constant FEED_SOURCE_URL Source Web page URL (should provide either HTML or XML content). You can specify any website URL which serves data suited for display in RSS feeds #Class constant XPATH_EXPRESSION_FEED_TITLE XPath expression for extracting the feed title from the source page. If this is left blank or does not provide any data BridgeAbstract::getName() is used instead as the feed\u2019s title. #Class constant XPATH_EXPRESSION_FEED_ICON XPath expression for extracting the feed favicon URL from the source page. If this is left blank or does not provide any data BridgeAbstract::getIcon() is used instead as the feed\u2019s favicon URL. #Class constant XPATH_EXPRESSION_ITEM XPath expression for extracting the feed items from the source page. Enter an XPath expression matching a list of dom nodes, each node containing one feed article item in total (usually a surrounding <div> or <span> tag). This will be the context nodes for all of the following expressions. This expression usually starts with a single forward slash. #Class constant XPATH_EXPRESSION_ITEM_TITLE XPath expression for extracting an item title from the item context. This expression should match a node contained within each article item node containing the article headline. It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. #Class constant XPATH_EXPRESSION_ITEM_CONTENT XPath expression for extracting an item\u2019s content from the item context. This expression should match a node contained within each article item node containing the article content or description. It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. #Class constant XPATH_EXPRESSION_ITEM_URI XPath expression for extracting an item link from the item context. This expression should match a node\u2019s attribute containing the article URL (usually the href attribute of an <a> tag). It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. Attributes can be selected by prepending an @ char before the attributes name. #Class constant XPATH_EXPRESSION_ITEM_AUTHOR XPath expression for extracting an item author from the item context. This expression should match a node contained within each article item node containing the article author\u2019s name. It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. #Class constant XPATH_EXPRESSION_ITEM_TIMESTAMP XPath expression for extracting an item timestamp from the item context. This expression should match a node or node\u2019s attribute containing the article timestamp or date (parsable by PHP\u2019s strtotime function). It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. Attributes can be selected by prepending an @ char before the attributes name. #Class constant XPATH_EXPRESSION_ITEM_ENCLOSURES XPath expression for extracting item enclosures (media content like images or movies) from the item context. This expression should match a node\u2019s attribute containing an article image URL (usually the src attribute of an tag or a style attribute). It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. Attributes can be selected by prepending an @ char before the attributes name. #Class constant XPATH_EXPRESSION_ITEM_CATEGORIES XPath expression for extracting an item category from the item context. This expression should match a node or node\u2019s attribute contained within each article item node containing the article category. This could be inside or tags or sometimes be hidden in a data attribute. It should start with a dot followed by two forward slashes, referring to any descendant nodes of the article item node. Attributes can be selected by prepending an @ char before the attributes name. #Class constant SETTING_FIX_ENCODING Turns on automatic fixing of encoding errors. Set this to true for fixing feed encoding by invoking PHP\u2019s utf8_decode function on all extracted texts. Try this in case you see \u201cbroken\u201d or \u201cweird\u201d characters in your feed where you\u2019d normally expect umlauts or any other non-ascii characters. #Optional methods XPathAbstract offers a set of methods which can be overridden by derived classes for fine tuning and customization. This is optional. The methods provided for overriding can be grouped into three categories. #Methods for providing XPath expressions Usually XPath expressions are defined in the class constants described above. By default the following base methods just return the value of its corresponding class constant. However deriving classed can override them in case if XPath expressions need to be formed dynamically or based on conditions. In case any of these methods is defined, the method\u2019s return value is used instead of the corresponding constant for providing the value. #Method getSourceUrl() Should return the source Web page URL used as a base for applying the XPath expressions. #Method getExpressionTitle() Should return the XPath expression for extracting the feed title from the source page. #Method getExpressionIcon() Should return the XPath expression for extracting the feed favicon from the source page. #Method getExpressionItem() Should return the XPath expression for extracting the feed items from the source page. #Method getExpressionItemTitle() Should return the XPath expression for extracting an item title from the item context. #Method getExpressionItemContent() Should return the XPath expression for extracting an item\u2019s content from the item context. #Method getSettingUseRawItemContent() Should return the \u2018Use raw item content\u2019 setting value (bool true or false). #Method getExpressionItemUri() Should return the XPath expression for extracting an item link from the item context. #Method getExpressionItemAuthor() Should return the XPath expression for extracting an item author from the item context. #Method getExpressionItemTimestamp() Should return the XPath expression for extracting an item timestamp from the item context. #Method getExpressionItemEnclosures() Should return the XPath expression for extracting item enclosures (media content like images or movies) from the item context. #Method getExpressionItemCategories() Should return the XPath expression for extracting an item category from the item context. #Method getSettingFixEncoding() Should return the Fix encoding setting value (bool true or false). #Methods for providing feed data Those methods are invoked for providing the HTML source as a base for applying the XPath expressions as well as feed meta data as the title and icon. #Method provideWebsiteContent() This method should return the HTML source as a base for the XPath expressions. Usually it merely returns the HTML content of the URL specified in the constant FEED_SOURCE_URL retrieved by curl. Some sites however require user authentication mechanisms, the use of special cookies and\/or headers, where the direct retrival using standard curl would not suffice. In that case this method should be overridden and take care of the page retrival. #Method provideFeedTitle() This method should provide the feed title. Usually the XPath expression defined in XPATH_EXPRESSION_FEED_TITLE is used for extracting the title directly from the page source. #Method provideFeedIcon() This method should provide the feed title. Usually the XPath expression defined in XPATH_EXPRESSION_FEED_ICON is used for extracting the title directly from the page source. #Method provideFeedItems() This method should provide the feed items. Usually the XPath expression defined in XPATH_EXPRESSION_ITEM is used for extracting the items from the page source. All other XPath expressions are applied on a per-item basis, item by item, and only on the item\u2019s contents. #Methods for formatting and filtering feed item attributes The following methods are invoked after extraction of the feed items from the source. Each of them expect one parameter, the value of the corresponding field, which then can be processed and transformed by the method. You can override these methods in order to format or filter parts of the feed output. #Method formatItemTitle() Accepts the items title values as parameter, processes and returns it. Should return a string. #Method formatItemContent() Accepts the items content as parameter, processes and returns it. Should return a string. #Method formatItemUri() Accepts the items link URL as parameter, processes and returns it. Should return a string. #Method formatItemAuthor() Accepts the items author as parameter, processes and returns it. Should return a string. #Method formatItemTimestamp() Accepts the items creation timestamp as parameter, processes and returns it. Should return a unix timestamp as integer. #Method cleanImageUrl() Method invoked for cleaning feed icon and item image URL\u2019s. Extracts the image URL from the passed parameter, stripping any additional content. Furthermore makes sure that relative image URL\u2019s get transformed to absolute ones. #Method fixEncoding() Only invoked when class constant SETTING_FIX_ENCODING is set to true. It then passes all extracted string values through PHP\u2019s utf8_decode function. #Method generateItemId() This method plays in important role for generating feed item ids for all extracted items. Every feed item needs an unique identifier (Uid), so that your feed reader updates the original item instead of adding a duplicate in case an items content is updated on the source site. Usually the items link URL is a good candidate the the Uid. #Template Use this template to create your own bridge. Please remove any unnecessary comments and parameters. <?php class TestBridge extends XPathAbstract { const NAME = 'Test'; const URI = 'https:\/\/www.unbemerkt.eu\/de\/blog\/'; const DESCRIPTION = 'Test'; const MAINTAINER = 'your name'; const CACHE_TIMEOUT = 3600; const FEED_SOURCE_URL = 'https:\/\/www.unbemerkt.eu\/de\/blog\/'; const XPATH_EXPRESSION_ITEM = '\/html[1]\/body[1]\/section[1]\/section[1]\/div[1]\/div[1]\/div[1]\/div[1]\/div[1]\/div[*]\/article[1]'; const XPATH_EXPRESSION_ITEM_TITLE = '.\/\/a[@target="_self"]'; const XPATH_EXPRESSION_ITEM_CONTENT = '.\/\/div[@class="post-content"]'; const XPATH_EXPRESSION_ITEM_URI = '.\/\/a[@class="more-btn"]\/@href'; const XPATH_EXPRESSION_ITEM_AUTHOR = '\/html[1]\/body[1]\/section[1]\/div[2]\/div[1]\/div[1]\/h1[1]'; const XPATH_EXPRESSION_ITEM_TIMESTAMP = '.\/\/time\/@datetime'; const XPATH_EXPRESSION_ITEM_ENCLOSURES = '.\/\/img\/@data-src'; const SETTING_FIX_ENCODING = false; }","tags":"","url":"Bridge_API\/XPathAbstract.html"},{"title":"Helper functions","text":"#getInput The getInput function is used to receive a value for a parameter, specified in const PARAMETERS $this->getInput('your input name here'); getInput will either return the value for your parameter or null if the parameter is unknown or not specified. Defined in lib\/BridgeAbstract.php #getKey The getKey function is used to receive the key name to a selected list value given the name of the list, specified in const PARAMETERS Is able to work with multidimensional list arrays. \/\/ Given a multidimensional array like this const PARAMETERS = [[ 'country' => [ 'name' => 'Country', 'type' => 'list', 'values' => [ 'North America' => [ 'Mexico' => 'mx', 'United States' => 'us' ], 'South America' => [ 'Uruguay' => 'uy', 'Venezuela' => 've' ], ] ] ]], \/\/ Provide the list name to the function $this->getKey('country'); \/\/ if the selected value was "ve", this function will return "Venezuela" getKey will either return the key name for your parameter or null if the parameter is unknown or not specified. Defined in lib\/BridgeAbstract.php #getContents The getContents function uses cURL to acquire data from the specified URI while respecting the various settings defined at a global level by RSS-Bridge (i.e., proxy host, user agent, etc.). This function accepts a few parameters: Parameter Type Optional Description url string required The URL of the contents to acquire header array optional An array of HTTP header fields to set, in the format array('Content-type: text\/plain', 'Content-length: 100'), see CURLOPT_HTTPHEADER opts array optional An array of cURL options in the format array(CURLOPT_POST => 1);, see curl_setopt for a complete list of options. returnFull boolean optional Specifies whether to return the response body from cURL (default) or the response body, code, headers, etc. $header = array('Content-type:text\/plain', 'Content-length: 100'); $opts = array(CURLOPT_POST => 1); $html = getContents($url, $header, $opts); Defined in lib\/contents.php #getSimpleHTMLDOM The getSimpleHTMLDOM function is a wrapper for the simple_html_dom file_get_html function in order to provide context by design. $html = getSimpleHTMLDOM('your URI'); Defined in lib\/contents.php #getSimpleHTMLDOMCached The getSimpleHTMLDOMCached function does the same as the getSimpleHTMLDOM function, except that the content received for the given URI is stored in a cache and loaded from cache on the next request if the specified cache duration was not reached. Use this function for data that is very unlikely to change between consecutive requests to RSS-Bridge. This function allows to specify the cache duration with the second parameter. $html = getSimpleHTMLDOMCached('your URI', 86400); \/\/ Duration 24h Defined in lib\/contents.php #returnClientError The returnClientError function aborts execution of the current bridge and returns the given error message with error code 400: returnClientError('Your error message') Use this function when the user provided invalid parameter or a required parameter is missing. Defined in lib\/utils.php #returnServerError The returnServerError function aborts execution of the current bridge and returns the given error message with error code 500: returnServerError('Your error message') Use this function when a problem occurs that has nothing to do with the parameters provided by the user. (like: Host service gone missing, empty data received, etc\u2026) Defined in lib\/utils.php #defaultLinkTo Automatically replaces any relative URL in a given string or DOM object (i.e. the one returned by getSimpleHTMLDOM) with an absolute URL. defaultLinkTo ( mixed $content, string $server ) : object Returns a DOM object (even if provided a string). Remarks Only handles <a> and <img> tags. Example $html = '<img src=\"\/blob\/master\/README.md\">'; $html = defaultLinkTo($html, 'https:\/\/www.github.com\/rss-bridge\/rss-bridge'); \/\/ Using custom server $html = defaultLinkTo($html, $this->getURI()); \/\/ Using bridge URL \/\/ Output \/\/ <img src=\"https:\/\/www.github.com\/rss-bridge\/rss-bridge\/blob\/master\/README.md\"> Defined in lib\/html.php #backgroundToImg Replaces tags with styles of backgroud-image by <img \/> tags. backgroundToImg(mixed $htmlContent) : object Returns a DOM object (even if provided a string). Defined in lib\/html.php #extractFromDelimiters Extract the first part of a string matching the specified start and end delimiters. function extractFromDelimiters(string $string, string $start, string $end) : mixed Returns the extracted string if delimiters were found and false otherwise. Example $string = '<div>Post author: John Doe<\/div>'; $start = 'author: '; $end = '<'; $extracted = extractFromDelimiters($string, $start, $end); \/\/ Output \/\/ 'John Doe' Defined in lib\/html.php #stripWithDelimiters Remove one or more part(s) of a string using a start and end delimiter. It is the inverse of extractFromDelimiters. function stripWithDelimiters(string $string, string $start, string $end) : string Returns the cleaned string, even if no delimiters were found. Example $string = 'foo<script>superscript()<\/script>bar'; $start = '<script>'; $end = '<\/script>'; $cleaned = stripWithDelimiters($string, $start, $end); \/\/ Output \/\/ 'foobar' Defined in lib\/html.php #stripRecursiveHTMLSection Remove HTML sections containing one or more sections using the same HTML tag. function stripRecursiveHTMLSection(string $string, string $tag_name, string $tag_start) : string Example $string = 'foo<div class=\"ads\"><div>ads<\/div>ads<\/div>bar'; $tag_name = 'div'; $tag_start = '<div class=\"ads\">'; $cleaned = stripRecursiveHTMLSection($string, $tag_name, $tag_start); \/\/ Output \/\/ 'foobar' Defined in lib\/html.php #markdownToHtml Converts markdown input to HTML using Parsedown. Parameter Type Optional Description string string required The URL of the contents to acquire config array optional An array of Parsedown options in the format ['breaksEnabled' => true] Valid options: Option Default Description breaksEnabled false Enable automatic line breaks markupEscaped false Escape inline markup (HTML) urlsLinked true Automatically convert URLs to links function markdownToHtml(string $string, array $config = []) : string Example $input = <<<EOD RELEASE-2.8 * Share QR code of a token * Dark mode improvemnet * Fix some layout issues * Add shortcut to launch the app with screenshot mode on * Translation improvements EOD; $html = markdownToHtml($input); \/\/ Output: \/\/ <p>RELEASE-2.8<\/p> \/\/ <ul> \/\/ <li>Share QR code of a token<\/li> \/\/ <li>Dark mode improvemnet<\/li> \/\/ <li>Fix some layout issues<\/li> \/\/ <li>Add shortcut to launch the app with screenshot mode on<\/li> \/\/ <li>Translation improvements<\/li> \/\/ <\/ul> Defined in lib\/html.php #e The e function is used to convert special characters to HTML entities e('0 < 1 and 2 > 1'); e will return the content of the string escape that can be rendered as is in HTML Defined in lib\/html.php #truncate The truncate function is used to shorten a string if exceeds a certain length, and add a string indicating that the string has been shortened. truncate('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a neque nunc. Nam nibh sem.', 20 , '...'); Defined in lib\/html.php #sanitize The sanitize function is used to remove some tags from a given HTML text. $html = '<head><title>Sample Page<\/title><\/head> <body><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...<\/p> <iframe src="https:\/\/www.example.com" width="600" height="400" frameborder="0" allowfullscreen><\/iframe> <\/body> <\/html>'; $tags_to_remove = ['script', 'iframe', 'input', 'form']; $attributes_to_keep = ['title', 'href', 'src']; $text_to_keep = []; sanitize($html, $tags_to_remove, $attributes_to_keep, $text_to_keep); This function returns a simplehtmldom object of the remaining contents. Defined in lib\/html.php #convertLazyLoading The convertLazyLoading function is used to convert onvert lazy-loading images and frames (video embeds) into static elements. It accepts the HTML content as HTML objects or string objects. It returns the HTML content with fixed image\/frame URLs (same type as input). $html = '<html> <body style="background-image: url('bgimage.jpg');"> <h1>Hello world!<\/h1> <\/body> <\/html> backgroundToImg($html); Defined in lib\/html.php #Json::encode The Json::encode function is used to encode a value as \u00e0 JSON string. $array = [ "foo" => "bar", "bar" => "foo", ]; Json::encode($array, true, true); Defined in lib\/utils.php #Json::decode The Json::decode function is used to decode a JSON string into \u00e0 PHP variable. $json = '{ "foo": "bar", "bar": "foo" }'; Json::decode($json); Defined in lib\/utils.php","tags":"","url":"Helper_functions\/index.html"},{"title":"Cache API","text":"A Cache is a class that allows RSS-Bridge to store fetched data in a local storage area on the server. Cache imlementations are placed in the caches\/ folder (see Folder structure). A cache must implement the CacheInterface interface. For more information about how to create a new Cache, read How to create a new cache?","tags":"","url":"Cache_API\/index.html"},{"title":"How to create a new cache","text":"Create a new file in the caches\/ folder (see Folder structure). See NullCache and SQLiteCache for examples.","tags":"","url":"Cache_API\/How_to_create_a_new_cache.html"},{"title":"CacheInterface","text":"See CacheInterface. interface CacheInterface { public function get(string $key, $default = null); public function set(string $key, $value, int $ttl = null): void; public function delete(string $key): void; public function clear(): void; public function prune(): void; }","tags":"","url":"Cache_API\/CacheInterface.html"},{"title":"Technical recommendations","text":"#General recommendations Use HTTPS (https:\/\/...) over HTTP (http:\/\/...) whenever possible #Test a site before building a bridge Some sites make use of anti-bot mechanisms (e.g.: by using JavaScript) in which case they work fine in regular browsers, but not in the PHP environment. To check if a site works with RSS-Bridge, create a new bridge using the template and load a valid URL (not the base URL!). Example (using github.com) <?php class TestBridge extends BridgeAbstract { const NAME = 'Unnamed bridge'; const URI = ''; const DESCRIPTION = 'No description provided'; const MAINTAINER = 'No maintainer'; const PARAMETERS = []; const CACHE_TIMEOUT = 3600; public function collectData(){ $html = getSimpleHTMLDOM('https:\/\/github.com\/rss-bridge\/rss-bridge') or returnServerError('No contents received!'); } } This bridge should return an empty page (HTML format)","tags":"","url":"Technical_recommendations\/index.html"},{"title":"ActivityPub (Mastodon)","text":"#MastodonBridge (aka. ActivityPub Bridge) Certain ActivityPub implementations, such as Mastodon and Pleroma, allow instances to require requests to ActivityPub endpoints to be signed. RSS-Bridge can handle the HTTP signature header if a private key is provided, while the ActivityPub instance must be able to know the corresponding public key. You do not need to configure this if the usage on your RSS-Bridge instance is limited to accessing ActivityPub instances that do not have such requirements. While the majority of ActivityPub instances don\u2019t have them at the time of writing, the situation may change in the future. #Configuration This article is referenced. Select a domain. It may, but does not need to, be the one RSS-Bridge is on. For all subsequent steps, replace DOMAIN with this domain. Run the following commands on your machine: $ openssl genrsa -out private.pem 2048 $ openssl rsa -in private.pem -outform PEM -pubout -out public.pem Place private.pem in an appropriate location and note down its absolute path. Serve the following page at https:\/\/DOMAIN\/.well-known\/webfinger: { \"subject\": \"acct:DOMAIN@DOMAIN\", \"aliases\": [\"https:\/\/DOMAIN\/actor\"], \"links\": [{ \"rel\": \"self\", \"type\": \"application\/activity+json\", \"href\": \"https:\/\/DOMAIN\/actor\" }] } Serve the following page at https:\/\/DOMAIN\/actor, replacing the value of publicKeyPem with the contents of the public.pem file in step 2, with all line breaks substituted with \\n: { \"@context\": [ \"https:\/\/www.w3.org\/ns\/activitystreams\", \"https:\/\/w3id.org\/security\/v1\" ], \"id\": \"https:\/\/DOMAIN\/actor\", \"type\": \"Application\", \"inbox\": \"https:\/\/DOMAIN\/actor\/inbox\", \"preferredUsername\": \"DOMAIN\", \"publicKey\": { \"id\": \"https:\/\/DOMAIN\/actor#main-key\", \"owner\": \"https:\/\/DOMAIN\/actor\", \"publicKeyPem\": \"-----BEGIN PUBLIC KEY-----\\n...\\n-----END PUBLIC KEY-----\\n\" } } Add the following configuration in config.ini.php in your RSS-Bridge folder, replacing the path with the one from step 3: [MastodonBridge] private_key = \"\/absolute\/path\/to\/your\/private.pem\" key_id = \"https:\/\/DOMAIN\/actor#main-key\" #Considerations Any ActivityPub instance your users requested content from will be able to identify requests from your RSS-Bridge instance by the domain you specified in the configuration. This also means that an ActivityPub instance may choose to block this domain should they judge your instance\u2019s usage excessive. Therefore, public instance operators should monitor for abuse and prepare to communicate with ActivityPub instance admins when necessary. You may also leave contact information as the summary value in the actor JSON (step 5).","tags":"","url":"Bridge_Specific\/ActivityPub_(Mastodon).html"},{"title":"FacebookBridge","text":"#FacebookBridge State of this bridge: Facebook Groups (and probably other sections too) do not work at all No maintainer Needs cookie consent support for public pages Needs login support see this example for Instagram) for private groups Due to the 2020 Facebook redesign and the requirement to accept cookies users are getting problems with Facebook on public RSS-Bridge instances. #Relevant Info Facebook Cookies \u201cDatr\u201d is a unique identifier for your browser and it has a lifespan of two years. \u201cc_user\u201d and \u201cxs\u201d cookies to verify the account and have a lifespan of 365 days","tags":"","url":"Bridge_Specific\/FacebookBridge.html"},{"title":"FurAffinityBridge","text":"#FurAffinityBridge By default this bridge will only return submissions that are rated \u201cGeneral\u201d and are public. To unlock the ability to load submissions that require an account to view or are rated \u201cMature\u201d and higher, you must set the following in config.ini.php with cookies from an existing FurAffinity account with the desired maturity ratings enabled in Account Settings. [FurAffinityBridge] aCookie = "your-a-cookie-value-here" ; from cookie "a" bCookie = "your-b-cookie-value-here" ; from cookie "b" To confirm the bridge is authenticated, the name of the authenticating account will be shown in the bridge\u2019s name once the bridge has been used at least once. (Example: user's FurAffinity Bridge)","tags":"","url":"Bridge_Specific\/FurAffinityBridge.html"},{"title":"Furaffinityuser","text":"#FuraffinityuserBridge #How to retrieve and use cookie values The following steps describe how to get the session cookies using a Chromium-based browser. Other browser may require slightly different steps. Keyword search \u201chow to find cookie values\u201d in your favorite search engine. #Retreiving session cookies. Login to Furaffinity Open DevTools by pressing F12 Open \u201cApplication\u201d On the left side, select \u201cCookies\u201d -> \u201cFuraffinity.net\u201d There will be (at least) two cookie informations in the main window. You need the values of the \u201ca\u201d key and \u201cb\u201d key #Configuring RSS-Bridge Copy\/Paste the values from cookies \u201ca\u201d and \u201cb\u201d into their respective fields in the bridge config and generate the feed","tags":"","url":"Bridge_Specific\/Furaffinityuser.html"},{"title":"Instagram","text":"#InstagramBridge To somehow bypass the rate limiting issue it is suggested to deploy a private RSS-Bridge instance that uses a working Instagram account. NOTE: There exists alternative bridges (e.g. PicukiBridge and PicnobBridge) for viewing posts without a working account. #Configuration Retreiving session id and ds_user_id. The following steps describe how to get the session id and ds user id using a Chromium-based browser. Create an Instagram account, that you will use for your RSS-Bridge instance. It is NOT recommended to use your existing account that is used for common interaction with Instagram services. Login to Instagram Open DevTools by pressing F12 Open \u201cNetworks tab\u201d In the \u201cFilter\u201d field input \u201ci.instagram.com\u201d Click on \u201cFetch\/XHR\u201d Refresh web page Click on any item from the table of http requests In the new frame open the \u201cHeaders\u201d tab and scroll to \u201cRequest Headers\u201d There will be a cookie param will lots of <key>=<value>; text. You need the value of the \u201csessionid\u201d and \u201cds_user_id\u201d keys. Copy them. Configuring RSS-Bridge In config.ini.php add following configuration: [InstagramBridge] session_id = %sessionid from step 1% ds_user_id = %ds_user_id from step 1% cache_timeout = %cache timeout in seconds% The bigger the cache_timeout value, the smaller the chance for RSS-Bridge to throw 429 errors. Default cache_timeout is 3600 seconds (1 hour).","tags":"","url":"Bridge_Specific\/Instagram.html"},{"title":"PixivBridge","text":"#PixivBridge #Image proxy As Pixiv requires images to be loaded with the Referer "https:\/\/www.pixiv.net\/" header set, caching or image proxy is required to use this bridge. To turn off image caching, set the proxy_url value in this bridge\u2019s configuration section of config.ini.php to the url of the proxy. The bridge will then use the proxy in this format (essentially replacing https:\/\/i.pximg.net with the proxy): Before: https:\/\/i.pximg.net\/img-original\/img\/0000\/00\/00\/00\/00\/00\/12345678_p0.png After: https:\/\/proxy.example.com\/img-original\/img\/0000\/00\/00\/00\/00\/00\/12345678_p0.png proxy_url = "https:\/\/proxy.example.com" #Authentication Authentication is required to view and search R-18+ and non-public images. To enable this, set the following in this bridge\u2019s configuration in config.ini.php. ; from cookie \"PHPSESSID\". Recommend to get in incognito browser. cookie = \"00000000_hashedsessionidhere\"","tags":"","url":"Bridge_Specific\/PixivBridge.html"},{"title":"TwitterV2","text":"#TwitterV2Bridge To automatically retrieve Tweets containing potentially sensitive\/age-restricted content, you\u2019ll need to acquire your own unique API Bearer token, which will be used by this Bridge to query Twitter\u2019s API v2. #Configuration Make a Twitter Developer account Developer Portal: https:\/\/dev.twitter.com I will not detail exactly how to do this, as the specific process will likely change over time. You should easily be able to find guides using your search engine of choice. Note: as of April 2023, the \u201cFree\u201d access level no longer allows read access. The cheapest access level with read access is called \u201cBasic\u201d. Create a Twitter Project and App, get Bearer Token Once you have an active Twitter Developer account, sign in to the dev portal Create a new Project (name doesn\u2019t matter) Create an App within the Project (again, name doesn\u2019t matter) Go to the Keys and tokens tab Generate a Bearer Token (you don\u2019t want the API Key and Secret, or the Access Token and Secret) Configure RSS-Bridge In config.ini.php (in rss-bridge root directory) add following lines at the end: [TwitterV2Bridge] twitterv2apitoken = %Bearer Token from step 2% If you don\u2019t have a config.ini.php, create one by making a copy of config.default.ini.php","tags":"","url":"Bridge_Specific\/TwitterV2.html"},{"title":"Vk2","text":"#Vk2Bridge \u0420\u0430\u0431\u043e\u0442\u0430 \u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 VK API. \u041f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 VkBridge \u0443 \u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u0440\u0438\u0435\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438. #\u041f\u0440\u0438\u0435\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0421\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u0421\u043a\u0440\u0438\u043f\u0442 \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 HTML-\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b VK \u0433\u0440\u0443\u043f\u043f \u0438\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. #\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438 \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u0412\u041a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c access_token, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u201c\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u201d \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u0440\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u043c \u043a\u044d\u0448\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e - 5000 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0441\u0443\u0442\u043a\u0438 #\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 my_personal_app \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u0441\u0441\u044b\u043b\u043a\u0443 \u0432\u0438\u0434\u0430 https:\/\/oauth.vk.com\/blank.html#access_token=MNOGO_BUKAV&expires_in=0&user_id=123456. \u0418\u0437 \u044d\u0442\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 MNOGO_BUKAV. \u0412 config.ini.php \u0432 \u0440\u0430\u0437\u0434\u0435\u043b Vk2Bridge \u0432\u0441\u0442\u0430\u0432\u044c\u0442\u0435 access_token [Vk2Bridge] access_token = "MNOGO_BUKAV" \u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f @em92. \u0414\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u043e \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0432\u043e\u0435\u0433\u043e standalone-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0434\u043e \u0432 \u0441\u0441\u044b\u043b\u043a\u0435 \u0438\u0437 \u043f.1. \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 client_id \u043d\u0430 \u0441\u0432\u043e\u0439.","tags":"","url":"Bridge_Specific\/Vk2.html"}]});
\ No newline at end of file