diff --git a/kwaylon/__init__.py b/kwaylon/__init__.py
index 23f93a6..8cc0e4a 100644
--- a/kwaylon/__init__.py
+++ b/kwaylon/__init__.py
@@ -1 +1,3 @@
-from .kwaylon import Kwaylon
\ No newline at end of file
+from .kwaylon import Kwaylon
+from .data import MsgData
+from .jokes import Joke, GifJoke
diff --git a/kwaylon/jokes/__init__.py b/kwaylon/jokes/__init__.py
new file mode 100644
index 0000000..ce764cd
--- /dev/null
+++ b/kwaylon/jokes/__init__.py
@@ -0,0 +1,12 @@
+from . import jokes
+from .base import Joke, GifJoke
+
+
+def collect_jokes():
+ for name in dir(jokes):
+ print(name)
+ try:
+ if issubclass((j := getattr(jokes, name)), Joke):
+ yield j
+ except TypeError as e:
+ continue
diff --git a/kwaylon/jokes/base.py b/kwaylon/jokes/base.py
new file mode 100644
index 0000000..d85a339
--- /dev/null
+++ b/kwaylon/jokes/base.py
@@ -0,0 +1,22 @@
+import re
+
+import discord
+
+
+class Joke:
+ @property
+ def regex(self) -> re.Pattern:
+ raise NotImplementedError
+
+ def scan(self, message: discord.Message) -> re.Match:
+ return self.regex.search(message.content)
+
+ async def respond(self, message: discord.Message, client: discord.Client, match: re.Match):
+ raise NotImplementedError
+
+
+class GifJoke(Joke):
+ url: str
+
+ async def respond(self, message: discord.Message, client: discord.Client, match: re.Match):
+ await message.channel.send(self.url)
diff --git a/kwaylon/jokes/helpers.py b/kwaylon/jokes/helpers.py
new file mode 100644
index 0000000..5e46008
--- /dev/null
+++ b/kwaylon/jokes/helpers.py
@@ -0,0 +1,34 @@
+import nltk
+
+pattern = 'NP: {
?*}'
+cp = nltk.RegexpParser(pattern)
+
+
+def token_list(s):
+ return nltk.chunk.tree2conlltags(
+ cp.parse(
+ nltk.pos_tag(
+ nltk.word_tokenize(s)
+ )))
+
+
+def assify(s):
+ tag_list = token_list(s)
+ for i, (text, tag, iob) in enumerate(tag_list):
+ if text[-3:].lower() == 'ass':
+ try:
+ next_tag = tag_list[i + 1][1]
+ if next_tag == 'NN' or next_tag == 'NNS':
+ return f'ass-{tag_list[i + 1][0]}'
+ except IndexError as e:
+ return
+
+
+def unblack(s):
+ tag_list = token_list(s)
+ for i, (text, tag, iob) in enumerate(tag_list):
+ if text.lower() == 'black':
+ if tag.startswith('JJ') or tag.startswith('NN'):
+ for text, tag, iob in tag_list[i + 1:]:
+ if tag.startswith('NN'):
+ return f'Or as I would say, {text.lower()}'
diff --git a/kwaylon/jokes.py b/kwaylon/jokes/jokes.py
similarity index 65%
rename from kwaylon/jokes.py
rename to kwaylon/jokes/jokes.py
index b4fd611..8c864aa 100644
--- a/kwaylon/jokes.py
+++ b/kwaylon/jokes/jokes.py
@@ -1,9 +1,12 @@
import re
import discord
-import nltk
import stockquotes
+from .helpers import assify, unblack
+from . import base
+
+
# TODO implement new jokes
# - j'accuse
# - egos
@@ -21,19 +24,7 @@ import stockquotes
# - strip club
-class Joke:
- @property
- def regex(self) -> re.Pattern:
- raise NotImplementedError
-
- def scan(self, message: discord.Message) -> re.Match:
- return self.regex.search(message.content)
-
- async def respond(self, message: discord.Message, client: discord.Client, match: re.Match):
- raise NotImplementedError
-
-
-class CumJoke(Joke):
+class CumJoke(base.Joke):
@property
def regex(self) -> re.Pattern:
words = [
@@ -51,7 +42,7 @@ class CumJoke(Joke):
await message.add_reaction(discord.utils.get(client.emojis, name='kaylon'))
-class BlackJoke(Joke):
+class BlackJoke(base.Joke):
@property
def regex(self) -> re.Pattern:
return re.compile('black (\w+)', re.IGNORECASE)
@@ -63,7 +54,7 @@ class BlackJoke(Joke):
await msg.add_reaction(discord.utils.get(client.emojis, name='kaylon'))
-class AssJoke(Joke):
+class AssJoke(base.Joke):
@property
def regex(self) -> re.Pattern:
return re.compile('[ \-]ass[ \-](?P\w+)', re.IGNORECASE)
@@ -74,7 +65,7 @@ class AssJoke(Joke):
await message.reply(f'{res} {discord.utils.get(client.emojis, name="kaylon")}')
-class DominosJoke(Joke):
+class DominosJoke(base.Joke):
@property
def regex(self) -> re.Pattern:
return re.compile('domino\'?s', re.IGNORECASE)
@@ -87,14 +78,7 @@ class DominosJoke(Joke):
await message.reply(msg)
-class GifJoke(Joke):
- url: str
-
- async def respond(self, message: discord.Message, client: discord.Client, match: re.Match):
- await message.channel.send(self.url)
-
-
-class BeansJoke(GifJoke):
+class BeansJoke(base.GifJoke):
url = 'https://c.tenor.com/TjX1yORoln0AAAAM/this-is-beans-beans.gif'
@property
@@ -106,7 +90,7 @@ class BeansJoke(GifJoke):
await super().respond(message, client, match)
-class NotLikeThisJoke(GifJoke):
+class NotLikeThisJoke(base.GifJoke):
url = 'https://tenor.com/view/not-like-this-the-matrix-panic-neo-angry-gif-5216157'
@property
@@ -117,7 +101,7 @@ class NotLikeThisJoke(GifJoke):
await message.reply(self.url)
-class ChiliJoke(GifJoke):
+class ChiliJoke(base.GifJoke):
url = 'https://tenor.com/view/office-gif-20038284'
@property
@@ -126,37 +110,3 @@ class ChiliJoke(GifJoke):
async def respond(self, message: discord.Message, client: discord.Client, match: re.Match):
await message.reply(self.url)
-
-
-pattern = 'NP: {?*}'
-cp = nltk.RegexpParser(pattern)
-
-
-def token_list(s):
- return nltk.chunk.tree2conlltags(
- cp.parse(
- nltk.pos_tag(
- nltk.word_tokenize(s)
- )))
-
-
-def assify(s):
- tag_list = token_list(s)
- for i, (text, tag, iob) in enumerate(tag_list):
- if text[-3:].lower() == 'ass':
- try:
- next_tag = tag_list[i + 1][1]
- if next_tag == 'NN' or next_tag == 'NNS':
- return f'ass-{tag_list[i + 1][0]}'
- except IndexError as e:
- return
-
-
-def unblack(s):
- tag_list = token_list(s)
- for i, (text, tag, iob) in enumerate(tag_list):
- if text.lower() == 'black':
- if tag.startswith('JJ') or tag.startswith('NN'):
- for text, tag, iob in tag_list[i + 1:]:
- if tag.startswith('NN'):
- return f'Or as I would say, {text.lower()}'
diff --git a/kwaylon/kwaylon.py b/kwaylon/kwaylon.py
index f2651f0..dd05a27 100644
--- a/kwaylon/kwaylon.py
+++ b/kwaylon/kwaylon.py
@@ -23,6 +23,7 @@ class Kwaylon(discord.Client):
attrs = filter(lambda n: n.endswith('Joke') and n not in ['Joke', 'GifJoke'], dir(jokes))
attrs = map(lambda n: getattr(jokes, n)(), attrs)
self.jokes = list(attrs)
+
self.most_regex = re.compile(
'^who is the most\s+(?P\S+)\s*?(?:in the past (?P\d+) days)?\??$',
re.IGNORECASE,