mirror of
https://github.com/JohnDoee/deluge-streaming/
synced 2026-07-01 07:31:17 -07:00
a bit of cleanup
This commit is contained in:
@@ -39,18 +39,21 @@
|
|||||||
|
|
||||||
from deluge.plugins.init import PluginInitBase
|
from deluge.plugins.init import PluginInitBase
|
||||||
|
|
||||||
|
|
||||||
class CorePlugin(PluginInitBase):
|
class CorePlugin(PluginInitBase):
|
||||||
def __init__(self, plugin_name):
|
def __init__(self, plugin_name):
|
||||||
from core import Core as _plugin_cls
|
from core import Core as _plugin_cls
|
||||||
self._plugin_cls = _plugin_cls
|
self._plugin_cls = _plugin_cls
|
||||||
super(CorePlugin, self).__init__(plugin_name)
|
super(CorePlugin, self).__init__(plugin_name)
|
||||||
|
|
||||||
|
|
||||||
class GtkUIPlugin(PluginInitBase):
|
class GtkUIPlugin(PluginInitBase):
|
||||||
def __init__(self, plugin_name):
|
def __init__(self, plugin_name):
|
||||||
from gtkui import GtkUI as _plugin_cls
|
from gtkui import GtkUI as _plugin_cls
|
||||||
self._plugin_cls = _plugin_cls
|
self._plugin_cls = _plugin_cls
|
||||||
super(GtkUIPlugin, self).__init__(plugin_name)
|
super(GtkUIPlugin, self).__init__(plugin_name)
|
||||||
|
|
||||||
|
|
||||||
class WebUIPlugin(PluginInitBase):
|
class WebUIPlugin(PluginInitBase):
|
||||||
def __init__(self, plugin_name):
|
def __init__(self, plugin_name):
|
||||||
from webui import WebUI as _plugin_cls
|
from webui import WebUI as _plugin_cls
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ from copy import copy
|
|||||||
|
|
||||||
from deluge import component, configmanager
|
from deluge import component, configmanager
|
||||||
from deluge._libtorrent import lt
|
from deluge._libtorrent import lt
|
||||||
from deluge.core.rpcserver import export, check_ssl_keys
|
from deluge.core.rpcserver import export
|
||||||
from deluge.plugins.pluginbase import CorePluginBase
|
from deluge.plugins.pluginbase import CorePluginBase
|
||||||
|
|
||||||
from twisted.internet import reactor, defer, task
|
from twisted.internet import reactor, defer
|
||||||
from twisted.python import randbytes
|
from twisted.python import randbytes
|
||||||
from twisted.web import server, resource, static, http, client
|
from twisted.web import server, resource, static, client
|
||||||
|
|
||||||
from .filelike import FilelikeObjectResource
|
from .filelike import FilelikeObjectResource
|
||||||
from .resource import Resource
|
from .resource import Resource
|
||||||
@@ -80,11 +80,13 @@ DEFAULT_PREFS = {
|
|||||||
|
|
||||||
PRIORITY_INCREASE = 5
|
PRIORITY_INCREASE = 5
|
||||||
|
|
||||||
|
|
||||||
def sleep(seconds):
|
def sleep(seconds):
|
||||||
d = defer.Deferred()
|
d = defer.Deferred()
|
||||||
reactor.callLater(seconds, d.callback, seconds)
|
reactor.callLater(seconds, d.callback, seconds)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class ServerContextFactory(object):
|
class ServerContextFactory(object):
|
||||||
def __init__(self, cert_file, key_file):
|
def __init__(self, cert_file, key_file):
|
||||||
self._cert_file = cert_file
|
self._cert_file = cert_file
|
||||||
@@ -103,6 +105,7 @@ class ServerContextFactory(object):
|
|||||||
ctx.use_privatekey_file(self._key_file)
|
ctx.use_privatekey_file(self._key_file)
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class FileServeResource(resource.Resource):
|
class FileServeResource(resource.Resource):
|
||||||
isLeaf = True
|
isLeaf = True
|
||||||
|
|
||||||
@@ -131,6 +134,7 @@ class FileServeResource(resource.Resource):
|
|||||||
tfr = f.open()
|
tfr = f.open()
|
||||||
return FilelikeObjectResource(tfr, f.size).render_GET(request)
|
return FilelikeObjectResource(tfr, f.size).render_GET(request)
|
||||||
|
|
||||||
|
|
||||||
class StreamResource(Resource):
|
class StreamResource(Resource):
|
||||||
isLeaf = True
|
isLeaf = True
|
||||||
|
|
||||||
@@ -180,12 +184,15 @@ class StreamResource(Resource):
|
|||||||
result = yield self.client.stream_torrent(infohash=infohash, filepath_or_index=path, wait_for_end_pieces=wait_for_end_pieces)
|
result = yield self.client.stream_torrent(infohash=infohash, filepath_or_index=path, wait_for_end_pieces=wait_for_end_pieces)
|
||||||
defer.returnValue(json.dumps(result))
|
defer.returnValue(json.dumps(result))
|
||||||
|
|
||||||
|
|
||||||
class UnknownTorrentException(Exception):
|
class UnknownTorrentException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class UnknownFileException(Exception):
|
class UnknownFileException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TorrentFileReader(object):
|
class TorrentFileReader(object):
|
||||||
def __init__(self, torrent_file):
|
def __init__(self, torrent_file):
|
||||||
self.torrent_file = torrent_file
|
self.torrent_file = torrent_file
|
||||||
@@ -222,7 +229,8 @@ class TorrentFileReader(object):
|
|||||||
def seek(self, offset, whence=os.SEEK_SET):
|
def seek(self, offset, whence=os.SEEK_SET):
|
||||||
self.position = offset
|
self.position = offset
|
||||||
|
|
||||||
class TorrentFile(object): # can be read from, knows about itself
|
|
||||||
|
class TorrentFile(object): # can be read from, knows about itself
|
||||||
def __init__(self, torrent, first_piece, last_piece, piece_size, offset, path, full_path, size, index):
|
def __init__(self, torrent, first_piece, last_piece, piece_size, offset, path, full_path, size, index):
|
||||||
self.torrent = torrent
|
self.torrent = torrent
|
||||||
self.first_piece = first_piece
|
self.first_piece = first_piece
|
||||||
@@ -244,7 +252,6 @@ class TorrentFile(object): # can be read from, knows about itself
|
|||||||
|
|
||||||
self.alerts = component.get("AlertManager")
|
self.alerts = component.get("AlertManager")
|
||||||
|
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
"""
|
"""
|
||||||
Returns a filelike object
|
Returns a filelike object
|
||||||
@@ -335,6 +342,7 @@ class TorrentFile(object): # can be read from, knows about itself
|
|||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
self.do_shutdown = True
|
self.do_shutdown = True
|
||||||
|
|
||||||
|
|
||||||
class Torrent(object):
|
class Torrent(object):
|
||||||
def __init__(self, torrent_handler, infohash):
|
def __init__(self, torrent_handler, infohash):
|
||||||
self.infohash = infohash
|
self.infohash = infohash
|
||||||
@@ -347,8 +355,7 @@ class Torrent(object):
|
|||||||
self.torrent_files = None
|
self.torrent_files = None
|
||||||
self.priority_increased = defaultdict(set)
|
self.priority_increased = defaultdict(set)
|
||||||
self.do_shutdown = False
|
self.do_shutdown = False
|
||||||
self.torrent_released = True # set to True if all the files are set to download
|
self.torrent_released = True # set to True if all the files are set to download
|
||||||
|
|
||||||
|
|
||||||
self.populate_files()
|
self.populate_files()
|
||||||
self.file_priorities = [0] * len(self.torrent_files)
|
self.file_priorities = [0] * len(self.torrent_files)
|
||||||
@@ -427,7 +434,7 @@ class Torrent(object):
|
|||||||
if self.torrent_released:
|
if self.torrent_released:
|
||||||
should_update_priorities = True
|
should_update_priorities = True
|
||||||
|
|
||||||
if should_update_priorities and not f.is_complete(): # Need to do this stuff on seek too
|
if should_update_priorities and not f.is_complete(): # Need to do this stuff on seek too
|
||||||
self.torrent.set_file_priorities(self.file_priorities)
|
self.torrent.set_file_priorities(self.file_priorities)
|
||||||
|
|
||||||
return f
|
return f
|
||||||
@@ -456,7 +463,7 @@ class Torrent(object):
|
|||||||
for tf in self.torrent_files:
|
for tf in self.torrent_files:
|
||||||
tf.shutdown()
|
tf.shutdown()
|
||||||
|
|
||||||
def update_piece_priority(self): # if file streamed has reached end, unblacklist all prior pieces
|
def update_piece_priority(self): # if file streamed has reached end, unblacklist all prior pieces
|
||||||
if self.do_shutdown:
|
if self.do_shutdown:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -464,13 +471,13 @@ class Torrent(object):
|
|||||||
currently_downloading = self.get_currently_downloading()
|
currently_downloading = self.get_currently_downloading()
|
||||||
|
|
||||||
for f in self.torrent_files:
|
for f in self.torrent_files:
|
||||||
if not f.file_requested and not f.current_readers: # nobody wants the file and nobody is watching
|
if not f.file_requested and not f.current_readers: # nobody wants the file and nobody is watching
|
||||||
continue
|
continue
|
||||||
|
|
||||||
logger.debug('Rescheduling file %s' % (f.path, ))
|
logger.debug('Rescheduling file %s' % (f.path, ))
|
||||||
|
|
||||||
heads = set()
|
heads = set()
|
||||||
if f.file_requested: # we expect a piece head to be at start
|
if f.file_requested: # we expect a piece head to be at start
|
||||||
heads.add(f.first_piece)
|
heads.add(f.first_piece)
|
||||||
|
|
||||||
waiting_for_pieces = set()
|
waiting_for_pieces = set()
|
||||||
@@ -480,7 +487,7 @@ class Torrent(object):
|
|||||||
waiting_for_pieces.add(tfr.waiting_for_piece)
|
waiting_for_pieces.add(tfr.waiting_for_piece)
|
||||||
|
|
||||||
piece = max(tfr.waiting_for_piece, tfr.current_piece)
|
piece = max(tfr.waiting_for_piece, tfr.current_piece)
|
||||||
if piece is not None:
|
if piece is not None:
|
||||||
heads.add(piece)
|
heads.add(piece)
|
||||||
|
|
||||||
if not heads:
|
if not heads:
|
||||||
@@ -491,7 +498,6 @@ class Torrent(object):
|
|||||||
for head_piece in heads:
|
for head_piece in heads:
|
||||||
priority_increased = 0
|
priority_increased = 0
|
||||||
for piece, status in enumerate(self.torrent.status.pieces[head_piece:f.last_piece+1], head_piece):
|
for piece, status in enumerate(self.torrent.status.pieces[head_piece:f.last_piece+1], head_piece):
|
||||||
#logger.debug('Checking status for %s/%s/%s/%s' % (head_piece, piece, status, self.torrent.handle.piece_priority(piece)))
|
|
||||||
if status or piece in currently_downloading:
|
if status or piece in currently_downloading:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -547,6 +553,7 @@ class Torrent(object):
|
|||||||
|
|
||||||
reactor.callLater(1, self.update_piece_priority)
|
reactor.callLater(1, self.update_piece_priority)
|
||||||
|
|
||||||
|
|
||||||
class TorrentHandler(object):
|
class TorrentHandler(object):
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.torrents = {}
|
self.torrents = {}
|
||||||
@@ -584,6 +591,7 @@ class TorrentHandler(object):
|
|||||||
for torrent in self.torrents.values():
|
for torrent in self.torrents.values():
|
||||||
torrent.shutdown()
|
torrent.shutdown()
|
||||||
|
|
||||||
|
|
||||||
class Core(CorePluginBase):
|
class Core(CorePluginBase):
|
||||||
listening = None
|
listening = None
|
||||||
base_url = None
|
base_url = None
|
||||||
@@ -618,7 +626,7 @@ class Core(CorePluginBase):
|
|||||||
|
|
||||||
self.base_url = 'http'
|
self.base_url = 'http'
|
||||||
if self.config['serve_method'] == 'standalone':
|
if self.config['serve_method'] == 'standalone':
|
||||||
if self.config['use_ssl'] and self.check_ssl(): # use default deluge (or webui), input custom
|
if self.config['use_ssl'] and self.check_ssl(): # use default deluge (or webui), input custom
|
||||||
if self.config['ssl_source'] == 'daemon':
|
if self.config['ssl_source'] == 'daemon':
|
||||||
web_config = configmanager.ConfigManager("web.conf", {"pkey": "ssl/daemon.pkey",
|
web_config = configmanager.ConfigManager("web.conf", {"pkey": "ssl/daemon.pkey",
|
||||||
"cert": "ssl/daemon.cert"})
|
"cert": "ssl/daemon.cert"})
|
||||||
@@ -642,7 +650,7 @@ class Core(CorePluginBase):
|
|||||||
|
|
||||||
port = self.config['port']
|
port = self.config['port']
|
||||||
ip = self.config['ip']
|
ip = self.config['ip']
|
||||||
elif self.config['serve_method'] == 'webui' and self.check_webui(): # this webserver is fubar
|
elif self.config['serve_method'] == 'webui' and self.check_webui(): # this webserver is fubar
|
||||||
plugin_manager = component.get("CorePluginManager")
|
plugin_manager = component.get("CorePluginManager")
|
||||||
|
|
||||||
webui_plugin = plugin_manager['WebUi'].plugin
|
webui_plugin = plugin_manager['WebUi'].plugin
|
||||||
@@ -762,4 +770,4 @@ class Core(CorePluginBase):
|
|||||||
'auto_open_stream_urls': self.config['auto_open_stream_urls'],
|
'auto_open_stream_urls': self.config['auto_open_stream_urls'],
|
||||||
'url': '%s/streaming/file/%s/%s' % (self.base_url, self.fsr.add_file(tf),
|
'url': '%s/streaming/file/%s/%s' % (self.base_url, self.fsr.add_file(tf),
|
||||||
urllib.quote_plus(filename))
|
urllib.quote_plus(filename))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ class SingleRangeStaticProducer(static.SingleRangeStaticProducer):
|
|||||||
if not self.request:
|
if not self.request:
|
||||||
return
|
return
|
||||||
|
|
||||||
data = yield defer.maybeDeferred(self.fileObject.read,
|
data = yield defer.maybeDeferred(self.fileObject.read, min(self.bufferSize, self.size - self.bytesWritten))
|
||||||
min(self.bufferSize, self.size - self.bytesWritten))
|
|
||||||
|
|
||||||
if not self.request:
|
if not self.request:
|
||||||
return
|
return
|
||||||
@@ -62,9 +61,7 @@ class MultipleRangeStaticProducer(static.MultipleRangeStaticProducer):
|
|||||||
dataLength += len(self.partBoundary)
|
dataLength += len(self.partBoundary)
|
||||||
data.append(self.partBoundary)
|
data.append(self.partBoundary)
|
||||||
self.partBoundary = None
|
self.partBoundary = None
|
||||||
p = yield defer.maybeDeferred(self.fileObject.read,
|
p = yield defer.maybeDeferred(self.fileObject.read, min(self.bufferSize - dataLength, self._partSize - self._partBytesWritten))
|
||||||
min(self.bufferSize - dataLength,
|
|
||||||
self._partSize - self._partBytesWritten))
|
|
||||||
self._partBytesWritten += len(p)
|
self._partBytesWritten += len(p)
|
||||||
dataLength += len(p)
|
dataLength += len(p)
|
||||||
data.append(p)
|
data.append(p)
|
||||||
|
|||||||
@@ -37,7 +37,6 @@
|
|||||||
# statement from all source files in the program, then also delete it here.
|
# statement from all source files in the program, then also delete it here.
|
||||||
#
|
#
|
||||||
|
|
||||||
import json
|
|
||||||
import gtk
|
import gtk
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
@@ -50,8 +49,7 @@ from deluge.plugins.pluginbase import GtkPluginBase
|
|||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
import deluge.common
|
import deluge.common
|
||||||
|
|
||||||
from twisted.internet import reactor, defer, threads
|
from twisted.internet import defer, threads
|
||||||
from twisted.web import server, resource
|
|
||||||
|
|
||||||
from common import get_resource
|
from common import get_resource
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
from twisted.web.resource import Resource as TwistedResource, _computeAllowedMethods
|
from twisted.web.resource import Resource as TwistedResource, _computeAllowedMethods
|
||||||
from twisted.web import server, error
|
from twisted.web import server
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
|
||||||
|
|
||||||
class Resource(TwistedResource):
|
class Resource(TwistedResource):
|
||||||
content_type = 'application/json'
|
content_type = 'application/json'
|
||||||
|
|
||||||
def __init__(self, username=None, password=None, *args, **kwargs):
|
def __init__(self, username=None, password=None, *args, **kwargs):
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password = password
|
self.password = password
|
||||||
TwistedResource.__init__(self, *args, **kwargs)
|
TwistedResource.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
def render(self, request): # Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
|
def render(self, request): # Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
|
||||||
"""
|
"""
|
||||||
Adds support for deferred render methods
|
Adds support for deferred render methods
|
||||||
"""
|
"""
|
||||||
auth_header = request.getHeader('Authorization')
|
auth_header = request.getHeader('Authorization')
|
||||||
|
|
||||||
if self.username or self.password:
|
if self.username or self.password:
|
||||||
authenticated = False
|
authenticated = False
|
||||||
if auth_header:
|
if auth_header:
|
||||||
@@ -27,14 +27,13 @@ class Resource(TwistedResource):
|
|||||||
username, password = userpass
|
username, password = userpass
|
||||||
if self.username == username and self.password == password:
|
if self.username == username and self.password == password:
|
||||||
authenticated = True
|
authenticated = True
|
||||||
|
|
||||||
|
|
||||||
if not authenticated:
|
if not authenticated:
|
||||||
print auth_header
|
print auth_header
|
||||||
print self.username, self.password
|
print self.username, self.password
|
||||||
request.setResponseCode(401)
|
request.setResponseCode(401)
|
||||||
return 'Unauthorized'
|
return 'Unauthorized'
|
||||||
|
|
||||||
m = getattr(self, 'render_' + request.method, None)
|
m = getattr(self, 'render_' + request.method, None)
|
||||||
if not m:
|
if not m:
|
||||||
# This needs to be here until the deprecated subclasses of the
|
# This needs to be here until the deprecated subclasses of the
|
||||||
@@ -43,18 +42,18 @@ class Resource(TwistedResource):
|
|||||||
allowedMethods = (getattr(self, 'allowedMethods', 0) or
|
allowedMethods = (getattr(self, 'allowedMethods', 0) or
|
||||||
_computeAllowedMethods(self))
|
_computeAllowedMethods(self))
|
||||||
raise UnsupportedMethod(allowedMethods)
|
raise UnsupportedMethod(allowedMethods)
|
||||||
|
|
||||||
result = defer.maybeDeferred(m, request)
|
result = defer.maybeDeferred(m, request)
|
||||||
|
|
||||||
def write_rest(defer_result, request):
|
def write_rest(defer_result, request):
|
||||||
request.write(defer_result)
|
request.write(defer_result)
|
||||||
request.finish()
|
request.finish()
|
||||||
|
|
||||||
def err_rest(defer_result=None):
|
def err_rest(defer_result=None):
|
||||||
defer_result.printTraceback()
|
defer_result.printTraceback()
|
||||||
request.finish()
|
request.finish()
|
||||||
|
|
||||||
result.addCallback(write_rest, request)
|
result.addCallback(write_rest, request)
|
||||||
result.addErrback(err_rest)
|
result.addErrback(err_rest)
|
||||||
|
|
||||||
return server.NOT_DONE_YET
|
return server.NOT_DONE_YET
|
||||||
|
|||||||
@@ -44,6 +44,6 @@ from deluge.plugins.pluginbase import WebPluginBase
|
|||||||
|
|
||||||
from common import get_resource
|
from common import get_resource
|
||||||
|
|
||||||
class WebUI(WebPluginBase):
|
|
||||||
|
|
||||||
scripts = [get_resource("streaming.js")]
|
class WebUI(WebPluginBase):
|
||||||
|
scripts = [get_resource("streaming.js")]
|
||||||
|
|||||||
Reference in New Issue
Block a user