Skip to content

Add scamimages cog - detect scam images and auto-ban posters#391

Open
b1ume wants to merge 3 commits into
rHomelab:mainfrom
b1ume:main
Open

Add scamimages cog - detect scam images and auto-ban posters#391
b1ume wants to merge 3 commits into
rHomelab:mainfrom
b1ume:main

Conversation

@b1ume

@b1ume b1ume commented Jul 20, 2026

Copy link
Copy Markdown

Initial Checklist

  • Has @tigattack been added as a reviewer?
  • If applicable, have the relevant project(s), milestone(s), and label(s) been applied?
  • If applicable, have you added details of the cog to the readme as per README.md?

Details

Does this resolve an issue?
No, this is a new feature.

Changes

Features

  • Adds scamimages cog that detects known scam images (e.g. MrBeast giveaway scams) using perceptual hashing and automatically bans users who post them.
  • All commands are admin-only. Similarity threshold is hardcoded at 10.
  • Commands: add, remove, list, scan, logchannel, clear.

Additional

Requires imagehash and Pillow (listed in cog info.json requirements field).

b1ume and others added 3 commits July 20, 2026 07:25
Switch image fetching to a persistent aiohttp ClientSession with a 15s timeout and close it in cog_unload to avoid creating sessions per request. Normalize guild log channel storage to integer IDs (including defaults and reads/writes), and narrow confirmation timeout handling to asyncio.TimeoutError instead of catching all exceptions.
@b1ume
b1ume marked this pull request as ready for review July 21, 2026 04:00
Copilot AI review requested due to automatic review settings July 21, 2026 04:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a new moderation cog (scamimages) to detect known scam images via perceptual hashing and automatically take enforcement action, along with documentation and dependency metadata so it can be installed as part of this cog collection.

Changes:

  • Introduces scamimages cog with admin-only commands to manage a per-guild image-hash database and to manually scan images.
  • Adds an on_message listener that hashes image attachments and bans users when a match is detected.
  • Documents the new cog in the repository README and declares required third-party libraries in info.json.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 6 comments.

File Description
scamimages/scamimages.py Implements perceptual-hash scanning, admin commands, and automatic ban/logging behavior.
scamimages/info.json Declares cog metadata and Python package requirements (imagehash, Pillow).
scamimages/__init__.py Registers the cog with Red via setup().
README.md Adds the ScamImages cog summary and command list to project documentation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scamimages/scamimages.py
if not message.attachments:
return

image_attachments = [a for a in message.attachments if a.content_type and a.content_type.startswith("image/")]
Comment thread scamimages/scamimages.py
Comment on lines +125 to +135
async def _compute_phash_from_url(self, url: str) -> Optional[imagehash.ImageHash]:
async with self.session.get(url, timeout=REQUEST_TIMEOUT) as response:
if response.status != 200:
return None
image_data = await response.read()

try:
image = Image.open(BytesIO(image_data))
return imagehash.phash(image)
except Exception:
return None
Comment thread scamimages/scamimages.py
ban_reason = f"Automatic ban: posted a known scam image. Hash: {str(phash)}"

try:
await message.guild.ban(message.author, reason=ban_reason, delete_message_days=1)
Comment thread scamimages/scamimages.py

async def _compute_phash_from_message(self, message: discord.Message) -> list[Optional[imagehash.ImageHash]]:
results = []
image_attachments = [a for a in message.attachments if a.content_type and a.content_type.startswith("image/")]
Comment thread scamimages/scamimages.py
Comment on lines +363 to +377
try:
reaction, _ = await self.bot.wait_for("reaction_add", timeout=30.0, check=check)
except asyncio.TimeoutError:
await confirm_msg.clear_reactions()
await ctx.send("Timed out. Database was not cleared.")
return

if str(reaction.emoji) == "✅":
await self.config.guild(ctx.guild).hashes.set([])
await confirm_msg.clear_reactions()
await ctx.send("Scam image database has been cleared.")
log.info("Scam image database cleared for guild %s (%s)", ctx.guild.name, ctx.guild.id)
else:
await confirm_msg.clear_reactions()
await ctx.send("Cancelled. Database was not cleared.")
Comment thread scamimages/scamimages.py
Comment on lines +72 to +74
if phash - stored_hash <= SIMILARITY_THRESHOLD:
await self._handle_match(message, attachment, phash, stored_hash_str)
return
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants