237 lines
9.4 KiB
Python
237 lines
9.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
'''
|
|
Torrenter v2 plugin for XBMC/Kodi
|
|
Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
'''
|
|
|
|
import thread
|
|
import os
|
|
import urllib2
|
|
import hashlib
|
|
import re
|
|
from StringIO import StringIO
|
|
import gzip
|
|
import sys
|
|
from contextlib import closing
|
|
|
|
import xbmc
|
|
import xbmcgui
|
|
import xbmcvfs
|
|
import xbmcplugin
|
|
import Localization
|
|
from functions import file_encode, isSubtitle, DownloadDB, log, debug, is_writable, unquote
|
|
from torrent2http import State, Engine, MediaType
|
|
|
|
class Anteoloader:
|
|
magnetLink = None
|
|
startPart = 0
|
|
endPart = 0
|
|
partOffset = 0
|
|
torrentHandle = None
|
|
session = None
|
|
engine = None
|
|
downloadThread = None
|
|
threadComplete = False
|
|
|
|
def __init__(self, storageDirectory='', torrentFile='', torrentFilesDirectory='torrents'):
|
|
self.storageDirectory = storageDirectory
|
|
self.torrentFilesPath = os.path.join(self.storageDirectory, torrentFilesDirectory) + os.sep
|
|
if not is_writable(self.storageDirectory):
|
|
xbmcgui.Dialog().ok(self.localize('Torrenter v2'),
|
|
self.localize('Your storage path is not writable or not local! Please change it in settings!'),
|
|
self.localize(self.storageDirectory))
|
|
|
|
sys.exit(1)
|
|
|
|
#pre settings
|
|
self.pre_buffer_bytes = 15*1024*1024
|
|
print torrentFile
|
|
torrentFile=unquote(torrentFile)
|
|
print torrentFile
|
|
print str(xbmcvfs.exists(torrentFile))
|
|
print str(os.path.exists(torrentFile))
|
|
|
|
|
|
self.engine = Engine(uri=torrentFile)
|
|
|
|
def __exit__(self):
|
|
log('on __exit__')
|
|
if self.engine:
|
|
self.engine.close()
|
|
log('__exit__ worked!')
|
|
|
|
|
|
def getContentList(self, media_types=None):
|
|
files = []
|
|
filelist = []
|
|
with closing(self.engine):
|
|
self.engine.start()
|
|
if media_types is None:
|
|
media_types=[MediaType.VIDEO, MediaType.AUDIO, MediaType.SUBTITLES, MediaType.UNKNOWN]
|
|
|
|
while not files and not xbmc.abortRequested:
|
|
files = self.engine.list(media_types)
|
|
self.engine.check_torrent_error()
|
|
xbmc.sleep(200)
|
|
|
|
for fs in files:
|
|
stringdata = {"title": fs.name, "size": fs.size, "ind": fs.index,
|
|
'offset': fs.offset}
|
|
filelist.append(stringdata)
|
|
|
|
|
|
def stream(self, params):
|
|
self.params = params
|
|
self.get = self.params.get
|
|
self.contentId = int(self.get("url")) if self.get("url") else 0
|
|
#with closing(self.engine):
|
|
self.engine.start(self.contentId)
|
|
|
|
ready = self.buffer()
|
|
if ready:
|
|
file_status = self.engine.file_status(self.contentId)
|
|
listitem = xbmcgui.ListItem('xxxx')
|
|
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
|
playlist.clear()
|
|
playlist.add(file_status.url, listitem)
|
|
xbmc.Player().play(playlist)
|
|
while not xbmc.abortRequested and xbmc.Player().isPlaying():
|
|
xbmc.sleep(500)
|
|
xbmc.Player().stop()
|
|
|
|
def buffer(self):
|
|
ready = False
|
|
progressBar = xbmcgui.DialogProgress()
|
|
progressBar.create(self.localize('Please Wait'),
|
|
self.localize('Seeds searching.'))
|
|
#if self.subs_dl:
|
|
# subs = self.torrent.getSubsIds(os.path.basename(self.torrent.getFilePath(self.contentId)))
|
|
# if len(subs) > 0:
|
|
# for ind, title in subs:
|
|
# self.torrent.continueSession(ind)
|
|
|
|
#FileStatus = namedtuple('FileStatus', "name, save_path, url, size, offset, download, progress, index, media_type")
|
|
|
|
#SessionStatus = namedtuple('SessionStatus', "name, state, state_str, error, progress, download_rate, upload_rate, "
|
|
# "total_download, total_upload, num_peers, num_seeds, total_seeds, "
|
|
# "total_peers")
|
|
|
|
while not xbmc.abortRequested and not ready:
|
|
xbmc.sleep(500)
|
|
status = self.engine.status()
|
|
self.engine.check_torrent_error(status)
|
|
file_status = self.engine.file_status(self.contentId)
|
|
if not file_status:
|
|
continue
|
|
log('[buffer] file_status:'+str(file_status))
|
|
log('[buffer] status:'+str(status))
|
|
#self.torrent.debug()
|
|
fullSize = file_status.size / 1024 / 1024
|
|
downloadedSize = status.total_download / 1024 / 1024
|
|
getDownloadRate = status.download_rate / 1024 * 8
|
|
getUploadRate = status.upload_rate / 1024 * 8
|
|
getSeeds, getPeers = status.num_seeds, status.num_peers
|
|
iterator = int(round(float(file_status.download) / self.pre_buffer_bytes, 2) * 100)
|
|
if iterator > 99: iterator = 99
|
|
if status.state == State.QUEUED_FOR_CHECKING:
|
|
progressBar.update(iterator, self.localize('Checking preloaded files...'), ' ', ' ')
|
|
elif status.state == State.DOWNLOADING:
|
|
dialogText = self.localize('Preloaded: ') + "%d MB / %d MB" % \
|
|
(int(downloadedSize), int(fullSize))
|
|
peersText = ' [%s: %s; %s: %s]' % (
|
|
self.localize('Seeds'), getSeeds, self.localize('Peers'), getPeers)
|
|
speedsText = '%s: %d Mbit/s; %s: %d Mbit/s' % (
|
|
self.localize('Downloading'), int(getDownloadRate),
|
|
self.localize('Uploading'), int(getUploadRate))
|
|
#if self.debug:
|
|
# peersText=peersText + ' ' + self.torrent.get_debug_info('dht_state')
|
|
# dialogText=dialogText.replace(self.localize('Preloaded: '),'') + ' ' + self.torrent.get_debug_info('trackers_sum')
|
|
progressBar.update(iterator, self.localize('Seeds searching.') + peersText, dialogText,
|
|
speedsText)
|
|
|
|
if file_status.download >= self.pre_buffer_bytes:
|
|
ready = True
|
|
break
|
|
elif status.state in [State.FINISHED, State.SEEDING]:
|
|
ready = True
|
|
break
|
|
else:
|
|
progressBar.update(iterator, self.localize('UNKNOWN STATUS'), ' ', ' ')
|
|
if progressBar.iscanceled():
|
|
ready = False
|
|
break
|
|
|
|
progressBar.update(0)
|
|
progressBar.close()
|
|
return ready
|
|
|
|
def localize(self, string):
|
|
try:
|
|
return Localization.localize(string)
|
|
except:
|
|
return string
|
|
|
|
|
|
def saveTorrent(self, torrentUrl):
|
|
if not xbmcvfs.exists(torrentUrl):
|
|
if re.match("^magnet\:.+$", torrentUrl):
|
|
self.magnetLink = torrentUrl
|
|
self.magnetToTorrent(torrentUrl)
|
|
self.magnetLink = None
|
|
return self.torrentFile
|
|
else:
|
|
if not xbmcvfs.exists(self.torrentFilesPath):
|
|
xbmcvfs.mkdirs(self.torrentFilesPath)
|
|
torrentFile = self.torrentFilesPath + self.md5(
|
|
torrentUrl) + '.torrent'
|
|
try:
|
|
if not re.match("^http\:.+$", torrentUrl):
|
|
content = xbmcvfs.File(torrentUrl, "rb").read()
|
|
else:
|
|
request = urllib2.Request(torrentUrl)
|
|
request.add_header('Referer', torrentUrl)
|
|
request.add_header('Accept-encoding', 'gzip')
|
|
result = urllib2.urlopen(request)
|
|
if result.info().get('Content-Encoding') == 'gzip':
|
|
buf = StringIO(result.read())
|
|
f = gzip.GzipFile(fileobj=buf)
|
|
content = f.read()
|
|
else:
|
|
content = result.read()
|
|
|
|
localFile = xbmcvfs.File(torrentFile, "w+b")
|
|
localFile.write(content)
|
|
localFile.close()
|
|
except Exception, e:
|
|
print 'Unable to save torrent file from "' + torrentUrl + '" to "' + torrentFile + '" in Torrent::saveTorrent' + '. Exception: ' + str(
|
|
e)
|
|
return
|
|
else:
|
|
torrentFile = torrentUrl
|
|
if xbmcvfs.exists(torrentFile):
|
|
self.torrentFile = "file:///"+torrentFile.replace('\\','//').replace('////','//')
|
|
return self.torrentFile
|
|
|
|
def md5(self, string):
|
|
hasher = hashlib.md5()
|
|
try:
|
|
hasher.update(string)
|
|
except:
|
|
hasher.update(string.encode('utf-8', 'ignore'))
|
|
return hasher.hexdigest()
|
|
|
|
def magnetToTorrent(self, magnet):
|
|
self.torrentFile = magnet |