Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions futaba/cogs/optional/simplewriter/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# cogs/optional/simplewriter/__init__.py
#
# futaba - A Discord Mod bot for the Programming server
# Copyright (c) 2017-2020 Jake Richardson, Ammon Smith, jackylam5
#
# futaba is available free of charge under the terms of the MIT
# License. You are free to redistribute and/or modify it under those
# terms. It is distributed in the hopes that it will be useful, but
# WITHOUT ANY WARRANTY. See the LICENSE file for more details.
#

from .core import SimplewriterCog


def setup(bot):
setup_simplewriter(bot)


def setup_simplewriter(bot):
cog = SimplewriterCog(bot)
bot.add_listener(cog.on_message, "on_message")
bot.add_listener(cog.on_message_edit, "on_message_edit")
bot.add_cog(cog)


def teardown(bot):
teardown_simplewriter(bot)


def teardown_simplewriter(bot):
bot.remove_cog(SimplewriterCog.__name__)
45 changes: 45 additions & 0 deletions futaba/cogs/optional/simplewriter/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#
# cogs/optional/simplewriter/core.py
#
# futaba - A Discord Mod bot for the Programming server
# Copyright (c) 2017-2020 Jake Richardson, Ammon Smith, jackylam5
#
# futaba is available free of charge under the terms of the MIT
# License. You are free to redistribute and/or modify it under those
# terms. It is distributed in the hopes that it will be useful, but
# WITHOUT ANY WARRANTY. See the LICENSE file for more details.
#

"""
A thing that lets you write stuff in one word box, but only if it's made up of
the first ten hundred most used words of the language.

(https://xkcd.com/simplewriter)
"""

from futaba.cogs.abc import AbstractCog

from .simple_filter import simple_filter


class SimplewriterCog(AbstractCog):
__slots__ = ("journal", "channel_id")

def __init__(self, bot):
super().__init__(bot)
self.journal = bot.get_broadcaster("/simplewriter")
self.channel_id = int(bot.config.optional_cogs["simplewriter"]["channel-id"])

def setup(self):
pass

def cog_unload(self):
self.bot.remove_listener(self.on_message, "on_message")
self.bot.remove_listener(self.on_message_edit, "on_message_edit")

async def on_message(self, message):
await simple_filter(self, message)

async def on_message_edit(self, before, after):
if after:
await simple_filter(self, after)
110 changes: 110 additions & 0 deletions futaba/cogs/optional/simplewriter/simple_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#
# cogs/optional/simplewriter/simple_filter.py
#
# futaba - A Discord Mod bot for the Programming server
# Copyright (c) 2017-2020 Jake Richardson, Ammon Smith, jackylam5
#
# futaba is available free of charge under the terms of the MIT
# License. You are free to redistribute and/or modify it under those
# terms. It is distributed in the hopes that it will be useful, but
# WITHOUT ANY WARRANTY. See the LICENSE file for more details.
#

"""
Filters messages through the allowed wordlist, deleting unallowed words.
"""

import logging
import re
from datetime import datetime

import discord
from discord import MessageType

from futaba.utils import plural

from .words import core_words_list

logger = logging.getLogger(__name__)
REGEX_SPLIT = r"[^a-zA-Z0-9_']"

__all__ = ["simple_filter"]


async def simple_filter(cog, message):
"""
Filter Discord messages for the simplewriter channel
"""

# Message is in designated channel
if message.channel.id != cog.channel_id:
return

# Don't filter bot messages
if message.author.id == cog.bot.user.id:
return

# Not a special message type
if message.type != MessageType.default:
return

# Make sure we actually can remove this message
if not message.channel.permissions_for(message.guild.me).manage_messages:
return

logger.debug(
"Checking message id %d (by '%s' (%d)) against simplewriter core words list",
message.id,
message.author.name,
message.author.id,
)

split = re.split(REGEX_SPLIT, message.content)
bad_words = []
for word in split:
cleaned = word.strip()
if not cleaned:
continue
if not cleaned.lower() in core_words_list:
if not cleaned in bad_words:
try: # test to see if input is a number
int(cleaned)
except ValueError:
bad_words.append(cleaned)

if len(bad_words) > 0:
await message.delete()

content = (
f"Message id {message.id} (by '{message.author.name}' ({message.author.id})) filtered from "
"simplewriter channel"
)
cog.journal.send(
"message/delete",
message.guild,
content,
icon="delete",
channel=message.channel,
message=message,
)

bad_words_plural = plural(len(bad_words))
article = "some" if len(bad_words) > 1 else "a"

help_embed = discord.Embed()
help_embed.color = discord.Color.red()
help_embed.title = f"You used {article} less simple word{bad_words_plural}."
help_embed.description = (
f"Your message in {message.channel.mention} has been removed.\n"
"You can use [xkcd's simplewriter](https://xkcd.com/simplewriter) "
"to see what words are valid in this channel."
)
help_embed.timestamp = datetime.now()
help_embed.add_field(name="Full message", value=message.content)
help_embed.add_field(
name=f"Bad word{bad_words_plural}", value=", ".join(bad_words)
)
help_embed.set_footer(text=message.id)

dm_channel = message.author.dm_channel or await message.author.create_dm()
await dm_channel.send(embed=help_embed)
15 changes: 15 additions & 0 deletions futaba/cogs/optional/simplewriter/words/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# cogs/optional/simplewriter/words/__init__.py
#
# futaba - A Discord Mod bot for the Programming server
# Copyright (c) 2017-2020 Jake Richardson, Ammon Smith, jackylam5
#
# futaba is available free of charge under the terms of the MIT
# License. You are free to redistribute and/or modify it under those
# terms. It is distributed in the hopes that it will be useful, but
# WITHOUT ANY WARRANTY. See the LICENSE file for more details.
#

__all__ = ["core_words_list"]

from .words import core_words_list

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions futaba/cogs/optional/simplewriter/words/words.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#
# cogs/optional/simplewriter/words/words.py
#
# futaba - A Discord Mod bot for the Programming server
# Copyright (c) 2017-2020 Jake Richardson, Ammon Smith, jackylam5
#
# futaba is available free of charge under the terms of the MIT
# License. You are free to redistribute and/or modify it under those
# terms. It is distributed in the hopes that it will be useful, but
# WITHOUT ANY WARRANTY. See the LICENSE file for more details.
#

import os

__all__ = ["core_words_list"]

core_words_list = []
core_words_list_path = os.path.join(os.path.dirname(__file__), "core_words_list.txt")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't always expect this directory to be writeable, it might be in /usr or something. Just have a line in the config instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for a read operation of a text file in the same directory as this source file. The text file will not change and is not configurable through means other than a commit due to the static nature of the source.


with open(core_words_list_path, "r") as f:
core_words_list = f.read().split(",")
2 changes: 1 addition & 1 deletion futaba/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def wrapper(value):
"prefix": str,
"error-channel-id": Or(And(str, ID_REGEX.match), "0"),
},
"cogs": {"example": object, "statbot": object},
"cogs": {"example": object, "statbot": object, "simplewriter": object},
"moderation": {
"max-cleanup-messages": And(str, _check_gtz(int)),
"ping-cooldown": And(str, _check_gtz(int)),
Expand Down
6 changes: 6 additions & 0 deletions misc/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ enabled = true
enabled = false
url = "postgres://statbot:passwordhere@localhost/statbot_ro"

[cogs.simplewriter]
enabled = false
# The ID of the text channel to enforce the simplewriter vocabulary in
# Set to "0" to implicitly disable simplewriter
channel-id = "0"

[moderation]
# Maximum number of messages that may be specified
# when doing a bulk message cleanup
Expand Down