Compare commits
2 Commits
b9e7e1bfca
...
74753d94be
| Author | SHA1 | Date | |
|---|---|---|---|
|
74753d94be
|
|||
|
02741c1e77
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
/test.xml
|
||||
/uv.lock
|
||||
/main.py
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "1.0.0"
|
||||
__version__ = "1.0.1"
|
||||
|
||||
@@ -3,8 +3,9 @@ from pathlib import Path
|
||||
from pkgutil import iter_modules
|
||||
from typing import Optional, Type
|
||||
|
||||
from parsers.generic.parsers import DataParser
|
||||
from parsers.generic.watfag import WATFAG, SeedStatus
|
||||
from watfag.parsers.generic.parsers import DataParser
|
||||
from watfag.parsers.generic.watfag import *
|
||||
from watfag.parsers.generic.watfag import WATFAG
|
||||
|
||||
|
||||
class Release:
|
||||
@@ -23,6 +24,18 @@ class Release:
|
||||
self.seed_status: Optional[SeedStatus] = None
|
||||
self.parser_results: dict[str, bool] = {} # Stores which parsers have been run and their results.
|
||||
|
||||
self.group: Optional[Group] = None
|
||||
self.group_name: Optional[str] = None
|
||||
self.quality: Optional[Resolution] = None
|
||||
self.source: Optional[Source] = None
|
||||
self.streaming: Optional[StreamingService] = None
|
||||
self.video_codec: Optional[VideoCodec] = None
|
||||
self.audio_codec: Optional[AudioCodec] = None
|
||||
self.audio_layout: Optional[AudioLayout] = None
|
||||
self.dynamic_range: Optional[DynamicRange] = None
|
||||
self.repack: Optional[Repack] = None
|
||||
self.multi: Optional[Multi] = None
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.watfag < other.watfag
|
||||
|
||||
@@ -63,6 +76,7 @@ class GenericParser:
|
||||
|
||||
class ParserManager:
|
||||
"""Manages and runs parsers on releases."""
|
||||
|
||||
def __init__(self):
|
||||
self.parsers: list[Type[DataParser]] = []
|
||||
self.collect_parsers()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic import GenericParser
|
||||
from parsers.generic.parsers import DataParser
|
||||
from parsers.generic.watfag import AudioCodec, AudioLayout
|
||||
from watfag.parsers.generic import GenericParser
|
||||
from watfag.parsers.generic.parsers import DataParser
|
||||
from watfag.parsers.generic.watfag import AudioCodec, AudioLayout
|
||||
|
||||
patterns = [
|
||||
re.compile(
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic import GenericParser
|
||||
from parsers.generic.watfag import Group
|
||||
from parsers.generic.parsers import DataParser
|
||||
from watfag.parsers.generic import GenericParser
|
||||
from watfag.parsers.generic.watfag import Group
|
||||
from watfag.parsers.generic.parsers import DataParser
|
||||
|
||||
patterns = [
|
||||
re.compile(r"(?:-| - )(?P<group>[a-zA-Z0-9 &]*)\)?$", re.UNICODE),
|
||||
re.compile(r"\[(?P<group>[a-zA-Z0-9 &]*)\]?$", re.UNICODE),
|
||||
re.compile(r"(?: )\[?(?P<group>[a-zA-Z0-9]*?)]?\)?$", re.UNICODE)
|
||||
]
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic import GenericParser
|
||||
from parsers.generic.parsers import CheckParser
|
||||
from parsers.generic.watfag import DynamicRange
|
||||
from watfag.parsers.generic import GenericParser
|
||||
from watfag.parsers.generic.parsers import CheckParser
|
||||
from watfag.parsers.generic.watfag import DynamicRange
|
||||
|
||||
checks = {
|
||||
re.compile(r"hybrid|do?vi? ?hdr(?:10)?[\+p]?", re.IGNORECASE): DynamicRange.HYBRID,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic import GenericParser
|
||||
from parsers.generic.parsers import CheckParser
|
||||
from parsers.generic.watfag import Multi
|
||||
from watfag.parsers.generic import GenericParser
|
||||
from watfag.parsers.generic.parsers import CheckParser
|
||||
from watfag.parsers.generic.watfag import Multi
|
||||
|
||||
checks = {
|
||||
re.compile(r"multi", re.IGNORECASE): Multi.MULTI
|
||||
|
||||
@@ -3,7 +3,7 @@ from typing import Optional, TYPE_CHECKING
|
||||
from regex import Pattern
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from parsers.generic import WATFAG, Release
|
||||
from watfag.parsers.generic import WATFAG, Release
|
||||
|
||||
|
||||
class DataParser:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic import GenericParser
|
||||
from parsers.generic.parsers import CheckParser
|
||||
from parsers.generic.watfag import Repack
|
||||
from watfag.parsers.generic import GenericParser
|
||||
from watfag.parsers.generic.parsers import CheckParser
|
||||
from watfag.parsers.generic.watfag import Repack
|
||||
|
||||
checks = {
|
||||
re.compile(r"repack", re.IGNORECASE): Repack.REPACK,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic import GenericParser
|
||||
from parsers.generic.parsers import CheckParser
|
||||
from parsers.generic.watfag import Resolution
|
||||
from watfag.parsers.generic import GenericParser
|
||||
from watfag.parsers.generic.parsers import CheckParser
|
||||
from watfag.parsers.generic.watfag import Resolution
|
||||
|
||||
checks = {
|
||||
re.compile(r"2160p", re.IGNORECASE): Resolution.UHD,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic import GenericParser
|
||||
from parsers.generic.parsers import CheckParser
|
||||
from parsers.generic.watfag import SeedStatus
|
||||
from watfag.parsers.generic import GenericParser
|
||||
from watfag.parsers.generic.parsers import CheckParser
|
||||
from watfag.parsers.generic.watfag import SeedStatus
|
||||
|
||||
class SeederParser(CheckParser, GenericParser):
|
||||
def parse(self) -> bool:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic import GenericParser
|
||||
from parsers.generic.parsers import CheckParser
|
||||
from parsers.generic.watfag import Source
|
||||
from watfag.parsers.generic import GenericParser
|
||||
from watfag.parsers.generic.parsers import CheckParser
|
||||
from watfag.parsers.generic.watfag import Source
|
||||
|
||||
checks = {
|
||||
re.compile(r"remux", re.IGNORECASE): Source.REMUX,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic import GenericParser
|
||||
from parsers.generic.parsers import CheckParser
|
||||
from parsers.generic.watfag import StreamingService
|
||||
from watfag.parsers.generic import GenericParser
|
||||
from watfag.parsers.generic.parsers import CheckParser
|
||||
from watfag.parsers.generic.watfag import StreamingService
|
||||
|
||||
checks = {
|
||||
re.compile(r"ATVP"): StreamingService.ATVP,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic import GenericParser
|
||||
from parsers.generic.parsers import CheckParser
|
||||
from parsers.generic.watfag import VideoCodec
|
||||
from watfag.parsers.generic import GenericParser
|
||||
from watfag.parsers.generic.parsers import CheckParser
|
||||
from watfag.parsers.generic.watfag import VideoCodec
|
||||
|
||||
checks = {
|
||||
re.compile(r"avc|[hx][\. -]?264", re.IGNORECASE): VideoCodec.AVC,
|
||||
|
||||
@@ -189,6 +189,7 @@ class Group(WATFAG):
|
||||
"""
|
||||
FLUX = "FLUX", 10 # Very good WEB-DL releases and fast
|
||||
HONE = "HONE", 10 # High quality re-encodes
|
||||
TAOE = "TAoE", 10 # High quality re-encodes
|
||||
PHOCIS = "PHOCiS", 8 # Same as FLUX
|
||||
LEGION = "LEGi0N", 8 # Same as FLUX
|
||||
AOC = "AOC", 1 # Often low quality CAM releases. While fast, not worth it for most movies.
|
||||
|
||||
@@ -3,32 +3,22 @@ from pathlib import Path
|
||||
from pkgutil import iter_modules
|
||||
from typing import Optional
|
||||
|
||||
from parsers.generic import Release, ParserManager
|
||||
from parsers.generic.watfag import *
|
||||
from watfag.parsers.generic import Release, ParserManager
|
||||
|
||||
|
||||
class MovieRelease(Release):
|
||||
"""Holds info representing a release of a movie."""
|
||||
|
||||
def __init__(self, unparsed_text, dl_link, **kwargs):
|
||||
super().__init__(unparsed_text, dl_link, **kwargs)
|
||||
self.title: str = ""
|
||||
self.year: int = 0
|
||||
self.edition: Optional[str] = None
|
||||
self.group: Optional[Group] = None
|
||||
self.group_name: Optional[str] = None
|
||||
self.quality: Optional[Resolution] = None
|
||||
self.source: Optional[Source] = None
|
||||
self.streaming: Optional[StreamingService] = None
|
||||
self.video_codec: Optional[VideoCodec] = None
|
||||
self.audio_codec: Optional[AudioCodec] = None
|
||||
self.audio_layout: Optional[AudioLayout] = None
|
||||
self.dynamic_range: Optional[DynamicRange] = None
|
||||
self.repack: Optional[Repack] = None
|
||||
self.multi: Optional[Multi] = None
|
||||
|
||||
def __str__(self):
|
||||
parts = [f"{self.title} ({self.year})" + (f" [{self.edition}]" if self.edition else "")]
|
||||
for attr in ['quality', 'video_codec', 'audio_codec', 'audio_layout', 'dynamic_range', 'repack', 'multi', 'source']:
|
||||
for attr in ['quality', 'video_codec', 'audio_codec', 'audio_layout', 'dynamic_range', 'repack', 'multi',
|
||||
'source']:
|
||||
value = getattr(self, attr)
|
||||
parts.append(f"{attr.capitalize()}: {value if value else 'Unknown'}")
|
||||
if self.streaming:
|
||||
@@ -39,12 +29,14 @@ class MovieRelease(Release):
|
||||
parts.append(f"WATFAG: {self.watfag:.2f}")
|
||||
return " | ".join(parts)
|
||||
|
||||
|
||||
class MovieParser:
|
||||
"""
|
||||
This class can be inherited by any parser that is specific to movies.
|
||||
It allows dynamic importing of parser classes and provides a method to run all parsers on a given movie release.
|
||||
"""
|
||||
|
||||
|
||||
class MovieParserManager(ParserManager):
|
||||
"""Parses movie releases."""
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic.parsers import DataParser
|
||||
from parsers.movie import MovieParser, MovieRelease
|
||||
from parsers.movie.title_year import edition_regex
|
||||
from watfag.parsers.generic.parsers import DataParser
|
||||
from watfag.parsers.movie import MovieParser, MovieRelease
|
||||
from watfag.parsers.movie.title_year import edition_regex
|
||||
|
||||
|
||||
class EditionParser(DataParser, MovieParser):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic.parsers import DataParser
|
||||
from parsers.movie import MovieParser, MovieRelease
|
||||
from watfag.parsers.generic.parsers import DataParser
|
||||
from watfag.parsers.movie import MovieParser, MovieRelease
|
||||
|
||||
# Shamelessly stolen from Radarr: https://github.com/Radarr/Radarr/blob/develop/src/NzbDrone.Core/Parser/Parser.cs
|
||||
edition_regex = r"\(?\b(?P<edition>(((Recut.|Extended.|Ultimate.)?(Director.?s|Collector.?s|Theatrical|Ultimate|Extended|Despecialized|(Special|Rouge|Final|Assembly|Imperial|Diamond|Signature|Hunter|Rekall)(?=(.(Cut|Edition|Version)))|\d{2,3}(th)?.Anniversary)(?:.(Cut|Edition|Version))?(.(Extended|Uncensored|Remastered|Unrated|Uncut|Open.?Matte|IMAX|Fan.?Edit))?|((Uncensored|Remastered|Unrated|Uncut|Open?.Matte|IMAX|Fan.?Edit|Restored|((2|3|4)in1))))))\b\)?"
|
||||
|
||||
@@ -3,8 +3,7 @@ from pathlib import Path
|
||||
from pkgutil import iter_modules
|
||||
from typing import Optional
|
||||
|
||||
from parsers.generic import Release, ParserManager
|
||||
from parsers.generic.watfag import *
|
||||
from watfag.parsers.generic import Release, ParserManager
|
||||
|
||||
|
||||
class TVBoxSetRelease(Release):
|
||||
@@ -13,17 +12,6 @@ class TVBoxSetRelease(Release):
|
||||
super().__init__(unparsed_text, dl_link, **kwargs)
|
||||
self.show_title: str = ""
|
||||
self.seasons: Optional[str] = None
|
||||
self.group: Optional[Group] = None
|
||||
self.group_name: Optional[str] = None
|
||||
self.quality: Optional[Resolution] = None
|
||||
self.source: Optional[Source] = None
|
||||
self.streaming: Optional[StreamingService] = None
|
||||
self.video_codec: Optional[VideoCodec] = None
|
||||
self.audio_codec: Optional[AudioCodec] = None
|
||||
self.audio_layout: Optional[AudioLayout] = None
|
||||
self.dynamic_range: Optional[DynamicRange] = None
|
||||
self.repack: Optional[Repack] = None
|
||||
self.multi: Optional[Multi] = None
|
||||
|
||||
def __str__(self):
|
||||
parts = [f"{self.show_title} (Seasons: {self.seasons})"]
|
||||
@@ -46,7 +34,6 @@ class TVBoxSetParser:
|
||||
|
||||
class TVBoxSetParserManager(ParserManager):
|
||||
"""Parses TV box set releases."""
|
||||
|
||||
def collect_parsers(self):
|
||||
"""Dynamically imports all TV box set parsers."""
|
||||
super().collect_parsers()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import regex as re
|
||||
|
||||
from parsers.generic.parsers import DataParser
|
||||
from parsers.tvboxset import TVBoxSetParser, TVBoxSetRelease
|
||||
from watfag.parsers.generic.parsers import DataParser
|
||||
from watfag.parsers.tvboxset import TVBoxSetParser, TVBoxSetRelease
|
||||
|
||||
patterns = [
|
||||
re.compile( # Show Name S01-S02 (year)
|
||||
|
||||
@@ -2,9 +2,9 @@ from xml.etree import ElementTree
|
||||
|
||||
from httpx import AsyncClient
|
||||
|
||||
from parsers.generic import Release
|
||||
from parsers.movie import MovieRelease, MovieParserManager
|
||||
from parsers.tvboxset import TVBoxSetRelease, TVBoxSetParserManager
|
||||
from watfag.parsers.generic import Release
|
||||
from watfag.parsers.movie import MovieRelease, MovieParserManager
|
||||
from watfag.parsers.tvboxset import TVBoxSetRelease, TVBoxSetParserManager
|
||||
|
||||
|
||||
class Jackett:
|
||||
|
||||
Reference in New Issue
Block a user