plexflow 0.0.64__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. plexflow/__init__.py +0 -0
  2. plexflow/__main__.py +15 -0
  3. plexflow/core/.DS_Store +0 -0
  4. plexflow/core/__init__.py +0 -0
  5. plexflow/core/context/__init__.py +0 -0
  6. plexflow/core/context/metadata/__init__.py +0 -0
  7. plexflow/core/context/metadata/context.py +32 -0
  8. plexflow/core/context/metadata/tmdb/__init__.py +0 -0
  9. plexflow/core/context/metadata/tmdb/context.py +45 -0
  10. plexflow/core/context/partial_context.py +46 -0
  11. plexflow/core/context/partials/__init__.py +8 -0
  12. plexflow/core/context/partials/cache.py +16 -0
  13. plexflow/core/context/partials/context.py +12 -0
  14. plexflow/core/context/partials/ids.py +37 -0
  15. plexflow/core/context/partials/movie.py +115 -0
  16. plexflow/core/context/partials/tgx_batch.py +33 -0
  17. plexflow/core/context/partials/tgx_context.py +34 -0
  18. plexflow/core/context/partials/torrents.py +23 -0
  19. plexflow/core/context/partials/watchlist.py +35 -0
  20. plexflow/core/context/plexflow_context.py +29 -0
  21. plexflow/core/context/plexflow_property.py +36 -0
  22. plexflow/core/context/root/__init__.py +0 -0
  23. plexflow/core/context/root/context.py +25 -0
  24. plexflow/core/context/select/__init__.py +0 -0
  25. plexflow/core/context/select/context.py +45 -0
  26. plexflow/core/context/torrent/__init__.py +0 -0
  27. plexflow/core/context/torrent/context.py +43 -0
  28. plexflow/core/context/torrent/tpb/__init__.py +0 -0
  29. plexflow/core/context/torrent/tpb/context.py +45 -0
  30. plexflow/core/context/torrent/yts/__init__.py +0 -0
  31. plexflow/core/context/torrent/yts/context.py +45 -0
  32. plexflow/core/context/watchlist/__init__.py +0 -0
  33. plexflow/core/context/watchlist/context.py +46 -0
  34. plexflow/core/downloads/__init__.py +0 -0
  35. plexflow/core/downloads/candidates/__init__.py +0 -0
  36. plexflow/core/downloads/candidates/download_candidate.py +210 -0
  37. plexflow/core/downloads/candidates/filtered.py +51 -0
  38. plexflow/core/downloads/candidates/utils.py +39 -0
  39. plexflow/core/env/__init__.py +0 -0
  40. plexflow/core/env/env.py +31 -0
  41. plexflow/core/genai/__init__.py +0 -0
  42. plexflow/core/genai/bot.py +9 -0
  43. plexflow/core/genai/plexa.py +54 -0
  44. plexflow/core/genai/torrent/imdb_verify.py +65 -0
  45. plexflow/core/genai/torrent/movie.py +25 -0
  46. plexflow/core/genai/utils/__init__.py +0 -0
  47. plexflow/core/genai/utils/loader.py +5 -0
  48. plexflow/core/metadata/__init__.py +0 -0
  49. plexflow/core/metadata/auto/__init__.py +0 -0
  50. plexflow/core/metadata/auto/auto_meta.py +40 -0
  51. plexflow/core/metadata/auto/auto_providers/__init__.py +0 -0
  52. plexflow/core/metadata/auto/auto_providers/auto/__init__.py +0 -0
  53. plexflow/core/metadata/auto/auto_providers/auto/episode.py +49 -0
  54. plexflow/core/metadata/auto/auto_providers/auto/item.py +55 -0
  55. plexflow/core/metadata/auto/auto_providers/auto/movie.py +13 -0
  56. plexflow/core/metadata/auto/auto_providers/auto/season.py +43 -0
  57. plexflow/core/metadata/auto/auto_providers/auto/show.py +26 -0
  58. plexflow/core/metadata/auto/auto_providers/imdb/__init__.py +0 -0
  59. plexflow/core/metadata/auto/auto_providers/imdb/movie.py +36 -0
  60. plexflow/core/metadata/auto/auto_providers/imdb/show.py +45 -0
  61. plexflow/core/metadata/auto/auto_providers/moviemeter/__init__.py +0 -0
  62. plexflow/core/metadata/auto/auto_providers/moviemeter/movie.py +40 -0
  63. plexflow/core/metadata/auto/auto_providers/plex/__init__.py +0 -0
  64. plexflow/core/metadata/auto/auto_providers/plex/movie.py +39 -0
  65. plexflow/core/metadata/auto/auto_providers/tmdb/__init__.py +0 -0
  66. plexflow/core/metadata/auto/auto_providers/tmdb/episode.py +30 -0
  67. plexflow/core/metadata/auto/auto_providers/tmdb/movie.py +36 -0
  68. plexflow/core/metadata/auto/auto_providers/tmdb/season.py +23 -0
  69. plexflow/core/metadata/auto/auto_providers/tmdb/show.py +41 -0
  70. plexflow/core/metadata/auto/auto_providers/tmdb.py +92 -0
  71. plexflow/core/metadata/auto/auto_providers/tvdb/__init__.py +0 -0
  72. plexflow/core/metadata/auto/auto_providers/tvdb/episode.py +28 -0
  73. plexflow/core/metadata/auto/auto_providers/tvdb/movie.py +36 -0
  74. plexflow/core/metadata/auto/auto_providers/tvdb/season.py +25 -0
  75. plexflow/core/metadata/auto/auto_providers/tvdb/show.py +41 -0
  76. plexflow/core/metadata/providers/__init__.py +0 -0
  77. plexflow/core/metadata/providers/imdb/__init__.py +0 -0
  78. plexflow/core/metadata/providers/imdb/datatypes.py +53 -0
  79. plexflow/core/metadata/providers/imdb/imdb.py +112 -0
  80. plexflow/core/metadata/providers/moviemeter/__init__.py +0 -0
  81. plexflow/core/metadata/providers/moviemeter/datatypes.py +111 -0
  82. plexflow/core/metadata/providers/moviemeter/moviemeter.py +42 -0
  83. plexflow/core/metadata/providers/plex/__init__.py +0 -0
  84. plexflow/core/metadata/providers/plex/datatypes.py +693 -0
  85. plexflow/core/metadata/providers/plex/plex.py +167 -0
  86. plexflow/core/metadata/providers/tmdb/__init__.py +0 -0
  87. plexflow/core/metadata/providers/tmdb/datatypes.py +460 -0
  88. plexflow/core/metadata/providers/tmdb/tmdb.py +85 -0
  89. plexflow/core/metadata/providers/tvdb/__init__.py +0 -0
  90. plexflow/core/metadata/providers/tvdb/datatypes.py +257 -0
  91. plexflow/core/metadata/providers/tvdb/tv_datatypes.py +554 -0
  92. plexflow/core/metadata/providers/tvdb/tvdb.py +65 -0
  93. plexflow/core/metadata/providers/universal/__init__.py +0 -0
  94. plexflow/core/metadata/providers/universal/movie.py +130 -0
  95. plexflow/core/metadata/providers/universal/old.py +192 -0
  96. plexflow/core/metadata/providers/universal/show.py +107 -0
  97. plexflow/core/plex/__init__.py +0 -0
  98. plexflow/core/plex/api/context/authorized.py +15 -0
  99. plexflow/core/plex/api/context/discover.py +14 -0
  100. plexflow/core/plex/api/context/library.py +14 -0
  101. plexflow/core/plex/discover/__init__.py +0 -0
  102. plexflow/core/plex/discover/activity.py +448 -0
  103. plexflow/core/plex/discover/comment.py +89 -0
  104. plexflow/core/plex/discover/feed.py +11 -0
  105. plexflow/core/plex/hooks/__init__.py +0 -0
  106. plexflow/core/plex/hooks/plex_authorized.py +60 -0
  107. plexflow/core/plex/hooks/plexflow_database.py +6 -0
  108. plexflow/core/plex/library/__init__.py +0 -0
  109. plexflow/core/plex/library/library.py +103 -0
  110. plexflow/core/plex/token/__init__.py +0 -0
  111. plexflow/core/plex/token/auto_token.py +91 -0
  112. plexflow/core/plex/utils/__init__.py +0 -0
  113. plexflow/core/plex/utils/paginated.py +39 -0
  114. plexflow/core/plex/watchlist/__init__.py +0 -0
  115. plexflow/core/plex/watchlist/datatypes.py +124 -0
  116. plexflow/core/plex/watchlist/watchlist.py +23 -0
  117. plexflow/core/storage/__init__.py +0 -0
  118. plexflow/core/storage/object/__init__.py +0 -0
  119. plexflow/core/storage/object/plexflow_storage.py +143 -0
  120. plexflow/core/storage/object/redis_storage.py +169 -0
  121. plexflow/core/subtitles/__init__.py +0 -0
  122. plexflow/core/subtitles/providers/__init__.py +0 -0
  123. plexflow/core/subtitles/providers/auto_subtitles.py +48 -0
  124. plexflow/core/subtitles/providers/oss/__init__.py +0 -0
  125. plexflow/core/subtitles/providers/oss/datatypes.py +104 -0
  126. plexflow/core/subtitles/providers/oss/download.py +48 -0
  127. plexflow/core/subtitles/providers/oss/old.py +144 -0
  128. plexflow/core/subtitles/providers/oss/oss.py +400 -0
  129. plexflow/core/subtitles/providers/oss/oss_subtitle.py +32 -0
  130. plexflow/core/subtitles/providers/oss/search.py +52 -0
  131. plexflow/core/subtitles/providers/oss/unlimited_oss.py +231 -0
  132. plexflow/core/subtitles/providers/oss/utils/__init__.py +0 -0
  133. plexflow/core/subtitles/providers/oss/utils/config.py +63 -0
  134. plexflow/core/subtitles/providers/oss/utils/download_client.py +22 -0
  135. plexflow/core/subtitles/providers/oss/utils/exceptions.py +35 -0
  136. plexflow/core/subtitles/providers/oss/utils/file_utils.py +83 -0
  137. plexflow/core/subtitles/providers/oss/utils/languages.py +78 -0
  138. plexflow/core/subtitles/providers/oss/utils/response_base.py +221 -0
  139. plexflow/core/subtitles/providers/oss/utils/responses.py +176 -0
  140. plexflow/core/subtitles/providers/oss/utils/srt.py +561 -0
  141. plexflow/core/subtitles/results/__init__.py +0 -0
  142. plexflow/core/subtitles/results/subtitle.py +170 -0
  143. plexflow/core/torrents/__init__.py +0 -0
  144. plexflow/core/torrents/analyzers/analyzed_torrent.py +143 -0
  145. plexflow/core/torrents/analyzers/analyzer.py +45 -0
  146. plexflow/core/torrents/analyzers/torrentquest/analyzer.py +47 -0
  147. plexflow/core/torrents/auto/auto_providers/auto/__init__.py +0 -0
  148. plexflow/core/torrents/auto/auto_providers/auto/torrent.py +64 -0
  149. plexflow/core/torrents/auto/auto_providers/tpb/torrent.py +62 -0
  150. plexflow/core/torrents/auto/auto_torrents.py +29 -0
  151. plexflow/core/torrents/providers/__init__.py +0 -0
  152. plexflow/core/torrents/providers/ext/__init__.py +0 -0
  153. plexflow/core/torrents/providers/ext/ext.py +18 -0
  154. plexflow/core/torrents/providers/ext/utils.py +64 -0
  155. plexflow/core/torrents/providers/extratorrent/__init__.py +0 -0
  156. plexflow/core/torrents/providers/extratorrent/extratorrent.py +21 -0
  157. plexflow/core/torrents/providers/extratorrent/utils.py +66 -0
  158. plexflow/core/torrents/providers/eztv/__init__.py +0 -0
  159. plexflow/core/torrents/providers/eztv/eztv.py +47 -0
  160. plexflow/core/torrents/providers/eztv/utils.py +83 -0
  161. plexflow/core/torrents/providers/rarbg2/__init__.py +0 -0
  162. plexflow/core/torrents/providers/rarbg2/rarbg2.py +19 -0
  163. plexflow/core/torrents/providers/rarbg2/utils.py +76 -0
  164. plexflow/core/torrents/providers/snowfl/__init__.py +0 -0
  165. plexflow/core/torrents/providers/snowfl/snowfl.py +36 -0
  166. plexflow/core/torrents/providers/snowfl/utils.py +59 -0
  167. plexflow/core/torrents/providers/tgx/__init__.py +0 -0
  168. plexflow/core/torrents/providers/tgx/context.py +50 -0
  169. plexflow/core/torrents/providers/tgx/dump.py +40 -0
  170. plexflow/core/torrents/providers/tgx/tgx.py +22 -0
  171. plexflow/core/torrents/providers/tgx/utils.py +61 -0
  172. plexflow/core/torrents/providers/therarbg/__init__.py +0 -0
  173. plexflow/core/torrents/providers/therarbg/therarbg.py +17 -0
  174. plexflow/core/torrents/providers/therarbg/utils.py +61 -0
  175. plexflow/core/torrents/providers/torrentquest/__init__.py +0 -0
  176. plexflow/core/torrents/providers/torrentquest/torrentquest.py +20 -0
  177. plexflow/core/torrents/providers/torrentquest/utils.py +70 -0
  178. plexflow/core/torrents/providers/tpb/__init__.py +0 -0
  179. plexflow/core/torrents/providers/tpb/tpb.py +17 -0
  180. plexflow/core/torrents/providers/tpb/utils.py +139 -0
  181. plexflow/core/torrents/providers/yts/__init__.py +0 -0
  182. plexflow/core/torrents/providers/yts/utils.py +57 -0
  183. plexflow/core/torrents/providers/yts/yts.py +31 -0
  184. plexflow/core/torrents/results/__init__.py +0 -0
  185. plexflow/core/torrents/results/torrent.py +165 -0
  186. plexflow/core/torrents/results/universal.py +220 -0
  187. plexflow/core/torrents/results/utils.py +15 -0
  188. plexflow/events/__init__.py +0 -0
  189. plexflow/events/download/__init__.py +0 -0
  190. plexflow/events/download/torrent_events.py +96 -0
  191. plexflow/events/publish/__init__.py +0 -0
  192. plexflow/events/publish/publish.py +34 -0
  193. plexflow/logging/__init__.py +0 -0
  194. plexflow/logging/log_setup.py +8 -0
  195. plexflow/spiders/quiet_logger.py +9 -0
  196. plexflow/spiders/tgx/pipelines/dump_json_pipeline.py +30 -0
  197. plexflow/spiders/tgx/pipelines/meta_pipeline.py +13 -0
  198. plexflow/spiders/tgx/pipelines/publish_pipeline.py +14 -0
  199. plexflow/spiders/tgx/pipelines/torrent_info_pipeline.py +12 -0
  200. plexflow/spiders/tgx/pipelines/validation_pipeline.py +17 -0
  201. plexflow/spiders/tgx/settings.py +36 -0
  202. plexflow/spiders/tgx/spider.py +72 -0
  203. plexflow/utils/__init__.py +0 -0
  204. plexflow/utils/antibot/human_like_requests.py +122 -0
  205. plexflow/utils/api/__init__.py +0 -0
  206. plexflow/utils/api/context/http.py +62 -0
  207. plexflow/utils/api/rest/__init__.py +0 -0
  208. plexflow/utils/api/rest/antibot_restful.py +68 -0
  209. plexflow/utils/api/rest/restful.py +49 -0
  210. plexflow/utils/captcha/__init__.py +0 -0
  211. plexflow/utils/captcha/bypass/__init__.py +0 -0
  212. plexflow/utils/captcha/bypass/decode_audio.py +34 -0
  213. plexflow/utils/download/__init__.py +0 -0
  214. plexflow/utils/download/gz.py +26 -0
  215. plexflow/utils/filesystem/__init__.py +0 -0
  216. plexflow/utils/filesystem/search.py +129 -0
  217. plexflow/utils/gmail/__init__.py +0 -0
  218. plexflow/utils/gmail/mails.py +116 -0
  219. plexflow/utils/hooks/__init__.py +0 -0
  220. plexflow/utils/hooks/http.py +84 -0
  221. plexflow/utils/hooks/postgresql.py +93 -0
  222. plexflow/utils/hooks/redis.py +112 -0
  223. plexflow/utils/image/storage.py +36 -0
  224. plexflow/utils/imdb/__init__.py +0 -0
  225. plexflow/utils/imdb/imdb_codes.py +107 -0
  226. plexflow/utils/pubsub/consume.py +82 -0
  227. plexflow/utils/pubsub/produce.py +25 -0
  228. plexflow/utils/retry/__init__.py +0 -0
  229. plexflow/utils/retry/utils.py +38 -0
  230. plexflow/utils/strings/__init__.py +0 -0
  231. plexflow/utils/strings/filesize.py +55 -0
  232. plexflow/utils/strings/language.py +14 -0
  233. plexflow/utils/subtitle/search.py +76 -0
  234. plexflow/utils/tasks/decorators.py +78 -0
  235. plexflow/utils/tasks/k8s/task.py +70 -0
  236. plexflow/utils/thread_safe/safe_list.py +54 -0
  237. plexflow/utils/thread_safe/safe_set.py +69 -0
  238. plexflow/utils/torrent/__init__.py +0 -0
  239. plexflow/utils/torrent/analyze.py +118 -0
  240. plexflow/utils/torrent/extract/common.py +37 -0
  241. plexflow/utils/torrent/extract/ext.py +2391 -0
  242. plexflow/utils/torrent/extract/extratorrent.py +56 -0
  243. plexflow/utils/torrent/extract/kat.py +1581 -0
  244. plexflow/utils/torrent/extract/tgx.py +96 -0
  245. plexflow/utils/torrent/extract/therarbg.py +170 -0
  246. plexflow/utils/torrent/extract/torrentquest.py +171 -0
  247. plexflow/utils/torrent/files.py +36 -0
  248. plexflow/utils/torrent/hash.py +90 -0
  249. plexflow/utils/transcribe/__init__.py +0 -0
  250. plexflow/utils/transcribe/speech2text.py +40 -0
  251. plexflow/utils/video/__init__.py +0 -0
  252. plexflow/utils/video/subtitle.py +73 -0
  253. plexflow-0.0.64.dist-info/METADATA +71 -0
  254. plexflow-0.0.64.dist-info/RECORD +256 -0
  255. plexflow-0.0.64.dist-info/WHEEL +4 -0
  256. plexflow-0.0.64.dist-info/entry_points.txt +24 -0
@@ -0,0 +1,40 @@
1
+ from plexflow.core.metadata.auto.auto_providers.auto.movie import AutoMovie
2
+ from plexflow.core.metadata.auto.auto_providers.auto.show import AutoShow
3
+ from plexflow.core.metadata.auto.auto_providers.tmdb.movie import AutoTmdbMovie
4
+ from plexflow.core.metadata.auto.auto_providers.tvdb.movie import AutoTvdbMovie
5
+ from plexflow.core.metadata.auto.auto_providers.moviemeter.movie import AutoMovieMeterMovie
6
+ from plexflow.core.metadata.auto.auto_providers.imdb.movie import AutoImdbMovie
7
+ from plexflow.core.metadata.auto.auto_providers.tmdb.show import AutoTmdbShow
8
+ from plexflow.core.metadata.auto.auto_providers.tvdb.show import AutoTvdbShow
9
+ from plexflow.core.metadata.auto.auto_providers.imdb.show import AutoImdbShow
10
+ from plexflow.core.metadata.auto.auto_providers.plex.movie import AutoPlexMovie
11
+
12
+ class AutoMeta:
13
+ @staticmethod
14
+ def movie(imdb_id: str = None, source: str = 'tmdb', rating_key: str = None) -> AutoMovie:
15
+ if source == 'tmdb':
16
+ return AutoTmdbMovie(imdb_id)
17
+ elif source == 'tvdb':
18
+ return AutoTvdbMovie(imdb_id)
19
+ elif source =='moviemeter':
20
+ return AutoMovieMeterMovie(imdb_id)
21
+ elif source == 'imdb':
22
+ return AutoImdbMovie(imdb_id)
23
+ elif source == "plex":
24
+ if isinstance(rating_key, str):
25
+ return AutoPlexMovie(rating_key)
26
+ else:
27
+ raise ValueError("if source = 'plex', rating_key must be set")
28
+ else:
29
+ raise ValueError(f"Invalid source: {source}")
30
+
31
+ @staticmethod
32
+ def show(imdb_id: str, source: str = 'tmdb') -> AutoShow:
33
+ if source == 'tmdb':
34
+ return AutoTmdbShow(imdb_id)
35
+ elif source == 'tvdb':
36
+ return AutoTvdbShow(imdb_id)
37
+ elif source == 'imdb':
38
+ return AutoImdbShow(imdb_id)
39
+ else:
40
+ raise ValueError(f"Invalid source: {source}")
File without changes
@@ -0,0 +1,49 @@
1
+ from abc import ABC, abstractmethod
2
+ from datetime import datetime
3
+
4
+ from plexflow.core.metadata.auto.auto_providers.auto.season import AutoSeason
5
+
6
+ class AutoEpisode(ABC):
7
+ def __init__(self, parent: AutoSeason) -> None:
8
+ self._parent = parent
9
+
10
+ @property
11
+ def source(self) -> str:
12
+ return self._parent.source
13
+
14
+ @property
15
+ def season(self) -> AutoSeason:
16
+ return self._parent
17
+
18
+ @property
19
+ @abstractmethod
20
+ def runtime(self) -> int:
21
+ pass
22
+
23
+ @property
24
+ def year(self) -> int:
25
+ return self.release_date.year
26
+
27
+ @property
28
+ @abstractmethod
29
+ def episode_number(self) -> int:
30
+ pass
31
+
32
+ @property
33
+ def season_number(self) -> int:
34
+ return self._parent.season_number
35
+
36
+ @property
37
+ @abstractmethod
38
+ def summary(self) -> str:
39
+ pass
40
+
41
+ @property
42
+ @abstractmethod
43
+ def title(self) -> str:
44
+ pass
45
+
46
+ @property
47
+ @abstractmethod
48
+ def release_date(self) -> datetime:
49
+ pass
@@ -0,0 +1,55 @@
1
+ from abc import ABC, abstractmethod
2
+ from datetime import datetime
3
+ from typing import Any
4
+
5
+ class AutoItem(ABC):
6
+ def __init__(self, imdb_id: str, source: str) -> None:
7
+ self._imdb_id = imdb_id
8
+ self._source = source
9
+
10
+ @property
11
+ @abstractmethod
12
+ def id(self) -> Any:
13
+ pass
14
+
15
+ @property
16
+ @abstractmethod
17
+ def title(self) -> str:
18
+ pass
19
+
20
+ @property
21
+ @abstractmethod
22
+ def release_date(self) -> datetime:
23
+ pass
24
+
25
+ @property
26
+ @abstractmethod
27
+ def runtime(self) -> int:
28
+ pass
29
+
30
+ @property
31
+ def year(self) -> int:
32
+ return self.release_date.year
33
+
34
+ @property
35
+ @abstractmethod
36
+ def titles(self) -> list:
37
+ pass
38
+
39
+ @property
40
+ @abstractmethod
41
+ def summary(self) -> str:
42
+ pass
43
+
44
+ @property
45
+ @abstractmethod
46
+ def language(self) -> str:
47
+ pass
48
+
49
+ @property
50
+ def imdb_id(self) -> str:
51
+ return self._imdb_id
52
+
53
+ @property
54
+ def source(self) -> str:
55
+ return self._source
@@ -0,0 +1,13 @@
1
+ from abc import ABC, abstractmethod
2
+ from datetime import datetime
3
+ from plexflow.core.metadata.providers.imdb.imdb import search_movie_by_imdb
4
+ from plexflow.core.metadata.auto.auto_providers.auto.item import AutoItem
5
+
6
+ class AutoMovie(AutoItem):
7
+ def __init__(self, imdb_id: str, source: str) -> None:
8
+ super().__init__(imdb_id, source)
9
+ self._imdb_info = search_movie_by_imdb(self.imdb_id)
10
+
11
+ @property
12
+ def rank(self) -> int:
13
+ return self._imdb_info.rank
@@ -0,0 +1,43 @@
1
+ from typing import TYPE_CHECKING
2
+ from abc import ABC, abstractmethod
3
+ from datetime import datetime
4
+
5
+ if TYPE_CHECKING:
6
+ from plexflow.core.metadata.auto.auto_providers.auto.episode import AutoEpisode
7
+
8
+ from plexflow.core.metadata.auto.auto_providers.auto.show import AutoShow
9
+
10
+ class AutoSeason(ABC):
11
+ def __init__(self, parent: AutoShow) -> None:
12
+ self._parent = parent
13
+
14
+ @property
15
+ def show(self) -> AutoShow:
16
+ return self._parent
17
+
18
+ @property
19
+ def source(self) -> str:
20
+ return self._parent.source
21
+
22
+ @property
23
+ def total_episodes(self) -> int:
24
+ return len(self.episodes)
25
+
26
+ @property
27
+ @abstractmethod
28
+ def season_number(self) -> int:
29
+ pass
30
+
31
+ @property
32
+ @abstractmethod
33
+ def episodes(self) -> list['AutoEpisode']:
34
+ pass
35
+
36
+ @property
37
+ def year(self):
38
+ return self.release_date.year
39
+
40
+ @property
41
+ @abstractmethod
42
+ def release_date(self) -> datetime:
43
+ pass
@@ -0,0 +1,26 @@
1
+ from typing import TYPE_CHECKING
2
+ from abc import abstractmethod
3
+
4
+ if TYPE_CHECKING:
5
+ from plexflow.core.metadata.auto.auto_providers.auto.season import AutoSeason
6
+
7
+ from plexflow.core.metadata.providers.imdb.imdb import search_show_by_imdb
8
+ from plexflow.core.metadata.auto.auto_providers.auto.item import AutoItem
9
+
10
+ class AutoShow(AutoItem):
11
+ def __init__(self, imdb_id: str, source: str) -> None:
12
+ super().__init__(imdb_id, source)
13
+ self._imdb_info = search_show_by_imdb(self.imdb_id)
14
+
15
+ @property
16
+ def rank(self) -> int:
17
+ return self._imdb_info.rank
18
+
19
+ @property
20
+ def total_seasons(self) -> int:
21
+ return len(self.seasons)
22
+
23
+ @property
24
+ @abstractmethod
25
+ def seasons(self) -> list['AutoSeason']:
26
+ pass
@@ -0,0 +1,36 @@
1
+ from plexflow.core.metadata.auto.auto_providers.auto.movie import AutoMovie
2
+ from plexflow.core.metadata.providers.imdb.imdb import search_movie_by_imdb
3
+ from datetime import datetime
4
+
5
+ class AutoImdbMovie(AutoMovie):
6
+ def __init__(self, imdb_id: str) -> None:
7
+ super().__init__(imdb_id, 'imdb')
8
+ self._movie = search_movie_by_imdb(self.imdb_id)
9
+
10
+ @property
11
+ def id(self) -> str:
12
+ return self._movie.imdb_id
13
+
14
+ @property
15
+ def title(self) -> str:
16
+ return self._movie.title
17
+
18
+ @property
19
+ def release_date(self) -> datetime:
20
+ return self._movie.release_date
21
+
22
+ @property
23
+ def runtime(self) -> int:
24
+ return round(self._movie.runtime / 60)
25
+
26
+ @property
27
+ def titles(self) -> list:
28
+ return []
29
+
30
+ @property
31
+ def summary(self) -> str:
32
+ return None
33
+
34
+ @property
35
+ def language(self) -> str:
36
+ return None
@@ -0,0 +1,45 @@
1
+ from plexflow.core.metadata.auto.auto_providers.auto.show import AutoShow
2
+ from plexflow.core.metadata.providers.imdb.imdb import search_show_by_imdb
3
+ from datetime import datetime
4
+ from plexflow.core.metadata.auto.auto_providers.tmdb.season import AutoTmdbSeason, AutoSeason
5
+
6
+ class AutoImdbShow(AutoShow):
7
+ def __init__(self, imdb_id: str) -> None:
8
+ super().__init__(imdb_id, 'imdb')
9
+ self._show = search_show_by_imdb(self.imdb_id)
10
+
11
+ @property
12
+ def id(self) -> int:
13
+ return self._show.imdb_id
14
+
15
+ @property
16
+ def title(self) -> str:
17
+ return self._show.title
18
+
19
+ @property
20
+ def release_date(self) -> datetime:
21
+ return self._show.release_date
22
+
23
+ @property
24
+ def runtime(self) -> int:
25
+ return round(self._show.runtime / 60)
26
+
27
+ @property
28
+ def titles(self) -> list:
29
+ return []
30
+
31
+ @property
32
+ def summary(self) -> str:
33
+ return None
34
+
35
+ @property
36
+ def language(self) -> str:
37
+ return None
38
+
39
+ @property
40
+ def seasons(self) -> list[AutoSeason]:
41
+ return []
42
+
43
+ @property
44
+ def total_seasons(self) -> int:
45
+ return self._show.seasons
@@ -0,0 +1,40 @@
1
+ from plexflow.core.metadata.auto.auto_providers.auto.movie import AutoMovie
2
+ from plexflow.core.metadata.providers.moviemeter.moviemeter import search_movie_by_imdb
3
+ from datetime import datetime
4
+
5
+ class AutoMovieMeterMovie(AutoMovie):
6
+ def __init__(self, imdb_id: str) -> None:
7
+ super().__init__(imdb_id, 'moviemeter')
8
+ self._movie = search_movie_by_imdb(self.imdb_id)
9
+
10
+ @property
11
+ def id(self) -> int:
12
+ return self._movie.id
13
+
14
+ @property
15
+ def title(self) -> str:
16
+ return self._movie.display_title
17
+
18
+ @property
19
+ def release_date(self) -> datetime:
20
+ return None
21
+
22
+ @property
23
+ def runtime(self) -> int:
24
+ return self._movie.duration
25
+
26
+ @property
27
+ def titles(self) -> list:
28
+ return list(filter(lambda x: x, [self._movie.title, self._movie.alternative_title]))
29
+
30
+ @property
31
+ def summary(self) -> str:
32
+ return self._movie.plot
33
+
34
+ @property
35
+ def year(self) -> int:
36
+ return self._movie.year
37
+
38
+ @property
39
+ def language(self) -> str:
40
+ return None
@@ -0,0 +1,39 @@
1
+ from plexflow.core.metadata.auto.auto_providers.auto.movie import AutoMovie
2
+ from plexflow.core.metadata.providers.plex.plex import search_movie_by_rating_key
3
+ from datetime import datetime
4
+ from plexflow.utils.imdb.imdb_codes import extract_imdb_code
5
+
6
+ class AutoPlexMovie(AutoMovie):
7
+ def __init__(self, rating_key: str) -> None:
8
+ self._movie = search_movie_by_rating_key(rating_key)
9
+ imdb_id = next((next(extract_imdb_code(g.id), None) for g in self._movie.Guid), None)
10
+
11
+ super().__init__(imdb_id, 'plex')
12
+
13
+ @property
14
+ def id(self) -> str:
15
+ return self._movie.ratingKey
16
+
17
+ @property
18
+ def title(self) -> str:
19
+ return self._movie.title
20
+
21
+ @property
22
+ def release_date(self) -> datetime:
23
+ return datetime.strptime(self._movie.originallyAvailableAt, '%Y-%m-%d')
24
+
25
+ @property
26
+ def runtime(self) -> int:
27
+ return self._movie.duration // 60000 if isinstance(self._movie.duration, int) else None
28
+
29
+ @property
30
+ def titles(self) -> list:
31
+ return []
32
+
33
+ @property
34
+ def summary(self) -> str:
35
+ return self._movie.summary
36
+
37
+ @property
38
+ def language(self) -> str:
39
+ return None
@@ -0,0 +1,30 @@
1
+ from datetime import datetime
2
+ from plexflow.core.metadata.auto.auto_providers.auto.episode import AutoEpisode
3
+ from plexflow.core.metadata.auto.auto_providers.auto.season import AutoSeason
4
+ from plexflow.core.metadata.providers.tmdb.tmdb import get_season_by_show_id
5
+ from plexflow.core.metadata.providers.tmdb.datatypes import SeasonEpisode
6
+
7
+ class AutoTmdbEpisode(AutoEpisode):
8
+ def __init__(self, parent: AutoSeason, episode: SeasonEpisode) -> None:
9
+ super().__init__(parent=parent)
10
+ self._episode = episode
11
+
12
+ @property
13
+ def release_date(self) -> datetime:
14
+ return datetime.strptime(self._episode.air_date, '%Y-%m-%d') if self._episode.air_date else None
15
+
16
+ @property
17
+ def episode_number(self) -> int:
18
+ return self._episode.episode_number
19
+
20
+ @property
21
+ def title(self) -> str:
22
+ return self._episode.name
23
+
24
+ @property
25
+ def runtime(self) -> int:
26
+ return self._episode.runtime
27
+
28
+ @property
29
+ def summary(self) -> str:
30
+ return self._episode.overview
@@ -0,0 +1,36 @@
1
+ from plexflow.core.metadata.auto.auto_providers.auto.movie import AutoMovie
2
+ from plexflow.core.metadata.providers.tmdb.tmdb import search_movie_by_imdb, search_show_by_imdb, get_all_seasons_by_imdb_id
3
+ from datetime import datetime
4
+
5
+ class AutoTmdbMovie(AutoMovie):
6
+ def __init__(self, imdb_id: str) -> None:
7
+ super().__init__(imdb_id, 'tmdb')
8
+ self._movie = search_movie_by_imdb(self.imdb_id)
9
+
10
+ @property
11
+ def id(self) -> int:
12
+ return self._movie.id
13
+
14
+ @property
15
+ def title(self) -> str:
16
+ return self._movie.title
17
+
18
+ @property
19
+ def release_date(self) -> datetime:
20
+ return datetime.strptime(self._movie.release_date, '%Y-%m-%d')
21
+
22
+ @property
23
+ def runtime(self) -> int:
24
+ return self._movie.runtime
25
+
26
+ @property
27
+ def titles(self) -> list:
28
+ return [x.title for x in self._movie.alternative_titles.titles]
29
+
30
+ @property
31
+ def summary(self) -> str:
32
+ return self._movie.overview
33
+
34
+ @property
35
+ def language(self) -> str:
36
+ return self._movie.original_language
@@ -0,0 +1,23 @@
1
+ from datetime import datetime
2
+ from plexflow.core.metadata.auto.auto_providers.auto.season import AutoSeason
3
+ from plexflow.core.metadata.auto.auto_providers.auto.show import AutoShow
4
+ from plexflow.core.metadata.auto.auto_providers.auto.episode import AutoEpisode
5
+ from plexflow.core.metadata.auto.auto_providers.tmdb.episode import AutoTmdbEpisode
6
+ from plexflow.core.metadata.providers.tmdb.tmdb import get_season_by_show_id
7
+
8
+ class AutoTmdbSeason(AutoSeason):
9
+ def __init__(self, parent: AutoShow, season_number: int) -> None:
10
+ super().__init__(parent)
11
+ self._season = get_season_by_show_id(self._parent.id, season=season_number)
12
+
13
+ @property
14
+ def episodes(self) -> list[AutoEpisode]:
15
+ return [AutoTmdbEpisode(self, x) for x in self._season.episodes]
16
+
17
+ @property
18
+ def release_date(self) -> datetime:
19
+ return datetime.strptime(self._season.air_date, '%Y-%m-%d')
20
+
21
+ @property
22
+ def season_number(self) -> int:
23
+ return self._season.season_number
@@ -0,0 +1,41 @@
1
+ from plexflow.core.metadata.auto.auto_providers.auto.show import AutoShow
2
+ from plexflow.core.metadata.providers.tmdb.tmdb import search_show_by_imdb, get_all_seasons_by_imdb_id
3
+ from datetime import datetime
4
+ from plexflow.core.metadata.auto.auto_providers.tmdb.season import AutoTmdbSeason, AutoSeason
5
+
6
+ class AutoTmdbShow(AutoShow):
7
+ def __init__(self, imdb_id: str) -> None:
8
+ super().__init__(imdb_id, 'tmdb')
9
+ self._show = search_show_by_imdb(self.imdb_id)
10
+
11
+ @property
12
+ def id(self) -> int:
13
+ return self._show.id
14
+
15
+ @property
16
+ def title(self) -> str:
17
+ return self._show.original_name
18
+
19
+ @property
20
+ def release_date(self) -> datetime:
21
+ return datetime.strptime(self._show.first_air_date, '%Y-%m-%d')
22
+
23
+ @property
24
+ def runtime(self) -> int:
25
+ return self._show.last_episode_to_air.runtime if self._show.last_episode_to_air else next(iter(self._show.episode_run_time), None)
26
+
27
+ @property
28
+ def titles(self) -> list:
29
+ return [x.title for x in self._show.alternative_titles.results]
30
+
31
+ @property
32
+ def summary(self) -> str:
33
+ return self._show.overview
34
+
35
+ @property
36
+ def language(self) -> str:
37
+ return self._show.original_language
38
+
39
+ @property
40
+ def seasons(self) -> list[AutoSeason]:
41
+ return [AutoTmdbSeason(self, x.season_number) for x in self._show.seasons]
@@ -0,0 +1,92 @@
1
+ from plexflow.core.metadata.providers.tmdb.tmdb import search_movie_by_imdb, search_show_by_imdb, get_all_seasons_by_imdb_id
2
+ from datetime import datetime
3
+
4
+ class AutoTmdbMovie:
5
+ """
6
+ Represents a movie retrieved from the TMDb (The Movie Database) API.
7
+
8
+ Attributes:
9
+ imdb_id (str): The IMDb ID of the movie.
10
+
11
+ Properties:
12
+ title (str): The title of the movie.
13
+ release_date (datetime): The release date of the movie.
14
+ runtime (int): The runtime of the movie in minutes.
15
+ year (int): The year of the movie's release.
16
+ titles (list): A list of alternative titles for the movie.
17
+ summary (str): The summary or overview of the movie.
18
+ language (str): The original language of the movie.
19
+ """
20
+
21
+ def __init__(self, imdb_id: str) -> None:
22
+ self.imdb_id = imdb_id
23
+ self._movie = search_movie_by_imdb(self.imdb_id)
24
+
25
+ @property
26
+ def title(self) -> str:
27
+ return self._movie.title
28
+
29
+ @property
30
+ def release_date(self) -> datetime:
31
+ return datetime.strptime(self._movie.release_date, '%Y-%m-%d')
32
+
33
+ @property
34
+ def runtime(self) -> int:
35
+ return self._movie.runtime
36
+
37
+ @property
38
+ def year(self) -> int:
39
+ return self.release_date.year
40
+
41
+ @property
42
+ def titles(self) -> list:
43
+ return [x.title for x in self._movie.alternative_titles]
44
+
45
+ @property
46
+ def summary(self) -> str:
47
+ return self._movie.overview
48
+
49
+ @property
50
+ def language(self) -> str:
51
+ return self._movie.original_language
52
+
53
+ class AutoTmdbShow:
54
+ def __init__(self, imdb_id: str) -> None:
55
+ self.imdb_id = imdb_id
56
+ self._show = search_show_by_imdb(self.imdb_id)
57
+
58
+ @property
59
+ def title(self) -> str:
60
+ return self._show.original_name
61
+
62
+ @property
63
+ def release_date(self) -> datetime:
64
+ return datetime.strptime(self._show.first_air_date, '%Y-%m-%d')
65
+
66
+ @property
67
+ def runtime(self) -> int:
68
+ return self._show.episode_run_time
69
+
70
+ @property
71
+ def year(self) -> int:
72
+ return self.release_date.year
73
+
74
+ @property
75
+ def titles(self) -> list:
76
+ return [x.title for x in self._show.alternative_titles.results]
77
+
78
+ @property
79
+ def summary(self) -> str:
80
+ return self._show.overview
81
+
82
+ @property
83
+ def language(self) -> str:
84
+ return self._show.original_language
85
+
86
+ @property
87
+ def total_seasons(self) -> int:
88
+ return self._show.number_of_seasons
89
+
90
+ @property
91
+ def seasons(self) -> list:
92
+ return get_all_seasons_by_imdb_id(self.imdb_id)
@@ -0,0 +1,28 @@
1
+ from datetime import datetime
2
+ from plexflow.core.metadata.auto.auto_providers.auto.episode import AutoEpisode
3
+ from plexflow.core.metadata.auto.auto_providers.auto.season import AutoSeason
4
+
5
+ class AutoTvdbEpisode(AutoEpisode):
6
+ def __init__(self, parent: AutoSeason, episode: dict) -> None:
7
+ super().__init__(parent=parent)
8
+ self._episode = episode
9
+
10
+ @property
11
+ def release_date(self) -> datetime:
12
+ return datetime.strptime(self._episode.get('aired'), '%Y-%m-%d') if self._episode.get('aired') else None
13
+
14
+ @property
15
+ def episode_number(self) -> int:
16
+ return self._episode.get('number')
17
+
18
+ @property
19
+ def title(self) -> str:
20
+ return self._episode.get('name')
21
+
22
+ @property
23
+ def runtime(self) -> int:
24
+ return self._episode.get('runtime')
25
+
26
+ @property
27
+ def summary(self) -> str:
28
+ return self._episode.get('overview')