Skip to content

Commit d59373e

Browse files
authored
Add a new Cog for Pinned Messages which keeps reminders as the latest message in a channel (#113)
1 parent e2c4ced commit d59373e

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

cogs/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
from . import inclusive_language
44
from . import mentor_requests
55
from . import mod_message
6+
from . import pinned_message
67
from . import streaming_events
78
from . import track_react
89

910
CloseSupportThread = close_support.CloseSupportThread
1011
InclusiveLanguage = inclusive_language.InclusiveLanguage
1112
RequestNotifier = mentor_requests.RequestNotifier
1213
ModMessage = mod_message.ModMessage
14+
PinnedMessage = pinned_message.PinnedMessage
1315
StreamingEvents = streaming_events.StreamingEvents
1416
TrackReact = track_react.TrackReact

cogs/pinned_message.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""Discord Cog to keep a message "pinned" at the end of a discussion."""
2+
3+
import logging
4+
5+
import discord
6+
from discord.ext import commands
7+
8+
from cogs import base_cog
9+
10+
logger = logging.getLogger(__name__)
11+
12+
13+
class PinnedMessage(base_cog.BaseCog):
14+
"""Keep a message pinned to the end of a channel."""
15+
16+
qualified_name = "Pinned Message"
17+
18+
def __init__(
19+
self,
20+
bot: commands.Bot,
21+
messages: dict[int, str],
22+
**kwargs,
23+
) -> None:
24+
super().__init__(bot=bot, **kwargs)
25+
self.bot = bot
26+
self.messages: dict[int, str] = messages
27+
self.last_message: dict[int, discord.Message] = {}
28+
29+
@commands.Cog.listener()
30+
async def on_ready(self) -> None:
31+
"""Popular prior messages from channel histories."""
32+
if self.bot.user:
33+
for channel_id, content in self.messages.items():
34+
message = await self.find_prior_message(channel_id, content)
35+
if message:
36+
self.last_message[channel_id] = message
37+
38+
async def find_prior_message(self, channel_id: int, content: str) -> None | discord.Message:
39+
"""Return a prior message from a channel history."""
40+
assert self.bot.user is not None
41+
for guild in self.bot.guilds:
42+
channel = guild.get_channel(channel_id)
43+
if isinstance(channel, discord.TextChannel):
44+
async for message in channel.history(limit=50, oldest_first=None):
45+
if message.author.id == self.bot.user.id and message.content == content:
46+
return message
47+
return None
48+
49+
async def bump_message(self, channel: discord.TextChannel) -> None:
50+
"""Bump a pinned message in a channel."""
51+
if last := self.last_message.get(channel.id):
52+
await last.delete()
53+
54+
msg = await channel.send(self.messages[channel.id], silent=True)
55+
self.last_message[channel.id] = msg
56+
57+
@commands.Cog.listener()
58+
async def on_message(self, message: discord.Message) -> None:
59+
"""Move message to the end of the channel."""
60+
if message.author.bot:
61+
return
62+
if not isinstance(message.channel, discord.TextChannel):
63+
return
64+
if message.channel.id not in self.messages:
65+
return
66+
await self.bump_message(message.channel)

conf.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"CloseSupportThread",
88
"InclusiveLanguage",
99
"ModMessage",
10+
"PinnedMessage",
1011
"RequestNotifier",
1112
"StreamingEvents",
1213
"TrackReact",
@@ -129,3 +130,16 @@
129130

130131
# CloseSupportThread
131132
SUPPORT_RESOLVED = "✅"
133+
134+
135+
# PinnedMessage
136+
PINNED_MESSAGES = {
137+
# Test channel in test server.
138+
1091223069407842306: "This is a pinned message.",
139+
# Exercism photo channel
140+
1203795616594010192: """\
141+
This is the photos channel. It is for sharing _your photographs_, not images.
142+
If you did not take the photo yourself with a camera, please do not post it!
143+
If it is not a photograph (an image captured by a camera), it will be deleted.
144+
When responding to messages, please remember to use a thread. Thank you!""",
145+
}

exercism_discord_bot.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ def get_cogs(self) -> dict[commands.CogMeta, dict[str, Any]]:
104104
"pattern_response": conf.EXCLUSIVE_LANGUAGE
105105
},
106106
cogs.ModMessage: {"canned_messages": conf.CANNED_MESSAGES},
107+
cogs.PinnedMessage: {"messages": conf.PINNED_MESSAGES},
107108
cogs.RequestNotifier: {
108109
"channel_id": int(find_setting("MENTOR_REQUEST_CHANNEL")),
109110
"sqlite_db": find_setting("SQLITE_DB"),

0 commit comments

Comments
 (0)