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
plexflow/__init__.py ADDED
File without changes
plexflow/__main__.py ADDED
@@ -0,0 +1,15 @@
1
+ from plexflow.core.subtitles.providers.oss.search import get_subtitles
2
+ from plexflow.core.subtitles.providers.oss.download import download_subtitles
3
+ from plexflow.core.subtitles.providers.auto_subtitles import AutoSubtitles
4
+ from pathlib import Path
5
+ from typing import List
6
+
7
+ auto_subtitles = AutoSubtitles(
8
+ imdb_id="tt8367814",
9
+ languages=["nl", "en"],
10
+ credentials_path="config/credentials.yaml",
11
+ redis_host="localhost",
12
+ redis_port=6379,
13
+ )
14
+
15
+ download_subtitles(auto_subtitles)
Binary file
File without changes
File without changes
File without changes
@@ -0,0 +1,32 @@
1
+ from plexflow.core.storage.object.plexflow_storage import PlexflowObjectStore
2
+ from plexflow.core.context.plexflow_context import PlexflowContext
3
+ from plexflow.core.context.metadata.tmdb.context import TMDbMetadataContext
4
+
5
+ class MetadataContext(PlexflowContext):
6
+ """A class used to represent a Select Context in Plexflow.
7
+
8
+ This class extends PlexflowContext and adds a selected item property.
9
+
10
+ Attributes:
11
+ selected_item (PlexflowObjectProperty): The selected item in the context.
12
+ """
13
+
14
+ def __init__(self, store: PlexflowObjectStore, **kwargs):
15
+ """Initializes the SelectContext with the given object store and keyword arguments.
16
+
17
+ Args:
18
+ store (PlexflowObjectStore): The object store to be used.
19
+ **kwargs: Arbitrary keyword arguments.
20
+ """
21
+
22
+ super().__init__(store=store, **kwargs)
23
+
24
+ @property
25
+ def tmdb(self) -> TMDbMetadataContext:
26
+ """Gets the value of the selected item.
27
+
28
+ Returns:
29
+ Any: The value of the selected item.
30
+ """
31
+
32
+ return TMDbMetadataContext(store=self.object_store)
File without changes
@@ -0,0 +1,45 @@
1
+ from plexflow.core.storage.object.plexflow_storage import PlexflowObjectStore
2
+ from plexflow.core.context.plexflow_context import PlexflowContext
3
+ from plexflow.core.context.plexflow_property import PlexflowObjectProperty
4
+ from plexflow.core.metadata.providers.tmdb.datatypes import TmdbMovie
5
+ from typing import Union
6
+
7
+ class TMDbMetadataContext(PlexflowContext):
8
+ """A class used to represent a Select Context in Plexflow.
9
+
10
+ This class extends PlexflowContext and adds a selected item property.
11
+
12
+ Attributes:
13
+ selected_item (PlexflowObjectProperty): The selected item in the context.
14
+ """
15
+
16
+ def __init__(self, store: PlexflowObjectStore, **kwargs):
17
+ """Initializes the SelectContext with the given object store and keyword arguments.
18
+
19
+ Args:
20
+ store (PlexflowObjectStore): The object store to be used.
21
+ **kwargs: Arbitrary keyword arguments.
22
+ """
23
+
24
+ super().__init__(store=store, **kwargs)
25
+ self.movie_details = PlexflowObjectProperty(self.object_store, "movie_details", local=True)
26
+
27
+ @property
28
+ def movie_data(self) -> Union[TmdbMovie, None]:
29
+ """Gets the value of the selected item.
30
+
31
+ Returns:
32
+ Any: The value of the selected item.
33
+ """
34
+
35
+ return self.movie_details.value
36
+
37
+ @movie_data.setter
38
+ def movie_data(self, val: TmdbMovie):
39
+ """Sets the value of the selected item.
40
+
41
+ Args:
42
+ val (Any): The value to be set.
43
+ """
44
+
45
+ self.movie_details.value = val
@@ -0,0 +1,46 @@
1
+ from plexflow.core.storage.object.plexflow_storage import PlexflowObjectStore
2
+ from typing import Any
3
+ from ulid import ULID
4
+
5
+ class PartialContext:
6
+ @staticmethod
7
+ def create_universal_id(dag_run_id: str):
8
+ store = PlexflowObjectStore(dag_run_id)
9
+ try:
10
+ print("try retrieving universal id")
11
+ universal_id = store.retrieve(store.make_key(dag_run_id))
12
+ if isinstance(universal_id, str) and len(universal_id) > 0:
13
+ return universal_id
14
+ except Exception:
15
+ print("creating universal id")
16
+
17
+ universal_id = str(ULID())
18
+ store.store_temporarily(key=store.make_key(dag_run_id), obj=universal_id)
19
+ return universal_id
20
+
21
+ def __init__(self, context_id: str, dag_run_id: str, default_ttl: int, **kwargs) -> None:
22
+ self.context_id = context_id
23
+ self.dag_run_id = dag_run_id
24
+ self.default_ttl = default_ttl
25
+ self.store = PlexflowObjectStore(context_id, **kwargs)
26
+
27
+ def update_universal_id(self, value: str):
28
+ self.store.store_temporarily(key=self.store.make_key(self.dag_run_id), obj=value)
29
+
30
+ def set(self, key: str, value: Any, ttl: int = None) -> None:
31
+ self.store.store_temporarily(key=self.store.make_run_key(key), obj=value, ttl=ttl or self.default_ttl)
32
+
33
+ def set_global(self, key: str, value: Any, ttl: int = None) -> None:
34
+ self.store.store_temporarily(key=self.store.make_key(key), obj=value, ttl=ttl or self.default_ttl)
35
+
36
+ def get(self, key: str) -> Any:
37
+ return self.store.retrieve(key=self.store.make_run_key(key))
38
+
39
+ def get_global(self, key: str) -> Any:
40
+ return self.store.retrieve(key=self.store.make_key(key))
41
+
42
+ def get_keys(self, pattern: str):
43
+ return list(map(lambda key_bytes: key_bytes.decode('utf-8'), self.store.retrieve_keys(self.store.make_run_key(pattern))))
44
+
45
+ def get_by_pattern(self, pattern: str):
46
+ return self.store.retrieve_values(self.store.make_run_key(pattern))
@@ -0,0 +1,8 @@
1
+ from plexflow.core.context.partials.ids import Ids
2
+ from plexflow.core.context.partials.watchlist import Watchlist
3
+ from plexflow.core.context.partials.cache import LRUCache
4
+ from plexflow.core.context.partials.movie import Movie
5
+ from plexflow.core.context.partials.context import Context
6
+ from plexflow.core.context.partials.torrents import Torrents
7
+ from plexflow.core.context.partials.tgx_context import TgxRequestContext
8
+ from plexflow.core.context.partials.tgx_batch import TgxBatch
@@ -0,0 +1,16 @@
1
+ from plexflow.core.context.partial_context import PartialContext
2
+ from datetime import datetime as dt
3
+
4
+ class LRUCache(PartialContext):
5
+ def __init__(self, **kwargs) -> None:
6
+ super().__init__(**kwargs)
7
+
8
+ def touch(self, media_id: str) -> None:
9
+ self.set_global(f"cache/processing/{media_id}", dt.now())
10
+
11
+ def last_used(self, media_id: str) -> dt:
12
+ try:
13
+ return self.get_global(f"cache/processing/{media_id}")
14
+ except Exception:
15
+ return None
16
+
@@ -0,0 +1,12 @@
1
+ from plexflow.core.context.partial_context import PartialContext
2
+
3
+ class Context(PartialContext):
4
+ def __init__(self, **kwargs) -> None:
5
+ super().__init__(**kwargs)
6
+
7
+ def update(self, id: str):
8
+ self.update_universal_id(id)
9
+
10
+ @property
11
+ def id(self) -> str:
12
+ return self.context_id
@@ -0,0 +1,37 @@
1
+ from plexflow.core.context.partial_context import PartialContext
2
+
3
+ class Ids(PartialContext):
4
+ def __init__(self, **kwargs) -> None:
5
+ super().__init__(**kwargs)
6
+
7
+ @property
8
+ def imdb_id(self) -> str:
9
+ return self.get("imdb_id")
10
+
11
+ @imdb_id.setter
12
+ def imdb_id(self, value: str) -> None:
13
+ self.set("imdb_id", value)
14
+
15
+ @property
16
+ def tmdb_id(self) -> int:
17
+ return self.get("tmdb_id")
18
+
19
+ @tmdb_id.setter
20
+ def tmdb_id(self, value: int) -> None:
21
+ self.set("tmdb_id", value)
22
+
23
+ @property
24
+ def tvdb_id(self) -> int:
25
+ return self.get("tvdb_id")
26
+
27
+ @tvdb_id.setter
28
+ def tvdb_id(self, value: int) -> None:
29
+ self.set("tvdb_id", value)
30
+
31
+ @property
32
+ def plex_id(self) -> str:
33
+ return self.get("plex_id")
34
+
35
+ @plex_id.setter
36
+ def plex_id(self, value: str) -> None:
37
+ self.set("plex_id", value)
@@ -0,0 +1,115 @@
1
+ from plexflow.core.context.partial_context import PartialContext
2
+ from datetime import datetime as dt
3
+ from plexflow.core.metadata.auto.auto_providers.auto.movie import AutoMovie
4
+ from plexflow.core.metadata.auto.auto_providers.tmdb.movie import AutoTmdbMovie
5
+ from plexflow.core.metadata.auto.auto_providers.tvdb.movie import AutoTvdbMovie
6
+ from plexflow.core.metadata.auto.auto_providers.moviemeter.movie import AutoMovieMeterMovie
7
+ from plexflow.core.metadata.auto.auto_providers.imdb.movie import AutoImdbMovie
8
+ from plexflow.core.metadata.auto.auto_providers.tmdb.show import AutoTmdbShow
9
+ from plexflow.core.metadata.auto.auto_providers.tvdb.show import AutoTvdbShow
10
+ from plexflow.core.metadata.auto.auto_providers.imdb.show import AutoImdbShow
11
+ from plexflow.core.metadata.auto.auto_providers.plex.movie import AutoPlexMovie
12
+
13
+ class Movie(PartialContext):
14
+ def __init__(self, **kwargs) -> None:
15
+ super().__init__(**kwargs)
16
+
17
+ @property
18
+ def sources(self) -> list:
19
+ keys = self.get_keys("movie/*")
20
+ # extract the source from the key
21
+ return [key.split("/")[-1] for key in keys]
22
+
23
+ def from_source(self, source: str) -> AutoMovie:
24
+ return self.get(f"movie/{source}")
25
+
26
+ @property
27
+ def title(self) -> str:
28
+ for source in self.sources:
29
+ details = self.from_source(source)
30
+ if details and details.title:
31
+ return details.title
32
+
33
+ @property
34
+ def year(self) -> int:
35
+ for source in self.sources:
36
+ details = self.from_source(source)
37
+ if details and details.year:
38
+ return details.year
39
+
40
+ @property
41
+ def release_date(self) -> dt:
42
+ for source in self.sources:
43
+ details = self.from_source(source)
44
+ if details and details.release_date:
45
+ return details.release_date
46
+
47
+ @property
48
+ def rank(self) -> int:
49
+ return self.plex.rank
50
+
51
+ @property
52
+ def released(self) -> bool:
53
+ dates = []
54
+ for source in self.sources:
55
+ details = self.from_source(source)
56
+ if details and details.release_date:
57
+ dates.append(details.release_date)
58
+
59
+ sorted_dates = sorted(dates)
60
+ now = dt.now()
61
+ return all([date < now for date in sorted_dates])
62
+
63
+ @property
64
+ def runtime(self) -> int:
65
+ for source in self.sources:
66
+ details = self.from_source(source)
67
+ if details and details.runtime:
68
+ return details.runtime
69
+
70
+ @property
71
+ def titles(self) -> set:
72
+ titles = set()
73
+ for source in self.sources:
74
+ details = self.from_source(source)
75
+ if details and details.title:
76
+ titles.add(details.title)
77
+ titles.update(details.titles)
78
+ return titles
79
+
80
+ @property
81
+ def summary(self) -> str:
82
+ for source in self.sources:
83
+ details = self.from_source(source)
84
+ if details and details.summary:
85
+ return details.summary
86
+
87
+ @property
88
+ def language(self) -> str:
89
+ for source in self.sources:
90
+ details = self.from_source(source)
91
+ if details and details.language:
92
+ return details.language
93
+
94
+ @property
95
+ def plex(self) -> AutoPlexMovie:
96
+ return self.from_source("plex")
97
+
98
+ @property
99
+ def tmdb(self) -> AutoTmdbMovie:
100
+ return self.from_source("tmdb")
101
+
102
+ @property
103
+ def imdb(self) -> AutoImdbMovie:
104
+ return self.from_source("imdb")
105
+
106
+ @property
107
+ def tvdb(self) -> AutoTvdbMovie:
108
+ return self.from_source("tvdb")
109
+
110
+ @property
111
+ def moviemeter(self) -> AutoMovieMeterMovie:
112
+ return self.from_source("moviemeter")
113
+
114
+ def update(self, movie: AutoMovie):
115
+ self.set(f"movie/{movie.source}", movie)
@@ -0,0 +1,33 @@
1
+ from plexflow.core.context.partial_context import PartialContext
2
+
3
+ class TgxBatch(PartialContext):
4
+ def __init__(self, **kwargs) -> None:
5
+ super().__init__(**kwargs)
6
+
7
+ def update(self, ids):
8
+ self.set("tgx/ids", ids)
9
+
10
+ def update_finished(self, ids):
11
+ self.set("tgx/finished", ids)
12
+
13
+ def update_unfinished(self, ids):
14
+ self.set("tgx/unfinished", ids)
15
+
16
+ def update_finished_items(self, items):
17
+ self.set("tgx/finished_items", items)
18
+
19
+ @property
20
+ def ids(self) -> set:
21
+ return self.get("tgx/ids")
22
+
23
+ @property
24
+ def finished(self) -> set:
25
+ return self.get("tgx/finished")
26
+
27
+ @property
28
+ def unfinished(self) -> set:
29
+ return self.get("tgx/unfinished")
30
+
31
+ @property
32
+ def finished_items(self) -> list:
33
+ return self.get("tgx/finished_items")
@@ -0,0 +1,34 @@
1
+ from plexflow.core.context.partial_context import PartialContext
2
+
3
+ class TgxRequestContext(PartialContext):
4
+ def __init__(self, **kwargs) -> None:
5
+ super().__init__(**kwargs)
6
+
7
+ def update(self, cookies: dict):
8
+ self.set_global("tgx/cookies", cookies)
9
+
10
+ @property
11
+ def session_id(self) -> str:
12
+ """
13
+ Cookies is a dictionary like below:
14
+
15
+ [{'name': 'PHPSESSID', 'value': 'a95el556bo30414fslulnbdi03', 'domain': 'torrentgalaxy.to', 'path': '/', 'expires': -1, 'httpOnly': False, 'secure': False, 'sameSite': 'Lax'}, {'name': 'AdskeeperStorage', 'value': '%7B%220%22%3A%7B%22svspr%22%3A%22https%3A%2F%2Ftorrentgalaxy.to%2Ftorrent%2F16100045%22%2C%22svsds%22%3A2%7D%2C%22C385455%22%3A%7B%22page%22%3A1%2C%22time%22%3A%221722597496754%22%7D%2C%22C1543068%22%3A%7B%22page%22%3A1%2C%22time%22%3A%221722597496757%22%7D%2C%22C1343686%22%3A%7B%22page%22%3A1%2C%22time%22%3A%221722597497305%22%7D%7D', 'domain': 'torrentgalaxy.to', 'path': '/', 'expires': -1, 'httpOnly': False, 'secure': False, 'sameSite': 'Lax'}]
16
+ """
17
+ try:
18
+ cookies = self.get_global("tgx/cookies")
19
+ for cookie in cookies:
20
+ if cookie["name"] == "PHPSESSID":
21
+ return cookie["value"]
22
+ except Exception:
23
+ return None
24
+
25
+ @property
26
+ def cookies(self) -> dict:
27
+ try:
28
+ cookies = self.get_global("tgx/cookies")
29
+ simple_cookies = {}
30
+ for cookie in cookies:
31
+ simple_cookies[cookie["name"]] = cookie["value"]
32
+ return simple_cookies
33
+ except Exception:
34
+ return None
@@ -0,0 +1,23 @@
1
+ from plexflow.core.context.partial_context import PartialContext
2
+ from datetime import datetime as dt
3
+ from plexflow.core.torrents.results.torrent import Torrent
4
+ from typing import List
5
+
6
+ class Torrents(PartialContext):
7
+ def __init__(self, **kwargs) -> None:
8
+ super().__init__(**kwargs)
9
+
10
+ @property
11
+ def sources(self) -> list[str]:
12
+ keys = self.get_keys("torrents/*")
13
+ # extract the source from the key
14
+ return [key.split("/")[-1] for key in keys]
15
+
16
+ def from_source(self, source: str) -> List[Torrent]:
17
+ return self.get(f"torrents/{source}")
18
+
19
+ def update(self, torrents: Torrent):
20
+ if len(torrents) == 0:
21
+ return
22
+ source = next(iter(torrents)).source
23
+ self.set(f"torrents/{source}", torrents)
@@ -0,0 +1,35 @@
1
+ from plexflow.core.context.partial_context import PartialContext
2
+ from plexflow.core.plex.watchlist.datatypes import MediaContainer, PlexMetadata
3
+ from ulid import ULID
4
+ from typing import Generator, Any
5
+
6
+ class Watchlist(PartialContext):
7
+ def __init__(self, **kwargs) -> None:
8
+ super().__init__(**kwargs)
9
+
10
+ @property
11
+ def selected(self) -> PlexMetadata:
12
+ try:
13
+ return self.get("watchlist/selected")
14
+ except Exception:
15
+ return None
16
+
17
+ def select(self, value: PlexMetadata) -> None:
18
+ self.set("watchlist/selected", value)
19
+
20
+ def update(self, container: MediaContainer) -> None:
21
+ tag = ULID()
22
+ self.set(f"watchlist/items/{tag}", container)
23
+
24
+ def __iter__(self):
25
+ return self.generator()
26
+
27
+ def raw(self):
28
+ return self.get_by_pattern("watchlist/items/*")
29
+
30
+ def generator(self) -> Generator[Any, Any, Any]:
31
+ items = self.get_by_pattern("watchlist/items/*")
32
+ for part in items:
33
+ part: MediaContainer = part
34
+ for item in part.Metadata:
35
+ yield item
@@ -0,0 +1,29 @@
1
+ from plexflow.core.storage.object.plexflow_storage import PlexflowObjectStore
2
+
3
+ class PlexflowContext:
4
+ """A class used to represent the Plexflow Context.
5
+
6
+ This class provides a context for Plexflow computations, allowing access to an object store.
7
+
8
+ Attributes:
9
+ store (PlexflowObjectStore): The object store used in the Plexflow context.
10
+ """
11
+
12
+ def __init__(self, store: PlexflowObjectStore):
13
+ """Initializes the PlexflowContext with the given object store.
14
+
15
+ Args:
16
+ store (PlexflowObjectStore): The object store to be used in the Plexflow context.
17
+ """
18
+
19
+ self.store = store
20
+
21
+ @property
22
+ def object_store(self) -> PlexflowObjectStore:
23
+ """Gets the object store used in the Plexflow context.
24
+
25
+ Returns:
26
+ PlexflowObjectStore: The object store used in the Plexflow context.
27
+ """
28
+
29
+ return self.store
@@ -0,0 +1,36 @@
1
+ from plexflow.core.storage.object.plexflow_storage import PlexflowObjectStore
2
+
3
+ class PlexflowObjectProperty:
4
+ """A class used to represent a property of a Plexflow object."""
5
+
6
+ def __init__(self, store: PlexflowObjectStore, key: str, local: bool = True):
7
+ """Initializes the PlexflowObjectProperty with the given object store, key, and locality.
8
+
9
+ Args:
10
+ store (PlexflowObjectStore): The object store to be used.
11
+ key (str): The key of the object.
12
+ local (bool, optional): Whether the key is local. Defaults to True.
13
+ """
14
+
15
+ self.store = store
16
+ self.object_key = self.store.make_run_key(key) if local else self.store.make_key(key)
17
+
18
+ @property
19
+ def value(self):
20
+ """Gets the value of the object from the object store.
21
+
22
+ Returns:
23
+ Any: The value of the object.
24
+ """
25
+
26
+ return self.store.retrieve(self.object_key)
27
+
28
+ @value.setter
29
+ def value(self, val):
30
+ """Sets the value of the object in the object store.
31
+
32
+ Args:
33
+ val (Any): The value to be set.
34
+ """
35
+
36
+ self.store.store_temporarily(self.object_key, val)
File without changes
@@ -0,0 +1,25 @@
1
+ from plexflow.core.context.plexflow_context import PlexflowContext
2
+ from plexflow.core.context.select.context import SelectContext
3
+ from plexflow.core.context.watchlist.context import WatchlistContext
4
+ from plexflow.core.context.metadata.context import MetadataContext
5
+ from plexflow.core.context.torrent.context import TorrentContext
6
+
7
+ class RootContext(PlexflowContext):
8
+ def __init__(self, **kwargs):
9
+ super().__init__(**kwargs)
10
+
11
+ @property
12
+ def select(self):
13
+ return SelectContext(self.object_store)
14
+
15
+ @property
16
+ def watchlist(self):
17
+ return WatchlistContext(self.object_store)
18
+
19
+ @property
20
+ def metadata(self):
21
+ return MetadataContext(self.object_store)
22
+
23
+ @property
24
+ def torrent(self):
25
+ return TorrentContext(self.object_store)
File without changes
@@ -0,0 +1,45 @@
1
+ from plexflow.core.storage.object.plexflow_storage import PlexflowObjectStore
2
+ from plexflow.core.context.plexflow_context import PlexflowContext
3
+ from plexflow.core.context.plexflow_property import PlexflowObjectProperty
4
+ from plexflow.core.plex.watchlist.datatypes import PlexMetadata
5
+ from typing import Union
6
+
7
+ class SelectContext(PlexflowContext):
8
+ """A class used to represent a Select Context in Plexflow.
9
+
10
+ This class extends PlexflowContext and adds a selected item property.
11
+
12
+ Attributes:
13
+ selected_item (PlexflowObjectProperty): The selected item in the context.
14
+ """
15
+
16
+ def __init__(self, store: PlexflowObjectStore, **kwargs):
17
+ """Initializes the SelectContext with the given object store and keyword arguments.
18
+
19
+ Args:
20
+ store (PlexflowObjectStore): The object store to be used.
21
+ **kwargs: Arbitrary keyword arguments.
22
+ """
23
+
24
+ super().__init__(store=store, **kwargs)
25
+ self.selected_item = PlexflowObjectProperty(self.object_store, "selected", local=True)
26
+
27
+ @property
28
+ def item(self) -> Union[PlexMetadata, None]:
29
+ """Gets the value of the selected item.
30
+
31
+ Returns:
32
+ Any: The value of the selected item.
33
+ """
34
+
35
+ return self.selected_item.value
36
+
37
+ @item.setter
38
+ def item(self, val: PlexMetadata):
39
+ """Sets the value of the selected item.
40
+
41
+ Args:
42
+ val (Any): The value to be set.
43
+ """
44
+
45
+ self.selected_item.value = val
File without changes
@@ -0,0 +1,43 @@
1
+ from plexflow.core.storage.object.plexflow_storage import PlexflowObjectStore
2
+ from plexflow.core.context.plexflow_context import PlexflowContext
3
+ from plexflow.core.context.torrent.tpb.context import ThePirateBayTorrentContext
4
+ from plexflow.core.context.torrent.yts.context import YTSTorrentContext
5
+
6
+ class TorrentContext(PlexflowContext):
7
+ """A class used to represent a Select Context in Plexflow.
8
+
9
+ This class extends PlexflowContext and adds a selected item property.
10
+
11
+ Attributes:
12
+ selected_item (PlexflowObjectProperty): The selected item in the context.
13
+ """
14
+
15
+ def __init__(self, store: PlexflowObjectStore, **kwargs):
16
+ """Initializes the SelectContext with the given object store and keyword arguments.
17
+
18
+ Args:
19
+ store (PlexflowObjectStore): The object store to be used.
20
+ **kwargs: Arbitrary keyword arguments.
21
+ """
22
+
23
+ super().__init__(store=store, **kwargs)
24
+
25
+ @property
26
+ def tpb(self) -> ThePirateBayTorrentContext:
27
+ """Gets the value of the selected item.
28
+
29
+ Returns:
30
+ Any: The value of the selected item.
31
+ """
32
+
33
+ return ThePirateBayTorrentContext(store=self.object_store)
34
+
35
+ @property
36
+ def yts(self) -> YTSTorrentContext:
37
+ """Gets the value of the selected item.
38
+
39
+ Returns:
40
+ Any: The value of the selected item.
41
+ """
42
+
43
+ return YTSTorrentContext(store=self.object_store)
File without changes