ChandimaPrabath commited on
Commit
bdb91bb
1 Parent(s): 02fc71e
Files changed (3) hide show
  1. Instance.py +8 -14
  2. app.backup.py +0 -368
  3. tvdb.py +0 -70
Instance.py CHANGED
@@ -195,8 +195,7 @@ class Instance:
195
  return {"total": total, "downloaded": downloaded, "progress": progress, "status": status, "eta": eta}
196
  return {"total": 0, "downloaded": 0, "progress": 0, "status": "Not Found", "eta": None}
197
 
198
- @staticmethod
199
- def update_film_store_json(title, cache_path):
200
  """
201
  Updates the film store JSON with the new file.
202
 
@@ -204,16 +203,14 @@ class Instance:
204
  title (str): The title of the film.
205
  cache_path (str): The local path where the file is saved.
206
  """
207
- FILM_STORE_JSON_PATH = os.path.join(CACHE_DIR, "film_store.json")
208
-
209
  film_store_data = {}
210
- if os.path.exists(FILM_STORE_JSON_PATH):
211
- with open(FILM_STORE_JSON_PATH, 'r') as json_file:
212
  film_store_data = json.load(json_file)
213
 
214
  film_store_data[title] = cache_path
215
 
216
- with open(FILM_STORE_JSON_PATH, 'w') as json_file:
217
  json.dump(film_store_data, json_file, indent=2)
218
  print(f'Film store updated with {title}.')
219
 
@@ -261,8 +258,7 @@ class Instance:
261
  if download_progress[episode_id]["status"] != "Downloading":
262
  download_progress[episode_id]["end_time"] = time.time()
263
 
264
- @staticmethod
265
- def update_tv_store_json(title, cache_path):
266
  """
267
  Updates the TV store JSON with the new file, organizing by title, season, and episode.
268
 
@@ -270,11 +266,9 @@ class Instance:
270
  title (str): The title of the TV show.
271
  cache_path (str): The local path where the file is saved.
272
  """
273
- TV_STORE_JSON_PATH = os.path.join(CACHE_DIR, "tv_store.json")
274
-
275
  tv_store_data = {}
276
- if os.path.exists(TV_STORE_JSON_PATH):
277
- with open(TV_STORE_JSON_PATH, 'r') as json_file:
278
  tv_store_data = json.load(json_file)
279
 
280
  # Extract season and episode information from the cache_path
@@ -291,7 +285,7 @@ class Instance:
291
  # Assuming episode_part is unique for each episode within a season
292
  tv_store_data[title][season_part][episode_part] = cache_path
293
 
294
- with open(TV_STORE_JSON_PATH, 'w') as json_file:
295
  json.dump(tv_store_data, json_file, indent=2)
296
 
297
  print(f'TV store updated with {title}, {season_part}, {episode_part}.')
 
195
  return {"total": total, "downloaded": downloaded, "progress": progress, "status": status, "eta": eta}
196
  return {"total": 0, "downloaded": 0, "progress": 0, "status": "Not Found", "eta": None}
197
 
198
+ def update_film_store_json(self,title, cache_path):
 
199
  """
200
  Updates the film store JSON with the new file.
201
 
 
203
  title (str): The title of the film.
204
  cache_path (str): The local path where the file is saved.
205
  """
 
 
206
  film_store_data = {}
207
+ if os.path.exists(self.FILM_STORE_JSON_PATH):
208
+ with open(self.FILM_STORE_JSON_PATH, 'r') as json_file:
209
  film_store_data = json.load(json_file)
210
 
211
  film_store_data[title] = cache_path
212
 
213
+ with open(self.FILM_STORE_JSON_PATH, 'w') as json_file:
214
  json.dump(film_store_data, json_file, indent=2)
215
  print(f'Film store updated with {title}.')
216
 
 
258
  if download_progress[episode_id]["status"] != "Downloading":
259
  download_progress[episode_id]["end_time"] = time.time()
260
 
261
+ def update_tv_store_json(self, title, cache_path):
 
262
  """
263
  Updates the TV store JSON with the new file, organizing by title, season, and episode.
264
 
 
266
  title (str): The title of the TV show.
267
  cache_path (str): The local path where the file is saved.
268
  """
 
 
269
  tv_store_data = {}
270
+ if os.path.exists(self.TV_STORE_JSON_PATH):
271
+ with open(self.TV_STORE_JSON_PATH, 'r') as json_file:
272
  tv_store_data = json.load(json_file)
273
 
274
  # Extract season and episode information from the cache_path
 
285
  # Assuming episode_part is unique for each episode within a season
