KaruMediaServer/api/karumedia/tasks.py

282 lines
8.0 KiB
Python

from uwsgi_tasks import *
from .models import *
from time import sleep
from requests import get
import transmissionrpc
from pprint import pprint
from base64 import b64decode
from urllib.parse import urlencode, quote
import PTN
from imdbpie import Imdb
import os
import subprocess
import requests
import magic
import json
YTKEY = os.environ.get("YTKEY")
if not YTKEY:
error("YTKEY not set")
exit(1)
default_trackers = [
'udp://glotorrents.pw:6969/announce',
'udp://tracker.openbittorrent.com:80',
'udp://tracker.coppersurfer.tk:6969',
'udp://tracker.leechers-paradise.org:6969',
'udp://p4p.arenabg.ch:1337',
'udp://tracker.internetwarriors.net:1337',
'udp://tracker.opentrackr.org:1337/announce'
]
r = get("https://raw.githubusercontent.com/ngosang/trackerslist/master/trackers_best.txt")
best_trackers = r.text
for tracker in best_trackers.split("\n"):
tracker = tracker.strip()
if tracker:
default_trackers.append(tracker)
def hash_to_magnet(infoHash, name=None, trackers=None):
try:
b64decode(infoHash)
except:
raise Exception("Invalid infoHash")
magnet = {
"dn": name,
"tr": list(default_trackers)
}
if not name:
del magnet["dn"]
if trackers:
magnet["tr"].extend(trackers)
return "magnet:?xt=urn:btih:{}&".format(infoHash) + urlencode(magnet, doseq=True)
tc = transmissionrpc.Client("172.20.1.2", user="admin", password="minemetsa")
imdb = Imdb()
def guess_imdb_code(title):
info = PTN.parse(title)
if 'year' not in info:
print("No title year found in title")
results = imdb.search_for_title(info["title"])
if not results:
return None
if 'year' in info:
match = [movie for movie in results if movie["year"] == str(info["year"])]
if not match:
pprint(results)
return None
else:
match = match[0]["imdb_id"]
else:
match = results[0]["imdb_id"]
return match
@task
def metainfo_dl(task_id):
task = TaskMetainfoDl.objects.get(id=task_id)
magnet = hash_to_magnet(task.info_hash)
t = tc.add_torrent(magnet)
print(task.info_hash.lower())
print(t.hashString)
task.state = "running"
task.save()
while True:
t = tc.get_torrent(t.hashString)
print(t.name, t.status, t.metadataPercentComplete*100, t.percentDone*100)
if t.metadataPercentComplete == 1:
break
task.progress = t.metadataPercentComplete*100
task.save()
sleep(1)
pprint(t.files())
t.stop()
if not task.imdb_id:
imdb_id = guess_imdb_code(t.name)
else:
imdb_id = task.imdb_id
print("imdb_id:", imdb_id)
try:
media = Media.objects.get(imdb_id=imdb_id)
print("Found existing media object:", media)
except DoesNotExist:
media = Media()
media.imdb_id = imdb_id
media.save()
print("Created a new media object:", media, media.imdb_id)
imdb_dl_task = TaskImdbDl(imdb_id=imdb_id)
imdb_dl_task.media = media
imdb_dl_task.save()
imdb_dl(str(imdb_dl_task.id))
torrent_dl_task = TaskTorrentDl(info_hash=t.hashString, imdb_id=imdb_id)
torrent_dl_task.media = media
torrent_dl_task.save()
torrent_dl(str(torrent_dl_task.id))
task.state = "done"
task.sub_tasks.append(imdb_dl_task)
task.sub_tasks.append(torrent_dl_task)
task.media = media
task.save()
@task
def imdb_dl(task_id):
task = TaskImdbDl.objects.get(id=task_id)
task.state = "running"
task.save()
print("imdb_id:", task.imdb_id)
try:
media = Media.objects.get(imdb_id=task.imdb_id)
print("Using existing media object:", media)
except DoesNotExist:
media = Media()
print("Creating a new media object")
media.imdb_id = task.imdb_id
title = imdb.get_title_by_id(task.imdb_id)
media.title = title.title
media.year = title.year
media.runtime = int(title.runtime)
media.genres = title.genres
media.mpa_rating = title.certification
media.release_date = title.release_date
media.type = title.type
media.plot_outline = title.plot_outline
media.plots = title.plots
media.rating = title.rating
media.save()
task.media = media
task.save()
params = {"key": YTKEY,
"part":"id", "maxResults":1,
"q":"{} ({}) trailer".format(media.title, media.year)}
r = requests.get("https://www.googleapis.com/youtube/v3/search", params=params)
media.yt_trailer_code = r.json()["items"][0]["id"]["videoId"]
media.save()
task.state = "done"
task.progress = 100
task.save()
def probe(vid_file_path):
''' Give a json from ffprobe command line
@vid_file_path : The absolute (full) path of the video file, string.
'''
if type(vid_file_path) != str:
raise Exception('Gvie ffprobe a full file path of the video')
return
command = ["ffprobe",
"-loglevel", "quiet",
"-print_format", "json",
"-show_format",
"-show_streams",
vid_file_path
]
pipe = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, err = pipe.communicate()
return json.loads(out)
def duration(vid_file_path):
''' Video's duration in seconds, return a float number
'''
_json = probe(vid_file_path)
pprint(_json)
if 'format' in _json:
if 'duration' in _json['format']:
return float(_json['format']['duration'])
if 'streams' in _json:
# commonly stream 0 is the video
for s in _json['streams']:
if 'duration' in s:
return float(s['duration'])
# if everything didn't happen,
# we got here because no single 'return' in the above happen.
raise Exception('I found no duration')
#return None
@task
def torrent_dl(task_id):
task = TaskTorrentDl.objects.get(id=task_id)
task.state = "running"
task.save()
t = tc.get_torrent(task.info_hash)
t.start()
while True:
t = tc.get_torrent(task.info_hash)
print(t.name, t.status, t.metadataPercentComplete*100, t.percentDone*100)
if t.percentDone == 1:
break
task.progress = t.percentDone*100
task.save()
sleep(1)
if "imdb_id" in task:
try:
media = Media.objects.get(imdb_id=task.imdb_id)
except DoesNotExist:
pass
else:
tc.rename_torrent_path(task.info_hash, t.name, f"{media.title} ({media.year})")
tc.move_torrent_data(task.info_hash, "/srv/media/Filmid")
with magic.Magic(flags=magic.MAGIC_MIME_TYPE) as m:
for file_id, file_data in t.files().items():
file_path = "/srv/media/Filmid/"+file_data["name"]
file_type = m.id_filename(file_path)
video_duration = None
if file_type.startswith("video"):
video_duration = duration(file_path)
print(file_path, file_type, video_duration)
if not MediaFile.objects(path = file_path):
media_file = MediaFile()
media_file.media = Media.objects.get(imdb_id=task.imdb_id)
media_file.path = file_path
media_file.url = f"http://media.arti.ee/Filmid/{quote(file_data['name'])}"
media_file.mimetype = file_type
media_file.resolution = "native"
media_file.save()
media = task.media
cover_path = f"/srv/media/Filmid/{media.title} ({media.year})/cover.jpg"
if not MediaFile.objects(media=media, path=cover_path):
subprocess.call(['wget', imdb.get_title_by_id(media.imdb_id).cover_url,
"-O", cover_path])
media_poster = MediaFile()
media_poster.path = cover_path
movie_name_and_year = quote(f"{media.title} ({media.year})")
media_poster.url = f"https://media.arti.ee/Filmid/{movie_name_and_year}/cover.jpg"
media_poster.save()
task.state = "done"
task.progress = 100
task.save()