-
-
Save vvoody/2637963d3812e64a6fb4738ed7723a33 to your computer and use it in GitHub Desktop.
Xunlei subtitle downloader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# -*- coding: utf-8 -*- | |
# __author__ = 'ihciah' | |
# cid_hash_file function from https://github.com/binux/lixian.xunlei/blob/master/libs/tools.py | |
import hashlib | |
import inotify.adapters | |
import os | |
import requests | |
import re | |
class SubtitleDownloader: | |
video_types = [u'mkv', u'mp4', u'avi', u'rm', u'rmvb', u'wmv', u'webm', u'mpeg', u'mpe', u'flv', u'3gp'] | |
subtitle_types = [u'ass', u'srt', u'sub', u'sst', u'son', u'ssa', u'smi', u'tts', u'psb', u'pjs', u'stl', u'vsf'] | |
download_count = 3 | |
watch_dir = b'/hdd/downloads' | |
@staticmethod | |
def download_srt(subtitle_url, video_base_path, video_name, num): | |
dot = subtitle_url.rfind(u'.') | |
if dot < 0: | |
return | |
subtitle_type = subtitle_url[dot + 1:].lower() | |
if subtitle_type not in SubtitleDownloader.subtitle_types: | |
return | |
response = requests.get(subtitle_url) | |
if response.status_code == 200: | |
with open(os.path.join(video_base_path, video_name + u'.%d.' % num + subtitle_type), 'wb') as f: | |
f.write(response.content) | |
@staticmethod | |
def cid_hash_file(path): | |
h = hashlib.sha1() | |
size = os.path.getsize(path) | |
with open(path, 'rb') as stream: | |
if size < 0xF000: | |
h.update(stream.read()) | |
else: | |
h.update(stream.read(0x5000)) | |
stream.seek(size//3) | |
h.update(stream.read(0x5000)) | |
stream.seek(size-0x5000) | |
h.update(stream.read(0x5000)) | |
return h.hexdigest().upper() | |
@staticmethod | |
def fetch_subtitle_list(cid): | |
patten = re.compile(b'surl="(.*?)"') | |
url_base = u'http://subtitle.kankan.xunlei.com:8000/submatch/%s/%s/%s.lua' | |
r = requests.get(url_base % (cid[:2], cid[-2:], cid)).content | |
srt_urls = patten.findall(r)[:SubtitleDownloader.download_count] | |
return list(map(lambda url: url.decode(u'utf-8'), srt_urls)) | |
@staticmethod | |
def download_subtitle(video): | |
if not video or not os.path.isfile(video): | |
print(u"Video file does not exist.") | |
return -1 | |
video_base_path, video_filename = os.path.split(os.path.abspath(video)) | |
dot = video_filename.rfind(u'.') | |
if dot < 0: | |
print(u"Not a video file.") | |
return -1 | |
video_name = video_filename[:dot] | |
video_type = video_filename[dot+1:] | |
if video_type.lower() not in SubtitleDownloader.video_types: | |
print(u"Not a video file.") | |
return -2 | |
cid = SubtitleDownloader.cid_hash_file(video) | |
subtitle_list = SubtitleDownloader.fetch_subtitle_list(cid) | |
for num, subtitle in enumerate(subtitle_list): | |
SubtitleDownloader.download_srt(subtitle, video_base_path, video_name, num) | |
@staticmethod | |
def inotify_loop(): | |
i = inotify.adapters.InotifyTree(SubtitleDownloader.watch_dir) | |
try: | |
for event in i.event_gen(): | |
if event is not None: | |
try: | |
(header, type_names, watch_path, filename) = event | |
filename = filename.decode('utf-8') | |
watch_path = watch_path.decode('utf-8') | |
if 'IN_DELETE' in type_names and filename.endswith(u'.aria2'): | |
video_filename = filename[:filename.rfind(u'.')] | |
SubtitleDownloader.download_subtitle(os.path.join(watch_path, video_filename)) | |
except: | |
pass | |
except: | |
pass | |
if __name__ == '__main__': | |
SubtitleDownloader.inotify_loop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment