summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2021-02-28 00:02:11 +0300
committerAndrew Dolgov <[email protected]>2021-02-28 00:02:11 +0300
commit1abb8eaf818b64133b91a4fc27a81ce42803296c (patch)
tree4d9825abcc3498b9bc8f73bb0bd7e2837529f411
initial
-rwxr-xr-xinit.php164
-rw-r--r--schema.sql11
2 files changed, 175 insertions, 0 deletions
diff --git a/init.php b/init.php
new file mode 100755
index 0000000..b11e14b
--- /dev/null
+++ b/init.php
@@ -0,0 +1,164 @@
+<?php
+class Reddit_Delay extends Plugin {
+
+ /** @var PluginHost $host */
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Delay posts in Reddit feeds",
+ "fox");
+ }
+
+ function init($host) {
+ $this->host = $host;
+
+ $host->add_hook(PluginHost::HOOK_FEED_FETCHED, $this);
+ $host->add_hook(PluginHost::HOOK_PREFS_TAB, $this);
+ }
+
+ private function cache_exists(int $feed_id, string $link) {
+ $sth = $this->pdo->prepare("SELECT id FROM ttrss_plugin_reddit_delay_cache WHERE feed_id = ? AND link = ?");
+ $sth->execute([$feed_id, $link]);
+
+ if ($sth->fetch()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private function cache_push(int $feed_id, FeedItem $item, DOMNode $entry) {
+ $entry_xml = $entry->ownerDocument->saveXML($entry);
+
+ $sth = $this->pdo->prepare("INSERT INTO ttrss_plugin_reddit_delay_cache
+ (feed_id, link, item, orig_ts)
+ VALUES
+ (?, ?, ?, ?)");
+
+ $sth->execute([$feed_id, $item->get_link(), $entry_xml, date("Y-m-d H:i:s", $item->get_date())]);
+ }
+
+ private function cache_pull_older(int $feed_id, int $delay, DOMDocument $doc, DOMXPath $xpath) {
+ $sth = $this->pdo->prepare("SELECT id, link, item, orig_ts
+ FROM ttrss_plugin_reddit_delay_cache
+ WHERE feed_id = ? AND orig_ts < NOW() - INTERVAL '$delay hours'");
+ $sth->execute([$feed_id]);
+
+ $dsth = $this->pdo->prepare("DELETE FROM ttrss_plugin_reddit_delay_cache WHERE id = ?");
+
+ $target = $xpath->query("//atom:feed")->item(0);
+
+ while ($row = $sth->fetch()) {
+ Debug::log(sprintf("[delay] pulling from cache: %s [%s]",
+ $row["link"], $row["orig_ts"]), Debug::$LOG_VERBOSE);
+
+ $tmpdoc = new DOMDocument();
+
+ if ($tmpdoc->loadXML($row["item"])) {
+ $tmpxpath = new DOMXPath($tmpdoc);
+
+ $imported_entry = $doc->importNode($tmpxpath->query("//entry")->item(0), true);
+
+ $dsth->execute([$row["id"]]);
+ }
+ }
+ }
+
+ function hook_feed_fetched($feed_data, $fetch_url, $owner_uid, $feed_id) {
+ $delay = (int) $this->host->get($this, "delay");
+
+ if (strpos($fetch_url, ".reddit.com") !== false) {
+
+ $doc = new DOMDocument();
+
+ if ($doc->loadXML($feed_data)) {
+ $xpath = new DOMXPath($doc);
+ $xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');
+
+ $entries = $xpath->query("//atom:entry");
+
+ foreach ($entries as $entry) {
+
+ $item = new FeedItem_Atom($entry, $doc, $xpath);
+
+ $cutoff_timestamp = time() - ($delay * 60 * 60);
+
+ Debug::log(sprintf("[delay] %s [%s vs %s]",
+ $item->get_link(),
+ date("Y-m-d H:i:s", $item->get_date()),
+ date("Y-m-d H:i:s", $cutoff_timestamp)), Debug::$LOG_VERBOSE);
+
+ if ($item->get_date() > $cutoff_timestamp) {
+ if ($this->cache_exists($feed_id, $item->get_link())) {
+ Debug::log("[delay] article is too new, already cached.", Debug::$LOG_VERBOSE);
+ } else {
+ Debug::log("[delay] article is too new, delaying it.", Debug::$LOG_VERBOSE);
+
+ $this->cache_push($feed_id, $item, $entry);
+ }
+
+ $entry->parentNode->removeChild($entry);
+ }
+ }
+
+ $this->cache_pull_older($feed_id, $delay, $doc, $xpath);
+
+ return $doc->saveXML();
+ }
+ }
+
+ return $feed_data;
+ }
+
+ function hook_prefs_tab($args) {
+ if ($args != "prefFeeds") return;
+
+ $delay = (int) $this->host->get($this, "delay");
+ ?>
+
+ <div dojoType="dijit.layout.AccordionPane"
+ title="<i class='material-icons'>extension</i> <?= __('Delay Reddit posts (reddit_delay)') ?>">
+
+ <form dojoType='dijit.form.Form'>
+
+ <?= \Controls\pluginhandler_tags($this, "save") ?>
+
+ <script type="dojo/method" event="onSubmit" args="evt">
+ evt.preventDefault();
+ if (this.validate()) {
+ Notify.progress('Saving data...', true);
+ xhr.post("backend.php", this.getValues(), (reply) => {
+ Notify.info(reply);
+ })
+ }
+ </script>
+
+ <fieldset class='narrow'>
+ <label>
+ <?= __("Delay posts by this amount (hours, 0 - disables):") ?>
+ </label>
+ <input dojoType="dijit.form.NumberSpinner" name="delay" value="<?= $delay ?>">
+ </fieldset>
+
+ <hr/>
+ <?= \Controls\submit_tag(__("Save")) ?>
+ </form>
+ </div>
+
+ <?php
+ }
+
+ function save() {
+ $delay = (int) ($_POST["delay"] ?? 0);
+
+ $this->host->set($this, "delay", $delay);
+
+ echo __("Configuration saved");
+ }
+
+ function api_version() {
+ return 2;
+ }
+
+}
diff --git a/schema.sql b/schema.sql
new file mode 100644
index 0000000..1b61cf0
--- /dev/null
+++ b/schema.sql
@@ -0,0 +1,11 @@
+drop table ttrss_plugin_reddit_delay_cache;
+
+create table ttrss_plugin_reddit_delay_cache (id serial not null primary key,
+ feed_id integer not null REFERENCES ttrss_feeds(id) on DELETE cascade,
+ link text not null,
+ item text not NULL,
+ orig_ts timestamp not null);
+
+create unique index ttrss_plugin_reddit_delay_cache_idx on ttrss_plugin_reddit_delay_cache(feed_id, link);
+create index ttrss_plugin_reddit_delay_cache_link_idx on ttrss_plugin_reddit_delay_cache(link);
+create index ttrss_plugin_reddit_delay_cache_feed_id_idx on ttrss_plugin_reddit_delay_cache(feed_id);