Skip to content

Commit da2f70e

Browse files
committed
Add image_hash utilities
1 parent 8838715 commit da2f70e

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

bot/exts/filtering/_image_hash.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
from bot import instance
3+
from bot.constants import Keys, URLs
4+
5+
# Maximum number of seconds to wait for Rhodium API.
6+
_TIMEOUT = 5
7+
8+
9+
class RhodiumAPIError(Exception):
10+
"""Exception raised when the Rhodium API returns an error."""
11+
12+
13+
async def get_image_hash(image_url: str) -> int:
14+
"""Return the signed i64 perceptual hash for an image URL from Rhodium."""
15+
async with instance.http_session.post(
16+
url=URLs.rhodium_api,
17+
headers={"Authorization": f"Bearer {Keys.rhodium}"},
18+
json={"url": image_url},
19+
timeout=_TIMEOUT,
20+
) as response:
21+
if response.status != 200:
22+
contents = await response.text()
23+
raise RhodiumAPIError(f"Rhodium API returned status code {response.status}: {contents}")
24+
25+
response_data = await response.json()
26+
hash_hex = response_data.get("hex")
27+
if not hash_hex:
28+
raise RhodiumAPIError("Rhodium API response did not include a hex hash.")
29+
30+
unsigned = int(str(hash_hex).removeprefix("0x"), 16)
31+
if unsigned >= (1 << 63):
32+
return unsigned - (1 << 64)
33+
return unsigned
34+
35+
36+
def signed_i64_to_hex(value: int) -> str:
37+
"""Convert a signed 64-bit integer to a normalized lowercase 16-char hexadecimal string."""
38+
return f"{value & ((1 << 64) - 1):016x}"

0 commit comments

Comments
 (0)