mirror of
https://git.squeakyrat.moe/faggot-chan/
synced 2026-11-04 18:35:45 +01:00
added inline emojis, and on_edit for tenor and also the bot only saves gifv embeds instead of all images/videos whatever links... i think (i asked claude to do that for me because i couldn't figure it out) if it works as intended it should only save gifs and links ending with .gif
This commit is contained in:
1 parent
d704581548
commit
dc06343909
1 file changed
+34
-10
@@ -85,7 +85,8 @@ QUOTA_COOLDOWN = 3600 # after gemini says it's out of quota go straight to the
|
||||
quota_until = 0.0 # unix timestamp
|
||||
|
||||
MAX_REACTION_OPTIONS = 25 # per kind (stickers/emojis/media), random sample so the prompt stays small
|
||||
REACTION_TAG = re.compile(r'\[(sticker|emoji|media):\s*([^\]]+?)\s*\]', re.I)
|
||||
REACTION_TAG = re.compile(r'\[(sticker|reaction|media):\s*([^\]]+?)\s*\]', re.I)
|
||||
EMOJI_TAG = re.compile(r'\[emoji:\s*([^\]]+?)\s*\]', re.I) # inline, this one can go anywhere in the message
|
||||
|
||||
QUIET_COOLDOWN = 600 # seconds of silence before she's allowed to send a random message (10 mins)
|
||||
|
||||
@@ -297,11 +298,11 @@ async def steal_attachments(message):
|
||||
]
|
||||
|
||||
for embed in message.embeds:
|
||||
#tenor/klipy links come as gifv embeds with an mp4 in embed.video direct gif links are plain image embeds
|
||||
# tenor/klipy links come as "gifv" embeds with an mp4 in embed.video, direct .gif links are plain image embeds
|
||||
for part in (embed.image, embed.video):
|
||||
if part and part.url:
|
||||
ext = Path(urlparse(part.url).path).suffix # no extension no preview on discord not worth keeping
|
||||
if ext and (embed.type == "gifv" or ext.lower() == ".gif"):
|
||||
ext = Path(urlparse(part.url).path).suffix # no extension, no preview on discord, not worth keeping
|
||||
if ext and (embed.type == "gifv" or ext.lower() == ".gif"):
|
||||
media.append((part.url, hashlib.sha1(part.url.encode()).hexdigest()[:16] + ext))
|
||||
|
||||
for url, name in media:
|
||||
@@ -456,13 +457,23 @@ def reaction_tool_prompt(guild) -> str:
|
||||
sections.append(f"{key}:\n" + "\n".join(f"- {n}: {d}" if d else f"- {n}" for n, d in options))
|
||||
if not sections:
|
||||
return ""
|
||||
return ("\n\nREACTIONS: you can send a sticker, an emoji reaction or a media file instead of (or along with) words, but only when it really fits the moment, most of the time just reply normally. "
|
||||
"to do it put ONE tag at the end of your message: [sticker: name], [emoji: name] or [media: name], using exactly one of the names below. "
|
||||
"the tag alone is fine if you have nothing to say. never invent names.\n" + "\n".join(sections))
|
||||
emoji_note = ("\n\nyou can also put a server emoji inside the text of your message with [emoji: name], like \"hi [emoji: name] hello\", using a name from the emojis list. "
|
||||
"don't use emojis in every message, most of your messages should have none.") if any(s.startswith("emojis:") for s in sections) else ""
|
||||
return ("\n\nREACTIONS: you can send a sticker, react to the message with an emoji or send a media file instead of (or along with) words, but only when it really fits the moment, most of the time just reply normally. "
|
||||
"to do it put ONE tag at the end of your message: [sticker: name], [reaction: name] or [media: name], using exactly one of the names below ([reaction: name] uses the emoji names). "
|
||||
"the tag alone is fine if you have nothing to say. never invent names.\n" + "\n".join(sections) + emoji_note)
|
||||
|
||||
def split_reactions(text: str) -> tuple[str, list]:
|
||||
return REACTION_TAG.sub("", text).strip(), [(k.lower(), n) for k, n in REACTION_TAG.findall(text)]
|
||||
|
||||
def fill_emojis(text: str, guild) -> str:
|
||||
# [emoji: name] inside a message becomes the real custom emoji, same check as the reactions (has to exist and be available), a made up name just disappears
|
||||
def replace(m):
|
||||
name = m.group(1).strip().strip(":").lower()
|
||||
chosen = next((e for e in guild.emojis if e.available and e.name.lower() == name), None)
|
||||
return str(chosen) if chosen else ""
|
||||
return EMOJI_TAG.sub(replace, text)
|
||||
|
||||
async def send_reaction(message, kind: str, name: str):
|
||||
# looks the name up for real, a made up name just does nothing
|
||||
name = name.strip().strip(":").lower()
|
||||
@@ -473,7 +484,7 @@ async def send_reaction(message, kind: str, name: str):
|
||||
await message.channel.send(stickers=[chosen])
|
||||
log_message(f"[{now_str()}] Faggot-chan sent sticker: {chosen.name}")
|
||||
print(f"[{now_str()}] Faggot-chan sent sticker: {chosen.name}")
|
||||
elif kind == "emoji":
|
||||
elif kind == "reaction":
|
||||
chosen = next((e for e in message.guild.emojis if e.available and e.name.lower() == name), None)
|
||||
if chosen:
|
||||
await message.add_reaction(chosen)
|
||||
@@ -596,9 +607,10 @@ async def on_message(message):
|
||||
if not result.strip() and not reactions:
|
||||
return
|
||||
|
||||
shown = fill_emojis(result, message.guild) # what gets sent, result keeps the [emoji: x] tags for the log and history
|
||||
try:
|
||||
if result.strip():
|
||||
await send_reply(message, result)
|
||||
if shown.strip():
|
||||
await send_reply(message, shown)
|
||||
print(f"[{now_str()}] {message.author} said: {content}\n[{now_str()}] Faggot-chan said: {result}")
|
||||
log_message(f"[{now_str()}] Faggot-chan said: {result}")
|
||||
if str(message.author.id) == settings["moralfag_id"]:
|
||||
@@ -611,4 +623,16 @@ async def on_message(message):
|
||||
except Exception as e:
|
||||
await handle_error(f"[{now_str()}] failed to send reply: {e}", notify_channel=message.channel)
|
||||
|
||||
@client.event
|
||||
async def on_message_edit(before, after):
|
||||
# discord builds link embeds (tenor etc) a moment after the message is sent, so message.embeds is still empty in on_message
|
||||
# and the embed shows up here as an edit instead
|
||||
if after.author == client.user or after.author.bot or after.guild is None:
|
||||
return
|
||||
if not after.embeds or before.embeds: # only when embeds just appeared
|
||||
return
|
||||
if after.channel.name not in ["general", "announcements"] or str(after.author.id) in load_blocked():
|
||||
return
|
||||
await steal_attachments(after)
|
||||
|
||||
client.run(TOKEN)
|
||||
Reference in new issue
Block a user