Compare commits
	
		
			2 Commits
		
	
	
		
			8c1bd5bd71
			...
			2399b5e882
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2399b5e882 | |||
| ed538d6045 | 
| @ -7,6 +7,7 @@ import irc.client | ||||
| import markov.lib as markovlib | ||||
| from ircbot.lib import Plugin, reply_destination_for_event | ||||
| from ircbot.models import IrcChannel | ||||
| from markov.models import MarkovContext, MarkovTarget | ||||
| 
 | ||||
| log = logging.getLogger('markov.ircplugin') | ||||
| 
 | ||||
| @ -40,7 +41,7 @@ class Markov(Plugin): | ||||
| 
 | ||||
|         min_size = 15 | ||||
|         max_size = 30 | ||||
|         context = markovlib.get_or_create_target_context(target) | ||||
|         context = self.get_or_create_target_context(target) | ||||
| 
 | ||||
|         if match.group(2): | ||||
|             min_size = int(match.group(2)) | ||||
| @ -90,12 +91,12 @@ class Markov(Plugin): | ||||
|             recursing = getattr(event, 'recursing', False) | ||||
|             if not recursing: | ||||
|                 log.debug("learning %s", learning_what) | ||||
|                 context = markovlib.get_or_create_target_context(target) | ||||
|                 context = self.get_or_create_target_context(target) | ||||
|                 markovlib.learn_line(learning_what, context) | ||||
| 
 | ||||
|         log.debug("searching '%s' for '%s'", what, all_nicks) | ||||
|         if re.search(all_nicks, what, re.IGNORECASE) is not None: | ||||
|             context = markovlib.get_or_create_target_context(target) | ||||
|             context = self.get_or_create_target_context(target) | ||||
| 
 | ||||
|             addressed_pattern = r'^(({nicks})[:,]|@({nicks}))\s+(?P<addressed_msg>.*)'.format(nicks=all_nicks) | ||||
|             match = re.match(addressed_pattern, what, re.IGNORECASE) | ||||
| @ -113,5 +114,31 @@ class Markov(Plugin): | ||||
|                 return self.bot.reply(event, "{0:s}" | ||||
|                                       "".format(" ".join(markovlib.generate_line(context, topics=topics)))) | ||||
| 
 | ||||
|     def get_or_create_target_context(self, target_name): | ||||
|         """Return the context for a provided nick/channel, creating missing ones.""" | ||||
|         target_name = target_name.lower() | ||||
| 
 | ||||
|         # find the stuff, or create it | ||||
|         try: | ||||
|             target = MarkovTarget.objects.get(name=target_name) | ||||
|         except MarkovTarget.DoesNotExist: | ||||
|             # we need to create a context and a target, and we have to make the context first | ||||
|             # make a context --- lacking a good idea, just create one with this target name until configured otherwise | ||||
|             channel, c = IrcChannel.objects.get_or_create(name=target_name, server=self.connection.server_config) | ||||
|             context, c = MarkovContext.objects.get_or_create(name=target_name) | ||||
|             target, c = MarkovTarget.objects.get_or_create(name=target_name, context=context, channel=channel) | ||||
| 
 | ||||
|             return target.context | ||||
| 
 | ||||
|         try: | ||||
|             return target.context | ||||
|         except MarkovContext.DoesNotExist: | ||||
|             # make a context --- lacking a good idea, just create one with this target name until configured otherwise | ||||
|             context, c = MarkovContext.objects.get_or_create(name=target_name) | ||||
|             target.context = context | ||||
|             target.save() | ||||
| 
 | ||||
|             return target.context | ||||
| 
 | ||||
| 
 | ||||
| plugin = Markov | ||||
|  | ||||
| @ -4,7 +4,7 @@ import random | ||||
| 
 | ||||
| from django.db.models import Sum | ||||
| 
 | ||||
| from markov.models import MarkovContext, MarkovState, MarkovTarget | ||||
| from markov.models import MarkovState | ||||
| 
 | ||||
| log = logging.getLogger(__name__) | ||||
| 
 | ||||
| @ -124,32 +124,6 @@ def generate_sentence(context, topics=None, min_words=15, max_words=30): | ||||
|     return words | ||||
| 
 | ||||
| 
 | ||||
| def get_or_create_target_context(target_name): | ||||
|     """Return the context for a provided nick/channel, creating missing ones.""" | ||||
|     target_name = target_name.lower() | ||||
| 
 | ||||
|     # find the stuff, or create it | ||||
|     try: | ||||
|         target = MarkovTarget.objects.get(name=target_name) | ||||
|     except MarkovTarget.DoesNotExist: | ||||
|         # we need to create a context and a target, and we have to make the context first | ||||
|         # make a context --- lacking a good idea, just create one with this target name until configured otherwise | ||||
|         context, c = MarkovContext.objects.get_or_create(name=target_name) | ||||
|         target, c = MarkovTarget.objects.get_or_create(name=target_name, context=context) | ||||
| 
 | ||||
|         return target.context | ||||
| 
 | ||||
|     try: | ||||
|         return target.context | ||||
|     except MarkovContext.DoesNotExist: | ||||
|         # make a context --- lacking a good idea, just create one with this target name until configured otherwise | ||||
|         context, c = MarkovContext.objects.get_or_create(name=target_name) | ||||
|         target.context = context | ||||
|         target.save() | ||||
| 
 | ||||
|         return target.context | ||||
| 
 | ||||
| 
 | ||||
| def get_word_out_of_states(states, backwards=False): | ||||
|     """Pick one random word out of the given states.""" | ||||
|     # work around possible broken data, where a k1,k2 should have a value but doesn't | ||||
|  | ||||
							
								
								
									
										20
									
								
								markov/migrations/0005_markovtarget_channel.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								markov/migrations/0005_markovtarget_channel.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| # Generated by Django 3.2.18 on 2023-02-20 00:09 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| import django.db.models.deletion | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('ircbot', '0019_ircchannel_discord_bridge'), | ||||
|         ('markov', '0004_alter_markovstate_context'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name='markovtarget', | ||||
|             name='channel', | ||||
|             field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='ircbot.ircchannel'), | ||||
|         ), | ||||
|     ] | ||||
							
								
								
									
										24
									
								
								markov/migrations/0006_link_markovtarget_to_ircchannel.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								markov/migrations/0006_link_markovtarget_to_ircchannel.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| """Generated by Django 3.2.18 on 2023-02-19 23:15.""" | ||||
| from django.db import migrations | ||||
| 
 | ||||
| 
 | ||||
| def link_markovcontext_to_ircchannel(apps, schema_editor): | ||||
|     """Link the markov targets to a hopefully matching channel, by name.""" | ||||
|     IrcChannel = apps.get_model('ircbot', 'IrcChannel') | ||||
|     MarkovTarget = apps.get_model('markov', 'MarkovTarget') | ||||
|     for target in MarkovTarget.objects.all(): | ||||
|         channel = IrcChannel.objects.get(name=target.name) | ||||
|         target.channel = channel | ||||
|         target.save() | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
|     """Populate the markov target to IRC channel link.""" | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('markov', '0005_markovtarget_channel'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.RunPython(link_markovcontext_to_ircchannel) | ||||
|     ] | ||||
							
								
								
									
										20
									
								
								markov/migrations/0007_alter_markovtarget_channel.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								markov/migrations/0007_alter_markovtarget_channel.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| # Generated by Django 3.2.18 on 2023-02-20 00:11 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| import django.db.models.deletion | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('ircbot', '0019_ircchannel_discord_bridge'), | ||||
|         ('markov', '0006_link_markovtarget_to_ircchannel'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AlterField( | ||||
|             model_name='markovtarget', | ||||
|             name='channel', | ||||
|             field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ircbot.ircchannel'), | ||||
|         ), | ||||
|     ] | ||||
| @ -3,6 +3,8 @@ import logging | ||||
| 
 | ||||
| from django.db import models | ||||
| 
 | ||||
| from ircbot.models import IrcChannel | ||||
| 
 | ||||
| log = logging.getLogger(__name__) | ||||
| 
 | ||||
| 
 | ||||
| @ -21,6 +23,7 @@ class MarkovTarget(models.Model): | ||||
| 
 | ||||
|     name = models.CharField(max_length=200, unique=True) | ||||
|     context = models.ForeignKey(MarkovContext, on_delete=models.CASCADE) | ||||
|     channel = models.ForeignKey(IrcChannel, on_delete=models.CASCADE) | ||||
| 
 | ||||
|     chatter_chance = models.IntegerField(default=0) | ||||
| 
 | ||||
|  | ||||
| @ -3,7 +3,7 @@ from unittest import mock | ||||
| 
 | ||||
| from django.test import TestCase | ||||
| 
 | ||||
| from ircbot.models import IrcServer | ||||
| from ircbot.models import IrcChannel, IrcServer | ||||
| from markov.ircplugin import Markov | ||||
| 
 | ||||
| 
 | ||||
| @ -100,3 +100,15 @@ class MarkovTestCase(TestCase): | ||||
|                 self.plugin.handle_chatter(self.mock_connection, mock_event) | ||||
| 
 | ||||
|         self.assertEqual(mock_learn_line.call_args.args[0], 'hello this is a test message') | ||||
| 
 | ||||
|     def test_autocreate_ircchannel(self): | ||||
|         """Test that we create the necessary config objects when seeing a target for the first time.""" | ||||
|         self.assertEqual(IrcChannel.objects.filter(name='#fakechannel').count(), 0) | ||||
|         context = self.plugin.get_or_create_target_context('#fakechannel') | ||||
| 
 | ||||
|         self.assertEqual(IrcChannel.objects.filter(name='#fakechannel').count(), 1) | ||||
|         self.assertIsNotNone(context) | ||||
|         self.assertIsNotNone(context.markovtarget_set) | ||||
|         self.assertIsNotNone(context.markovtarget_set.all()[0].channel) | ||||
|         self.assertEqual(context.markovtarget_set.all()[0].channel.name, '#fakechannel') | ||||
|         self.assertEqual(context.markovtarget_set.all()[0].name, '#fakechannel') | ||||
|  | ||||
							
								
								
									
										17
									
								
								tests/test_markov_lib.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								tests/test_markov_lib.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| """Test markov utility methods.""" | ||||
| from django.test import TestCase | ||||
| 
 | ||||
| from markov.lib import get_word_out_of_states, learn_line | ||||
| from markov.models import MarkovContext, MarkovState | ||||
| 
 | ||||
| 
 | ||||
| class MarkovLibTestCase(TestCase): | ||||
|     """Test library methods used by the Markov plugin.""" | ||||
| 
 | ||||
|     fixtures = ['tests/fixtures/irc_server_fixture.json', 'tests/fixtures/markov_fixture.json'] | ||||
| 
 | ||||
|     def test_learn_and_get(self): | ||||
|         """Test that we can learn some lines and get a word back.""" | ||||
|         learn_line("the elephant goes ERRRRRRRRRRRRR", MarkovContext.objects.get(pk=1)) | ||||
|         word = get_word_out_of_states(MarkovState.objects.all()) | ||||
|         self.assertIn(word, ['the', 'elephant', 'goes', 'ERRRRRRRRRRRRR', '__stop']) | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user