add markov module and irc plugin
just listens to servers right now, doesn't speak up (yet)
This commit is contained in:
parent
7ec643afda
commit
51edb54ed7
|
@ -40,6 +40,7 @@ INSTALLED_APPS = [
|
|||
'bot',
|
||||
'dice',
|
||||
'logger',
|
||||
'markov',
|
||||
'weather',
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
"""Display Markov data elements in the Django admin."""
|
||||
from django.contrib import admin
|
||||
|
||||
from markov.models import MarkovContext, MarkovState
|
||||
|
||||
admin.site.register(MarkovContext)
|
||||
admin.site.register(MarkovState)
|
|
@ -0,0 +1,6 @@
|
|||
"""App config for the markov module."""
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MarkovConfig(AppConfig):
|
||||
name = 'markov'
|
|
@ -0,0 +1,33 @@
|
|||
"""Observe Markov chains from Discord."""
|
||||
import logging
|
||||
|
||||
from bot import hitomi
|
||||
from markov import lib
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info("loading markov plugin")
|
||||
|
||||
|
||||
def on_message(message):
|
||||
"""Keep the observed Markov chains."""
|
||||
# ignore self
|
||||
if message.author == hitomi.user:
|
||||
logger.debug("markov ignoring message authored by self")
|
||||
return
|
||||
|
||||
if message.channel.is_private:
|
||||
# DMs have a context of the author
|
||||
context_name = message.author
|
||||
else:
|
||||
# channels have a context of the server, but we should ignore channels that override @everyone's read ability
|
||||
for changed_role in message.channel.changed_roles:
|
||||
if changed_role.is_everyone:
|
||||
if not changed_role.permissions.read_messages:
|
||||
logger.debug("markov ignoring channel that @everyone can't read")
|
||||
return
|
||||
context_name = message.server.id
|
||||
|
||||
lib.learn_line(message.content, context_name)
|
||||
|
||||
|
||||
hitomi.on_message_handlers.append(on_message)
|
|
@ -0,0 +1,30 @@
|
|||
"""Shared methods for the Markov module."""
|
||||
import logging
|
||||
|
||||
from markov.models import MarkovContext, MarkovState
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def learn_line(line, context_name):
|
||||
"""Create a bunch of MarkovStates for a given line of text."""
|
||||
logger.debug("learning %s...", line[:40])
|
||||
|
||||
context, created = MarkovContext.objects.get_or_create(name=context_name)
|
||||
|
||||
words = line.split()
|
||||
words = [MarkovState.start1, MarkovState.start2] + words + [MarkovState.stop]
|
||||
|
||||
for word in words:
|
||||
if len(word) > MarkovState._meta.get_field('k1').max_length:
|
||||
return
|
||||
|
||||
for i, word in enumerate(words):
|
||||
logger.debug("'{0:s}','{1:s}' -> '{2:s}'".format(words[i], words[i + 1], words[i + 2]))
|
||||
state, created = MarkovState.objects.get_or_create(context=context, k1=words[i], k2=words[i + 1],
|
||||
v=words[i + 2])
|
||||
state.count += 1
|
||||
state.save()
|
||||
|
||||
if i > len(words) - 4:
|
||||
break
|
|
@ -0,0 +1,41 @@
|
|||
# Generated by Django 2.0.1 on 2018-01-09 19:57
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='MarkovContext',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200, unique=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MarkovState',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('k1', models.CharField(max_length=256)),
|
||||
('k2', models.CharField(max_length=256)),
|
||||
('v', models.CharField(max_length=256)),
|
||||
('count', models.IntegerField(default=0)),
|
||||
('context', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='markov.MarkovContext')),
|
||||
],
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='markovstate',
|
||||
unique_together={('context', 'k1', 'k2', 'v')},
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
name='markovstate',
|
||||
index_together={('context', 'k1', 'k2'), ('context', 'v')},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,43 @@
|
|||
"""Database objects for storing Markov chains."""
|
||||
|
||||
import logging
|
||||
|
||||
from django.db import models
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MarkovContext(models.Model):
|
||||
"""Define contexts for Markov chains."""
|
||||
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
|
||||
def __str__(self):
|
||||
"""String representation."""
|
||||
return "{0:s}".format(self.name)
|
||||
|
||||
|
||||
class MarkovState(models.Model):
|
||||
"""One element in a Markov chain, some text or something."""
|
||||
|
||||
start1 = '__start1'
|
||||
start2 = '__start2'
|
||||
stop = '__stop'
|
||||
|
||||
k1 = models.CharField(max_length=256)
|
||||
k2 = models.CharField(max_length=256)
|
||||
v = models.CharField(max_length=256)
|
||||
|
||||
count = models.IntegerField(default=0)
|
||||
context = models.ForeignKey(MarkovContext, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
index_together = [
|
||||
['context', 'k1', 'k2'],
|
||||
['context', 'v'],
|
||||
]
|
||||
unique_together = ('context', 'k1', 'k2', 'v')
|
||||
|
||||
def __str__(self):
|
||||
"""String representation."""
|
||||
return "{0:s},{1:s} -> {2:s} (count: {3:d})".format(self.k1, self.k2, self.v, self.count)
|
Loading…
Reference in New Issue