Skip to content

Commit

Permalink
Merge pull request #25 from LimeDrive:limedrive-zilean-pg
Browse files Browse the repository at this point in the history
Limedrive-zilean-pg
  • Loading branch information
LimeDrive authored Aug 24, 2024
2 parents 4f45247 + 6e3b90b commit ed5ec42
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 154 deletions.
59 changes: 18 additions & 41 deletions deploy/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ services:
environment:
SECRET_API_KEY: 'superkey_that_can_be_changed'
TMDB_API_KEY: 'REDATED'
FLARESOLVERR_HOST: flaresolverr
JACKETT_HOST: jackett
JACKETT_API_KEY: 'REDACTED'
ZILEAN_URL: 'http://zilean:8181'
REDIS_HOST: redis
REDIS_PORT: 6379
LOG_LEVEL: DEBUG
LOG_REDACTED: False
USE_HTTPS: True
TZ: Europe/London
ports:
- 8080:8080
Expand All @@ -25,7 +25,7 @@ services:
- redis
- zilean
- jackett
- flaresolverr
- postgres
restart: unless-stopped

redis:
Expand All @@ -47,50 +47,30 @@ services:
deploy:
resources:
limits:
memory: 1g
memory: 3g
volumes:
- ./zilean_data:/app/data
environment:
- Zilean__ElasticSearch__Url=http://elasticsearch:9200
Zilean__Database__ConnectionString: "Host=postgres;Port=5432;Database=zilean;Username=zilean;Password=zilean"
Zilean__Dmm__ImportBatched: "true"
Zilean__Dmm__MaxFilteredResults: 200
Zilean__Dmm__MinimumScoreMatch: 0.85
depends_on:
elasticsearch:
condition: service_healthy
- postgres


elasticsearch:
image: elasticsearch:8.14.3@sha256:1ddbb1ae0754278f3ab53edc24fcc5c790ebc2422cc47abea760b24abee2d88a
container_name: elasticsearch
postgres:
image: postgres:16.3-alpine3.20
container_name: postgres
restart: unless-stopped
environment:
ES_SETTING_DISCOVERY_TYPE: single-node
ES_SETTING_XPACK_SECURITY_ENABLED: false
ES_SETTING_BOOTSTRAP_MEMORY__LOCK: true
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
PGDATA: /var/lib/postgresql/data/pgdata
POSTGRES_USER: zilean
POSTGRES_PASSWORD: zilean
POSTGRES_DB: zilean
expose:
- 9200
deploy:
resources:
limits:
memory: 2g
healthcheck:
test: ["CMD-SHELL", "curl -s http://localhost:9200 | grep -q 'You Know, for Search'"]
interval: 10s
timeout: 10s
retries: 5
- 5432
volumes:
- elastic_data:/usr/share/elasticsearch/data:rw

flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:latest
container_name: flaresolverr
environment:
- LOG_LEVEL=${LOG_LEVEL:-info}
- LOG_HTML=${LOG_HTML:-false}
- CAPTCHA_SOLVER=${CAPTCHA_SOLVER:-none}
- TZ=Europe/London
expose:
- 8191
restart: unless-stopped
- ./zilean_postgresql:/var/lib/postgresql/data/pgdata

jackett:
image: lscr.io/linuxserver/jackett:latest
Expand All @@ -104,7 +84,4 @@ services:
- ./blackhole:/downloads
ports:
- 9117:9117
restart: unless-stopped

volumes:
elastic_data:
restart: unless-stopped
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "stream-fusion"
version = "1.0.0"
version = "1.1.0"
description = "StreamFusion is an advanced plugin for Stremio that significantly enhances its streaming capabilities with debrid service."
authors = ["LimeDrive <[email protected]>"]
readme = "README.md"
Expand Down
121 changes: 50 additions & 71 deletions stream_fusion/utils/zilean/zilean_api.py
Original file line number Diff line number Diff line change
@@ -1,69 +1,55 @@
import requests
from typing import List, Optional, Tuple
from pydantic import BaseModel, Field, ValidationError
from pydantic import BaseModel, Field
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

from stream_fusion.settings import settings
from stream_fusion.logging_config import logger


class DmmQueryRequest(BaseModel):
class DMMQueryRequest(BaseModel):
queryText: Optional[str] = None


class TorrentInfo(BaseModel):
resolution: Optional[str] = None
year: Optional[int] = None
remastered: bool = False
source: Optional[str] = None
codec: Optional[str] = None
group: Optional[str] = None
episodes: Tuple[int, ...] = Field(default_factory=tuple)
seasons: Tuple[int, ...] = Field(default_factory=tuple)
languages: Tuple[str, ...] = Field(default_factory=tuple)
class DMMImdbFile(BaseModel):
imdbId: Optional[str] = None
category: Optional[str] = None
title: Optional[str] = None
rawTitle: Optional[str] = None
size: int = 0
infoHash: Optional[str] = None
isPossibleMovie: bool = False
adult: bool = False
year: int = 0

class Config:
frozen = True

class DMMImdbSearchResult(BaseModel):
title: Optional[str] = None
imdbId: Optional[str] = None
year: int = 0
score: float = 0.0
category: Optional[str] = None

class ExtractedDmmEntry(BaseModel):
filename: str
infoHash: str
filesize: int
parseResponse: Optional[TorrentInfo] = None

resolution: Optional[str] = None
class DMMTorrentInfo(BaseModel):
info_hash: Optional[str] = None
resolution: Tuple[str, ...] = Field(default_factory=tuple)
year: Optional[int] = None
remastered: bool = False
source: Optional[str] = None
codec: Optional[str] = None
group: Optional[str] = None
episodes: Optional[Tuple[int, ...]] = None
seasons: Optional[Tuple[int, ...]] = None
languages: Optional[Tuple[str, ...]] = None
title: Optional[str] = None
rawTitle: Optional[str] = None
size: Optional[int] = None
isPossibleMovie: bool = False
remastered: Optional[bool] = None
codec: Tuple[str, ...] = Field(default_factory=tuple)
audio: Tuple[str, ...] = Field(default_factory=tuple)
quality: Tuple[str, ...] = Field(default_factory=tuple)
episode: Tuple[int, ...] = Field(default_factory=tuple)
season: Tuple[int, ...] = Field(default_factory=tuple)
language: Tuple[str, ...] = Field(default_factory=tuple)
parsed_title: Optional[str] = None
raw_title: Optional[str] = None
size: int = 0
category: Optional[str] = None
imdb_id: Optional[str] = None
imdb: Optional[DMMImdbFile] = None

class Config:
frozen = True


class ImdbFile(BaseModel):
imdbId: Optional[str] = None
category: Optional[str] = None
title: Optional[str] = None
adult: bool = False
year: int = 0


