From f5cd78d9fadedb56e3921664e5e0ff32e9a8634f Mon Sep 17 00:00:00 2001 From: Cool Fire Date: Wed, 14 Mar 2018 13:16:34 +0100 Subject: [PATCH] Add first testing version of redditnews plugin --- data/reddit-auth.json.example | 4 + data/reddit-data.json.example | 1 + plugins/redditnews.rb | 146 ++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 data/reddit-auth.json.example create mode 100644 data/reddit-data.json.example create mode 100755 plugins/redditnews.rb diff --git a/data/reddit-auth.json.example b/data/reddit-auth.json.example new file mode 100644 index 0000000..0658fbe --- /dev/null +++ b/data/reddit-auth.json.example @@ -0,0 +1,4 @@ +{ + "username":"yourusername", + "password":"yourpassword" +} diff --git a/data/reddit-data.json.example b/data/reddit-data.json.example new file mode 100644 index 0000000..7f8e0f0 --- /dev/null +++ b/data/reddit-data.json.example @@ -0,0 +1 @@ +{"follow":["/r/netsec"],"buffer":[]} diff --git a/plugins/redditnews.rb b/plugins/redditnews.rb new file mode 100755 index 0000000..8e77389 --- /dev/null +++ b/plugins/redditnews.rb @@ -0,0 +1,146 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# Plugin to announce new posts for selected subreddits +# Requires "reddit-base" gem to be installed. +class Redditnews + require 'json' + require 'reddit/base' + + # This method is called when the plugin is first loaded + def initialize(status, config, output, irc, timer) + @status = status + @config = config + @output = output + @irc = irc + @timer = timer + + # Plugin specific variables + @authfile = "#{@config.datadir}/reddit-auth.json" + @datafile = "#{@config.datadir}/reddit-data.json" + @follow = [] + @buffer = [] + @buffmax = 100 + @timeout = 300 + @channel = '#news' + + # Bootstrap and launch thread to fetch posts + load_data + @fthread = Thread.new { fetcher_thread } + end + + # Method that will get called just before a plugin is unloaded/reloaded. + def unload + save_data + @fthread.exit + true + end + + # Default method, called when no argument is given + def main(_nick, _user, _host, from, _msg, _arguments, _con) + @irc.message(from, "Please see 'redditnews help' for list of functions.") + end + + # Function to send help about this plugin (Can also be called by the help plugin.) + def help(nick, _user, _host, _from, _msg, _arguments, con) + help = [ + 'Plugin to fetch reddit posts.', + ' redditnews following - List subreddits that are being followed.', + ' redditnews follow - Add new subreddit to follow.', + ' redditnews unfollow - Remove subreddit to follow.' + ] + + # Print out help + help.each do |line| + if con + @output.c(line + "\n") + else + @irc.notice(nick, line) + end + end + end + + # List subreddits being followed + def following(_nick, _user, _host, from, _msg, _arguments, _con) + @irc.message(from, "Following: #{@follow.join(', ')}.") + end + + # Manage subreddits + def follow(_nick, _user, host, from, _msg, arguments, con) + if @config.auth(host, con) + if !arguments.nil? && !arguments.empty? + @follow.push arguments + save_data + line = "Added #{arguments}." + else + line = 'Expecting subreddit name to follow' + end + @irc.message(from, line) + end + end + + def unfollow(_nick, _user, host, from, _msg, arguments, con) + if @config.auth(host, con) + if !arguments.nil? && !arguments.empty? + if @follow.include? arguments + @follow.delete arguments + line = "Removed #{arguments}." + else + line = "Already not following #{arguments}." + end + else + line = 'Expecting subreddit name to unfollow.' + end + @irc.message(from, line) + end + end + + private + + def start_client + conf = JSON.parse(File.read(@authfile)) + Reddit::Base::Client.new(user: conf['username'], password: conf['password']) + end + + # Load and save current state + def load_data + data = JSON.parse(File.read(@datafile)) + @follow = data['follow'] + @buffer = data['buffer'] + data + end + + def save_data + # Write @following and @buffer to @datafile + File.write(@datafile, ({ 'follow' => @follow, 'buffer' => @buffer }).to_json) + end + + def fetcher_thread + client = start_client + loop do + begin + @follow.each do |subreddit| + resp = client.get subreddit + resp.body.data.children.each do |item| + if @buffer.include? item.data.id + # Purge from buffer so the most current recurring entries stay at the top + @buffer.delete item.data.id + else + # Appears to be a new post + @irc.message(@channel, "#{subreddit}: #{item.data.title} | #{item.data.url}") + @irc.message(@channel, ' ') + end + @buffer.push item.data.id + + # Trim the cache buffer if it has gotten too big + @buffer.shift(@buffer.length - @buffmax) if @buffer.length > @buffmax + end + end + save_data + rescue + @out.debug('Failed to retreive subreddit posts') + end + sleep(@timeout) + end + end +end -- GitLab