def add_torrent(self, torrentdl, atp): # If we are collecting the torrent for this infohash, abort this first. with self.metainfo_lock: ltsession = self.get_session(atp.pop('hops', 0)) if 'ti' in atp: infohash = str(atp['ti'].info_hash()) elif 'url' in atp: infohash = binascii.hexlify(parse_magnetlink(atp['url'])[1]) else: raise ValueError('No ti or url key in add_torrent_params') # Check if we added this torrent before known = [str(h.info_hash()) for h in ltsession.get_torrents()] if infohash in known: self.torrents[infohash] = (torrentdl, ltsession) infohash_bin = binascii.unhexlify(infohash) return ltsession.find_torrent(lt.big_number(infohash_bin)) # Otherwise, add it anew torrent_handle = ltsession.add_torrent(encode_atp(atp)) infohash = str(torrent_handle.info_hash()) if infohash in self.torrents: raise DuplicateDownloadException( "This download already exists.") self.torrents[infohash] = (torrentdl, ltsession) self._logger.debug("added torrent %s", infohash) return torrent_handle
def start_download(self, torrentfilename=None, infohash=None, tdef=None, dconfig=None): self._logger.debug(u"starting download: filename: %s, torrent def: %s", torrentfilename, tdef) if infohash is not None: assert isinstance(infohash, str), "infohash type: %s" % type(infohash) assert len(infohash) == 20, "infohash length is not 20: %s, %s" % ( len(infohash), infohash) # the priority of the parameters is: (1) tdef, (2) infohash, (3) torrent_file. # so if we have tdef, infohash and torrent_file will be ignored, and so on. if tdef is None: if infohash is not None: # try to get the torrent from torrent_store if the infohash is provided torrent_data = self.trsession.get_collected_torrent(infohash) if torrent_data is not None: # use this torrent data for downloading tdef = TorrentDef.load_from_memory(torrent_data) if tdef is None: assert torrentfilename is not None, "torrent file must be provided if tdef and infohash are not given" # try to get the torrent from the given torrent file torrent_data = fix_torrent(torrentfilename) if torrent_data is None: raise TorrentFileException( "error while decoding torrent file") tdef = TorrentDef.load_from_memory(torrent_data) assert tdef is not None, "tdef MUST not be None after loading torrent" d = self.trsession.get_download(tdef.get_infohash()) if d: new_trackers = list( set(tdef.get_trackers_as_single_tuple()) - set(d.get_def().get_trackers_as_single_tuple())) if not new_trackers: raise DuplicateDownloadException( "This download already exists.") else: self.trsession.update_trackers(tdef.get_infohash(), new_trackers) return default_dl_config = DefaultDownloadStartupConfig.getInstance() dscfg = default_dl_config.copy() if dconfig is not None: dscfg = dconfig self._logger.info('start_download: Starting in VOD mode') result = self.trsession.start_download_from_tdef(tdef, dscfg) return result
def add_torrent(self, torrentdl, atp): # If we are collecting the torrent for this infohash, abort this first. with self.metainfo_lock: if atp.has_key('ti'): infohash = str(atp['ti'].info_hash()) elif atp.has_key('url'): infohash = binascii.hexlify(parse_magnetlink(atp['url'])[1]) else: infohash = str(atp["info_hash"]) if infohash in self.metainfo_requests: print >> sys.stderr, "LibtorrentMgr: killing get_metainfo request for", infohash handle, _ = self.metainfo_requests.pop(infohash) if handle: self.ltsession.remove_torrent(handle, 0) handle = self.ltsession.add_torrent(atp) infohash = str(handle.info_hash()) with self.torlock: if infohash in self.torrents: raise DuplicateDownloadException() self.torrents[infohash] = torrentdl if DEBUG: print >> sys.stderr, "LibtorrentMgr: added torrent", infohash return handle
def add_torrent(self, torrentdl, atp): # If we are collecting the torrent for this infohash, abort this first. with self.metainfo_lock: ltsession = self.get_session(atp.pop('hops', 0)) if 'ti' in atp: infohash = str(atp['ti'].info_hash()) elif 'url' in atp: infohash = binascii.hexlify(parse_magnetlink(atp['url'])[1]) else: raise ValueError('No ti or url key in add_torrent_params') if infohash in self.metainfo_requests: self._logger.info("killing get_metainfo request for %s", infohash) request_handle = self.metainfo_requests.pop(infohash)['handle'] if request_handle: ltsession.remove_torrent(request_handle, 0) torrent_handle = ltsession.add_torrent(encode_atp(atp)) infohash = str(torrent_handle.info_hash()) if infohash in self.torrents: raise DuplicateDownloadException("This download already exists.") self.torrents[infohash] = (torrentdl, ltsession) self._logger.debug("added torrent %s", infohash) return torrent_handle
def add(self, tdef, dscfg, pstate=None, setupDelay=0, hidden=False, share_mode=False, checkpoint_disabled=False): """ Called by any thread """ d = None with self.session_lock: if not isinstance(tdef, TorrentDefNoMetainfo) and not tdef.is_finalized(): raise ValueError("TorrentDef not finalized") infohash = tdef.get_infohash() # Create the destination directory if it does not exist yet try: if not os.path.isdir(dscfg.get_dest_dir()): os.makedirs(dscfg.get_dest_dir()) except OSError: self._logger.error("Unable to create the download destination directory.") if dscfg.get_time_added() == 0: dscfg.set_time_added(int(timemod.time())) # Check if running or saved on disk if infohash in self.downloads: raise DuplicateDownloadException("This download already exists.") from Tribler.Core.Libtorrent.LibtorrentDownloadImpl import LibtorrentDownloadImpl d = LibtorrentDownloadImpl(self.session, tdef) if pstate is None: # not already resuming pstate = self.load_download_pstate_noexc(infohash) if pstate is not None: self._logger.debug("tlm: add: pstate is %s %s", pstate.get('dlstate', 'status'), pstate.get('dlstate', 'progress')) # Store in list of Downloads, always. self.downloads[infohash] = d setup_deferred = d.setup(dscfg, pstate, wrapperDelay=setupDelay, share_mode=share_mode, checkpoint_disabled=checkpoint_disabled) setup_deferred.addCallback(self.on_download_handle_created) if d and not hidden and self.session.config.get_megacache_enabled(): @forceDBThread def write_my_pref(): torrent_id = self.torrent_db.getTorrentID(infohash) data = {'destination_path': d.get_dest_dir()} self.mypref_db.addMyPreference(torrent_id, data) if isinstance(tdef, TorrentDefNoMetainfo): self.torrent_db.addOrGetTorrentID(tdef.get_infohash()) self.torrent_db.updateTorrent(tdef.get_infohash(), name=tdef.get_name_as_unicode()) write_my_pref() elif self.rtorrent_handler: self.rtorrent_handler.save_torrent(tdef, write_my_pref) else: self.torrent_db.addExternalTorrent(tdef, extra_info={'status': 'good'}) write_my_pref() return d
def add_torrent(self, torrentdl, atp): handle = self.ltsession.add_torrent(atp) infohash = str(handle.info_hash()) with self.torlock: if infohash in self.torrents: raise DuplicateDownloadException() self.torrents[infohash] = torrentdl if DEBUG: print >> sys.stderr, "LibtorrentMgr: added torrent", infohash return handle
def startDownload(self, torrentfilename=None, destdir=None, infohash=None, tdef=None, cmdline=False, vodmode=False, hops=0, selectedFiles=None, hidden=False): self._logger.debug(u"startDownload: %s %s %s %s %s", torrentfilename, destdir, tdef, vodmode, selectedFiles) # TODO(lipu): remove the assertions after it becomes stable if infohash is not None: assert isinstance(infohash, str), "infohash type: %s" % type(infohash) assert len(infohash) == 20, "infohash length is not 20: %s, %s" % ( len(infohash), infohash) # the priority of the parameters is: (1) tdef, (2) infohash, (3) torrent_file. # so if we have tdef, infohash and torrent_file will be ignored, and so on. if tdef is None: if infohash is not None: # try to get the torrent from torrent_store if the infohash is provided torrent_data = self.utility.session.get_collected_torrent( infohash) if torrent_data is not None: # use this torrent data for downloading tdef = TorrentDef.load_from_memory(torrent_data) if tdef is None: assert torrentfilename is not None, "torrent file must be provided if tdef and infohash are not given" # try to get the torrent from the given torrent file torrent_data = fix_torrent(torrentfilename) if torrent_data is None: # show error message: could not open torrent file dlg = wx.MessageBox( self, "Could not open torrent file %s" % torrentfilename, "Error", wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return tdef = TorrentDef.load_from_memory(torrent_data) assert tdef is not None, "tdef MUST not be None after loading torrent" try: d = self.utility.session.get_download(tdef.get_infohash()) if d: new_trackers = list( set(tdef.get_trackers_as_single_tuple()) - set(d.get_def().get_trackers_as_single_tuple())) if not new_trackers: raise DuplicateDownloadException() else: @forceWxThread def do_gui(): # Show update tracker dialog dialog = wx.MessageDialog( None, 'This torrent is already being downloaded. Do you wish to load the trackers from it?', 'Tribler', wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) if dialog.ShowModal() == wx.ID_YES: # Update trackers self.utility.session.update_trackers( tdef.get_infohash(), new_trackers) dialog.Destroy() do_gui() return defaultDLConfig = DefaultDownloadStartupConfig.getInstance() dscfg = defaultDLConfig.copy() cancelDownload = False useDefault = not self.utility.read_config('showsaveas') safe_seeding = self.utility.read_config( 'default_safeseeding_enabled') if not useDefault and not destdir: defaultname = tdef.get_name_as_unicode( ) if tdef.is_multifile_torrent() else None if wx.Thread_IsMain(): dlg = SaveAs(None, tdef, dscfg.get_dest_dir(), defaultname, selectedFiles) dlg.CenterOnParent() if isinstance(tdef, TorrentDefNoMetainfo): # Correct for the smaller size of the dialog if there is no metainfo center_pos = dlg.GetPosition() center_pos[1] -= 150 dlg.SetPosition(center_pos) if dlg.ShowModal() == wx.ID_OK: # If the dialog has collected a torrent, use the new tdef tdef = dlg.GetCollected() or tdef if tdef and tdef.is_multifile_torrent(): selectedFiles = dlg.GetSelectedFiles() destdir = dlg.GetPath() # Anonymity over exit nodes or hidden services safe_seeding = dlg.UseSafeSeeding() if dlg.UseTunnels(): hops = self.utility.read_config( 'default_number_hops') else: cancelDownload = True dlg.Destroy() else: raise Exception("cannot create dialog, not on wx thread") # use default setup else: if useDefault: if self.utility.read_config('default_anonymity_enabled'): # only load default anonymous level if we use default settings hops = self.utility.read_config('default_number_hops') else: hops = 0 if hops > 0: if not tdef: raise Exception( 'Currently only torrents can be downloaded in anonymous mode' ) dscfg.set_hops(hops) dscfg.set_safe_seeding(safe_seeding) if not cancelDownload: if destdir is not None: dscfg.set_dest_dir(destdir) if selectedFiles and len(selectedFiles) == 1: # we should filter files to see if they are all playable videofiles = selectedFiles elif tdef and not selectedFiles: videofiles = tdef.get_files(exts=videoextdefaults) else: videofiles = [] # disable vodmode if no videofiles, unless we still need to collect the torrent if vodmode and len(videofiles) == 0 and ( not tdef or not isinstance(tdef, TorrentDefNoMetainfo)): vodmode = False if vodmode: self._logger.info( 'MainFrame: startDownload: Starting in VOD mode') result = self.utility.session.start_download_from_tdef( tdef, dscfg) self.guiUtility.library_manager.playTorrent( tdef.get_infohash(), videofiles[0] if len(videofiles) == 1 else None) else: if selectedFiles: dscfg.set_selected_files(selectedFiles) self._logger.debug( 'MainFrame: startDownload: Starting in DL mode') result = self.utility.session.start_download_from_tdef( tdef, dscfg, hidden=hidden) if result and not hidden: self.show_saved(tdef) return result except DuplicateDownloadException as e: # If there is something on the cmdline, all other torrents start # in STOPPED state. Restart if cmdline: dlist = self.utility.session.get_downloads() for d in dlist: if d.get_def().get_infohash() == tdef.get_infohash(): d.restart() break if wx.Thread_IsMain(): # show nice warning dialog dlg = wx.MessageDialog( None, "You are already downloading this torrent, see the Downloads section.", "Duplicate download", wx.OK | wx.ICON_ERROR) result = dlg.ShowModal() dlg.Destroy() else: print_exc() self.onWarning(e) except Exception as e: print_exc() self.onWarning(e) return None
def test_duplicate_download_exception(self): raise DuplicateDownloadException("DuplicateDownloadException")
def add(self, tdef, dscfg, pstate=None, initialdlstatus=None, setupDelay=0, hidden=False): """ Called by any thread """ d = None self.sesslock.acquire() try: if not isinstance( tdef, TorrentDefNoMetainfo) and not tdef.is_finalized(): raise ValueError("TorrentDef not finalized") infohash = tdef.get_infohash() # Check if running or saved on disk if infohash in self.downloads: raise DuplicateDownloadException() from Tribler.Core.Libtorrent.LibtorrentDownloadImpl import LibtorrentDownloadImpl d = LibtorrentDownloadImpl(self.session, tdef) if pstate is None: # not already resuming pstate = self.load_download_pstate_noexc(infohash) if pstate is not None: self._logger.debug("tlm: add: pstate is %s %s", pstate.get('dlstate', 'status'), pstate.get('dlstate', 'progress')) # Store in list of Downloads, always. self.downloads[infohash] = d d.setup(dscfg, pstate, initialdlstatus, self.network_engine_wrapper_created_callback, wrapperDelay=setupDelay) finally: self.sesslock.release() if d and not hidden and self.session.get_megacache(): @forceDBThread def write_my_pref(): torrent_id = self.torrent_db.getTorrentID(infohash) data = {'destination_path': d.get_dest_dir()} self.mypref_db.addMyPreference(torrent_id, data) if isinstance(tdef, TorrentDefNoMetainfo): self.torrent_db.addOrGetTorrentID(tdef.get_infohash()) self.torrent_db.updateTorrent(tdef.get_infohash(), name=tdef.get_name_as_unicode()) write_my_pref() elif self.rtorrent_handler: self.rtorrent_handler.save_torrent(tdef, write_my_pref) else: self.torrent_db.addExternalTorrent( tdef, extra_info={'status': 'good'}) write_my_pref() return d