From 84ee09d4a3d0fdaef69d545772d68c5712547c67 Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sun, 16 Mar 2014 11:35:01 -0500 Subject: [PATCH] migrate Seen to django models and whatnot this also adds south and django_extensions stuff, because that is the natural thing to do. this is a pretty good start, i think --- dr_botzo/settings.py | 2 + ircbot/modules/Seen.py | 93 +++++++++---------------------- requirements.txt | 2 + seen/__init__.py | 0 seen/admin.py | 12 ++++ seen/migrations/0001_seen_data.py | 46 +++++++++++++++ seen/migrations/__init__.py | 0 seen/models.py | 29 ++++++++++ 8 files changed, 117 insertions(+), 67 deletions(-) create mode 100644 seen/__init__.py create mode 100644 seen/admin.py create mode 100644 seen/migrations/0001_seen_data.py create mode 100644 seen/migrations/__init__.py create mode 100644 seen/models.py diff --git a/dr_botzo/settings.py b/dr_botzo/settings.py index b9cefa0..408d945 100644 --- a/dr_botzo/settings.py +++ b/dr_botzo/settings.py @@ -36,6 +36,8 @@ INSTALLED_APPS = ( 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'south', + 'seen', ) MIDDLEWARE_CLASSES = ( diff --git a/ircbot/modules/Seen.py b/ircbot/modules/Seen.py index 82f29d7..0fd1092 100644 --- a/ircbot/modules/Seen.py +++ b/ircbot/modules/Seen.py @@ -1,6 +1,6 @@ """ Seen - track when a person speaks, and allow data to be queried -Copyright (C) 2010 Brian S. Stephan +Copyright (C) 2014 Brian S. Stephan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,92 +14,51 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . + """ import re -from dateutil.tz import * -import MySQLdb as mdb +from django.utils import timezone + +from seen.models import SeenNick from Module import Module + class Seen(Module): """Track when people say things in public channels, and report on it.""" - def db_init(self): - """Create the table to store seen data.""" - - version = self.db_module_registered(self.__class__.__name__) - if version == None: - db = self.get_db() - try: - version = 1 - cur = db.cursor(mdb.cursors.DictCursor) - cur.execute(''' - CREATE TABLE seen_nicks ( - nick VARCHAR(64) NOT NULL, - location VARCHAR(64) NOT NULL, - host VARCHAR(256) NOT NULL, - time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - what LONGTEXT NOT NULL - ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin - ''') - cur.execute(''' - CREATE UNIQUE INDEX seen_nicks_nick_and_location_index - ON seen_nicks (nick, location) - ''') - db.commit() - self.db_register_module_version(self.__class__.__name__, version) - except mdb.Error as e: - db.rollback() - self.log.error("database error trying to create tables") - self.log.exception(e) - raise - finally: cur.close() - def do(self, connection, event, nick, userhost, what, admin_unlocked): """Track pubmsg/privmsg events, and if asked, report on someone.""" where = event.target() - db = self.get_db() - # whatever it is, store it - try: - # if there's no where, this is probably a sub-command. don't learn it - if where: - cur = db.cursor(mdb.cursors.DictCursor) - statement = 'REPLACE INTO seen_nicks (nick, location, host, what) VALUES (%s, %s, %s, %s)' - cur.execute(statement, (nick, where, userhost, what)) - db.commit() - except mdb.Error as e: - db.rollback() - self.log.error("database error storing seen data") - self.log.exception(e) - raise - finally: cur.close() + # store the event. only learn events with real wheres + if where: + try: + seen_nick = SeenNick.objects.get(nick=nick, channel=where) + except SeenNick.DoesNotExist: + seen_nick = SeenNick() + seen_nick.nick = nick + seen_nick.channel = where + + seen_nick.host = userhost + seen_nick.what = what + seen_nick.save() match = re.search('^!seen\s+(\S+)$', what) if match: nick = match.group(1) - db = self.get_db() try: - cur = db.cursor(mdb.cursors.DictCursor) - query = 'SELECT * FROM seen_nicks WHERE nick = %s AND location = %s' - cur.execute(query, (nick,where)) - result = cur.fetchone() - if result: - seentime = result['time'].replace(tzinfo=tzlocal()) - replystr = 'last saw {0:s} in {3:s} at {1:s} saying \'{2:s}\'.'.format(result['nick'], seentime.astimezone(tzlocal()).strftime('%Y/%m/%d %H:%M:%S %Z'), result['what'], result['location']) - return self.irc.reply(event, replystr) - else: - return self.irc.reply(event, 'i have not seen {0:s} in {1:s}.'.format(nick, where)) - except mdb.Error as e: - db.rollback() - self.log.error("database error retrieving seen data") - self.log.exception(e) - raise - finally: cur.close() + seen_nick = SeenNick.objects.get(nick=nick, channel=where) + local_time = timezone.localtime(seen_nick.seen_time) + return self.irc.reply(event, + "last saw {0:s} in {1:s} at {2:s} saying '{3:s}'." + "".format(seen_nick.nick, seen_nick.channel, + local_time, seen_nick.what)) + except SeenNick.DoesNotExist: + return self.irc.reply(event, "i have not seen {0:s} in {1:s}.".format(nick, where)) # vi:tabstop=4:expandtab:autoindent -# kate: indent-mode python;indent-width 4;replace-tabs on; diff --git a/requirements.txt b/requirements.txt index c6a5363..f8bd732 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,7 @@ Django==1.6.2 MySQL-python==1.2.3 +South==0.8.4 +django-extensions==1.3.3 httplib2==0.7.4 logilab-astng==0.24.0 logilab-common==0.58.1 diff --git a/seen/__init__.py b/seen/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/seen/admin.py b/seen/admin.py new file mode 100644 index 0000000..bb96cc4 --- /dev/null +++ b/seen/admin.py @@ -0,0 +1,12 @@ +from django.contrib import admin + +from seen.models import SeenNick + + +class SeenNickAdmin(admin.ModelAdmin): + list_display = ('__unicode__', 'seen_time') + + +admin.site.register(SeenNick, SeenNickAdmin) + +# vi:tabstop=4:expandtab:autoindent diff --git a/seen/migrations/0001_seen_data.py b/seen/migrations/0001_seen_data.py new file mode 100644 index 0000000..0f6286b --- /dev/null +++ b/seen/migrations/0001_seen_data.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'SeenNick' + db.create_table(u'seen_seennick', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('nick', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('channel', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('host', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('seen_time', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now, blank=True)), + ('what', self.gf('django.db.models.fields.TextField')()), + )) + db.send_create_signal(u'seen', ['SeenNick']) + + # Adding unique constraint on 'SeenNick', fields ['nick', 'channel'] + db.create_unique(u'seen_seennick', ['nick', 'channel']) + + + def backwards(self, orm): + # Removing unique constraint on 'SeenNick', fields ['nick', 'channel'] + db.delete_unique(u'seen_seennick', ['nick', 'channel']) + + # Deleting model 'SeenNick' + db.delete_table(u'seen_seennick') + + + models = { + u'seen.seennick': { + 'Meta': {'ordering': "['-seen_time']", 'unique_together': "(('nick', 'channel'),)", 'object_name': 'SeenNick'}, + 'channel': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'host': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'nick': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'seen_time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'blank': 'True'}), + 'what': ('django.db.models.fields.TextField', [], {}) + } + } + + complete_apps = ['seen'] \ No newline at end of file diff --git a/seen/migrations/__init__.py b/seen/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/seen/models.py b/seen/models.py new file mode 100644 index 0000000..34452ee --- /dev/null +++ b/seen/models.py @@ -0,0 +1,29 @@ +from django.db import models +from django.utils import timezone + +from django_extensions.db.fields import ModificationDateTimeField + + +class SeenNick(models.Model): + + """Track when a nick was seen in any channel.""" + + nick = models.CharField(max_length=64) + channel = models.CharField(max_length=64) + + host = models.CharField(max_length=255) + seen_time = ModificationDateTimeField(editable=True) + what = models.TextField() + + class Meta: + ordering = ['-seen_time',] + unique_together = ('nick', 'channel') + + def __unicode__(self): + """String representation of a seen nick.""" + + local_time = timezone.localtime(self.seen_time) + return u"{0:s} seen in {1:s} at {2:s}".format(self.nick, self.channel, + local_time.strftime('%Y-%m-%d %H:%M:%S %Z')) + +# vi:tabstop=4:expandtab:autoindent