mirror of
https://github.com/NohamR/OqeeRewind.git
synced 2026-04-08 02:50:01 +00:00
Compare commits
3 Commits
3fb78d2dc0
...
05dca3c0cc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05dca3c0cc | ||
|
|
8609f6a6a2 | ||
|
|
754632a47a |
@@ -41,7 +41,12 @@ uv sync
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
Créez un fichier `.env` dans le répertoire racine et ajoutez vos identifiants Oqee (sinon le script essaiera d'abord d'utiliser la connexion par IP) :
|
Le script supporte trois méthodes d'authentification, toutes détectées automatiquement :
|
||||||
|
1. Connexion par IP : Si vous êtes sur un réseau Free, l'authentification se fait automatiquement via votre adresse IP (aucun identifiant requis)
|
||||||
|
2. Compte Freebox : Utilisez vos identifiants de compte Free (nom d'utilisateur contenant "fbx")
|
||||||
|
3. Compte OQEE : Utilisez vos identifiants de compte OQEE standard
|
||||||
|
|
||||||
|
Créez un fichier `.env` dans le répertoire racine et ajoutez vos identifiants Oqee (la connexion par IP est utilisée en dernier recours si les identifiants échouent) :
|
||||||
```bash
|
```bash
|
||||||
OQEE_USERNAME=votre_nom_utilisateur
|
OQEE_USERNAME=votre_nom_utilisateur
|
||||||
OQEE_PASSWORD=votre_mot_de_passe
|
OQEE_PASSWORD=votre_mot_de_passe
|
||||||
|
|||||||
@@ -41,7 +41,12 @@ uv sync
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
Create a `.env` file in the root directory and add your Oqee credentials (otherwise the script will try to use IP login first):
|
The script supports three authentication methods, all automatically detected:
|
||||||
|
1. IP Login: If you're on a Free network, authentication happens automatically via your IP address (no credentials required)
|
||||||
|
2. Freebox Account: Use your Free account credentials (username containing "fbx")
|
||||||
|
3. OQEE Account: Use your standard OQEE account credentials
|
||||||
|
|
||||||
|
Create a `.env` file in the root directory and add your Oqee credentials (IP login is used as fallback if credentials fail):
|
||||||
```bash
|
```bash
|
||||||
OQEE_USERNAME=your_username
|
OQEE_USERNAME=your_username
|
||||||
OQEE_PASSWORD=your_password
|
OQEE_PASSWORD=your_password
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ def get_date_input():
|
|||||||
"type": "input",
|
"type": "input",
|
||||||
"message": "Enter a start date/time (YYYY-MM-DD HH:MM:SS):",
|
"message": "Enter a start date/time (YYYY-MM-DD HH:MM:SS):",
|
||||||
"name": "datetime",
|
"name": "datetime",
|
||||||
"default": "2025-01-01 12:00:00",
|
"default": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
"validate": DatetimeValidator(),
|
"validate": DatetimeValidator(),
|
||||||
"invalid_message": "Invalid date/time format. Use YYYY-MM-DD HH:MM:SS",
|
"invalid_message": "Invalid date/time format. Use YYYY-MM-DD HH:MM:SS",
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ def get_date_input():
|
|||||||
"default": (
|
"default": (
|
||||||
start_date_result["datetime"]
|
start_date_result["datetime"]
|
||||||
if start_date_result
|
if start_date_result
|
||||||
else "2025-01-01 12:00:00"
|
else datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
),
|
),
|
||||||
"validate": DatetimeValidator(),
|
"validate": DatetimeValidator(),
|
||||||
"when": lambda answers: answers["input_type"] == "End date/time",
|
"when": lambda answers: answers["input_type"] == "End date/time",
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ class OqeeClient: # pylint: disable=too-many-instance-attributes
|
|||||||
self.right_token = None
|
self.right_token = None
|
||||||
self.profil_id = None
|
self.profil_id = None
|
||||||
self.lic_url = "https://license.oqee.net/api/v1/live/license/widevine"
|
self.lic_url = "https://license.oqee.net/api/v1/live/license/widevine"
|
||||||
|
if "fbx" in username.lower():
|
||||||
|
self.abo = True
|
||||||
|
else:
|
||||||
|
self.abo = False
|
||||||
|
|
||||||
self.configure(username, password)
|
self.configure(username, password)
|
||||||
|
|
||||||
@@ -124,10 +128,10 @@ class OqeeClient: # pylint: disable=too-many-instance-attributes
|
|||||||
data = self.session.get(
|
data = self.session.get(
|
||||||
"https://api.oqee.net/api/v2/user/profiles", headers=headers
|
"https://api.oqee.net/api/v2/user/profiles", headers=headers
|
||||||
).json()
|
).json()
|
||||||
logger.info("Selecting first profile by default.")
|
# logger.info("Selecting first profile by default.")
|
||||||
return data["result"][0]["id"]
|
return data["result"][0]["id"]
|
||||||
|
|
||||||
def login_cred(self, username, password):
|
def login_cred_abo(self, username, password):
|
||||||
"""Authenticate with OQEE service using Free account credentials."""
|
"""Authenticate with OQEE service using Free account credentials."""
|
||||||
headers = self._build_headers(
|
headers = self._build_headers(
|
||||||
overrides={
|
overrides={
|
||||||
@@ -210,6 +214,66 @@ class OqeeClient: # pylint: disable=too-many-instance-attributes
|
|||||||
).json()
|
).json()
|
||||||
return data["result"]["token"]
|
return data["result"]["token"]
|
||||||
|
|
||||||
|
def login_cred_free(self, username, password):
|
||||||
|
"""Authenticate with OQEE service using Free account credentials."""
|
||||||
|
headers = {
|
||||||
|
"accept": "*/*",
|
||||||
|
"accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
|
||||||
|
"cache-control": "no-cache",
|
||||||
|
"content-type": "application/json",
|
||||||
|
"origin": "https://tv.free.fr",
|
||||||
|
"pragma": "no-cache",
|
||||||
|
"priority": "u=1, i",
|
||||||
|
"referer": "https://tv.free.fr/",
|
||||||
|
"sec-ch-ua": '"Chromium";v="146", "Not-A.Brand";v="24", "Google Chrome";v="146"',
|
||||||
|
"sec-ch-ua-mobile": "?0",
|
||||||
|
"sec-ch-ua-platform": '"macOS"',
|
||||||
|
"sec-fetch-dest": "empty",
|
||||||
|
"sec-fetch-mode": "cors",
|
||||||
|
"sec-fetch-site": "cross-site",
|
||||||
|
"user-agent": (
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
),
|
||||||
|
"x-oqee-customization": "0",
|
||||||
|
"x-oqee-platform": "web",
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {"provider": "oqee", "platform": "web"}
|
||||||
|
|
||||||
|
response = self.session.post(
|
||||||
|
"https://api.oqee.net/api/v2/user/oauth/init", headers=headers, json=data
|
||||||
|
).json()
|
||||||
|
redirect_url = response["result"]["redirect_url"]
|
||||||
|
token = parse_qs(urlparse(redirect_url).query)["token"][0]
|
||||||
|
|
||||||
|
data = {"email": username, "password": password, "token": token}
|
||||||
|
response = self.session.post(
|
||||||
|
"https://api.oqee.net/api/v1/user/oauthorize",
|
||||||
|
headers=headers,
|
||||||
|
json=data,
|
||||||
|
).json()
|
||||||
|
|
||||||
|
if not response["success"]:
|
||||||
|
error_msg = response.get("error", {}).get("msg", "No error message")
|
||||||
|
raise ValueError(
|
||||||
|
f"Login failed: invalid credentials or error in authentication - {error_msg}"
|
||||||
|
)
|
||||||
|
parsed_url = parse_qs(urlparse(response["result"]["redirect_url"]).query)
|
||||||
|
if "code" not in parsed_url:
|
||||||
|
raise ValueError(
|
||||||
|
"Login failed: invalid credentials or error in authentication "
|
||||||
|
"- no code in redirect URL"
|
||||||
|
)
|
||||||
|
code = parsed_url["code"][0]
|
||||||
|
|
||||||
|
data = self.session.post(
|
||||||
|
"https://api.oqee.net/api/v5/user/login",
|
||||||
|
headers=headers,
|
||||||
|
json={"type": "oqeeoa", "token": code},
|
||||||
|
).json()
|
||||||
|
return data["result"]["token"]
|
||||||
|
|
||||||
def login_ip(self):
|
def login_ip(self):
|
||||||
"""
|
"""
|
||||||
Performs IP-based authentication with the OQEE service.
|
Performs IP-based authentication with the OQEE service.
|
||||||
@@ -231,9 +295,17 @@ class OqeeClient: # pylint: disable=too-many-instance-attributes
|
|||||||
logger.info("No credentials provided, using IP login.")
|
logger.info("No credentials provided, using IP login.")
|
||||||
self.access_token = self.login_ip()
|
self.access_token = self.login_ip()
|
||||||
else:
|
else:
|
||||||
logger.info("Logging in with provided credentials")
|
|
||||||
try:
|
try:
|
||||||
self.access_token = self.login_cred(username, password)
|
if self.abo:
|
||||||
|
logger.info(
|
||||||
|
"Logging in with provided credentials (abo account detected)."
|
||||||
|
)
|
||||||
|
self.access_token = self.login_cred_abo(username, password)
|
||||||
|
else:
|
||||||
|
logger.info(
|
||||||
|
"Logging in with provided credentials (free account detected)."
|
||||||
|
)
|
||||||
|
self.access_token = self.login_cred_free(username, password)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Credential login failed: %s. Falling back to IP login.", e
|
"Credential login failed: %s. Falling back to IP login.", e
|
||||||
@@ -242,8 +314,13 @@ class OqeeClient: # pylint: disable=too-many-instance-attributes
|
|||||||
|
|
||||||
logger.info("Fetching rights token")
|
logger.info("Fetching rights token")
|
||||||
self.right_token = self.right()
|
self.right_token = self.right()
|
||||||
|
logger.debug(
|
||||||
|
"Rights token obtained: %s",
|
||||||
|
self.right_token[:10] + "..." if self.right_token else "None",
|
||||||
|
)
|
||||||
logger.info("Fetching profile ID")
|
logger.info("Fetching profile ID")
|
||||||
self.profil_id = self.profil()
|
self.profil_id = self.profil()
|
||||||
|
logger.debug("Profile ID obtained: %s", self.profil_id)
|
||||||
|
|
||||||
self.headers = self._build_headers(
|
self.headers = self._build_headers(
|
||||||
overrides={
|
overrides={
|
||||||
|
|||||||
Reference in New Issue
Block a user