Skip to content

Commit f332431

Browse files
committed
Added @micolous' bots back in
1 parent e161423 commit f332431

File tree

7 files changed

+1056
-0
lines changed

7 files changed

+1056
-0
lines changed

ethicsbot.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import asyncore, random
2+
from hashlib import sha512
3+
from datetime import datetime, timedelta
4+
from ConfigParser import ConfigParser
5+
from sys import argv, exit
6+
from ircasync import *
7+
from subprocess import Popen, PIPE
8+
9+
ETHICAL_MESSAGES = [
10+
[ # unethical
11+
'your chairman resigns after the plan is revealed to the public by "60 Minutes".',
12+
'your company was fined 1.4m$ after a probe into your activities.',
13+
'your company was fined a record 600m$ by the EU after reports of bribery.',
14+
'accounting irregularities were exposed by a whistleblower, resulting in a fine for your company.',
15+
'the prime minister announces new taxes on employees because of a percieved lack of local investment by your company in rural areas.',
16+
],
17+
18+
[ # ethical
19+
'a jury found no misconduct by board members.',
20+
'testimony of key witnesses had to be striken from the record after finding they were all under the influence of drugs.',
21+
'the prime minister issued a public apology over the government\'s handling of your company\'s case in the media.',
22+
23+
],
24+
25+
[ # unsure
26+
'a royal commission is establisted into your activities.',
27+
'the government announces a bailout package for your company.',
28+
'your company\'s charity activities in the third world were recognised by the judge in giving your company a lenient sentence.',
29+
'your company owns a 70% share in local newspapers and television stations, meaning this incident is never brought to the public\'s attention.',
30+
],
31+
]
32+
33+
ETHICAL_STATES = [
34+
'unethical',
35+
'ethical',
36+
'unsure',
37+
]
38+
39+
config = ConfigParser()
40+
try:
41+
config.readfp(open(argv[1]))
42+
except:
43+
try:
44+
config.readfp(open('ethicsbot.ini'))
45+
except:
46+
print "Syntax:"
47+
print " %s [config]" % argv[0]
48+
print ""
49+
print "If no configuration file is specified or there was an error, it will default to `ethicsbot.ini'."
50+
print "If there was a failure reading the configuration, it will display this message."
51+
exit(1)
52+
53+
# read config
54+
SERVER = config.get('ethicsbot', 'server')
55+
try: PORT = config.getint('ethicsbot', 'port')
56+
except: PORT = DEFAULT_PORT
57+
NICK = config.get('ethicsbot', 'nick')
58+
CHANNEL = config.get('ethicsbot', 'channel')
59+
VERSION = 'ethicsbot hg:%s; http://hg.micolous.id.au/ircbots/'
60+
try: VERSION = VERSION % Popen(["hg","id"], stdout=PIPE).communicate()[0].strip()
61+
except: VERSION = VERSION % 'unknown'
62+
del Popen, PIPE
63+
64+
try: FLOOD_COOLDOWN = timedelta(seconds=config.getint('ethicsbot', 'flood_cooldown'))
65+
except: FLOOD_COOLDOWN = timedelta(seconds=5)
66+
try: NICKSERV_PASS = config.get('ethicsbot', 'nickserv_pass')
67+
except: NICKSERV_PASS = None
68+
69+
message_buffer = []
70+
last_message = datetime.now()
71+
flooders = []
72+
ignore_list = []
73+
74+
if config.has_section('ignore'):
75+
for k,v in config.items('ignore'):
76+
try:
77+
ignore_list.append(re.compile(v, re.I))
78+
except Exception, ex:
79+
print "Error compiling regular expression in ignore list (%s):" % k
80+
print " %s" % v
81+
print ex
82+
exit(1)
83+
84+
# main code
85+
86+
87+
def handle_msg(event, match):
88+
global message_buffer, MAX_MESSAGES, last_message, flooders, CHANNEL
89+
msg = event.text
90+
91+
if event.channel.lower() != CHANNEL.lower():
92+
# ignore messages not from our channel
93+
return
94+
95+
if msg.startswith('?ethical'):
96+
for item in ignore_list:
97+
if item.search(event.origin) != None:
98+
# ignore list item hit
99+
print "Ignoring message from %s because of: %s" % (event.origin, item.pattern)
100+
return
101+
102+
# now flood protect!
103+
delta = event.when - last_message
104+
last_message = event.when
105+
106+
if delta < FLOOD_COOLDOWN:
107+
# 5 seconds between requests
108+
# any more are ignored
109+
print "Flood protection hit, %s of %s seconds were waited" % (delta.seconds, FLOOD_COOLDOWN.seconds)
110+
return
111+
112+
parts = msg.split(' ')
113+
query = (''.join(parts[1:])).lower()
114+
115+
if len(query) == 0:
116+
event.reply("%s: you must give me an ethical conundrum to process!" % event.nick)
117+
return
118+
119+
# hash the request
120+
h = sha512()
121+
h.update(query)
122+
123+
ethical = 0
124+
for c in h.digest():
125+
for x in xrange(1,9):
126+
if ord(c) & (2 ** x) > 1:
127+
ethical = (ethical + 1) % 3
128+
129+
event.reply('%s: (%s) %s' % (event.nick, ETHICAL_STATES[ethical], random.choice(ETHICAL_MESSAGES[ethical])))
130+
131+
def handle_welcome(event, match):
132+
global NICKSERV_PASS
133+
# Compliance with most network's rules to set this mode on connect.
134+
event.connection.usermode("+B")
135+
if NICKSERV_PASS != None:
136+
event.connection.todo(['NickServ', 'identify', NICKSERV_PASS])
137+
138+
irc = IRC(nick=NICK, start_channels=[CHANNEL], version=VERSION)
139+
irc.bind(handle_msg, PRIVMSG)
140+
irc.bind(handle_welcome, RPL_WELCOME)
141+
142+
irc.make_conn(SERVER, PORT)
143+
asyncore.loop()
144+

feedbot.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import re, asyncore, feedparser
2+
from time import sleep
3+
from ConfigParser import ConfigParser
4+
from sys import argv, exit
5+
from ircasync import *
6+
from subprocess import Popen, PIPE
7+
from thread import start_new_thread
8+
9+
config = ConfigParser()
10+
try:
11+
config.readfp(open(argv[1]))
12+
except:
13+
try:
14+
config.readfp(open('feedbot.ini'))
15+
except:
16+
print "Syntax:"
17+
print " %s [config]" % argv[0]
18+
print ""
19+
print "If no configuration file is specified or there was an error, it will default to `feedbot.ini'."
20+
print "If there was a failure reading the configuration, it will display this message."
21+
exit(1)
22+
23+
# read config
24+
SERVER = config.get('feedbot', 'server')
25+
try: PORT = config.getint('feedbot', 'port')
26+
except: PORT = DEFAULT_PORT
27+
NICK = config.get('feedbot', 'nick')
28+
CHANNEL = config.get('feedbot', 'channel')
29+
VERSION = 'feedbot hg:%s; http://hg.micolous.id.au/ircbots/'
30+
try: VERSION = VERSION % Popen(["hg","id"], stdout=PIPE).communicate()[0].strip()
31+
except: VERSION = VERSION % 'unknown'
32+
del Popen, PIPE
33+
34+
try: NICKSERV_PASS = config.get('feedbot', 'nickserv_pass')
35+
except: NICKSERV_PASS = None
36+
try: UPDATE_FREQUENCY = config.getint('feedbot', 'update_frequency')
37+
except: UPDATE_FREQUENCY = 300
38+
39+
feed_urls = {}
40+
if config.has_section('feeds'):
41+
for k,v in config.items('feeds'):
42+
feed_urls[k] = v
43+
44+
feeds = {}
45+
last_feeds = {}
46+
47+
48+
def announce_post(irc, feed, entry):
49+
global CHANNEL
50+
link = entry.link
51+
# debug
52+
print 'NEW POST: %s: %s (%s)' % (entry.title, link, feed)
53+
irc.action(CHANNEL, 'found a new post on %s: %s: %s' % (str(feed), str(entry.title), link))
54+
55+
def update(irc):
56+
global feed_urls, feeds, last_feeds
57+
58+
last_feeds = feeds
59+
feeds = {}
60+
61+
# work though the urls
62+
for k in feed_urls:
63+
try:
64+
# download the new feed
65+
if last_feeds.has_key(k) and hasattr(last_feeds[k], 'modified'):
66+
feeds[k] = feedparser.parse(feed_urls[k], modified=last_feeds[k].modified)
67+
else:
68+
feeds[k] = feedparser.parse(feed_urls[k])
69+
70+
# there is data to process
71+
if len(feeds[k].entries) > 0:
72+
# see what the old feed had
73+
if last_feeds.has_key(k):
74+
# there was old feed data
75+
# we should see what entries are new, and stop when we encounter the last oldest one.
76+
# assume that the old feed has the newest entry at the time at the top
77+
x = 0
78+
for entry in feeds[k].entries:
79+
oldlink = False
80+
# see if link has been published yet
81+
for oldentry in last_feeds[k].entries:
82+
if entry.link == oldentry.link:
83+
oldlink = True
84+
break
85+
86+
if oldlink or x > 4:
87+
# link has been published, or 4 links have been pushed
88+
print "not publishing anymore links"
89+
break
90+
91+
# all good to announce
92+
announce_post(irc, k, entry)
93+
x += 1
94+
95+
else:
96+
# don't publish anything, this is an initial run
97+
print "Not publishing all data from new feed `%s'." % k
98+
else:
99+
# there's no new data, restore the old data back in here for now.
100+
if last_feeds.has_key(k):
101+
feeds[k] = last_feeds[k]
102+
103+
104+
except:
105+
print "Failure updating feed `%s'." % k
106+
107+
# revert to last version
108+
if last_feeds.has_key(k):
109+
feeds[k] = last_feeds[k]
110+
111+
def feed_updater(irc):
112+
global UPDATE_FREQUENCY
113+
114+
while True:
115+
sleep(UPDATE_FREQUENCY)
116+
print "Naptime over, updating..."
117+
update(irc)
118+
119+
# main code
120+
def handle_welcome(event, match):
121+
global NICKSERV_PASS
122+
# Compliance with most network's rules to set this mode on connect.
123+
event.connection.usermode("+B")
124+
if NICKSERV_PASS != None:
125+
event.connection.todo(['NickServ', 'identify', NICKSERV_PASS])
126+
update(event.connection)
127+
128+
irc = IRC(nick=NICK, start_channels=[CHANNEL], version=VERSION)
129+
irc.bind(handle_welcome, RPL_WELCOME)
130+
irc.make_conn(SERVER, PORT)
131+
start_new_thread(feed_updater, (irc,))
132+
asyncore.loop()
133+

gamebot.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import re, asyncore
2+
from time import sleep
3+
from ConfigParser import ConfigParser
4+
from sys import argv, exit
5+
from ircasync import *
6+
from subprocess import Popen, PIPE
7+
from thread import start_new_thread
8+
9+
config = ConfigParser()
10+
try:
11+
config.readfp(open(argv[1]))
12+
except:
13+
try:
14+
config.readfp(open('gamebot.ini'))
15+
except:
16+
print "Syntax:"
17+
print " %s [config]" % argv[0]
18+
print ""
19+
print "If no configuration file is specified or there was an error, it will default to `gamebot.ini'."
20+
print "If there was a failure reading the configuration, it will display this message."
21+
exit(1)
22+
23+
# read config
24+
SERVER = config.get('gamebot', 'server')
25+
try: PORT = config.getint('gamebot', 'port')
26+
except: PORT = DEFAULT_PORT
27+
NICK = config.get('gamebot', 'nick')
28+
CHANNEL = config.get('gamebot', 'channel')
29+
VERSION = 'gamebot hg:%s; http://hg.micolous.id.au/ircbots/'
30+
try: VERSION = VERSION % Popen(["hg","id"], stdout=PIPE).communicate()[0].strip()
31+
except: VERSION = VERSION % 'unknown'
32+
del Popen, PIPE
33+
34+
try: NICKSERV_PASS = config.get('gamebot', 'nickserv_pass')
35+
except: NICKSERV_PASS = None
36+
37+
def update(irc):
38+
irc.action(CHANNEL, 'would like to inform you that you all just lost the game.')
39+
40+
def game_updater(irc):
41+
while True:
42+
sleep(30*60)
43+
update(irc)
44+
45+
# main code
46+
def handle_welcome(event, match):
47+
global NICKSERV_PASS
48+
# Compliance with most network's rules to set this mode on connect.
49+
event.connection.usermode("+B")
50+
if NICKSERV_PASS != None:
51+
event.connection.todo(['NickServ', 'identify', NICKSERV_PASS])
52+
update(event.connection)
53+
54+
irc = IRC(nick=NICK, start_channels=[CHANNEL], version=VERSION)
55+
irc.bind(handle_welcome, RPL_WELCOME)
56+
irc.make_conn(SERVER, PORT)
57+
start_new_thread(game_updater, (irc,))
58+
asyncore.loop()
59+

0 commit comments

Comments
 (0)