286
  tv_store_data[title][season_part][episode_part] = cache_path
287
 
288
+ with open(self.TV_STORE_JSON_PATH, 'w') as json_file:
289
  json.dump(tv_store_data, json_file, indent=2)
290
 
291
  print(f'TV store updated with {title}, {season_part}, {episode_part}.')
app.backup.py DELETED
@@ -1,368 +0,0 @@
1
- from flask import Flask, jsonify, request, send_from_directory
2
- from flask_cors import CORS
3
- import os
4
- import json
5
- import threading
6
- import urllib.parse
7
- from hf_scrapper import download_film, download_episode, get_system_proxies, get_download_progress
8
- from indexer import indexer
9
- from tvdb import fetch_and_cache_json
10
- import re
11
-
12
- app = Flask(__name__)
13
- CORS(app)
14
-
15
- # Constants and Configuration
16
- CACHE_DIR = os.getenv("CACHE_DIR")
17
- INDEX_FILE = os.getenv("INDEX_FILE")
18
- TOKEN = os.getenv("TOKEN")
19
- FILM_STORE_JSON_PATH = os.path.join(CACHE_DIR, "film_store.json")
20
- TV_STORE_JSON_PATH = os.path.join(CACHE_DIR, "tv_store.json")
21
- REPO = os.getenv("REPO")
22
- download_threads = {}
23
-
24
- # Ensure CACHE_DIR exists
25
- if not os.path.exists(CACHE_DIR):
26
- os.makedirs(CACHE_DIR)
27
-
28
- for path in [FILM_STORE_JSON_PATH, TV_STORE_JSON_PATH]:
29
- if not os.path.exists(path):
30
- with open(path, 'w') as json_file:
31
- json.dump({}, json_file)
32
-
33
- # Index the file structure
34
- indexer()
35
-
36
- # Load the file structure JSON
37
- if not os.path.exists(INDEX_FILE):
38
- raise FileNotFoundError(f"{INDEX_FILE} not found. Please make sure the file exists.")
39
-
40
- with open(INDEX_FILE, 'r') as f:
41
- file_structure = json.load(f)
42
-
43
- # Function Definitions
44
-
45
- def load_json(file_path):
46
- """Load JSON data from a file."""
47
- with open(file_path, 'r') as file:
48
- return json.load(file)
49
-
50
- def find_movie_path(json_data, title):
51
- """Find the path of the movie in the JSON data based on the title."""
52
- for directory in json_data:
53
- if directory['type'] == 'directory' and directory['path'] == 'films':
54
- for sub_directory in directory['contents']:
55
- if sub_directory['type'] == 'directory':
56
- for item in sub_directory['contents']:
57
- if item['type'] == 'file' and title.lower() in item['path'].lower():
58
- return item['path']
59
- return None
60
-
61
- def find_tv_path(json_data, title):
62
- """Find the path of the TV show in the JSON data based on the title."""
63
- for directory in json_data:
64
- if directory['type'] == 'directory' and directory['path'] == 'tv':
65
- for sub_directory in directory['contents']:
66
- if sub_directory['type'] == 'directory' and title.lower() in sub_directory['path'].lower():
67
- return sub_directory['path']
68
- return None
69
-
70
- def get_tv_structure(json_data,title):
71
- """Find the path of the TV show in the JSON data based on the title."""
72
- for directory in json_data:
73
- if directory['type'] == 'directory' and directory['path'] == 'tv':
74
- for sub_directory in directory['contents']:
75
- if sub_directory['type'] == 'directory' and title.lower() in sub_directory['path'].lower():
76
- return sub_directory
77
- return None
78
-
79
- def get_film_id(title):
80
- """Generate a film ID based on the title."""
81
- return title.replace(" ", "_").lower()
82
-
83
- def prefetch_metadata():
84
- """Prefetch metadata for all items in the file structure."""
85
- for item in file_structure:
86
- if 'contents' in item:
87
- for sub_item in item['contents']:
88
- original_title = sub_item['path'].split('/')[-1]
89
- media_type = 'series' if item['path'].startswith('tv') else 'movie'
90
- title = original_title
91
- year = None
92
-
93
- # Extract year from the title if available
94
- match = re.search(r'\((\d{4})\)', original_title)
95
- if match:
96
- year_str = match.group(1)
97
- if year_str.isdigit() and len(year_str) == 4:
98
- title = original_title[:match.start()].strip()
99
- year = int(year_str)
100
- else:
101
- parts = original_title.rsplit(' ', 1)
102
- if len(parts) > 1 and parts[-1].isdigit() and len(parts[-1]) == 4:
103
- title = parts[0].strip()
104
- year = int(parts[-1])
105
-
106
- fetch_and_cache_json(original_title, title, media_type, year)
107
-
108
- def bytes_to_human_readable(num, suffix="B"):
109
- for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]:
110
- if abs(num) < 1024.0:
111
- return f"{num:3.1f} {unit}{suffix}"
112
- num /= 1024.0
113
- return f"{num:.1f} Y{suffix}"
114
-
115
- def encode_episodeid(title,season,episode):
116
- return f"{title}_{season}_{episode}"
117
-
118
- def get_all_tv_shows(indexed_cache):
119
- """Get all TV shows from the indexed cache structure JSON file."""
120
- tv_shows = {}
121
- for directory in indexed_cache:
122
- if directory['type'] == 'directory' and directory['path'] == 'tv':
123
- for sub_directory in directory['contents']:
124
- if sub_directory['type'] == 'directory':
125
- show_title = sub_directory['path'].split('/')[-1]
126
- tv_shows[show_title] = []
127
- for season_directory in sub_directory['contents']:
128
- if season_directory['type'] == 'directory':
129
- season = season_directory['path'].split('/')[-1]
130
- for episode in season_directory['contents']:
131
- if episode['type'] == 'file':
132
- tv_shows[show_title].append({
133
- "season": season,
134
- "episode": episode['path'].split('/')[-1],
135
- "path": episode['path']
136
- })
137
- return tv_shows
138
-
139
- def get_all_films(indexed_cache):
140
- """Get all films from the indexed cache structure JSON file."""
141
- films = []
142
- for directory in indexed_cache:
143
- if directory['type'] == 'directory' and directory['path'] == 'films':
144
- for sub_directory in directory['contents']:
145
- if sub_directory['type'] == 'directory':
146
- films.append(sub_directory['path'])
147
- return films
148
-
149
- def start_prefetching():
150
- """Start the metadata prefetching in a separate thread."""
151
- prefetch_metadata()
152
-
153
- # Start prefetching metadata
154
- thread = threading.Thread(target=start_prefetching)
155
- thread.daemon = True
156
- thread.start()
157
-
158
- # API Endpoints
159
-
160
- @app.route('/api/film', methods=['GET'])
161
- def get_movie_api():
162
- """Endpoint to get the movie by title."""
163
- title = request.args.get('title')
164
- if not title:
165
- return jsonify({"error": "Title parameter is required"}), 400
166
-
167
- # Load the film store JSON
168
- with open(FILM_STORE_JSON_PATH, 'r') as json_file:
169
- film_store_data = json.load(json_file)
170
-
171
- # Check if the film is already cached
172
- if title in film_store_data:
173
- cache_path = film_store_data[title]
174
- if os.path.exists(cache_path):
175
- return send_from_directory(os.path.dirname(cache_path), os.path.basename(cache_path))
176
-
177
- movie_path = find_movie_path(file_structure, title)
178
-
179
- if not movie_path:
180
- return jsonify({"error": "Movie not found"}), 404
181
-
182
- cache_path = os.path.join(CACHE_DIR, movie_path)
183
- file_url = f"https://huggingface.co/{REPO}/resolve/main/{movie_path}"
184
- proxies = get_system_proxies()
185
- film_id = get_film_id(title)
186
-
187
- # Start the download in a separate thread if not already downloading
188
- if film_id not in download_threads or not download_threads[film_id].is_alive():
189
- thread = threading.Thread(target=download_film, args=(file_url, TOKEN, cache_path, proxies, film_id, title))
190
- download_threads[film_id] = thread
191
- thread.start()
192
-
193
- return jsonify({"status": "Download started", "film_id": film_id})
194
-
195
- @app.route('/api/tv', methods=['GET'])
196
- def get_tv_show_api():
197
- """Endpoint to get the TV show by title, season, and episode."""
198
- title = request.args.get('title')
199
- season = request.args.get('season')
200
- episode = request.args.get('episode')
201
-
202
- if not title or not season or not episode:
203
- return jsonify({"error": "Title, season, and episode parameters are required"}), 400
204
-
205
- # Load the TV store JSON
206
- with open(TV_STORE_JSON_PATH, 'r') as json_file:
207
- tv_store_data = json.load(json_file)
208
-
209
- # Check if the episode is already cached
210
- if title in tv_store_data and season in tv_store_data[title]:
211
- for ep in tv_store_data[title][season]:
212
- if episode in ep:
213
- cache_path = tv_store_data[title][season][ep]
214
- if os.path.exists(cache_path):
215
- return send_from_directory(os.path.dirname(cache_path), os.path.basename(cache_path))
216
-
217
- tv_path = find_tv_path(file_structure, title)
218
-
219
- if not tv_path:
220
- return jsonify({"error": "TV show not found"}), 404
221
-
222
- episode_path = None
223
- for directory in file_structure:
224
- if directory['type'] == 'directory' and directory['path'] == 'tv':
225
- for sub_directory in directory['contents']:
226
- if sub_directory['type'] == 'directory' and title.lower() in sub_directory['path'].lower():
227
- for season_dir in sub_directory['contents']:
228
- if season_dir['type'] == 'directory' and season in season_dir['path']:
229
- for episode_file in season_dir['contents']:
230
- if episode_file['type'] == 'file' and episode in episode_file['path']:
231
- episode_path = episode_file['path']
232
- break
233
-
234
- if not episode_path:
235
- return jsonify({"error": "Episode not found"}), 404
236
-
237
- cache_path = os.path.join(CACHE_DIR, episode_path)
238
- file_url = f"https://huggingface.co/{REPO}/resolve/main/{episode_path}"
239
- proxies = get_system_proxies()
240
- episode_id = encode_episodeid(title,season,episode)
241
-
242
- # Start the download in a separate thread if not already downloading
243
- if episode_id not in download_threads or not download_threads[episode_id].is_alive():
244
- thread = threading.Thread(target=download_episode, args=(file_url, TOKEN, cache_path, proxies, episode_id, title))
245
- download_threads[episode_id] = thread
246
- thread.start()
247
-
248
- return jsonify({"status": "Download started", "episode_id": episode_id})
249
-
250
-
251
- @app.route('/api/progress/<id>', methods=['GET'])
252
- def get_progress_api(id):
253
- """Endpoint to get the download progress of a movie or TV show episode."""
254
- progress = get_download_progress(id)
255
- return jsonify({"id": id, "progress": progress})
256
-
257
- @app.route('/api/filmid', methods=['GET'])
258
- def get_film_id_by_title_api():
259
- """Endpoint to get the film ID by providing the movie title."""
260
- title = request.args.get('title')
261
- if not title:
262
- return jsonify({"error": "Title parameter is required"}), 400
263
- film_id = get_film_id(title)
264
- return jsonify({"film_id": film_id})
265
-
266
- @app.route('/api/episodeid', methods=['GET'])
267
- def get_episode_id_api():
268
- """Endpoint to get the episode ID by providing the TV show title, season, and episode."""
269
- title = request.args.get('title')
270
- season = request.args.get('season')
271
- episode = request.args.get('episode')
272
- if not title or not season or not episode:
273
- return jsonify({"error": "Title, season, and episode parameters are required"}), 400
274
- episode_id = encode_episodeid(title,season,episode)
275
- return jsonify({"episode_id": episode_id})
276
-
277
- @app.route('/api/cache/size', methods=['GET'])
278
- def get_cache_size_api():
279
- total_size = 0
280
- for dirpath, dirnames, filenames in os.walk(CACHE_DIR):
281
- for f in filenames:
282
- fp = os.path.join(dirpath, f)
283
- total_size += os.path.getsize(fp)
284
- readable_size = bytes_to_human_readable(total_size)
285
- return jsonify({"cache_size": readable_size})
286
-
287
- @app.route('/api/cache/clear', methods=['POST'])
288
- def clear_cache_api():
289
- for dirpath, dirnames, filenames in os.walk(CACHE_DIR):
290
- for f in filenames:
291
- fp = os.path.join(dirpath, f)
292
- os.remove(fp)
293
- return jsonify({"status": "Cache cleared"})
294
-
295
- @app.route('/api/tv/store', methods=['GET'])
296
- def get_tv_store_api():
297
- """Endpoint to get the TV store JSON."""
298
- if os.path.exists(TV_STORE_JSON_PATH):
299
- with open(TV_STORE_JSON_PATH, 'r') as json_file:
300
- tv_store_data = json.load(json_file)
301
- return jsonify(tv_store_data)
302
- return jsonify({}), 404
303
-
304
- @app.route('/api/film/store', methods=['GET'])
305
- def get_film_store_api():
306
- """Endpoint to get the film store JSON."""
307
- if os.path.exists(FILM_STORE_JSON_PATH):
308
- with open(FILM_STORE_JSON_PATH, 'r') as json_file:
309
- tv_store_data = json.load(json_file)
310
- return jsonify(tv_store_data)
311
- return jsonify({}), 404
312
-
313
- @app.route('/api/film/metadata', methods=['GET'])
314
- def get_film_metadata_api():
315
- """Endpoint to get the film metadata by title."""
316
- title = request.args.get('title')
317
- if not title:
318
- return jsonify({'error': 'No title provided'}), 400
319
-
320
- json_cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(title)}.json")
321
-
322
- if os.path.exists(json_cache_path):
323
- with open(json_cache_path, 'r') as f:
324
- data = json.load(f)
325
- return jsonify(data)
326
-
327
- return jsonify({'error': 'Metadata not found'}), 404
328
-
329
- @app.route('/api/tv/metadata', methods=['GET'])
330
- def get_tv_metadata_api():
331
- """Endpoint to get the TV show metadata by title."""
332
- title = request.args.get('title')
333
- if not title:
334
- return jsonify({'error': 'No title provided'}), 400
335
-
336
- json_cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(title)}.json")
337
-
338
- if os.path.exists(json_cache_path):
339
- with open(json_cache_path, 'r') as f:
340
- data = json.load(f)
341
-
342
- # Add the file structure to the metadata
343
- tv_structure_data = get_tv_structure(file_structure, title)
344
- if tv_structure_data:
345
- data['file_structure'] = tv_structure_data
346
-
347
- return jsonify(data)
348
-
349
- return jsonify({'error': 'Metadata not found'}), 404
350
-
351
-
352
- @app.route("/api/film/all")
353
- def get_all_films_api():
354
- return get_all_films(file_structure)
355
-
356
- @app.route("/api/tv/all")
357
- def get_all_tvshows_api():
358
- return get_all_tv_shows(file_structure)
359
-
360
-
361
- # Routes
362
- @app.route('/')
363
- def index():
364
- return "Server Running ..."
365
-
366
- # Main entry point
367
- if __name__ == "__main__":
368
- app.run(debug=True, host="0.0.0.0", port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tvdb.py DELETED
@@ -1,70 +0,0 @@
1
- # tvdb.py
2
- import os
3
- import requests
4
- import urllib.parse
5
- from datetime import datetime, timedelta
6
- from dotenv import load_dotenv
7
- import json
8
- from hf_scrapper import get_system_proxies
9
-
10
- load_dotenv()
11
- THETVDB_API_KEY = os.getenv("THETVDB_API_KEY")
12
- THETVDB_API_URL = os.getenv("THETVDB_API_URL")
13
- CACHE_DIR = os.getenv("CACHE_DIR")
14
- TOKEN_EXPIRY = None
15
- THETVDB_TOKEN = None
16
-
17
-
18
- proxies = get_system_proxies()
19
-
20
- def authenticate_thetvdb():
21
- global THETVDB_TOKEN, TOKEN_EXPIRY
22
- auth_url = f"{THETVDB_API_URL}/login"
23
- auth_data = {
24
- "apikey": THETVDB_API_KEY
25
- }
26
- try:
27
- response = requests.post(auth_url, json=auth_data, proxies=proxies)
28
- response.raise_for_status()
29
- response_data = response.json()
30
- THETVDB_TOKEN = response_data['data']['token']
31
- TOKEN_EXPIRY = datetime.now() + timedelta(days=30)
32
- except requests.RequestException as e:
33
- print(f"Authentication failed: {e}")
34
- THETVDB_TOKEN = None
35
- TOKEN_EXPIRY = None
36
-
37
- def get_thetvdb_token():
38
- global THETVDB_TOKEN, TOKEN_EXPIRY
39
- if not THETVDB_TOKEN or datetime.now() >= TOKEN_EXPIRY:
40
- authenticate_thetvdb()
41
- return THETVDB_TOKEN
42
-
43
- def fetch_and_cache_json(original_title, title, media_type, year=None):
44
- if year:
45
- search_url = f"{THETVDB_API_URL}/search?query={urllib.parse.quote(title)}&type={media_type}&year={year}"
46
- else:
47
- search_url = f"{THETVDB_API_URL}/search?query={urllib.parse.quote(title)}&type={media_type}"
48
-
49
- token = get_thetvdb_token()
50
- if not token:
51
- print("Authentication failed")
52
- return
53
-
54
- headers = {
55
- "Authorization": f"Bearer {token}",
56
- "accept": "application/json",
57
- }
58
-
59
- try:
60
- response = requests.get(search_url, headers=headers, proxies=proxies)
61
- response.raise_for_status()
62
- data = response.json()
63
-
64
- if 'data' in data and data['data']:
65
- json_cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(original_title)}.json")
66
- with open(json_cache_path, 'w') as f:
67
- json.dump(data, f)
68
-
69
- except requests.RequestException as e:
70
- print(f"Error fetching data: {e}")