File tree Expand file tree Collapse file tree
bot/exts/filtering/_filters/unique Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ import io
2+
3+ import imagehash
4+ from PIL import Image
5+
6+ from bot .exts .filtering ._filter_context import Event , FilterContext
7+ from bot .exts .filtering ._filters .filter import UniqueFilter
8+
9+ _THRESHOLD = 4
10+ _KNOWN_IMAGE_HASHES = [imagehash .hex_to_hash (s ) for s in ["c0d08f2f2f60f0cf" , "817c7e9391e46c1b" , "973c4178e79492cd" ]]
11+
12+
13+ def _image_is_match (image : Image .Image ) -> bool :
14+ """Return whether the one image matches any of those known to be posted by compromised accounts."""
15+ incoming_image_hash = imagehash .phash (image )
16+ has_match = any (
17+ incoming_image_hash - known_image_hash < _THRESHOLD
18+ for known_image_hash in _KNOWN_IMAGE_HASHES
19+ )
20+ return has_match
21+
22+
23+ class ImageFilter (UniqueFilter ):
24+ """Filter messages that contain an image attachment whose perceptual hash matches images associated with scams."""
25+
26+ name = "image"
27+ events = (Event .MESSAGE , )
28+
29+ async def triggered_on (self , ctx : FilterContext ) -> bool :
30+ """Return whether the message has an attached image that is known to be posted by compromised accounts."""
31+ for attachment in ctx .attachments :
32+ if not attachment .content_type .startswith ("image" ):
33+ continue
34+ image = Image .open (io .BytesIO (await attachment .read ()))
35+ if _image_is_match (image ):
36+ return True
37+
38+ return False
Original file line number Diff line number Diff line change @@ -24,6 +24,8 @@ dependencies = [
2424 " tenacity==9.1.2" ,
2525 " tldextract==5.3.0" ,
2626 " yarl==1.22.0" ,
27+ " imagehash>=4.3.2" ,
28+ " pillow>=12.2.0" ,
2729]
2830name = " bot"
2931version = " 1.0.1"
You can’t perform that action at this time.
0 commit comments