Skip to content

Instantly share code, notes, and snippets.

@dannon
Created February 4, 2015 13:53
Show Gist options
  • Save dannon/6084d815a40a24b9e640 to your computer and use it in GitHub Desktop.
Save dannon/6084d815a40a24b9e640 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
"""
Python script for tailing irc logs and mailing notifications.
"""
import os
import smtplib
import pickle
import copy
from optparse import OptionParser
STORAGE_FILE = 'chatminder.pickle'
FROMADDR = 'root@orangehack.com'
SUBJECT = 'ircmailer notification'
DEFAULT_CHANNELS = ['/home/yoplait/irclogs/freenode/#galaxyproject.log']
DEFAULT_DIR = ['/home/yoplait/irclogs/freenode/']
FILTERS = ['Netsplit', '] has quit','] has joined', '] has left', 'Day changed', '< robotobot>', 'is now known as', '--- Log', 'CIA-38']
STATUS_FILTERS = ['dannon>','dannon_>']
NOMAIL_CHANNELS = ['#truecrypt','#python', '#celery', '#boto', '#gmod', '#redmine', '#django',
'#jquery', '#bioinformatics', '#biology', '#sqlalchemy', '#gsoc', '#google-containers']
class ChatChannel(object):
def __init__(self, base_file, start_at_end = False):
self.base_file = base_file
self.last_updated = os.path.getmtime(base_file)
if not start_at_end:
self.last_updated = 0
self.last_line = 0
else:
f = open(self.base_file)
for i, line in enumerate(f.readlines()):
pass
f.close()
self.last_line = 0
def update(self):
newlines = ""
if self.last_updated != os.path.getmtime(self.base_file):
f = open(self.base_file)
for i, line in enumerate(f.readlines()):
if i > self.last_line:
newlines += line
self.last_line = i
f.close()
return newlines
class ChatMinder(object):
def __init__(self, rescan=True):
self.channels = []
if rescan:
self.rescan_defaults()
def rescan_default_dir(self):
for i in DEFAULT_DIR:
if os.path.isdir(i):
for j in os.listdir(i):
if j.endswith('.log'):
self.add_channel(os.path.join(i, j))
for i in DEFAULT_CHANNELS:
self.add_channel(i)
def update(self):
digest = ""
for channel in self.channels:
nt = channel.update()
no_mail = False
for nom in NOMAIL_CHANNELS:
if nom in channel.base_file:
no_mail = True
if no_mail:
continue
status_active = False
lines = []
for line in nt.split('\n'):
doline = True
for f in FILTERS:
if f in line:
doline = False
for f in STATUS_FILTERS:
if f in line:
status_active = True
if doline and line.strip():
lines.append(line)
if lines and not status_active:
digest += "=================================\n%s:\n%s\n\n" % (channel.base_file, '\n'.join(lines))
if digest:
# print "Sending digest!"
self.sendmail('dannon.baker@gmail.com', digest)
else:
# print "No update, not sending an email."
pass
def sendmail(self, user, text):
msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s"
% (FROMADDR, user, SUBJECT, text))
server = smtplib.SMTP('localhost')
server.sendmail(FROMADDR, user, msg)
server.quit()
def add_channel(self, new):
if new not in [c.base_file for c in self.channels]:
self.channels.append(ChatChannel(new))
#print "Added %s as a channel." % new
def add_channels(self, newlist):
for e in newlist:
self.add_channel(e)
def get_stored_cm(cmpickle):
if os.path.exists(cmpickle):
sf = open(cmpickle)
cm = pickle.load(sf)
sf.close()
return cm
return None
def main():
parser = OptionParser()
parser.add_option("-r", action="store_true", help="Reset channels?", default=False)
parser.add_option("-s", action="store_true", help="Rescan Default Channels?", default=False)
parser.add_option("-o", action="store_true", help="Rebuild Objects", default=False)
(opts, args) = parser.parse_args()
if opts.r:
# print "Resetting with a new ChatMinder"
cm = ChatMinder()
elif opts.o:
# print "Rebuilding the ChatMinder Object"
old_cm = get_stored_cm(STORAGE_FILE)
cm = ChatMinder(rescan=False)
if old_cm:
cm.channels = copy.deepcopy(old_cm.channels)
elif os.path.exists(STORAGE_FILE):
# print "Reloading old ChatMinder"
cm = get_stored_cm(STORAGE_FILE)
else:
# print "Starting a new ChatMinder"
cm = ChatMinder()
if opts.s:
# print "Rescanning default directories for new channels"
cm.rescan_default_dir()
cm.update()
sf = open(STORAGE_FILE, 'w')
pickle.dump(cm, sf)
sf.close()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment