diff options
Diffstat (limited to 'news')
-rw-r--r-- | news/.gitignore | 1 | ||||
-rwxr-xr-x | news/GfindFeeds4bot | 17 | ||||
-rw-r--r-- | news/feeds | 2 | ||||
l--------- | news/ircasy.py | 1 | ||||
-rw-r--r-- | news/new_feeds | 183 | ||||
-rw-r--r-- | news/newsbot.js | 272 | ||||
-rw-r--r-- | news/newsbot.py | 259 | ||||
-rw-r--r-- | news/package.json | 32 |
8 files changed, 767 insertions, 0 deletions
diff --git a/news/.gitignore b/news/.gitignore new file mode 100644 index 00000000..07e6e472 --- /dev/null +++ b/news/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/news/GfindFeeds4bot b/news/GfindFeeds4bot new file mode 100755 index 00000000..a5439c5a --- /dev/null +++ b/news/GfindFeeds4bot @@ -0,0 +1,17 @@ +#! /bin/sh +# usage: GfindFeeds4bot QUERY +set -euf + +export query="$1" +export data="$( + curl -sS "https://www.google.com/uds/GfindFeeds?v=1.0&q=$query" +)" + +node <<EOF + query = process.env.query + data = JSON.parse(process.env.data) + + data.responseData.entries.forEach(function (entry, index) { + console.log(query + index + '|' + entry.url) + }) +EOF diff --git a/news/feeds b/news/feeds new file mode 100644 index 00000000..50fe0667 --- /dev/null +++ b/news/feeds @@ -0,0 +1,2 @@ +HN|http://news.ycombinator.com/rss +Fefe|http://blog.fefe.de/rss.xml diff --git a/news/ircasy.py b/news/ircasy.py new file mode 120000 index 00000000..68231591 --- /dev/null +++ b/news/ircasy.py @@ -0,0 +1 @@ +../Reaktor/IRC/ircasy.py
\ No newline at end of file diff --git a/news/new_feeds b/news/new_feeds new file mode 100644 index 00000000..a5de8d72 --- /dev/null +++ b/news/new_feeds @@ -0,0 +1,183 @@ +aje|http://www.aljazeera.com/Services/Rss/?PostingId=2007731105943979989|#news +aktuelle_themen|http://bundestag.de/service/rss/Bundestag_Aktuelle_Themen.rss|#news #bundestag +allafrica|http://allafrica.com/tools/headlines/rdf/latest/headlines.rdf|#news +anon|http://anoninsiders.net/feed/|#news +antirez|http://antirez.com/rss|#news +arbor|http://feeds2.feedburner.com/asert/|#news +archlinux|http://www.archlinux.org/feeds/news/|#news +ars|http://feeds.arstechnica.com/arstechnica/index?format=xml|#news +asiaone_asia|http://news.asiaone.com/rss/asia|#news +asiaone_business|http://business.asiaone.com/rss.xml|#news +asiaone_sci|http://news.asiaone.com/rss/science-and-tech|#news +asiaone_world|http://news.asiaone.com/rss/world|#news +augustl|http://augustl.com/atom.xml|#news +bbc|http://feeds.bbci.co.uk/news/rss.xml|#news +bdt_drucksachen|http://www.bundestag.de/dip21rss/bundestag_drucksachen.rss|#news #bundestag +bdt_plenarproto|http://www.bundestag.de/rss_feeds/plenarprotokolle.rss|#news #bundestag +bdt_pressemitteilungen|http://bundestag.de/service/rss/Bundestag_Presse.rss|#news #bundestag +bdt_wd|http://bundestag.de/service/rss/Bundestag_WD.rss|#news #bundestag +bitcoinboard|http://bitcoinboard.net/feed/|#news #financial +bitcoinpakistan|https://bitcoinspakistan.com/feed/|#news #financial +businessweek|http://www.businessweek.com/feeds/homepage.rss|#news +cancer|http://feeds.feedburner.com/ncinewsreleases?format=xml|#news +carta|http://feeds2.feedburner.com/carta-standard-rss|#news +catholic_news|http://feeds.feedburner.com/catholicnewsagency/dailynews|#news +cbc_busi|http://rss.cbc.ca/lineup/business.xml|#news +cbc_offbeat|http://www.cbc.ca/cmlink/rss-offbeat|#news +cbc_pol|http://rss.cbc.ca/lineup/politics.xml|#news +cbc_tech|http://rss.cbc.ca/lineup/technology.xml|#news +cbc_top|http://rss.cbc.ca/lineup/topstories.xml|#news +ccc|http://www.ccc.de/rss/updates.rdf|#news +chan_b|http://boards.4chan.org/b/index.rss|#brainfuck +chan_biz|http://boards.4chan.org/biz/index.rss|#news #brainfuck +chan_g|http://boards.4chan.org/g/index.rss|#news #brainfuck +chan_int|http://boards.4chan.org/int/index.rss|#news #brainfuck +cna|http://www.channelnewsasia.com/starterkit/servlet/cna/rss/home.xml|#news +cryptanalysis|https://cryptanalys.is/rss.php|#news +coindesk|http://feeds.feedburner.com/CoinDesk?format=xml|#news #financial +coinspotting|http://coinspotting.com/rss|#news #financial +cryptoarticles|http://www.cryptoarticles.com/crypto-news?format=rss|#news +cryptocoinsnews|http://www.cryptocoinsnews.com/feed/|#news #financial +cryptogon|http://www.cryptogon.com/?feed=rss2|#news +csm|http://rss.csmonitor.com/feeds/csm|#news +csm_world|http://rss.csmonitor.com/feeds/world|#news +cyberguerrilla|https://www.cyberguerrilla.org/a/2012/?feed=rss2|#news +danisch|http://www.danisch.de/blog/feed/|#news +dwn|http://deutsche-wirtschafts-nachrichten.de/feed/customfeed/|#news +ecat|http://ecat.com/feed|#news +eia_press|http://www.eia.gov/rss/press_rss.xml|#news +eia_today|http://www.eia.gov/rss/todayinenergy.xml|#news +embargowatch|https://embargowatch.wordpress.com/feed/|#news +ethereum-comments|http://blog.ethereum.org/comments/feed|#news +ethereum|http://blog.ethereum.org/feed|#news +europa_ric|http://ec.europa.eu/research/infocentre/rss/infocentre-rss.xml|#news +eu_survei|http://www.eurosurveillance.org/public/RSSFeed/RSS.aspx|#news +exploitdb|http://www.exploit-db.com/rss.xml|#news +fars|http://www.farsnews.com/rss.php|#news #test +faz_feui|http://www.faz.net/rss/aktuell/feuilleton/|#news +faz_politik|http://www.faz.net/rss/aktuell/politik/|#news +faz_wirtschaft|http://www.faz.net/rss/aktuell/wirtschaft/|#news #financial +fbi|http://www.fbi.gov/homepage/RSS|#news #bullerei +fbi_news|http://www.fbi.gov/news/news_blog/rss.xml|#news +fbi_press|http://www.fbi.gov/news/current/rss.xml|#news #bullerei +fbi_stories|http://www.fbi.gov/news/stories/all-stories/rss.xml|#news #bullerei +fedreserve|http://www.federalreserve.gov/feeds/press_all.xml|#news #financial +fefe|http://blog.fefe.de/rss.xml|#news +forbes|http://www.forbes.com/forbes/feed2/|#news +forbes_realtime|http://www.forbes.com/real-time/feed2/|#news +fox|http://feeds.foxnews.com/foxnews/latest|#news +fvwm|http://freecode.com/projects/fvwm/releases.atom|#news +geheimorganisation|http://geheimorganisation.org/feed/|#news +GerForPol|http://www.german-foreign-policy.com/de/news/rss-2.0|#news +gmanet|http://www.gmanetwork.com/news/rss/news|#news +golem|http://www.golem.de/rss.php?feed=RSS1.0|#news +google|http://news.google.com/?output=rss|#news +guardian_uk|http://feeds.theguardian.com/theguardian/uk-news/rss|#news +gulli|http://ticker.gulli.com/rss/|#news +handelsblatt|http://www.handelsblatt.com/contentexport/feed/schlagzeilen|#news #financial +heise|http://heise.de.feedsportal.com/c/35207/f/653902/index.rss|#news +hindu_business|http://www.thehindubusinessline.com/?service=rss|#news #financial +hindu|http://www.thehindu.com/?service=rss|#news +hintergrund|http://www.hintergrund.de/index.php?option=com_bca-rss-syndicator&feed_id=8|#news +HN|http://news.ycombinator.com/rss|#news +ign|http://feeds.ign.com/ign/all|#news +independent|http://www.independent.com/rss/headlines/|#news +indymedia|http://de.indymedia.org/RSS/newswire.xml|#news +info_libera|http://www.informationliberation.com/rss.xml|#news +klagen-gegen-rundfuckbeitrag|http://klagen-gegen-rundfunkbeitrag.blogspot.com/feeds/posts/default|#news +korea_herald|http://www.koreaherald.com/rss_xml.php|#news +linuxinsider|http://www.linuxinsider.com/perl/syndication/rssfull.pl|#news +lisp|http://planet.lisp.org/rss20.xml|#news +liveleak|http://www.liveleak.com/rss|#news +lolmythesis|http://lolmythesis.com/rss|#news +LtU|http://lambda-the-ultimate.org/rss.xml|#news +lukepalmer|http://lukepalmer.wordpress.com/feed/|#news +mit|http://web.mit.edu/newsoffice/rss-feeds.feed?type=rss|#news +mongrel2_master|https://github.com/zedshaw/mongrel2/commits/master.atom|#news +nds|http://www.nachdenkseiten.de/?feed=atom|#news +netzpolitik|https://netzpolitik.org/feed/|#news +newsbtc|http://newsbtc.com/feed/|#news #financial +nnewsg|http://www.net-news-global.net/rss/rssfeed.xml|#news +npr_busi|http://www.npr.org/rss/rss.php?id=1006|#news +npr_headlines|http://www.npr.org/rss/rss.php?id=1001|#news +npr_pol|http://www.npr.org/rss/rss.php?id=1012|#news +npr_world|http://www.npr.org/rss/rss.php?id=1004|#news +nsa|http://www.nsa.gov/rss.shtml|#news #bullerei +nytimes|http://rss.nytimes.com/services/xml/rss/nyt/World.xml|#news +phys|http://phys.org/rss-feed/|#news +piraten|https://www.piratenpartei.de/feed/|#news +polizei_berlin|http://www.berlin.de/polizei/presse-fahndung/_rss_presse.xml|#news #bullerei +presse_polizei|http://www.presseportal.de/rss/polizei.rss2|#news #bullerei +presseportal|http://www.presseportal.de/rss/presseportal.rss2|#news +prisonplanet|http://prisonplanet.com/feed.rss|#news +proofmarket|https://proofmarket.org/feed_problem|#news +rawstory|http://www.rawstory.com/rs/feed/|#news +reddit_4chan|http://www.reddit.com/r/4chan/new/.rss|#news #brainfuck +reddit_anticonsum|http://www.reddit.com/r/Anticonsumption/new/.rss|#news +reddit_btc|http://www.reddit.com/r/Bitcoin/new/.rss|#news #financial +reddit_consp|http://reddit.com/r/conspiracy/.rss|#news +reddit_sci|http://www.reddit.com/r/science/.rss|#news +reddit_tech|http://www.reddit.com/r/technology/.rss|#news +reddit_tpp|http://www.reddit.com/r/twitchplayspokemon/.rss|#news #tpp +reddit_world|http://www.reddit.com/r/worldnews/.rss|#news +r-ethereum|http://www.reddit.com/r/ethereum/.rss|#news +reuters|http://feeds.reuters.com/Reuters/worldNews|#news +reuters-odd|http://feeds.reuters.com/reuters/oddlyEnoughNews?format=xml|#news +rt|http://rt.com/rss/news/|#news +schallurauch|http://feeds.feedburner.com/SchallUndRauch|#news +sciencemag|http://news.sciencemag.org/rss/current.xml|#news +scmp|http://www.scmp.com/rss/91/feed|#news +sec-db|http://feeds.security-database.com/SecurityDatabaseToolsWatch|#news +shackspace|http://shackspace.de/?feed=rss2|#news +shz_news|http://www.shz.de/nachrichten/newsticker/rss|#news +sky_busi|http://news.sky.com/feeds/rss/business.xml|#news +sky_pol|http://news.sky.com/feeds/rss/politics.xml|#news +sky_strange|http://news.sky.com/feeds/rss/strange.xml|#news +sky_tech|http://news.sky.com/feeds/rss/technology.xml|#news +sky_world|http://news.sky.com/feeds/rss/world.xml|#news +slashdot|http://rss.slashdot.org/Slashdot/slashdot|#news +slate|http://feeds.slate.com/slate|#news +spiegel_eil|http://www.spiegel.de/schlagzeilen/eilmeldungen/index.rss|#news +spiegelfechter|http://feeds.feedburner.com/DerSpiegelfechter?format=xml|#news +spiegel_top|http://www.spiegel.de/schlagzeilen/tops/index.rss|#news +standardmedia_ke|http://www.standardmedia.co.ke/rss/headlines.php|#news +stern|http://www.stern.de/feed/standard/all/|#news +stz|http://www.stuttgarter-zeitung.de/rss/topthemen.rss.feed|#news +sz_politik|http://rss.sueddeutsche.de/rss/Politik|#news +sz_wirtschaft|http://rss.sueddeutsche.de/rss/Wirtschaft|#news #financial +sz_wissen|http://suche.sueddeutsche.de/rss/Wissen|#news +tagesschau|http://www.tagesschau.de/newsticker.rdf|#news +taz|http://taz.de/Themen-des-Tages/!p15;rss/|#news +telegraph_finance|http://www.telegraph.co.uk/finance/rss|#news #financial +telegraph_pol|http://www.telegraph.co.uk/news/politics/rss|#news +telegraph_uk|http://www.telegraph.co.uk/news/uknews/rss|#news +telegraph_world|http://www.telegraph.co.uk/news/worldnews/rss|#news +telepolis|http://www.heise.de/tp/rss/news-atom.xml|#news +the_insider|http://www.theinsider.org/rss/news/headlines-xml.asp|#news +tigsource|http://www.tigsource.com/feed/|#news +times|http://www.thetimes.co.uk/tto/news/rss|#news +tinc|http://tinc-vpn.org/news/index.rss|#news +topix_b|http://www.topix.com/rss/wire/de/berlin|#news +torr_bits|http://feeds.feedburner.com/TorrentfreakBits|#news +torrentfreak|http://feeds.feedburner.com/Torrentfreak|#news +torr_news|http://feed.torrentfreak.com/Torrentfreak/|#news +travel_warnings|http://feeds.travel.state.gov/ca/travelwarnings-alerts|#news +truther|http://truthernews.wordpress.com/feed/|#news +un_afr|http://www.un.org/apps/news/rss/rss_africa.asp|#news +un_am|http://www.un.org/apps/news/rss/rss_americas.asp|#news +un_eu|http://www.un.org/apps/news/rss/rss_europe.asp|#news +un_me|http://www.un.org/apps/news/rss/rss_mideast.asp|#news +un_pac|http://www.un.org/apps/news/rss/rss_asiapac.asp|#news +un_top|http://www.un.org/apps/news/rss/rss_top.asp|#news +us_math_society|http://www.ams.org/cgi-bin/content/news_items.cgi?rss=1|#news +vimperator|https://sites.google.com/a/vimperator.org/www/blog/posts.xml|#news +weechat|http://dev.weechat.org/feed/atom|#news +wp_world|http://feeds.washingtonpost.com/rss/rss_blogpost|#news +xkcd|https://xkcd.com/rss.xml|#news +yahoo|http://news.yahoo.com/rss/|#news +zdnet|http://www.zdnet.com/news/rss.xml|#news +reddit_prog|http://www.reddit.com/r/programming/new/.rss|#news +bmj|[object Object]|#news +dod|http://www.defense.gov/news/afps2.xml|#news +greenpeace|http://feeds.feedburner.com/GreenpeaceNews|#news +painload|https://github.com/krebscode/painload/commits/master.atom|#news diff --git a/news/newsbot.js b/news/newsbot.js new file mode 100644 index 00000000..18b5f780 --- /dev/null +++ b/news/newsbot.js @@ -0,0 +1,272 @@ +var IRC = require('irc') +var FeedParser = require('feedparser') +var Request = require('request') +var Parse = require('shell-quote').parse +var FS = require('fs') +var HTTP = require('http') +var FormData = require('form-data') +var URL = require('url') + +var irc_server = 'ire.retiolum' +var master_nick = 'knews' +var news_channel = '#news' +var feeds_file = 'new_feeds' +var feedbot_loop_delay = 60 * 1000 // [ms] +var feedbot_create_delay = 200 // [ms] +var url_shortener_host = 'go' + +var slaves = {} + +function main () { + var master = new IRC.Client(irc_server, master_nick, { + channels: [ news_channel ], + }) + + master.on('message' + news_channel, function (nick, text, message) { + if (is_talking_to(master_nick, text)) { + var request = parse_request(text) + if (request) { + return run_command(request.method, request.params, function (error, result) { + if (error) { + return master.say(news_channel, '4' + error) + } else { + return master.say(news_channel, result) + } + }) + } + } + }) + + master.once('registered', function () { + // read feeds file and create a feedbot for each entry + FS + .readFileSync(feeds_file) + .toString() + .split('\n') + //.filter((function () { + // var n = 2; + // return function () { + // return n-- > 0 + // } + //})()) + .filter(function (line) { + return line.length > 0 + }) + .forEach(function (line, i) { + var parts = line.split('|') + if (parts.length !== 3) { + console.log('bad new_feeds line ' + lines + ': ' + line) + return + } + + var nick = parts[0] + var uri = parts[1] + var channels = parts[2].split(' ') + + setTimeout(function () { + return create_feedbot(nick, uri, channels) + }, i*feedbot_create_delay) + }) + }) +} + +function create_feedbot (nick, uri, channels) { + var client = new IRC.Client(irc_server, nick, { + channels: channels, + autoRejoin: false, + }) + + slaves[nick] = { + client: client, + nick: nick, + uri: uri, + } + + // say text in every joined channel + function broadcast (text) { + Object.keys(client.chans).forEach(function (channel) { + client.say(channel, text) + }) + } + + function broadcast_new_item (item) { + return getShortLink(item.link, function (error, shortlink) { + return broadcast(item.title + ' ' + shortlink) + }) + } + + client.once('registered', loop_feedparser) + client.once('registered', deaf_myself) + + client.on('invite', function (channel, from, message) { + client.join(channel, null) + }) + + client.on('error', function (error) { + console.log('Error:', error) + }) + + // TODO stopping criteria + function loop_feedparser () { + try { + var request = Request(uri) + var feedparser = new FeedParser() + } catch (error) { + return broadcast('4' + error) + } + + request.on('error', function (error) { + broadcast('4request ' + error) + }) + request.on('response', function (response) { + if (response.statusCode !== 200) { + return this.emit('error', new Error('Bad status code')) + } + var output = response + switch (response.headers['content-encoding']) { + case 'gzip': + output = zlib.createGunzip() + response.pipe(output) + break + case 'deflate': + output = zlib.createInflate() + response.pipe(output) + break + } + this.pipe(feedparser) + }) + + var items = [] + + feedparser.on('error', function (error) { + broadcast('4feedparser ' + error) + return continue_loop() + }) + feedparser.on('readable', function () { + for (var item; item = this.read(); ) { + items.push(item) + } + }) + feedparser.on('end', function () { + + if (client.lastItems) { + items.forEach(function (item) { + if (!client.lastItems.hasOwnProperty(item.title)) { + broadcast_new_item(item) + } + }) + } + + client.lastItems = {} + items.forEach(function (item) { + client.lastItems[item.title] = true + }) + + return continue_loop() + }) + + function continue_loop () { + setTimeout(loop_feedparser, feedbot_loop_delay) + } + } + function deaf_myself () { + client.send('mode', nick, '+D') + } +} + +// return true if text "is talking to" my_nick +function is_talking_to (my_nick, text) { + return text.slice(0, my_nick.length) === my_nick + && text[my_nick.length] === ':' +} + +function parse_request (text) { + var parse = Parse(text) + return { + method: parse[1], + params: parse.slice(2), + } +} + +function run_command (methodname, params, callback) { + var method = methods[methodname] + if (method) { + return method(params, callback) + } else { + return callback(new Error('dunno what ' + methodname + ' is')); + } +} + +function getShortLink (link, callback) { + var form = new FormData() + try { + form.append('uri', link) + } catch (err) { + console.log('link:', link) + throw err + } + + var request = HTTP.request({ + method: 'post', + host: url_shortener_host, + path: '/', + headers: form.getHeaders(), + }) + form.pipe(request) + + request.on('response', function (response) { + var data = '' + response.on('data', function (chunk) { + data += chunk + }) + response.on('end', function () { + callback(null, data.replace(/\r\n$/,'') + '#' + URL.parse(link).host) + }) + }) +} + +var methods = {} +methods.add = function (params, callback) { + if (slaves.hasOwnProperty(params[0])) { + return callback(new Error('name already taken')) + } else { + create_feedbot(params[0], params[1], [news_channel]) + return callback(null) + } +} +methods.del = function (params, callback) { + var nick = params[0] + if (slaves.hasOwnProperty(nick)) { + var slave = slaves[nick] + slave.client.disconnect() + delete slaves[nick] + return callback(null) + } else { + return callback(new Error('botname not found')) + } +} +methods.save = function (params, callback) { + var feeds = Object.keys(slaves) + .map(function (nick) { + return slaves[nick] + }) + .map(function (slave) { + return [ + slave.nick, + slave.uri, + Object.keys(slave.client.chans).join(' '), + ].join('|') + }).join('\n') + '\n' + return FS.writeFile(feeds_file, feeds, function (error) { + if (error) { + return callback(error) + } else { + return callback(null, 'Feeds saved') + } + }) +} + + +if (require.main === module) { + main() +} diff --git a/news/newsbot.py b/news/newsbot.py new file mode 100644 index 00000000..2f8bf635 --- /dev/null +++ b/news/newsbot.py @@ -0,0 +1,259 @@ +from ircasy import asybot +import threading +from asyncore import loop +import logging +import os +import subprocess + +import feedparser +import math +import re +import subprocess +from datetime import datetime +from time import sleep +#testbot = NewsBot('ire', 6667, 'crabman23', ['#retiolum'], loglevel=logging.DEBUG) + + + +## Newsbot Controller Class +class NewsBot(asybot): + def __init__(self, name, channels=['#test'], server='ire', port=6667, timeout=60, loglevel=logging.ERROR, url_shortener='http://localhost'): + asybot.__init__(self, server, port, name, channels, loglevel=loglevel) + self.to = timeout + self.url_shortener = url_shortener + self.ctrl_chan = channels[0] + + def send_msg(self, target, msg): + for line in msg.split('\n'): + self.PRIVMSG(target, line) + + def on_privmsg(self, prefix, command, params, rest): + args_array = rest.split() + if params[0] == self.nickname: + answer = self.read_message(args_array) + self.send_msg(prefix.split('!')[0], answer) + elif args_array[0].strip(':') == self.nickname: + answer = self.read_message(args_array[1:]) + self.send_msg([params[0]], answer) + + def on_invite(self, prefix, command, params, rest): + for chan in rest.split(): + self.push('JOIN ' + chan) + self.channels.append(chan) + + def read_message(self, args): + try: + if args[0] in [x for x in commands.__dict__.keys() if x.find('_')]: + func = getattr(commands, args[0]) + return func(self, args) + else: + return 'command not found' + except Exception as e: + return 'mimimi: ' + str(e) + +#Commands of NewsBot +class commands(): + def add(self, args): + if args[1] not in bots and args[1] != self.nickname: + try: + bot = RssBot(args[2], args[1], [self.ctrl_chan], url_shortener=self.url_shortener) + except Exception as e: + return 'add_mimi: ' + str(e) + sleep + bots[args[1]] = bot + bot.start_rss() + return "bot " + args[1] + " added" + else: + return args[1] + ' does already exist' + + def delete(self, args): + bots[args[1]].stop() + del bots[args[1]] + return "bot " + args[1] + " deleted" + + def rename(self, args): + if args[1] in bots: + if args[2] in bots: + return args[2] + ' already taken' + else: + bots[args[1]].connection.nick(args[2]) + bots[args[1]].name = args[2] + bots[args[2]] = bots[args[1]] + del bots[args[1]] + return 'renamed ' + args[1] + ' in ' + args[2] + else: + return args[1] + ' does not exist' + + def save(self, args): + output_buffer = '' + for bot in bots: + if bots[bot].loop: + output_buffer += bot + '|' + bots[bot].url + '|' + ' '.join(bots[bot].channels) + '\n' + + F = open(feedfile, "w") + F.writelines(output_buffer) + F.close() + + return "bots saved to " + feedfile + + def caps(self, args): + return ' '.join([x for x in commands.__dict__.keys() if x.find('_')]) + + def list(self, args): + output_buffer = '' + for bot in bots: + output_buffer += bot + ' url: ' + bots[bot].url + '\n' + return output_buffer + + def info(self, args): + if args[1] in bots: + output_buffer = '' + for data in ['title', 'link', 'updated']: + if data in bots[args[1]].feed.feed: + output_buffer += data + ': ' + bots[args[1]].feed.feed[data] + '\n' + output_buffer += 'lastnew: ' + bots[args[1]].lastnew.isoformat() + '\n' + output_buffer += 'rssurl: ' + bots[args[1]].url + return output_buffer + else: + return 'bot not found' + + def search(self, args): + output = subprocess.check_output(['./GfindFeeds4bot', args[1]]).decode() + return output + + def uptime(self, args): + output = subprocess.check_output(['uptime']).decode() + return output + + +##RssBot Class +class RssBot(asybot): + def __init__(self, rss, name, chans=['#news'], url_shortener="http://localhost", server='ire', port=6667, timeout=60): + try: + asybot.__init__(self, server, port, name, chans) + except Exception as e: + print(e) + self.url = rss + self.to = timeout + self.oldnews = [] + self.loop = True + self.lastnew = datetime.now() + self.url_shortener = url_shortener + self.retry = True + + def on_nickinuse(*bla): + pass + + def start_rss(self): + self.upd_loop = threading.Thread(target=self.updateloop) + self.upd_loop.start() + + def stop(self): + self.disconnect() + self.loop = False + + def updateloop(self): + failcount=0 + while True: + try: + self.feed = feedparser.parse(self.url) + for entry in self.feed.entries: + self.oldnews.append(entry.link) + break + except: + print(self.nickname + ': rss timeout occured') + failcount+=1 + if failcount>20: + print(self.nickname + ' is broken, going to die') + self.stop() + return + while self.loop: + try: + self.feed = feedparser.parse(self.url) + for entry in self.feed.entries: + if not entry.link in self.oldnews: + #try: + # self.send_msg(entry.title + " " + entry.link + " com: " + entry.comments) + #except AttributeError: + shorturl = self.shortenurl(entry.link) + self.sendall(entry.title + ' ' + shorturl) + self.oldnews.append(entry.link) + self.lastnew = datetime.now() + except Exception as e: + print(str(datetime.now().hour) + ':' + str(datetime.now().minute) + ' ' + self.nickname + ': ' + str(e)) + sleep(self.to) + + def shortenurl(self, url): + while True: + try: + shorturl = subprocess.check_output(["curl", "-sS", "-F", "uri=" + url, self.url_shortener]).decode().strip('\n').strip('\r') + '#' + url.partition('://')[2].partition('/')[0] + return shorturl + except: + print('url shortener error') + sleep(1) + + def last(self, target, num): + for feed in [x for x in self.feed.entries][:num]: + self.send_msg(target, feed.title + ' ' + self.shortenurl(feed.link)) + + def sendall(self, string): + try: + self.send_msg(self.channels, string) + except Exception as e: + print(self.nickname + ': failed sending all to ' + str(self.channels) + ' because of ' + str(e)); + + def send_msg(self, target, string): + if self.connected: + for line in string.split('\n'): + while len(line)>0: + if len(line) < 450: + self.PRIVMSG(target, line) + line = '' + else: + space = line.rfind(" ", 1, 450) + self.PRIVMSG(target, line[:space]) + line=line[space:] + else: + self.reconnect() + while not self.connected: + print(self.nickname + ' waiting for reconnect') + sleep(10) + self.send_msg(target, string) + + def on_invite(self, prefix, command, params, rest): + for chan in rest.split(): + self.push('JOIN ' + chan) + self.channels.append(chan) + + def on_welcome(self, prefix, command, params, rest): + asybot.on_welcome(self, prefix, command, params, rest) + self.push('MODE ' + self.nickname + ' +D') + +feedfile = 'new_feeds' +url_shortener = 'http://go' +init_channels = ['#news'] + +bots = {} +knews = NewsBot('knews', init_channels, url_shortener=url_shortener) + +#config file reading +F = open(feedfile, "r") +lines = F.readlines() +F.close() + +for line in lines: + line = line.strip('\n') + linear = line.split('|') + bot = RssBot(linear[1], linear[0], linear[2].split(), url_shortener=url_shortener) + bot.start_rss() + bots[linear[0]] = bot + +def thread_handler(): + while True: + try: + loop() + except Exception as e: + print('ohoh ' + e) + +th = threading.Thread(target=thread_handler) +th.start() diff --git a/news/package.json b/news/package.json new file mode 100644 index 00000000..52c19177 --- /dev/null +++ b/news/package.json @@ -0,0 +1,32 @@ +{ + "name": "news", + "version": "0.0.0", + "description": "", + "main": "newsbot.js", + "dependencies": { + "feedparser": "*", + "form-data": "*", + "irc": "*", + "request": "*", + "shell-quote": "*" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/krebscode/painload" + }, + "keywords": [ + "irc", + "news", + "feed" + ], + "author": "krebs", + "license": "WTFPLv2", + "bugs": { + "url": "https://github.com/krebscode/painload/issues" + }, + "homepage": "https://github.com/krebscode/painload" +} |