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,693 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import List, Optional, Dict
3
+ from dataclasses_json import dataclass_json, Undefined
4
+
5
+ @dataclass_json(undefined=Undefined.EXCLUDE)
6
+ @dataclass
7
+ class PlexImage:
8
+ """
9
+ Represents an image in Plex metadata.
10
+
11
+ Attributes:
12
+ alt (Optional[str]): The alternative text for the image.
13
+ type (Optional[str]): The type of the image.
14
+ url (Optional[str]): The URL of the image.
15
+ """
16
+ alt: Optional[str] = None
17
+ type: Optional[str] = None
18
+ url: Optional[str] = None
19
+
20
+ @dataclass_json(undefined=Undefined.EXCLUDE)
21
+ @dataclass
22
+ class PlexGenre:
23
+ """
24
+ Represents a genre in Plex metadata.
25
+
26
+ Attributes:
27
+ filter (Optional[str]): The filter associated with the genre.
28
+ id (Optional[str]): The ID of the genre.
29
+ ratingKey (Optional[str]): The rating key of the genre.
30
+ slug (Optional[str]): The slug of the genre.
31
+ tag (Optional[str]): The tag of the genre.
32
+ type (Optional[str]): The type of the genre.
33
+ context (Optional[str]): The context of the genre.
34
+ """
35
+ filter: Optional[str] = None
36
+ id: Optional[str] = None
37
+ ratingKey: Optional[str] = None
38
+ slug: Optional[str] = None
39
+ tag: Optional[str] = None
40
+ type: Optional[str] = None
41
+ context: Optional[str] = None
42
+
43
+ @dataclass_json(undefined=Undefined.EXCLUDE)
44
+ @dataclass
45
+ class PlexGuid:
46
+ """
47
+ Represents a Plex GUID.
48
+
49
+ Attributes:
50
+ id (Optional[str]): The ID of the Plex GUID.
51
+ """
52
+ id: Optional[str] = None
53
+
54
+ @dataclass_json(undefined=Undefined.EXCLUDE)
55
+ @dataclass
56
+ class PlexCollection:
57
+ """
58
+ Represents a collection in Plex.
59
+
60
+ Attributes:
61
+ art (Optional[str]): The URL of the collection's artwork.
62
+ guid (Optional[str]): The unique identifier of the collection.
63
+ key (Optional[str]): The key of the collection.
64
+ summary (Optional[str]): A summary or description of the collection.
65
+ thumb (Optional[str]): The URL of the collection's thumbnail.
66
+ tag (Optional[str]): A tag associated with the collection.
67
+ """
68
+ art: Optional[str] = None
69
+ guid: Optional[str] = None
70
+ key: Optional[str] = None
71
+ summary: Optional[str] = None
72
+ thumb: Optional[str] = None
73
+ tag: Optional[str] = None
74
+
75
+ @dataclass_json(undefined=Undefined.EXCLUDE)
76
+ @dataclass
77
+ class PlexCountry:
78
+ """
79
+ Represents a country in the Plex metadata.
80
+
81
+ Attributes:
82
+ tag (Optional[str]): The tag of the country.
83
+ """
84
+ tag: Optional[str] = None
85
+
86
+ @dataclass_json(undefined=Undefined.EXCLUDE)
87
+ @dataclass
88
+ class PlexRole:
89
+ """
90
+ Represents a role in Plex metadata.
91
+
92
+ Attributes:
93
+ key (Optional[str]): The key of the role.
94
+ id (Optional[str]): The ID of the role.
95
+ order (Optional[int]): The order of the role.
96
+ slug (Optional[str]): The slug of the role.
97
+ tag (Optional[str]): The tag of the role.
98
+ thumb (Optional[str]): The thumbnail of the role.
99
+ role (Optional[str]): The role name.
100
+ type (Optional[str]): The type of the role.
101
+ """
102
+ key: Optional[str] = None
103
+ id: Optional[str] = None
104
+ order: Optional[int] = None
105
+ slug: Optional[str] = None
106
+ tag: Optional[str] = None
107
+ thumb: Optional[str] = None
108
+ role: Optional[str] = None
109
+ type: Optional[str] = None
110
+
111
+ @dataclass_json(undefined=Undefined.EXCLUDE)
112
+ @dataclass
113
+ class PlexDirector:
114
+ """
115
+ Represents a director in Plex metadata.
116
+
117
+ Attributes:
118
+ key (Optional[str]): The key of the director.
119
+ id (Optional[str]): The ID of the director.
120
+ slug (Optional[str]): The slug of the director.
121
+ tag (Optional[str]): The tag of the director.
122
+ thumb (Optional[str]): The thumbnail URL of the director.
123
+ role (Optional[str]): The role of the director.
124
+ type (Optional[str]): The type of the director.
125
+ """
126
+ key: Optional[str] = None
127
+ id: Optional[str] = None
128
+ slug: Optional[str] = None
129
+ tag: Optional[str] = None
130
+ thumb: Optional[str] = None
131
+ role: Optional[str] = None
132
+ type: Optional[str] = None
133
+
134
+ @dataclass_json(undefined=Undefined.EXCLUDE)
135
+ @dataclass
136
+ class PlexProducer:
137
+ """
138
+ Represents a producer in Plex metadata.
139
+
140
+ Attributes:
141
+ key (Optional[str]): The key of the producer.
142
+ id (Optional[str]): The ID of the producer.
143
+ slug (Optional[str]): The slug of the producer.
144
+ tag (Optional[str]): The tag of the producer.
145
+ role (Optional[str]): The role of the producer.
146
+ type (Optional[str]): The type of the producer.
147
+ """
148
+ key: Optional[str] = None
149
+ id: Optional[str] = None
150
+ slug: Optional[str] = None
151
+ tag: Optional[str] = None
152
+ role: Optional[str] = None
153
+ type: Optional[str] = None
154
+
155
+ @dataclass_json(undefined=Undefined.EXCLUDE)
156
+ @dataclass
157
+ class PlexWriter:
158
+ """
159
+ Represents a writer in the Plex metadata provider.
160
+
161
+ Attributes:
162
+ key (Optional[str]): The key of the writer.
163
+ id (Optional[str]): The ID of the writer.
164
+ slug (Optional[str]): The slug of the writer.
165
+ tag (Optional[str]): The tag of the writer.
166
+ thumb (Optional[str]): The thumbnail URL of the writer.
167
+ role (Optional[str]): The role of the writer.
168
+ type (Optional[str]): The type of the writer.
169
+ """
170
+ key: Optional[str] = None
171
+ id: Optional[str] = None
172
+ slug: Optional[str] = None
173
+ tag: Optional[str] = None
174
+ thumb: Optional[str] = None
175
+ role: Optional[str] = None
176
+ type: Optional[str] = None
177
+
178
+ @dataclass_json(undefined=Undefined.EXCLUDE)
179
+ @dataclass
180
+ class PlexRating:
181
+ """
182
+ Represents a rating for a Plex item.
183
+
184
+ Attributes:
185
+ image (Optional[str]): The URL of the rating image.
186
+ type (Optional[str]): The type of the rating.
187
+ value (Optional[float]): The value of the rating.
188
+ """
189
+ image: Optional[str] = None
190
+ type: Optional[str] = None
191
+ value: Optional[float] = None
192
+
193
+ @dataclass_json(undefined=Undefined.EXCLUDE)
194
+ @dataclass
195
+ class PlexStudio:
196
+ """
197
+ Represents a studio in Plex.
198
+
199
+ Attributes:
200
+ tag (Optional[str]): The tag of the studio.
201
+ """
202
+ tag: Optional[str] = None
203
+
204
+ @dataclass_json(undefined=Undefined.EXCLUDE)
205
+ @dataclass
206
+ class PlexMovieMetadata:
207
+ """
208
+ Represents the metadata for a movie in Plex.
209
+
210
+ Attributes:
211
+ art (Optional[str]): The URL of the movie's artwork.
212
+ guid (Optional[str]): The unique identifier of the movie.
213
+ key (Optional[str]): The key of the movie in Plex.
214
+ primaryExtraKey (Optional[str]): The key of the primary extra associated with the movie.
215
+ rating (Optional[float]): The rating of the movie.
216
+ ratingKey (Optional[str]): The key of the rating in Plex.
217
+ studio (Optional[str]): The studio that produced the movie.
218
+ summary (Optional[str]): The summary of the movie.
219
+ tagline (Optional[str]): The tagline of the movie.
220
+ type (Optional[str]): The type of the movie.
221
+ thumb (Optional[str]): The URL of the movie's thumbnail.
222
+ addedAt (Optional[int]): The timestamp when the movie was added.
223
+ duration (Optional[int]): The duration of the movie in seconds.
224
+ publicPagesURL (Optional[str]): The URL of the movie's public page.
225
+ slug (Optional[str]): The slug of the movie.
226
+ userState (Optional[bool]): The user state of the movie.
227
+ title (Optional[str]): The title of the movie.
228
+ contentRating (Optional[str]): The content rating of the movie.
229
+ originallyAvailableAt (Optional[str]): The original release date of the movie.
230
+ year (Optional[int]): The year the movie was released.
231
+ audienceRating (Optional[float]): The audience rating of the movie.
232
+ audienceRatingImage (Optional[str]): The URL of the audience rating image.
233
+ ratingImage (Optional[str]): The URL of the rating image.
234
+ imdbRatingCount (Optional[int]): The number of IMDb ratings for the movie.
235
+ source (Optional[str]): The source of the movie.
236
+ Image (Optional[List[PlexImage]]): The list of images associated with the movie.
237
+ Genre (Optional[List[PlexGenre]]): The list of genres of the movie.
238
+ Guid (Optional[List[PlexGuid]]): The list of GUIDs associated with the movie.
239
+ Collection (Optional[List[PlexCollection]]): The list of collections the movie belongs to.
240
+ Country (Optional[List[PlexCountry]]): The list of countries associated with the movie.
241
+ Role (Optional[List[PlexRole]]): The list of roles in the movie.
242
+ Director (Optional[List[PlexDirector]]): The list of directors of the movie.
243
+ Producer (Optional[List[PlexProducer]]): The list of producers of the movie.
244
+ Writer (Optional[List[PlexWriter]]): The list of writers of the movie.
245
+ Rating (Optional[List[PlexRating]]): The list of ratings of the movie.
246
+ Studio (Optional[List[PlexStudio]]): The list of studios associated with the movie.
247
+ """
248
+ title: Optional[str]
249
+ guid: Optional[str]
250
+ key: Optional[str]
251
+ primaryExtraKey: Optional[str]
252
+ rating: Optional[float]
253
+ ratingKey: Optional[str]
254
+ studio: Optional[str]
255
+ summary: Optional[str]
256
+ tagline: Optional[str]
257
+ type: Optional[str]
258
+ thumb: Optional[str]
259
+ addedAt: Optional[int]
260
+ duration: Optional[int]
261
+ publicPagesURL: Optional[str]
262
+ slug: Optional[str]
263
+ userState: Optional[bool]
264
+ contentRating: Optional[str]
265
+ originallyAvailableAt: Optional[str]
266
+ year: Optional[int]
267
+ audienceRating: Optional[float]
268
+ audienceRatingImage: Optional[str]
269
+ ratingImage: Optional[str]
270
+ imdbRatingCount: Optional[int]
271
+ source: Optional[str] = field(default=None)
272
+ Image: Optional[List[PlexImage]] = field(default=None)
273
+ Genre: Optional[List[PlexGenre]] = field(default=None)
274
+ Guid: Optional[List[PlexGuid]] = field(default=None)
275
+ # Collection: Optional[List[PlexCollection]]
276
+ Country: Optional[List[PlexCountry]] = field(default=None)
277
+ Role: Optional[List[PlexRole]] = field(default=None)
278
+ Director: Optional[List[PlexDirector]] = field(default=None)
279
+ Producer: Optional[List[PlexProducer]] = field(default=None)
280
+ Writer: Optional[List[PlexWriter]] = field(default=None)
281
+ Rating: Optional[List[PlexRating]] = field(default=None)
282
+ Studio: Optional[List[PlexStudio]] = field(default=None)
283
+
284
+ def __post_init__(self):
285
+ self.Image = [PlexImage(**image) if isinstance(image, dict) else image for image in self.Image]
286
+ self.Genre = [PlexGenre(**genre) if isinstance(genre, dict) else genre for genre in self.Genre]
287
+ self.Guid = [PlexGuid(**guid) if isinstance(guid, dict) else guid for guid in self.Guid]
288
+ # self.Collection = [PlexCollection(**collection) if isinstance(collection, dict) else collection for collection in self.Collection]
289
+ self.Country = [PlexCountry(**country) if isinstance(country, dict) else country for country in self.Country]
290
+ self.Role = [PlexRole(**role) if isinstance(role, dict) else role for role in self.Role]
291
+ self.Director = [PlexDirector(**director) if isinstance(director, dict) else director for director in self.Director]
292
+ self.Producer = [PlexProducer(**producer) if isinstance(producer, dict) else producer for producer in self.Producer]
293
+ self.Writer = [PlexWriter(**writer) if isinstance(writer, dict) else writer for writer in self.Writer]
294
+ self.Rating = [PlexRating(**rating) if isinstance(rating, dict) else rating for rating in self.Rating]
295
+ self.Studio = [PlexStudio(**studio) if isinstance(studio, dict) else studio for studio in self.Studio]
296
+
297
+ @dataclass_json(undefined=Undefined.EXCLUDE)
298
+ @dataclass
299
+ class MovieMediaContainer:
300
+ """
301
+ Represents a container for movie media metadata in Plex.
302
+
303
+ Attributes:
304
+ offset (Optional[int]): The offset value.
305
+ totalSize (Optional[int]): The total size value.
306
+ identifier (Optional[str]): The identifier value.
307
+ size (Optional[int]): The size value.
308
+ Metadata (Optional[List[PlexMovieMetadata]]): A list of PlexMovieMetadata objects representing the movie metadata.
309
+
310
+ Methods:
311
+ __post_init__(): Initializes the MovieMediaContainer object and converts the metadata dictionaries to PlexMovieMetadata objects.
312
+ """
313
+ offset: Optional[int] = None
314
+ totalSize: Optional[int] = None
315
+ identifier: Optional[str] = None
316
+ size: Optional[int] = None
317
+ Metadata: Optional[List[PlexMovieMetadata]] = None
318
+
319
+ def __post_init__(self):
320
+ self.Metadata = [PlexMovieMetadata(**metadata) if isinstance(metadata, dict) else metadata for metadata in self.Metadata]
321
+
322
+
323
+ @dataclass_json(undefined=Undefined.EXCLUDE)
324
+ @dataclass
325
+ class PlexShowMetadata:
326
+ """
327
+ Represents the metadata for a TV show in Plex.
328
+
329
+ Attributes:
330
+ art (Optional[str]): The URL of the artwork for the show.
331
+ guid (Optional[str]): The unique identifier for the show.
332
+ key (Optional[str]): The key of the show.
333
+ primaryExtraKey (Optional[str]): The key of the primary extra associated with the show.
334
+ rating (Optional[float]): The rating of the show.
335
+ ratingKey (Optional[str]): The key of the rating for the show.
336
+ studio (Optional[str]): The studio that produced the show.
337
+ subtype (Optional[str]): The subtype of the show.
338
+ summary (Optional[str]): The summary of the show.
339
+ tagline (Optional[str]): The tagline of the show.
340
+ type (Optional[str]): The type of the show.
341
+ thumb (Optional[str]): The URL of the thumbnail for the show.
342
+ addedAt (Optional[int]): The timestamp when the show was added.
343
+ duration (Optional[int]): The duration of the show.
344
+ publicPagesURL (Optional[str]): The URL of the public pages for the show.
345
+ slug (Optional[str]): The slug of the show.
346
+ userState (Optional[bool]): The user state of the show.
347
+ title (Optional[str]): The title of the show.
348
+ leafCount (Optional[int]): The number of leaf items in the show.
349
+ childCount (Optional[int]): The number of child items in the show.
350
+ skipChildren (Optional[bool]): Indicates whether to skip child items.
351
+ isContinuingSeries (Optional[bool]): Indicates whether the show is a continuing series.
352
+ contentRating (Optional[str]): The content rating of the show.
353
+ originallyAvailableAt (Optional[str]): The original release date of the show.
354
+ year (Optional[int]): The year the show was released.
355
+ ratingImage (Optional[str]): The URL of the rating image for the show.
356
+ imdbRatingCount (Optional[int]): The number of IMDb ratings for the show.
357
+ source (Optional[str]): The source of the show.
358
+ Image (Optional[List[PlexImage]]): The list of images associated with the show.
359
+ Genre (Optional[List[PlexGenre]]): The list of genres for the show.
360
+ Guid (Optional[List[PlexGuid]]): The list of GUIDs for the show.
361
+ Country (Optional[List[PlexCountry]]): The list of countries for the show.
362
+ Role (Optional[List[PlexRole]]): The list of roles for the show.
363
+ Director (Optional[List[PlexDirector]]): The list of directors for the show.
364
+ Producer (Optional[List[PlexProducer]]): The list of producers for the show.
365
+ Writer (Optional[List[PlexWriter]]): The list of writers for the show.
366
+ Rating (Optional[List[PlexRating]]): The list of ratings for the show.
367
+ Studio (Optional[List[PlexStudio]]): The list of studios for the show.
368
+ _catchall (dict): A catch-all dictionary for any additional attributes.
369
+ """
370
+
371
+ def __post_init__(self):
372
+ self.Image = [PlexImage(**image) if isinstance(image, dict) else image for image in self.Image]
373
+ self.Genre = [PlexGenre(**genre) if isinstance(genre, dict) else genre for genre in self.Genre]
374
+ self.Guid = [PlexGuid(**guid) if isinstance(guid, dict) else guid for guid in self.Guid]
375
+ self.Country = [PlexCountry(**country) if isinstance(country, dict) else country for country in self.Country]
376
+ self.Role = [PlexRole(**role) if isinstance(role, dict) else role for role in self.Role]
377
+ self.Director = [PlexDirector(**director) if isinstance(director, dict) else director for director in self.Director]
378
+ self.Producer = [PlexProducer(**producer) if isinstance(producer, dict) else producer for producer in self.Producer]
379
+ self.Writer = [PlexWriter(**writer) if isinstance(writer, dict) else writer for writer in self.Writer]
380
+ self.Rating = [PlexRating(**rating) if isinstance(rating, dict) else rating for rating in self.Rating]
381
+ self.Studio = [PlexStudio(**studio) if isinstance(studio, dict) else studio for studio in self.Studio]
382
+
383
+
384
+ @dataclass_json(undefined=Undefined.EXCLUDE)
385
+ @dataclass
386
+ class ShowMediaContainer:
387
+ """
388
+ Represents a media container for TV shows in Plex.
389
+
390
+ Attributes:
391
+ offset (Optional[int]): The offset value.
392
+ totalSize (Optional[int]): The total size value.
393
+ identifier (Optional[str]): The identifier value.
394
+ size (Optional[int]): The size value.
395
+ Metadata (Optional[List[PlexShowMetadata]]): A list of PlexShowMetadata objects representing the metadata for the TV shows.
396
+
397
+ Methods:
398
+ __post_init__(): Initializes the ShowMediaContainer object and converts the metadata dictionaries to PlexShowMetadata objects.
399
+ """
400
+ offset: Optional[int] = None
401
+ totalSize: Optional[int] = None
402
+ identifier: Optional[str] = None
403
+ size: Optional[int] = None
404
+ Metadata: Optional[List[PlexShowMetadata]] = None
405
+
406
+ def __post_init__(self):
407
+ self.Metadata = [PlexShowMetadata(**metadata) if isinstance(metadata, dict) else metadata for metadata in self.Metadata]
408
+
409
+ @dataclass_json(undefined=Undefined.EXCLUDE)
410
+ @dataclass
411
+ class PlexSeasonMetadata:
412
+ """
413
+ Represents the metadata for a season in Plex.
414
+
415
+ Attributes:
416
+ art (Optional[str]): The URL of the artwork for the season.
417
+ guid (Optional[str]): The unique identifier of the season.
418
+ key (Optional[str]): The key of the season.
419
+ primaryExtraKey (Optional[str]): The key of the primary extra associated with the season.
420
+ ratingKey (Optional[str]): The rating key of the season.
421
+ summary (Optional[str]): The summary of the season.
422
+ type (Optional[str]): The type of the season.
423
+ thumb (Optional[str]): The URL of the thumbnail for the season.
424
+ addedAt (Optional[int]): The timestamp when the season was added.
425
+ publicPagesURL (Optional[str]): The public pages URL for the season.
426
+ userState (Optional[bool]): The user state of the season.
427
+ title (Optional[str]): The title of the season.
428
+ parentSlug (Optional[str]): The slug of the parent item.
429
+ parentTitle (Optional[str]): The title of the parent item.
430
+ parentType (Optional[str]): The type of the parent item.
431
+ parentArt (Optional[str]): The URL of the artwork for the parent item.
432
+ parentThumb (Optional[str]): The URL of the thumbnail for the parent item.
433
+ parentRatingKey (Optional[str]): The rating key of the parent item.
434
+ parentGuid (Optional[str]): The unique identifier of the parent item.
435
+ parentKey (Optional[str]): The key of the parent item.
436
+ leafCount (Optional[int]): The number of leaf items in the season.
437
+ index (Optional[int]): The index of the season.
438
+ contentRating (Optional[str]): The content rating of the season.
439
+ originallyAvailableAt (Optional[str]): The original release date of the season.
440
+ year (Optional[int]): The year of the season.
441
+ source (Optional[str]): The source of the season.
442
+ Image (Optional[List[PlexImage]]): The list of images associated with the season.
443
+ Guid (Optional[List[PlexGuid]]): The list of GUIDs associated with the season.
444
+ Role (Optional[List[PlexRole]]): The list of roles associated with the season.
445
+ Producer (Optional[List[PlexProducer]]): The list of producers associated with the season.
446
+ _catchall (dict): A catch-all field for any additional attributes not defined in the class.
447
+
448
+ Methods:
449
+ __post_init__: Initializes the class and converts nested dictionaries to objects.
450
+ """
451
+
452
+ art: Optional[str] = None
453
+ guid: Optional[str] = None
454
+ key: Optional[str] = None
455
+ primaryExtraKey: Optional[str] = None
456
+ ratingKey: Optional[str] = None
457
+ summary: Optional[str] = None
458
+ type: Optional[str] = None
459
+ thumb: Optional[str] = None
460
+ addedAt: Optional[int] = None
461
+ publicPagesURL: Optional[str] = None
462
+ userState: Optional[bool] = None
463
+ title: Optional[str] = None
464
+ parentSlug: Optional[str] = None
465
+ parentTitle: Optional[str] = None
466
+ parentType: Optional[str] = None
467
+ parentArt: Optional[str] = None
468
+ parentThumb: Optional[str] = None
469
+ parentRatingKey: Optional[str] = None
470
+ parentGuid: Optional[str] = None
471
+ parentKey: Optional[str] = None
472
+ leafCount: Optional[int] = None
473
+ index: Optional[int] = None
474
+ contentRating: Optional[str] = None
475
+ originallyAvailableAt: Optional[str] = None
476
+ year: Optional[int] = None
477
+ source: Optional[str] = None
478
+ Image: Optional[List[PlexImage]] = None
479
+ Guid: Optional[List[PlexGuid]] = None
480
+ Role: Optional[List[PlexRole]] = None
481
+ Producer: Optional[List[PlexProducer]] = None
482
+ _catchall: dict = field(default_factory=dict)
483
+
484
+ def __post_init__(self):
485
+ """
486
+ Initializes the PlexSeasonMetadata class and converts nested dictionaries to objects.
487
+ """
488
+ self.Image = [PlexImage(**image) if isinstance(image, dict) else image for image in self.Image]
489
+ self.Guid = [PlexGuid(**guid) if isinstance(guid, dict) else guid for guid in self.Guid]
490
+ self.Role = [PlexRole(**role) if isinstance(role, dict) else role for role in self.Role] if self.Role else []
491
+ self.Producer = [PlexProducer(**producer) if isinstance(producer, dict) else producer for producer in self.Producer] if self.Producer else []
492
+
493
+ @dataclass_json(undefined=Undefined.EXCLUDE)
494
+ @dataclass
495
+ class SeasonMediaContainer:
496
+ """
497
+ Represents a media container for a season in Plex.
498
+
499
+ Attributes:
500
+ offset (Optional[int]): The offset value.
501
+ totalSize (Optional[int]): The total size value.
502
+ identifier (Optional[str]): The identifier value.
503
+ size (Optional[int]): The size value.
504
+ Metadata (Optional[List[PlexSeasonMetadata]]): A list of PlexSeasonMetadata objects.
505
+ _catchall (dict): A catch-all dictionary for additional attributes.
506
+
507
+ Methods:
508
+ __post_init__(): Initializes the SeasonMediaContainer object and converts the Metadata list to PlexSeasonMetadata objects.
509
+ """
510
+ offset: Optional[int] = None
511
+ totalSize: Optional[int] = None
512
+ identifier: Optional[str] = None
513
+ size: Optional[int] = None
514
+ Metadata: Optional[List[PlexSeasonMetadata]] = None
515
+ _catchall: dict = field(default_factory=dict)
516
+
517
+ def __post_init__(self):
518
+ self.Metadata = [PlexSeasonMetadata(**metadata) if isinstance(metadata, dict) else metadata for metadata in self.Metadata]
519
+
520
+
521
+ @dataclass_json(undefined=Undefined.EXCLUDE)
522
+ @dataclass
523
+ class PlexEpisodeMetadata:
524
+ """
525
+ Represents the metadata for a Plex episode.
526
+
527
+ Attributes:
528
+ guid (Optional[str]): The unique identifier for the episode.
529
+ key (Optional[str]): The key of the episode.
530
+ rating (Optional[int]): The rating of the episode.
531
+ ratingKey (Optional[str]): The rating key of the episode.
532
+ summary (Optional[str]): The summary of the episode.
533
+ type (Optional[str]): The type of the episode.
534
+ thumb (Optional[str]): The thumbnail image URL of the episode.
535
+ addedAt (Optional[int]): The timestamp when the episode was added.
536
+ duration (Optional[int]): The duration of the episode in seconds.
537
+ publicPagesURL (Optional[str]): The public pages URL of the episode.
538
+ userState (Optional[bool]): The user state of the episode.
539
+ title (Optional[str]): The title of the episode.
540
+ grandparentTitle (Optional[str]): The title of the grandparent of the episode.
541
+ grandparentSlug (Optional[str]): The slug of the grandparent of the episode.
542
+ grandparentType (Optional[str]): The type of the grandparent of the episode.
543
+ grandparentArt (Optional[str]): The artwork URL of the grandparent of the episode.
544
+ grandparentThumb (Optional[str]): The thumbnail image URL of the grandparent of the episode.
545
+ grandparentRatingKey (Optional[str]): The rating key of the grandparent of the episode.
546
+ grandparentGuid (Optional[str]): The guid of the grandparent of the episode.
547
+ grandparentKey (Optional[str]): The key of the grandparent of the episode.
548
+ parentTitle (Optional[str]): The title of the parent of the episode.
549
+ parentType (Optional[str]): The type of the parent of the episode.
550
+ parentArt (Optional[str]): The artwork URL of the parent of the episode.
551
+ parentThumb (Optional[str]): The thumbnail image URL of the parent of the episode.
552
+ parentRatingKey (Optional[str]): The rating key of the parent of the episode.
553
+ parentGuid (Optional[str]): The guid of the parent of the episode.
554
+ parentKey (Optional[str]): The key of the parent of the episode.
555
+ index (Optional[int]): The index of the episode.
556
+ parentIndex (Optional[int]): The index of the parent of the episode.
557
+ contentRating (Optional[str]): The content rating of the episode.
558
+ originallyAvailableAt (Optional[str]): The original release date of the episode.
559
+ year (Optional[int]): The year of the episode.
560
+ ratingImage (Optional[str]): The rating image URL of the episode.
561
+ source (Optional[str]): The source of the episode.
562
+ Image (Optional[List[PlexImage]]): The list of images associated with the episode.
563
+ Guid (Optional[List[PlexGuid]]): The list of GUIDs associated with the episode.
564
+ Role (Optional[List[PlexRole]]): The list of roles associated with the episode.
565
+ Director (Optional[List[PlexDirector]]): The list of directors associated with the episode.
566
+ Writer (Optional[List[PlexWriter]]): The list of writers associated with the episode.
567
+ Rating (Optional[List[PlexRating]]): The list of ratings associated with the episode.
568
+ _catchall (dict): A catch-all dictionary for additional attributes.
569
+
570
+ Methods:
571
+ __post_init__(): Initializes the PlexEpisodeMetadata object and converts the Image, Guid, Role, Director, Writer, and Rating lists to their respective objects.
572
+ """
573
+
574
+ guid: Optional[str] = None
575
+ key: Optional[str] = None
576
+ rating: Optional[int] = None
577
+ ratingKey: Optional[str] = None
578
+ summary: Optional[str] = None
579
+ type: Optional[str] = None
580
+ thumb: Optional[str] = None
581
+ addedAt: Optional[int] = None
582
+ duration: Optional[int] = None
583
+ publicPagesURL: Optional[str] = None
584
+ userState: Optional[bool] = None
585
+ title: Optional[str] = None
586
+ grandparentTitle: Optional[str] = None
587
+ grandparentSlug: Optional[str] = None
588
+ grandparentType: Optional[str] = None
589
+ grandparentArt: Optional[str] = None
590
+ grandparentThumb: Optional[str] = None
591
+ grandparentRatingKey: Optional[str] = None
592
+ grandparentGuid: Optional[str] = None
593
+ grandparentKey: Optional[str] = None
594
+ parentTitle: Optional[str] = None
595
+ parentType: Optional[str] = None
596
+ parentArt: Optional[str] = None
597
+ parentThumb: Optional[str] = None
598
+ parentRatingKey: Optional[str] = None
599
+ parentGuid: Optional[str] = None
600
+ parentKey: Optional[str] = None
601
+ index: Optional[int] = None
602
+ parentIndex: Optional[int] = None
603
+ contentRating: Optional[str] = None
604
+ originallyAvailableAt: Optional[str] = None
605
+ year: Optional[int] = None
606
+ ratingImage: Optional[str] = None
607
+ source: Optional[str] = None
608
+ Image: Optional[List[PlexImage]] = None
609
+ Guid: Optional[List[PlexGuid]] = None
610
+ Role: Optional[List[PlexRole]] = None
611
+ Director: Optional[List[PlexDirector]] = None
612
+ Writer: Optional[List[PlexWriter]] = None
613
+ Rating: Optional[List[PlexRating]] = None
614
+ _catchall: dict = field(default_factory=dict)
615
+
616
+ def __post_init__(self):
617
+ self.Image = [PlexImage(**image) if isinstance(image, dict) else image for image in self.Image]
618
+ self.Guid = [PlexGuid(**guid) if isinstance(guid, dict) else guid for guid in self.Guid]
619
+ self.Role = [PlexRole(**role) if isinstance(role, dict) else role for role in self.Role] if self.Role else []
620
+ self.Director = [PlexDirector(**director) if isinstance(director, dict) else director for director in self.Director] if self.Director else []
621
+ self.Writer = [PlexWriter(**writer) if isinstance(writer, dict) else writer for writer in self.Writer] if self.Writer else []
622
+ self.Rating = [PlexRating(**rating) if isinstance(rating, dict) else rating for rating in self.Rating] if self.Rating else []
623
+
624
+ @dataclass_json(undefined=Undefined.EXCLUDE)
625
+ @dataclass
626
+ class EpisodeMediaContainer:
627
+ """
628
+ Represents a container for episode media information.
629
+
630
+ Attributes:
631
+ offset (Optional[int]): The offset value.
632
+ totalSize (Optional[int]): The total size value.
633
+ identifier (Optional[str]): The identifier value.
634
+ size (Optional[int]): The size value.
635
+ Metadata (Optional[List[PlexEpisodeMetadata]]): A list of PlexEpisodeMetadata objects.
636
+ _catchall (dict): A catch-all dictionary for additional attributes.
637
+
638
+ Methods:
639
+ __post_init__(): Initializes the EpisodeMediaContainer object and processes the Metadata attribute.
640
+ """
641
+ offset: Optional[int] = None
642
+ totalSize: Optional[int] = None
643
+ identifier: Optional[str] = None
644
+ size: Optional[int] = None
645
+ Metadata: Optional[List[PlexEpisodeMetadata]] = None
646
+ _catchall: dict = field(default_factory=dict)
647
+
648
+ def __post_init__(self):
649
+ self.Metadata = [PlexEpisodeMetadata(**metadata) if isinstance(metadata, dict) else metadata for metadata in self.Metadata]
650
+
651
+
652
+ @dataclass_json(undefined=Undefined.EXCLUDE)
653
+ @dataclass
654
+ class PlexUserState:
655
+ """
656
+ Represents the state of a Plex user for a specific media item.
657
+
658
+ Attributes:
659
+ grandparentWatchlistedAt (Optional[int]): The timestamp when the media item was watchlisted by the user.
660
+ viewCount (Optional[int]): The number of times the user has viewed the media item.
661
+ viewOffset (Optional[int]): The playback position (in milliseconds) where the user left off in the media item.
662
+ lastViewedAt (Optional[int]): The timestamp when the user last viewed the media item.
663
+ """
664
+ grandparentWatchlistedAt: Optional[int] = None
665
+ viewCount: Optional[int] = None
666
+ viewOffset: Optional[int] = None
667
+ lastViewedAt: Optional[int] = None
668
+ viewState: Optional[str] = None
669
+ ratingKey: Optional[str] = None
670
+ type: Optional[str] = None
671
+ _catchall: dict = field(default_factory=dict)
672
+
673
+ @dataclass_json(undefined=Undefined.EXCLUDE)
674
+ @dataclass
675
+ class WatchStateMediaContainer:
676
+ """
677
+ Represents the watch state of a media container in Plex.
678
+
679
+ Attributes:
680
+ identifier (Optional[str]): The identifier of the media container.
681
+ size (Optional[int]): The size of the media container.
682
+ UserState (Optional[PlexUserState]): The user state of the media container.
683
+ _catchall (dict): A catch-all field for any additional attributes.
684
+ """
685
+
686
+ identifier: Optional[str] = None
687
+ size: Optional[int] = None
688
+ UserState: Optional[PlexUserState] = None
689
+ _catchall: dict = field(default_factory=dict)
690
+
691
+ def __post_init__(self):
692
+ if isinstance(self.UserState, dict):
693
+ self.UserState = PlexUserState(**self.UserState)