Skip to content
This repository was archived by the owner on Jan 1, 2021. It is now read-only.

Commit 5ea2d43

Browse files
committed
Commit Initial Project
1 parent 648bf6e commit 5ea2d43

16 files changed

Lines changed: 165406 additions & 33 deletions

File tree

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
TMDBDUMP/*
2+
TMDBDUMP/**
3+
peewee/*
4+
peewee/**
5+
IMDBAPI.py
6+
ini.json
7+
**/IMDBAPI.py
8+
*.log
9+
*.pyc

.htaccess

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<Files "ini.json">
2+
Order Allow,Deny
3+
Deny from all
4+
</Files>

README.md

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,5 @@ Backend Stuff for Radarr regarding TMDB (Discover, lists, Mappings, etc.)
1111

1212
### Configuring the MySQL server to use with the API
1313

14-
After cloning the repo into the www folder of your webserver, create a file called ini.json in the following directory: `/path/to/www/../apps/radarr/ini/ini.json`.
15-
Your directory structure should now look as follows:
16-
```
17-
/ (root)
18-
path
19-
to
20-
-----------www
21-
RadarrApi.TMDB
22-
... (all of RadarrApi.TMDB source code)
23-
-----------apps
24-
radarr
25-
ini
26-
ini.json
27-
28-
```
29-
30-
Copy the following into your ini.json file and adjust it according to your mysql credentials:
31-
```
32-
{
33-
"tmdb_mysql" : {
34-
"url" : "localhost",
35-
"user" : "myuser",
36-
"pass" : "mypass",
37-
"db" : "tmdb_copy_database"
38-
},
39-
"tmdbt_mysql" : {
40-
"url" : "localhost",
41-
"user" : "myuser",
42-
"pass" : "mypass",
43-
"db" : "tmdbt_copy_database"
44-
}
45-
}
46-
```
14+
After cloning the repo into the www folder of your webserver, rename ini.sample.json to ini.json and edit it. There you can specify the mysql server connections to use.
4715
*Note: The second entry can safely point to the same database as the first one. It is only used for database maintanance on the main server*

