Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Xunlei subtitle downloader
#!/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
finally:
i.remove_watch(SubtitleDownloader.watch_dir)
if __name__ == '__main__':
SubtitleDownloader.inotify_loop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment