Add Discord IP retrieval
This commit is contained in:
parent
e5a8f01aaa
commit
acf9f187f0
10 changed files with 821 additions and 4 deletions
0
src/e/__init__.py
Normal file
0
src/e/__init__.py
Normal file
76
src/e/discord.py
Normal file
76
src/e/discord.py
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime # ruff: ignore[typing-only-standard-library-import]
|
||||
from enum import StrEnum
|
||||
from ipaddress import IPv4Network # ruff: ignore[typing-only-standard-library-import]
|
||||
|
||||
import wreq
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel
|
||||
from pydantic import ConfigDict
|
||||
from pydantic import Field
|
||||
from wreq import Client
|
||||
from wreq import Emulation
|
||||
|
||||
|
||||
class Service(StrEnum):
|
||||
"""What service the prefix is for."""
|
||||
|
||||
API = "api"
|
||||
MEDIA = "media"
|
||||
|
||||
|
||||
class Prefix(BaseModel):
|
||||
"""IP and if the IP is tied to API or media."""
|
||||
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
ipv4_prefix: IPv4Network = Field(alias="ipv4Prefix")
|
||||
services: list[Service]
|
||||
|
||||
|
||||
class DiscordIPs(BaseModel):
|
||||
"""Discord IPs."""
|
||||
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
creation_time: datetime = Field(alias="creationTime")
|
||||
"""\"creationTime\": \"2026-08-04T18:01:19Z\""""
|
||||
|
||||
sync_token: str = Field(alias="syncToken")
|
||||
"""\"syncToken\": \"4ce19406\""""
|
||||
|
||||
notes: str
|
||||
"""\"notes\": \"discord egress\""""
|
||||
|
||||
prefixes: list[Prefix]
|
||||
"""\"prefixes\": [
|
||||
{"ipv4Prefix": "104.196.222.45/32", "services": ["media"]},
|
||||
{"ipv4Prefix": "34.138.218.50/32", "services": ["api"]},
|
||||
]"""
|
||||
|
||||
|
||||
async def get_discord_ips() -> DiscordIPs:
|
||||
"""Grab the IPs that Discord uses.
|
||||
|
||||
Returns:
|
||||
DiscordIPs: The IPs that Discord uses.
|
||||
"""
|
||||
url = "https://cdn.discordapp.com/ipranges/discord.json"
|
||||
|
||||
client = Client(emulation=Emulation.Chrome149)
|
||||
resp: wreq.Response = await client.get(url)
|
||||
data: str = await resp.text()
|
||||
|
||||
parsed_data: DiscordIPs = DiscordIPs.model_validate_json(data)
|
||||
return parsed_data
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import asyncio
|
||||
|
||||
# Log the IPs that Discord uses.
|
||||
ips: DiscordIPs = asyncio.run(get_discord_ips())
|
||||
for ip in ips.prefixes:
|
||||
for service in ip.services:
|
||||
logger.info(f"[{service}]\t{ip.ipv4_prefix}")
|
||||
29
src/e/main.py
Normal file
29
src/e/main.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import uvicorn
|
||||
from litestar import Litestar
|
||||
from litestar import get
|
||||
|
||||
|
||||
@get("/")
|
||||
async def twitter() -> dict[str, str]: # ruff: ignore[unused-async]
|
||||
"""Handle Twitter requests.
|
||||
|
||||
https://twitter.com/DiscussingFilm/status/2086143411984208230
|
||||
https://e.lovinator.space/DiscussingFilm/status/2086143411984208230
|
||||
|
||||
If IP is from Discord:
|
||||
Download the image/video.
|
||||
Return custom HTML with metadata tags with the image/video.
|
||||
|
||||
Otherwise:
|
||||
Redirect to the original URL.
|
||||
|
||||
Returns:
|
||||
Redirect to the original URL, or custom HTML with metadata tags.
|
||||
"""
|
||||
return {"message": "Hello, World!"}
|
||||
|
||||
|
||||
app = Litestar(route_handlers=[twitter])
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run(app)
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
def main() -> None:
|
||||
print("Hello from e-lovinator-space!")
|
||||
Loading…
Reference in a new issue