Skip to content

Commit 8838715

Browse files
committed
Add image_hash filter
1 parent 98ba916 commit 8838715

1 file changed

Lines changed: 40 additions & 0 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import re
2+
3+
from discord.ext.commands import BadArgument
4+
5+
from bot.exts.filtering._filter_context import FilterContext
6+
from bot.exts.filtering._filters.filter import Filter
7+
8+
# Maximum perceptual hash difference for positive predictions.
9+
_THRESHOLD = 4
10+
_HEX_RE = re.compile(r"^(?:0x)?([0-9a-fA-F]{1,16})$")
11+
12+
13+
class ImageHashFilter(Filter):
14+
"""A filter which matches image perceptual hashes represented as hexadecimal values."""
15+
16+
name = "image_hash"
17+
18+
async def triggered_on(self, ctx: FilterContext) -> bool:
19+
"""Search for a perceptual hash match within a given context of attachment hashes."""
20+
candidate_hash = int(self.content, 16)
21+
22+
for image_hash in ctx.content:
23+
if int.bit_count(image_hash ^ candidate_hash) <= _THRESHOLD:
24+
ctx.matches.append(f"{image_hash:016x}")
25+
return True
26+
return False
27+
28+
@classmethod
29+
async def process_input(cls, content: str, description: str) -> tuple[str, str]:
30+
"""
31+
Process the content and description into a form which will work with the filtering.
32+
33+
A BadArgument should be raised if the content can't be used.
34+
"""
35+
match = _HEX_RE.fullmatch(content.strip())
36+
if not match:
37+
raise BadArgument("Image hash content must be hexadecimal (optionally prefixed with `0x`).")
38+
39+
normalized = f"{int(match.group(1), 16):016x}"
40+
return normalized, description

0 commit comments

Comments
 (0)