meme dupe snitching/misc

This commit is contained in:
2025-05-15 15:49:28 -04:00
parent 6a1fd659e8
commit 3dac803305
8 changed files with 105 additions and 55 deletions

View File

@ -100,7 +100,7 @@ class Util:
top_formatted: str = ""
for x, item in enumerate(top):
top_formatted += (
f"{x+1}. **{discord.utils.escape_markdown(item[0])}**: *{item[1]}*\n"
f"{x + 1}. **{discord.utils.escape_markdown(item[0])}**: *{item[1]}*\n"
)
top_formatted = top_formatted.strip()
embed: discord.Embed = discord.Embed(

View File

@ -4,6 +4,9 @@ import json
import io
import asyncio
import random
import copy
from PIL import Image, UnidentifiedImageError
import imagehash
from typing import LiteralString, Optional, Any, Union
import aiosqlite as sqlite3
import logging
@ -132,9 +135,12 @@ class Meme(commands.Cog):
def __init__(self, bot: Havoc) -> None:
self.bot: Havoc = bot
self.stats_db_path: LiteralString = os.path.join(
self.stats_db_path: str = os.path.join(
"/usr/local/share", "sqlite_dbs", "stats.db"
)
self.memedb_path: str = os.path.join(
"/usr/local/share", "sqlite_dbs", "meme.db"
)
self.meme_choices: list = []
self.meme_counter: int = 0
self.THREADS: dict[str, dict[int, list]] = {
@ -243,6 +249,45 @@ class Meme(commands.Cog):
count = result["count"]
self.meme_leaderboard[uid] = count
async def insert_meme(
self, discord_uid: int, timestamp: int, message_id: int, image_url: str
) -> Optional[bool]:
"""
INSERT MEME -> SQLITE DB
"""
try:
_image: io.BytesIO = io.BytesIO(
requests.get(image_url, stream=True, timeout=20).raw.read()
)
image_copy = copy.deepcopy(_image)
image = Image.open(image_copy)
except UnidentifiedImageError:
return None
phash: str = str(imagehash.phash(image))
query: str = "INSERT INTO memes(discord_uid, timestamp, image, message_ids, phash) VALUES(?, ?, ?, ?, ?)"
async with sqlite3.connect(self.memedb_path, timeout=2) as db_conn:
insert = await db_conn.execute_insert(
query, (discord_uid, timestamp, _image.read(), message_id, phash)
)
if insert:
await db_conn.commit()
return True
return None
async def dupe_check(self, image) -> bool | int:
"""
CHECK DB FOR DUPLICATE MEMES!
"""
phash: str = str(imagehash.phash(image))
query: str = "SELECT message_ids FROM memes WHERE phash = ? LIMIT 1"
async with sqlite3.connect(self.memedb_path, timeout=2) as db_conn:
db_conn.row_factory = sqlite3.Row
async with await db_conn.execute(query, (phash,)) as db_cursor:
result = await db_cursor.fetchone()
if result:
return result["message_ids"]
return False
@commands.Cog.listener()
async def on_ready(self) -> None:
"""Run on Bot Ready"""
@ -644,6 +689,7 @@ class Meme(commands.Cog):
Also monitors for messages to #memes-top-10 to autodelete, only Havoc may post in #memes-top-10!
"""
lb_chanid: int = 1352373745108652145
meme_chanid: int = 1147229098544988261
if not self.bot.user: # No valid client instance
return
if not isinstance(message.channel, discord.TextChannel):
@ -666,12 +712,37 @@ class Meme(commands.Cog):
return
if not message.guild:
return
if not message.channel.id == 1147229098544988261: # Not meme channel
if message.channel.id not in [
1157529874936909934,
meme_chanid,
]: # Not meme channel
return
if not message.attachments: # No attachments to consider a meme
return
await self.leaderboard_increment(message.author.id)
unique_memes: list = []
for item in message.attachments:
if item.url and len(item.url) >= 20:
image: io.BytesIO = io.BytesIO(
requests.get(item.url, stream=True, timeout=20).raw.read()
)
dupe_check = await self.dupe_check(Image.open(image))
if dupe_check:
channel = message.channel
original_message = await channel.fetch_message(dupe_check) # type: ignore
original_message_url = original_message.jump_url
await message.add_reaction(
emoji="<:quietscheentchen:1255956612804247635>"
)
await message.reply(original_message_url)
else:
unique_memes.append(item.url)
if unique_memes:
await self.leaderboard_increment(message.author.id)
for meme_url in unique_memes:
author_id: int = message.author.id
timestamp: int = int(message.created_at.timestamp())
await self.insert_meme(author_id, timestamp, message.id, meme_url)
async def get_top(self, n: int = 10) -> Optional[list[tuple]]:
"""
@ -686,9 +757,7 @@ class Meme(commands.Cog):
out_top: list[tuple[int, int]] = []
async with sqlite3.connect(self.stats_db_path, timeout=2) as db_conn:
db_conn.row_factory = sqlite3.Row
query: str = (
"SELECT discord_uid, count FROM memes WHERE count > 0 ORDER BY count DESC"
)
query: str = "SELECT discord_uid, count FROM memes WHERE count > 0 ORDER BY count DESC"
async with db_conn.execute(query) as db_cursor:
db_result = await db_cursor.fetchall()
for res in db_result:
@ -734,9 +803,7 @@ class Meme(commands.Cog):
if not member:
continue
display_name: str = member.display_name
top_formatted += (
f"{x+1}. **{discord.utils.escape_markdown(display_name)}**: *{count}*\n"
)
top_formatted += f"{x + 1}. **{discord.utils.escape_markdown(display_name)}**: *{count}*\n"
top_formatted = top_formatted.strip()
embed: discord.Embed = discord.Embed(
title=f"Top {n} Memes", description=top_formatted, colour=0x25BD6B

View File

@ -215,9 +215,7 @@ class Misc(commands.Cog):
logging.debug("Failed to add xmas reaction: %s", str(e))
await ctx.respond(
f"Only {days} days, {hours} hours, {minutes} minutes,\
{seconds} seconds and {ms} ms left! (UTC)".translate(
xmas_trans
)
{seconds} seconds and {ms} ms left! (UTC)".translate(xmas_trans)
)
except Exception as e:
traceback.print_exc()
@ -1292,7 +1290,7 @@ class Misc(commands.Cog):
Satan(!?)
"""
out_msg: str = (
"## There is no Satan\n" "### He isn't real.\n" "-# And neither are you."
"## There is no Satan\n### He isn't real.\n-# And neither are you."
)
return await ctx.respond(out_msg)
@ -1403,7 +1401,7 @@ class Misc(commands.Cog):
except Exception as e:
traceback.print_exc()
return await ctx.respond(f"Error: {str(e)}")
@bridge.bridge_command()
async def no(self, ctx) -> None:
"""No (As A Service)"""

View File

@ -94,9 +94,7 @@ class Sing(commands.Cog):
search_result_src,
search_result_confidence,
search_result_time_taken,
) = search_result[
0
] # First index is a tuple
) = search_result[0] # First index is a tuple
search_result_wrapped: list[str] = search_result[
1
] # Second index is the wrapped lyrics
@ -124,9 +122,7 @@ class Sing(commands.Cog):
# if ctx.guild.id == 1145182936002482196:
# section = section.upper()
section = regex.sub(r"\p{Vert_Space}", " / ", section.strip())
msg: str = (
f"**{search_result_song}** by **{search_result_artist}**\n-# {section}\n{footer}"
)
msg: str = f"**{search_result_song}** by **{search_result_artist}**\n-# {section}\n{footer}"
if c > 1:
msg = "\n".join(msg.split("\n")[1:])
out_messages.append(msg.strip())
@ -159,9 +155,7 @@ class Sing(commands.Cog):
f"No activity detected to read for {member_display}.",
ephemeral=True,
)
member_id: int = (
member.id
) # if not(member.id == PODY_ID) else 1234134345497837679 # Use Thomas for Pody!
member_id: int = member.id # if not(member.id == PODY_ID) else 1234134345497837679 # Use Thomas for Pody!
activity: Optional[discord.Activity] = None
if IS_SPAMCHAN:
await ctx.respond(f"***Reading activity of {member_display}...***")
@ -199,9 +193,7 @@ class Sing(commands.Cog):
search_result_src,
search_result_confidence,
search_result_time_taken,
) = search_result[
0
] # First index is a tuple
) = search_result[0] # First index is a tuple
search_result_wrapped: list = search_result[
1
] # Second index is the wrapped lyrics
@ -230,9 +222,7 @@ class Sing(commands.Cog):
# if ctx.guild.id == 1145182936002482196:
# section = section.upper()
section = regex.sub(r"\p{Vert_Space}", " / ", section.strip())
msg: str = (
f"**{search_result_song}** by **{search_result_artist}**\n-# {section}\n{footer}"
)
msg: str = f"**{search_result_song}** by **{search_result_artist}**\n-# {section}\n{footer}"
if c > 1:
msg = "\n".join(msg.split("\n")[1:])
out_messages.append(msg.strip())