class ZileanAPI:
def __init__(
self,
Expand Down Expand Up @@ -105,9 +91,19 @@ def _request(self, method: str, endpoint: str, **kwargs):
logger.error(f"Erreur lors de la requête API : {e}")
raise

def dmm_search(self, query: DmmQueryRequest) -> List[ExtractedDmmEntry]:
def _convert_to_dmm_torrent_info(self, entry: dict) -> DMMTorrentInfo:
for key in ['resolution', 'codec', 'audio', 'quality', 'episode', 'season', 'language']:
if key in entry and isinstance(entry[key], list):
entry[key] = tuple(entry[key])

if 'imdb' in entry and entry['imdb']:
entry['imdb'] = DMMImdbFile(**entry['imdb'])

return DMMTorrentInfo(**entry)

def dmm_search(self, query: DMMQueryRequest) -> List[DMMTorrentInfo]:
response = self._request("POST", "/dmm/search", json=query.dict())
return [ExtractedDmmEntry(**entry) for entry in response.json()]
return [self._convert_to_dmm_torrent_info(entry) for entry in response.json()]

def dmm_filtered(
self,
Expand All @@ -117,37 +113,20 @@ def dmm_filtered(
year: Optional[int] = None,
language: Optional[str] = None,
resolution: Optional[str] = None,
) -> List[ExtractedDmmEntry]:
imdb_id: Optional[str] = None,
) -> List[DMMTorrentInfo]:
params = {
"Query": query,
"Season": season,
"Episode": episode,
"Year": year,
"Language": language,
"Resolution": resolution,
"ImdbId": imdb_id,
}
params = {k: v for k, v in params.items() if v is not None}
response = self._request("GET", "/dmm/filtered", params=params)

entries = []
for entry in response.json():
for key in ["episodes", "seasons", "languages"]:
if key in entry and isinstance(entry[key], list):
entry[key] = tuple(entry[key])

torrent_info = TorrentInfo(
**{k: v for k, v in entry.items() if k in TorrentInfo.__fields__}
)

extracted_entry = ExtractedDmmEntry(
filename=entry.get("rawTitle", ""),
infoHash=entry.get("infoHash", ""),
filesize=entry.get("size", 0),
parseResponse=torrent_info,
)
entries.append(extracted_entry)

return entries
return [self._convert_to_dmm_torrent_info(entry) for entry in response.json()]

def dmm_on_demand_scrape(self) -> None:
self._request("GET", "/dmm/on-demand-scrape")
Expand All @@ -157,12 +136,12 @@ def healthchecks_ping(self) -> str:
return response.text

def imdb_search(
self, query: Optional[str] = None, year: Optional[int] = None
) -> List[ImdbFile]:
params = {"Query": query, "Year": year}
self, query: Optional[str] = None, year: Optional[int] = None, category: Optional[str] = None
) -> List[DMMImdbSearchResult]:
params = {"Query": query, "Year": year, "Category": category}
params = {k: v for k, v in params.items() if v is not None}
response = self._request("POST", "/imdb/search", params=params)
return [ImdbFile(**file) for file in response.json()]
return [DMMImdbSearchResult(**file) for file in response.json()]

def __del__(self):
self.session.close()
self.session.close()
10 changes: 5 additions & 5 deletions stream_fusion/utils/zilean/zilean_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from stream_fusion.utils.torrent.torrent_item import TorrentItem
from stream_fusion.logging_config import logger
from stream_fusion.utils.detection import detect_languages
from stream_fusion.utils.zilean.zilean_api import ExtractedDmmEntry
from stream_fusion.utils.zilean.zilean_api import DMMTorrentInfo


class ZileanResult:
Expand Down Expand Up @@ -39,23 +39,23 @@ def convert_to_torrent_item(self):
self.parsed_data
)

def from_api_cached_item(self, api_cached_item: ExtractedDmmEntry, media):
def from_api_cached_item(self, api_cached_item: DMMTorrentInfo, media):
# if type(api_cached_item) is not dict:
# logger.error(api_cached_item)

self.info_hash = api_cached_item.infoHash
self.info_hash = api_cached_item.info_hash
if len(self.info_hash) != 40:
raise ValueError(f"The hash '{self.info_hash}' does not have the expected length of 40 characters.")

parsed_result = parse(api_cached_item.filename)
parsed_result = parse(api_cached_item.raw_title)

self.raw_title = parsed_result.raw_title
self.indexer = "DMM API"
self.magnet = "magnet:?xt=urn:btih:" + self.info_hash
self.link = self.magnet
self.languages = detect_languages(self.raw_title)
self.seeders = 0
self.size = api_cached_item.filesize
self.size = api_cached_item.size
self.type = media.type
self.privacy = "private"
self.from_cache = True
Expand Down
Loading

0 comments on commit ed5ec42

Please sign in to comment.