TMDB2SQL.py

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# -*- coding: utf-8 -*-
2+
import os, glob
3+
import traceback
4+
import sys
5+
import re
6+
import threading
7+
import unicodedata
8+
try:
9+
import queue
10+
except:
11+
import Queue as queue
12+
from datetime import timedelta
13+
import time
14+
import json
15+
import peewee
16+
import tmdbdb
17+
db = tmdbdb.database
18+
19+
from tmdbdb import Movies, Recommendations, AlternativeTitles, ReleaseDates
20+
DIR = "TMDBDUMP"
21+
22+
normal_title_regex = re.compile(r"((?:\b|_)(?<!^)(a(?!$)|an|the|and|or|of)(?:\b|_))|\W|_", flags=re.IGNORECASE)
23+
24+
class Worker(threading.Thread):
25+
def __init__(self, q, *args, **kwargs):
26+
self.q = q
27+
super(Worker, self).__init__(*args, **kwargs)
28+
29+
def run(self):
30+
while True:
31+
try:
32+
work = get_multiple_from_queue(self.q) #self.q.get(timeout=3) # 3s timeout
33+
do_work(work)
34+
except queue.Empty:
35+
#self.q.task_done()
36+
return
37+
for w in work:
38+
self.q.task_done()
39+
# do whatever work you have to do on work
40+
#self.q.task_done()
41+
42+
class PopWorker(threading.Thread):
43+
def __init__(self, q, *args, **kwargs):
44+
self.q = q
45+
super(PopWorker, self).__init__(*args, **kwargs)
46+
47+
def run(self):
48+
while True:
49+
try:
50+
work = get_multiple_from_queue(self.q, 4) #self.q.get(timeout=3) # 3s timeout
51+
#do_work_pop(work)
52+
except queue.Empty:
53+
self.q.task_done()
54+
return
55+
for w in work:
56+
self.q.task_done()
57+
# do whatever work you have to do on work
58+
#self.q.task_done()
59+
60+
def get_multiple_from_queue(q, m = 100):
61+
work = []
62+
for x in range(0, m):
63+
try:
64+
work.append(q.get(timeout=1))
65+
except queue.Empty as e:
66+
if len(work) == 0:
67+
raise e
68+
else:
69+
return work
70+
71+
return work
72+
73+
def do_work_pop(pops):
74+
global db
75+
with db.transaction():
76+
for tmdbid, pop in pops:
77+
Movies.update(popularity=pop).where(Movies.id == tmdbid).execute()
78+
print("Updated popularity for movies {0} - {1}".format(pops[0], pops[len(pops)-1]))
79+
80+
def clean_title(title):
81+
global normal_title_regex
82+
if title.isdigit():
83+
return title
84+
85+
title = title.lower()
86+
title = title.replace("ä", "ae")
87+
title = title.replace("ö", "oe")
88+
title = title.replace("ü", "ue")
89+
title = title.replace("Ä", "Ae")
90+
title = title.replace("Ö", "Oe")
91+
title = title.replace("Ü", "Ue")
92+
title = title.replace("ß", "ss")
93+
title = unicodedata.normalize('NFD', unicode(title.decode("utf-8")))
94+
title = title.encode('ascii', 'ignore')
95+
title = title.decode("utf-8")
96+
title = normal_title_regex.sub(repl="", string=title)
97+
title = title.lower()
98+
99+
return title
100+
101+
102+
103+
104+
def do_work(files, tables = ["movies", "recommendations"]):
105+
insertion = []
106+
reco_insert = []
107+
alt_insert = []
108+
dates_insert = []
109+
ids = []
110+
for f in files:
111+
try:
112+
with open(f, "r") as res:
113+
try:
114+
jres = json.loads(res.read())
115+
if jres["id"] == None or jres["id"] == "" or jres["id"] == 0:
116+
raise KeyError()
117+
118+
for reco in jres["recommendations"]["results"]:
119+
reco_insert.append({"tmdbid" : jres["id"], "recommended" : reco["id"]})
120+
for alt in jres["alternative_titles"]["titles"]:
121+
alt_insert.append({"tmdbid" : jres["id"], "alternative_title" : alt["title"], "clean_alt_title" : clean_title(str(alt["title"].encode("utf-8"))), "iso_3166_1" : alt["iso_3166_1"]})
122+
for iso_3166 in jres["release_dates"]["results"]:
123+
for date in iso_3166["release_dates"]:
124+
note = ""
125+
if "note" in date:
126+
note = date["note"]
127+
dates_insert.append({"tmdbid" : jres["id"], "iso_3166_1" : iso_3166["iso_3166_1"], "iso_639_1" : date["iso_639_1"], "certification" : date["certification"], "note" : note, "release_date" : date["release_date"], "release_type" : date["type"]})
128+
#print(jres["id"])
129+
ids.append(jres["id"])
130+
release_date = jres["release_date"]
131+
if release_date == "":
132+
print("No release date for movie: {0}".format(jres["title"]))
133+
trailer = (None, None)
134+
for video in jres["videos"]["results"]:
135+
if "trailer" in video["type"].lower() or "teaser" in video["type"].lower():
136+
trailer = (video["key"], video["site"].lower())
137+
genres = []
138+
for genre in jres["genres"]:
139+
genres.append(str(genre["id"]))
140+
insertion.append({"id" : jres["id"], "title" : jres["title"], "imdb_id" : jres["imdb_id"],
141+
"release_date" : release_date, "release_year" : release_date[0:4], "overview" : jres["overview"],
142+
"vote_count" : jres["vote_count"], "vote_average" : jres["vote_average"], "tagline" : jres["tagline"],
143+
"poster_path" : jres["poster_path"], "trailer_key" : trailer[0], "trailer_site" : trailer[1],
144+
"backdrop_path" : jres["backdrop_path"], "homepage" : jres["homepage"], "popularity" : jres["popularity"],
145+
"runtime" : jres["runtime"], "genres" : ",".join(genres), "clean_title" : clean_title(str(jres["title"].encode("utf-8")))})
146+
except Exception as e:
147+
#print(traceback.format_exc())
148+
#print("Invalid json for file: {0}".format(f))
149+
with open("invalid_files.txt", "a") as invalid_files:
150+
invalid_files.write(f + "\n")
151+
except Exception as e:
152+
#print(traceback.format_exc())
153+
ids.append(int(f.replace("TMDBDUMP/", "").replace(".json", "")))
154+
155+
try:
156+
if len(insertion) > 0:
157+
Movies.delete().where(Movies.id << ids).execute()
158+
Movies.insert_many(insertion).execute()
159+
if len(reco_insert) > 0:
160+
Recommendations.delete().where(Recommendations.tmdbid << ids).execute()
161+
Recommendations.insert_many(reco_insert).execute()
162+
if len(alt_insert) > 0:
163+
AlternativeTitles.delete().where(AlternativeTitles.tmdbid << ids).execute()
164+
AlternativeTitles.insert_many(alt_insert).execute()
165+
if len(dates_insert) > 0:
166+
ReleaseDates.delete().where(ReleaseDates.tmdbid << ids).execute()
167+
ReleaseDates.insert_many(dates_insert).execute()
168+
except Exception as e:
169+
print(e)
170+
print("Pushed movies {0} to {1}".format(files[0], files[len(files)-1]))
171+
172+
def add_all_to_db(limit = 2861730):
173+
q = queue.Queue()
174+
for f in sorted(glob.glob(DIR+"/*.json"), key=lambda name: int(name.replace(DIR + "/", "").replace(".json", "")))[0:limit+1]:
175+
q.put_nowait(f)
176+
177+
for _ in range(10):
178+
Worker(q).start()
179+
180+
try:
181+
q.join()
182+
except Exception as e:
183+
with q.mutex:
184+
q.queue.clear()
185+
raise e
186+
187+
def add_selected_ids(ids):
188+
q = queue.Queue()
189+
for i in ids:
190+
q.put_nowait("TMDBDUMP/"+str(i) + ".json")
191+
192+
for _ in range(10):
193+
Worker(q).start()
194+
195+
try:
196+
q.join()
197+
except Exception as e:
198+
with q.mutex:
199+
q.queue.clear()
200+
raise e
201+
202+
def update_popularity(pops):
203+
q = queue.Queue()
204+
for pop in pops:
205+
q.put_nowait(pop)
206+
207+
for _ in range(10):
208+
PopWorker(q).start()
209+
210+
try:
211+
q.join()
212+
except Exception as e:
213+
with q.mutex:
214+
q.queue.clear()
215+
raise e
216+
217+
218+
219+
220+
if __name__ == '__main__':
221+
add_all_to_db()

0 commit comments

Comments
 (0)