Принципиальные изменения движка

sandbox1
inpos 2016-03-19 17:25:09 +03:00
parent d3f3f729f5
commit bd646784cb
4 changed files with 58 additions and 113 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.module.pyrrent2http" name="pyrrent2http" version="0.8.4" provider-name="inpos">
<addon id="script.module.pyrrent2http" name="pyrrent2http" version="0.9.0" provider-name="inpos">
<requires>
<import addon="xbmc.python" version="2.14.0"/>
<import addon="script.module.libtorrent" />

View File

@ -1,3 +1,6 @@
[B]Version 0.9.0[/B]
+ Изменён принцип работы с торрентом
[B]Version 0.8.3[/B]
+ Исправил быстрый запуск (fix fast resume)

View File

@ -6,8 +6,10 @@ import pyrrent2http
import xbmc
from error import Error
from . import SessionStatus, FileStatus, PeerInfo, Encryption
from util import can_bind, find_free_port, localize_path, uri2path
from util import can_bind, find_free_port, localize_path, uri2path, detect_media_type
import threading
import urllib
import chardet
LOGGING = True
@ -286,7 +288,7 @@ class Engine:
if media_types is not None:
res = filter(lambda fs: fs.media_type in media_types, res)
return res
def list_from_info(self):
def list_from_info(self, media_types=None):
try:
info = pyrrent2http.lt.torrent_info(uri2path(self.uri))
except:
@ -294,18 +296,21 @@ class Engine:
files = []
for i in range(info.num_files()):
f = info.file_at(i)
Url = 'http://' + "%s:%s" % (self.bind_host, self.bind_port) + '/files/' + urllib.quote(f.path)
files.append({
'name': localize_path(f.path),
'size': f.size,
'offset': f.offset,
'media_type': '',
'media_type': media_types and detect_media_type(f.path.decode(chardet.detect(f.path)['encoding'])) or '',
'download': 0,
'progress': 0.0,
'save_path': '',
'url': ''
'url': Url
})
if files:
res = [FileStatus(index=index, **f) for index, f in enumerate(files)]
if media_types is not None:
res = filter(lambda fs: fs.media_type in media_types, res)
return res
def file_status(self, file_index, timeout=10):
@ -319,12 +324,12 @@ class Engine:
:return: File with specified index
:rtype: FileStatus
"""
res = self.list(timeout=timeout)
if res:
try:
return res[file_index]
except IndexError:
raise Error("Requested file index (%d) is invalid" % (file_index,), Error.INVALID_FILE_INDEX,
files = self.pyrrent2http.Ls()['files']
if files:
for f in files:
if f['index'] == file_index:
return FileStatus(**f)
raise Error("Requested file index (%d) is invalid" % (file_index,), Error.INVALID_FILE_INDEX,
file_index=file_index)
def peers(self, timeout=10):

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os
import json
import os
import chardet
try:
@ -19,7 +18,7 @@ except Exception, e:
from random import SystemRandom
import time
import urlparse, urllib
import urllib
import BaseHTTPServer
import SocketServer
import threading
@ -90,7 +89,8 @@ if not hasattr(os, 'getppid'):
AVOID_HTTP_SERVER_EXCEPTION_OUTPUT = True
VERSION = "0.6.0"
USER_AGENT = "pyrrent2http/" + VERSION + " libtorrent/" + lt.version
#USER_AGENT = "pyrrent2http/" + VERSION + " libtorrent/" + lt.version
USER_AGENT = 'libtorrent/1.0.9.0'
VIDEO_EXTS={'.avi':'video/x-msvideo','.mp4':'video/mp4','.mkv':'video/x-matroska',
'.m4v':'video/mp4','.mov':'video/quicktime', '.mpg':'video/mpeg','.ogv':'video/ogg',
@ -168,7 +168,7 @@ class TorrentFile(object):
self.filePtr = io.open(self.save_path, 'rb')
return self.filePtr
def log(self, message):
fnum = self.index
fnum = self.tfs.openedFiles.index(self)
logging.info("[%d] %s\n" % (fnum, message))
def Pieces(self):
startPiece, _ = self.pieceFromOffset(1)
@ -267,8 +267,9 @@ class TorrentFS(object):
self.waitForMetadata()
self.save_path = localize_path(self.root.torrentParams['save_path'])
self.priorities = list(self.handle.file_priorities())
self.files = self.__files_()
self.handle.set_piece_deadline(self.files[startIndex].startPiece, 50)
file_ = self.__file_at_(startIndex)
self.files = {file_.name: file_}
#self.handle.set_piece_deadline(self.files[startIndex].startPiece, 50)
if startIndex < 0:
logging.info('No -file-index specified, downloading will be paused until any file is requested')
@ -313,9 +314,9 @@ class TorrentFS(object):
return self.info is not None
def LoadFileProgress(self):
self.progresses = self.handle.file_progress()
for i, f in enumerate(self.files):
f.downloaded = self.getFileDownloadedBytes(i)
if f.size > 0: f.progress = float(f.downloaded)/float(f.size)
for k in self.files.keys():
self.files[k].downloaded = self.getFileDownloadedBytes(self.files[k].index)
if self.files[k].size > 0: self.files[k].progress = float(self.files[k].downloaded) / float(self.files[k].size)
def getFileDownloadedBytes(self, i):
try:
bytes_ = self.progresses[i]
@ -344,10 +345,9 @@ class TorrentFS(object):
index
)
def FileByName(self, name):
savePath = os.path.abspath(os.path.join(self.save_path, localize_path(name)))
for file_ in self.files:
if file_.save_path == savePath:
return file_
for i, f in enumerate(self.info.files()):
if f.path == name:
return self.__file_at_(i)
raise IOError
def Open(self, name):
if self.shuttingDown or not self.HasTorrentInfo():
@ -372,11 +372,12 @@ class TorrentFS(object):
tf.closed = False
self.fileCounter += 1
tf.num = self.fileCounter
tf.log('Opening %s...' % (tf.name,))
self.addOpenedFile(tf)
tf.log('Opened %s...' % (tf.name,))
tf.SetPriority(1)
self.handle.set_piece_deadline(tf.startPiece, 50)
self.lastOpenedFile = tf
self.addOpenedFile(tf)
self.files[tf.name] = tf
self.checkPriorities()
return tf
@ -393,23 +394,6 @@ def HttpHandlerFactory():
def do_GET(self):
#print ('---Headers---\n%s\n' % (self.headers,))
#print ('---Request---\n%s\n' % (self.path,))
'''if self.path == '/status':
self.statusHandler()
elif self.path == '/ls':
self.lsHandler()
elif self.path == '/peers':
self.peersHandler()
elif self.path == '/trackers':
self.trackersHandler()
elif self.path.startswith('/get/'): # Неясно, зачем
return
# self.getHandler() # этот запрос?
elif self.path == '/shutdown':
self.server.root_obj.forceShutdown = True
self.server.server_close()
self.end_headers()
self.wfile.write('OK')
elif self.path.startswith('/files/'):'''
if self.path.startswith('/files/'):
self.filesHandler()
else:
@ -471,56 +455,6 @@ def HttpHandlerFactory():
self.end_headers()
#print "Sending Bytes ",start_range, " to ", end_range, "...\n"
return (f, start_range, end_range)
'''def statusHandler(self):
self.send_response(200)
self.send_header("Content-type", "application/json")
self.end_headers()
status = self.server.root_obj.Status()
output = json.dumps(status)
self.wfile.write(output)'''
'''def lsHandler(self):
self.send_response(200)
self.send_header("Content-type", "application/json")
self.end_headers()
retFiles = self.server.root_obj.Ls()
output = json.dumps(retFiles)
self.wfile.write(output)'''
'''def peersHandler(self):
self.send_response(200)
self.send_header("Content-type", "application/json")
self.end_headers()
peers = self.server.root_obj.Peers()
output = json.dumps(peers)
self.wfile.write(output)'''
'''def trackersHandler(self):
self.send_response(200)
self.send_header("Content-type", "application/json")
self.end_headers()
ret = list()
try:
info = self.server.root_obj.torrentHandler.torrent_file()
except:
info = self.server.root_obj.torrentHandler.get_torrent_info()
for tracker in info.trackers():
pi = {
'Url': tracker.url,
'NextAnnounceIn': self.server.root_obj.torrentHandler.status().next_announce.seconds,
'MinAnnounceIn': 10, # FIXME неясно, откуда брать
'ErrorCode': 0, #FIXME неясно, откуда брать
'ErrorMessage': u'', #FIXME неясно, откуда брать
'Message': u'', #FIXME неясно, откуда брать
'Tier': tracker.tier,
'FailLimit': tracker.fail_limit,
'Fails': tracker.fails,
'Source': tracker.source,
'Verified': tracker.verified,
'Updating': tracker.updating,
'StartSent': tracker.start_sent,
'CompleteSent': tracker.complete_sent,
}
ret.append(pi)
output = json.dumps(ret)
self.wfile.write(output)'''
# Вырубаем access-log
def log_message(self, format, *args):
return
@ -805,16 +739,17 @@ class Pyrrent2http(object):
retFiles = {'files': []}
if self.TorrentFS.HasTorrentInfo():
files = self.TorrentFS.files
for file_ in files:
Url = 'http://' + self.config.bindAddress + '/files/' + urllib.quote(file_.name)
for name in files.keys():
Url = 'http://' + self.config.bindAddress + '/files/' + urllib.quote(name)
fi = {
'name': file_.unicode_name,
'media_type': file_.media_type,
'size': file_.size,
'offset': file_.offset,
'download': file_.downloaded,
'progress': file_.progress,
'save_path': file_.save_path,
'index': files[name].index,
'name': files[name].unicode_name,
'media_type': files[name].media_type,
'size': files[name].size,
'offset': files[name].offset,
'download': files[name].downloaded,
'progress': files[name].progress,
'save_path': files[name].save_path,
'url': Url
}
retFiles['files'].append(fi)
@ -837,7 +772,7 @@ class Pyrrent2http(object):
}
peers['peers'].append(pi)
return peers
def stats(self):
'''def stats(self):
status = self.torrentHandle.status()
dhtStatusStr = ''
if not status.has_metadata:
@ -865,7 +800,7 @@ class Pyrrent2http(object):
logging.info(str_)
if (self.config.showPiecesProgress or self.config.showAllStats) and self.TorrentFS.lastOpenedFile != None:
self.TorrentFS.lastOpenedFile.ShowPieces()
'''
def consumeAlerts(self):
alerts = self.session.pop_alerts()
for alert in alerts:
@ -883,7 +818,7 @@ class Pyrrent2http(object):
if type(alert) == alert_type:
return alert
def loop(self):
self.statsTicker = Ticker(30)
#self.statsTicker = Ticker(30)
self.saveResumeDataTicker = Ticker(5)
time_start = time.time()
while True:
@ -898,8 +833,8 @@ class Pyrrent2http(object):
if os.getppid() == 1:
self.forceShutdown = True
time_start = time.time()
if self.statsTicker.true:
self.stats()
#if self.statsTicker.true:
# self.stats()
if self.saveResumeDataTicker.true:
self.saveResumeData(True)
time.sleep(0.3)
@ -954,10 +889,12 @@ class Pyrrent2http(object):
def filesToRemove(self):
files = []
if self.TorrentFS.HasTorrentInfo():
for file in self.TorrentFS.files:
if (not self.config.keepComplete or not file.IsComplete()) and (not self.config.keepIncomplete or file.IsComplete()):
if os.path.exists(file.save_path):
files.append(file.save_path)
for i, f in enumerate(self.torrentHandle.files()):
isComplete = self.TorrentFS.progresses[i] == f.size
if (not self.config.keepComplete or not isComplete) and (not self.config.keepIncomplete or isComplete):
path = os.path.abspath(os.path.join(self.TorrentFS.save_path, localize_path(f.path)))
if os.path.exists(path):
files.append(path)
return files
def removeTorrent(self):
files = []
@ -977,7 +914,7 @@ class Pyrrent2http(object):
def shutdown(self):
logging.info('Stopping pyrrent2http...')
self.forceShutdown = True
self.statsTicker.stop()
#self.statsTicker.stop()
self.saveResumeDataTicker.stop()
self.httpListener.shutdown()
self.TorrentFS.Shutdown()