From 59d04f14754f9f91c10bfb0e5bcfe62521773cc0 Mon Sep 17 00:00:00 2001 From: mhdzumair Date: Sun, 21 Apr 2024 20:25:33 +0530 Subject: [PATCH] add user IP to RealDebrid POST requests --- api/middleware.py | 18 +----------------- streaming_providers/realdebrid/client.py | 20 ++++++++++++++++++++ streaming_providers/realdebrid/utils.py | 3 ++- streaming_providers/routes.py | 11 ++++++++++- utils/network.py | 18 ++++++++++++++++++ 5 files changed, 51 insertions(+), 19 deletions(-) diff --git a/api/middleware.py b/api/middleware.py index 6c564e9..2df6f89 100644 --- a/api/middleware.py +++ b/api/middleware.py @@ -11,23 +11,7 @@ from starlette.routing import Match from db.config import settings from db.schemas import UserData from utils import crypto, const - - -def get_client_ip(request: Request) -> str | None: - """ - Extract the client's real IP address from the request headers or fallback to the client host. - """ - x_forwarded_for = request.headers.get("X-Forwarded-For") - if x_forwarded_for: - # In some cases, this header can contain multiple IPs - # separated by commas. - # The first one is the original client's IP. - return x_forwarded_for.split(",")[0].strip() - # Fallback to X-Real-IP if X-Forwarded-For is not available - x_real_ip = request.headers.get("X-Real-IP") - if x_real_ip: - return x_real_ip - return request.client.host if request.client else "Unknown" +from utils.network import get_client_ip async def find_route_handler(app, request: Request) -> Optional[Callable]: diff --git a/streaming_providers/realdebrid/client.py b/streaming_providers/realdebrid/client.py index 0f3c3dc..6fd967e 100644 --- a/streaming_providers/realdebrid/client.py +++ b/streaming_providers/realdebrid/client.py @@ -10,6 +10,10 @@ class RealDebrid(DebridClient): OAUTH_URL = "https://api.real-debrid.com/oauth/v2" OPENSOURCE_CLIENT_ID = "X245A4XAIBGVM" + def __init__(self, token: str | None = None, user_ip: str | None = None): + self.user_ip = user_ip + super().__init__(token) + def _handle_service_specific_errors(self, error): if ( error.response.status_code == 403 @@ -19,6 +23,22 @@ class RealDebrid(DebridClient): "Real-Debrid Permission denied for free account", "need_premium.mp4" ) + def _make_request( + self, + method: str, + url: str, + data=None, + params=None, + is_return_none=False, + is_expected_to_fail=False, + ) -> dict: + if method == "POST" and self.user_ip and self.user_ip != "127.0.0.1": + data = data or {} + data["ip"] = self.user_ip + return super()._make_request( + method, url, data, params, is_return_none, is_expected_to_fail + ) + def initialize_headers(self): if self.token: token_data = self.decode_token_str(self.token) diff --git a/streaming_providers/realdebrid/utils.py b/streaming_providers/realdebrid/utils.py index 4b95eae..f3e3959 100644 --- a/streaming_providers/realdebrid/utils.py +++ b/streaming_providers/realdebrid/utils.py @@ -25,8 +25,9 @@ def get_direct_link_from_realdebrid( file_index: int, max_retries=5, retry_interval=5, + user_ip=None, ) -> str: - rd_client = RealDebrid(token=user_data.streaming_provider.token) + rd_client = RealDebrid(token=user_data.streaming_provider.token, user_ip=user_ip) torrent_info = rd_client.get_available_torrent(info_hash) if not torrent_info: torrent_id = rd_client.add_magent_link(magnet_link).get("id") diff --git a/streaming_providers/routes.py b/streaming_providers/routes.py index aff4fdf..c5ce6da 100644 --- a/streaming_providers/routes.py +++ b/streaming_providers/routes.py @@ -27,6 +27,7 @@ from streaming_providers.seedr.utils import get_direct_link_from_seedr from streaming_providers.torbox.utils import get_direct_link_from_torbox from streaming_providers.qbittorrent.utils import get_direct_link_from_qbittorrent from utils import crypto, torrent, wrappers, const +from utils.network import get_client_ip router = APIRouter() @@ -58,6 +59,7 @@ async def streaming_provider_endpoint( episode_data = stream.get_episode(season, episode) filename = episode_data.filename if episode_data else stream.filename + user_ip = get_client_ip(request) try: if user_data.streaming_provider.service == "seedr": @@ -66,7 +68,14 @@ async def streaming_provider_endpoint( ) elif user_data.streaming_provider.service == "realdebrid": video_url = get_direct_link_from_realdebrid( - info_hash, magnet_link, user_data, filename, stream.file_index, 1, 0 + info_hash, + magnet_link, + user_data, + filename, + stream.file_index, + 1, + 0, + user_ip=user_ip, ) elif user_data.streaming_provider.service == "alldebrid": video_url = get_direct_link_from_alldebrid( diff --git a/utils/network.py b/utils/network.py index ca1d81e..021e846 100644 --- a/utils/network.py +++ b/utils/network.py @@ -3,6 +3,7 @@ import logging from typing import Callable import httpx +from fastapi.requests import Request class CircuitBreakerOpenException(Exception): @@ -122,3 +123,20 @@ async def get_redirector_url(url: str, headers: dict) -> str | None: return str(response.url) except httpx.HTTPError as e: return + + +def get_client_ip(request: Request) -> str | None: + """ + Extract the client's real IP address from the request headers or fallback to the client host. + """ + x_forwarded_for = request.headers.get("X-Forwarded-For") + if x_forwarded_for: + # In some cases, this header can contain multiple IPs + # separated by commas. + # The first one is the original client's IP. + return x_forwarded_for.split(",")[0].strip() + # Fallback to X-Real-IP if X-Forwarded-For is not available + x_real_ip = request.headers.get("X-Real-IP") + if x_real_ip: + return x_real_ip + return request.client.host if request.client else "127.0.0.1"