def __init__(self, session): BaseChannelsEndpoint.__init__(self, session) child_handler_dict = {"subscribed": ChannelsSubscribedEndpoint, "discovered": ChannelsDiscoveredEndpoint, "popular": ChannelsPopularEndpoint} for path, child_cls in child_handler_dict.iteritems(): self.putChild(path, child_cls(self.session))
def render_POST(self, request): """ .. http:post:: /channels/discovered/(string: channelid)/playlists/(int: playlistid) Edit a specific playlist. The new name and description should be passed as parameter. **Example request**: .. sourcecode:: none curl -X POST http://localhost:8085/channels/discovered/abcd/playlists/3 --data "name=test&description=my test description" **Example response**: .. sourcecode:: javascript { "modified": True } :statuscode 404: if the specified channel (community) or playlist does not exist or if the name and description parameters are missing. """ parameters = http.parse_qs(request.content.read(), 1) if 'name' not in parameters or len(parameters['name']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "name parameter missing"}) if 'description' not in parameters or len( parameters['description']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "description parameter missing"}) channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsPlaylistsEndpoint.return_404(request) playlist = self.channel_db_handler.getPlaylist(self.playlist_id, ['Playlists.id']) if playlist is None: return BaseChannelsEndpoint.return_404( request, message="this playlist cannot be found") channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404( request, message="the community for the specific channel cannot be found" ) channel_community.modifyPlaylist( playlist[0], { 'name': parameters['name'][0], 'description': parameters['description'][0] }) return json.dumps({"modified": True})
def __init__(self, session, cid): BaseChannelsEndpoint.__init__(self, session) self.cid = bytes(cid.decode('hex')) child_handler_dict = {"torrents": ChannelsTorrentsEndpoint, "rssfeeds": ChannelsRssFeedsEndpoint, "playlists": ChannelsPlaylistsEndpoint, "recheckfeeds": ChannelsRecheckFeedsEndpoint} for path, child_cls in child_handler_dict.iteritems(): self.putChild(path, child_cls(session, self.cid))
def render_DELETE(self, request): """ .. http:delete:: /channels/discovered/(string: channelid)/playlists/(int: playlistid)/(string: infohash) Remove a torrent with a specified infohash from a specified playlist. **Example request**: .. sourcecode:: none curl -X DELETE http://localhost:8085/channels/discovered/abcd/playlists/3/abcdef **Example response**: .. sourcecode:: javascript { "removed": True } :statuscode 404: if the specified channel/playlist/torrent does not exist. """ channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsPlaylistsEndpoint.return_404(request) playlist = self.channel_db_handler.getPlaylist( self.playlist_id, ['Playlists.dispersy_id']) if playlist is None: return BaseChannelsEndpoint.return_404( request, message="this playlist cannot be found") channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404( request, message="the community for the specific channel cannot be found" ) # Check whether this torrent is present in this playlist and if so, get the dispersy ID torrent_dispersy_id = -1 for torrent in self.channel_db_handler.getTorrentsFromPlaylist( self.playlist_id, ["infohash", "PlaylistTorrents.dispersy_id"]): if torrent[0] == self.infohash: torrent_dispersy_id = torrent[1] break if torrent_dispersy_id == -1: request.setResponseCode(http.NOT_FOUND) return json.dumps( {"error": "this torrent is not in your playlist"}) channel_community.remove_playlist_torrents(int(self.playlist_id), [torrent_dispersy_id]) return json.dumps({"removed": True})
def __init__(self, session, cid): BaseChannelsEndpoint.__init__(self, session) self.cid = bytes(cid.decode('hex')) child_handler_dict = {"torrents": ChannelsTorrentsEndpoint, "rssfeeds": ChannelsRssFeedsEndpoint, "playlists": ChannelsPlaylistsEndpoint, "recheckfeeds": ChannelsRecheckFeedsEndpoint, "mdblob": ChannelsDiscoveredExportEndpoint} for path, child_cls in child_handler_dict.iteritems(): self.putChild(path, child_cls(session, self.cid))
def render_PUT(self, request): """ .. http:put:: /channels/discovered/(string: channelid)/playlists/(int: playlistid)/(string: infohash) Add a torrent with a specified infohash to a specified playlist. The torrent that is added to the playlist, should be present in the channel. **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered/abcd/playlists/3/abcdef **Example response**: .. sourcecode:: javascript { "added": True } :statuscode 404: if the specified channel/playlist/torrent does not exist. :statuscode 409: if the specified torrent is already in the specified playlist. """ channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsPlaylistsEndpoint.return_404(request) channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404(request, message="the community for the specific channel cannot be found") playlist = self.channel_db_handler.getPlaylist(self.playlist_id, ['Playlists.dispersy_id']) if playlist is None: return BaseChannelsEndpoint.return_404(request, message="this playlist cannot be found") # Check whether this torrent is present in your channel torrent_in_channel = False for torrent in self.channel_db_handler.getTorrentsFromChannelId(channel_info[0], True, ["infohash"]): if torrent[0] == self.infohash: torrent_in_channel = True break if not torrent_in_channel: return BaseChannelsEndpoint.return_404(request, message="this torrent is not available in your channel") # Check whether this torrent is not already present in this playlist for torrent in self.channel_db_handler.getTorrentsFromPlaylist(self.playlist_id, ["infohash"]): if torrent[0] == self.infohash: request.setResponseCode(http.CONFLICT) return json.dumps({"error": "this torrent is already in your playlist"}) channel_community.create_playlist_torrents(int(self.playlist_id), [self.infohash]) return json.dumps({"added": True})
def render_PUT(self, request): """ .. http:put:: /channels/discovered/(string: channelid)/playlists/(int: playlistid)/(string: infohash) Add a torrent with a specified infohash to a specified playlist. The torrent that is added to the playlist, should be present in the channel. **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered/abcd/playlists/3/abcdef **Example response**: .. sourcecode:: javascript { "added": True } :statuscode 404: if the specified channel/playlist/torrent does not exist. :statuscode 409: if the specified torrent is already in the specified playlist. """ channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsPlaylistsEndpoint.return_404(request) channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404(request, message="the community for the specific channel cannot be found") playlist = self.channel_db_handler.getPlaylist(self.playlist_id, ['Playlists.dispersy_id']) if playlist is None: return BaseChannelsEndpoint.return_404(request, message="this playlist cannot be found") # Check whether this torrent is present in your channel torrent_in_channel = False for torrent in self.channel_db_handler.getTorrentsFromChannelId(channel_info[0], True, ["infohash"]): if torrent[0] == self.infohash: torrent_in_channel = True break if not torrent_in_channel: return BaseChannelsEndpoint.return_404(request, message="this torrent is not available in your channel") # Check whether this torrent is not already present in this playlist for torrent in self.channel_db_handler.getTorrentsFromPlaylist(self.playlist_id, ["infohash"]): if torrent[0] == self.infohash: request.setResponseCode(http.CONFLICT) return json.dumps({"error": "this torrent is already in your playlist"}) channel_community.create_playlist_torrents(int(self.playlist_id), [self.infohash]) return json.dumps({"added": True})
def __init__(self, session): BaseChannelsEndpoint.__init__(self, session) child_handler_dict = { "subscribed": ChannelsSubscribedEndpoint, "discovered": ChannelsDiscoveredEndpoint, "popular": ChannelsPopularEndpoint } for path, child_cls in child_handler_dict.iteritems(): self.putChild(path, child_cls(self.session))
def render_POST(self, request): """ .. http:post:: /channels/discovered/(string: channelid)/playlists/(int: playlistid) Edit a specific playlist. The new name and description should be passed as parameter. **Example request**: .. sourcecode:: none curl -X POST http://localhost:8085/channels/discovered/abcd/playlists/3 --data "name=test&description=my test description" **Example response**: .. sourcecode:: javascript { "modified": True } :statuscode 404: if the specified channel (community) or playlist does not exist or if the name and description parameters are missing. """ parameters = http.parse_qs(request.content.read(), 1) if 'name' not in parameters or len(parameters['name']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "name parameter missing"}) if 'description' not in parameters or len(parameters['description']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "description parameter missing"}) channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsPlaylistsEndpoint.return_404(request) playlist = self.channel_db_handler.getPlaylist(self.playlist_id, ['Playlists.id']) if playlist is None: return BaseChannelsEndpoint.return_404(request, message="this playlist cannot be found") channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404(request, message="the community for the specific channel cannot be found") channel_community.modifyPlaylist(playlist[0], {'name': parameters['name'][0], 'description': parameters['description'][0]}) return json.dumps({"modified": True})
def render_DELETE(self, request): """ .. http:delete:: /channels/discovered/(string: channelid)/playlists/(int: playlistid)/(string: infohash) Remove a torrent with a specified infohash from a specified playlist. **Example request**: .. sourcecode:: none curl -X DELETE http://localhost:8085/channels/discovered/abcd/playlists/3/abcdef **Example response**: .. sourcecode:: javascript { "removed": True } :statuscode 404: if the specified channel/playlist/torrent does not exist. """ channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsPlaylistsEndpoint.return_404(request) playlist = self.channel_db_handler.getPlaylist(self.playlist_id, ['Playlists.dispersy_id']) if playlist is None: return BaseChannelsEndpoint.return_404(request, message="this playlist cannot be found") channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404(request, message="the community for the specific channel cannot be found") # Check whether this torrent is present in this playlist and if so, get the dispersy ID torrent_dispersy_id = -1 for torrent in self.channel_db_handler.getTorrentsFromPlaylist(self.playlist_id, ["infohash", "PlaylistTorrents.dispersy_id"]): if torrent[0] == self.infohash: torrent_dispersy_id = torrent[1] break if torrent_dispersy_id == -1: request.setResponseCode(http.NOT_FOUND) return json.dumps({"error": "this torrent is not in your playlist"}) channel_community.remove_playlist_torrents(int(self.playlist_id), [torrent_dispersy_id]) return json.dumps({"removed": True})
def render_DELETE(self, request): """ .. http:delete:: /channels/discovered/(string: channelid)/playlists/(int: playlistid) Remove a playlist with a specified playlist id. **Example request**: .. sourcecode:: none curl -X DELETE http://localhost:8085/channels/discovered/abcd/playlists/3 **Example response**: .. sourcecode:: javascript { "removed": True } :statuscode 404: if the specified channel (community) or playlist does not exist """ channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsPlaylistsEndpoint.return_404(request) playlist = self.channel_db_handler.getPlaylist( self.playlist_id, ['Playlists.dispersy_id', 'Playlists.id']) if playlist is None: return BaseChannelsEndpoint.return_404( request, message="this playlist cannot be found") channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404( request, message="the community for the specific channel cannot be found" ) # Remove all torrents from this playlist playlist_torrents = self.channel_db_handler.get_torrent_ids_from_playlist( playlist[1]) channel_community.remove_playlist_torrents( playlist[0], [dispersy_id for dispersy_id, in playlist_torrents]) # Remove the playlist itself channel_community.remove_playlists([playlist[0]]) return json.dumps({"removed": True})
def render_DELETE(self, request): """ .. http:delete:: /channels/discovered/(string: channelid)/torrents/(string: torrent infohash) Remove a torrent with a given infohash from a given channel. **Example request**: .. sourcecode:: none curl -X DELETE http://localhost:8085/channels/discovered/abcdefg/torrents/ 97d2d8f5d37e56cfaeaae151d55f05b077074779 **Example response**: .. sourcecode:: javascript { "removed": True } :statuscode 404: if the channel is not found or if the torrent is not found in the specified channel """ channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsTorrentsEndpoint.return_404(request) torrent_db_columns = [ 'Torrent.torrent_id', 'infohash', 'Torrent.name', 'length', 'Torrent.category', 'num_seeders', 'num_leechers', 'last_tracker_check', 'ChannelTorrents.dispersy_id' ] torrent_info = self.channel_db_handler.getTorrentFromChannelId( channel_info[0], self.path.decode('hex'), torrent_db_columns) if torrent_info is None: return BaseChannelsEndpoint.return_404(request, message=UNKNOWN_TORRENT_MSG) channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404( request, message=UNKNOWN_COMMUNITY_MSG) channel_community.remove_torrents([ torrent_info[8] ]) # the 8th index is the dispersy id of the channel torrent return json.dumps({"removed": True})
def _on_add_failed(failure): failure.trap(ValueError, DuplicateTorrentFileError, SchemeNotSupported) self._logger.exception(failure.value) request.write( BaseChannelsEndpoint.return_500(self, request, failure.value)) request.finish()
def render_DELETE(self, request): """ .. http:delete:: /channels/discovered/(string: channelid)/playlists/(int: playlistid) Remove a playlist with a specified playlist id. **Example request**: .. sourcecode:: none curl -X DELETE http://localhost:8085/channels/discovered/abcd/playlists/3 **Example response**: .. sourcecode:: javascript { "removed": True } :statuscode 404: if the specified channel (community) or playlist does not exist """ channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsPlaylistsEndpoint.return_404(request) playlist = self.channel_db_handler.getPlaylist(self.playlist_id, ['Playlists.dispersy_id', 'Playlists.id']) if playlist is None: return BaseChannelsEndpoint.return_404(request, message="this playlist cannot be found") channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404(request, message="the community for the specific channel cannot be found") # Remove all torrents from this playlist playlist_torrents = self.channel_db_handler.get_torrent_ids_from_playlist(playlist[1]) channel_community.remove_playlist_torrents(playlist[0], [dispersy_id for dispersy_id, in playlist_torrents]) # Remove the playlist itself channel_community.remove_playlists([playlist[0]]) return json.dumps({"removed": True})
def render_PUT(self, request): """ .. http:put:: /channels/discovered/(string: channelid)/torrents Add a torrent file to your own channel. Returns error 500 if something is wrong with the torrent file and DuplicateTorrentFileError if already added to your channel. The torrent data is passed as base-64 encoded string. The description is optional. **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered/abcd/torrents --data "torrent=...&description=funny video" **Example response**: .. sourcecode:: javascript { "added": True } :statuscode 404: if your channel does not exist. :statuscode 500: if the passed torrent data is corrupt. """ channel = self.get_channel_from_db(self.cid) if channel is None: return ChannelsTorrentsEndpoint.return_404(request) parameters = http.parse_qs(request.content.read(), 1) if 'torrent' not in parameters or len(parameters['torrent']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "torrent parameter missing"}) if 'description' not in parameters or len( parameters['description']) == 0: extra_info = {} else: extra_info = {'description': parameters['description'][0]} try: torrent = base64.b64decode(parameters['torrent'][0]) torrent_def = TorrentDef.load_from_memory(torrent) self.session.add_torrent_def_to_channel(channel[0], torrent_def, extra_info, forward=True) except (DuplicateTorrentFileError, ValueError) as ex: return BaseChannelsEndpoint.return_500(self, request, ex) return json.dumps({"added": True})
def render_POST(self, request): """ .. http:post:: /mychannel Modify the name and/or the description of your channel. This endpoint returns a 404 HTTP response if you have not created a channel (yet). **Example request**: .. sourcecode:: none curl -X POST http://localhost:8085/mychannel --data "name=My fancy playlist&description=This playlist contains some random movies" **Example response**: .. sourcecode:: javascript { "modified": True } :statuscode 404: if your channel has not been created (yet). """ my_channel_id = self.channel_db_handler.getMyChannelId() if my_channel_id is None: request.setResponseCode(http.NOT_FOUND) return json.dumps({"error": NO_CHANNEL_CREATED_RESPONSE_MSG}) channel_community = self.get_community_for_channel_id(my_channel_id) if channel_community is None: return BaseChannelsEndpoint.return_404( request, message="the community for the your channel cannot be found") parameters = http.parse_qs(request.content.read(), 1) my_channel = self.channel_db_handler.getChannel(my_channel_id) if not get_parameter(parameters, 'name'): request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": 'channel name cannot be empty'}) changes = {} if my_channel[2] != get_parameter(parameters, 'name'): changes['name'] = unicode(get_parameter(parameters, 'name'), 'utf-8') if my_channel[3] != get_parameter(parameters, 'description'): changes['description'] = unicode( get_parameter(parameters, 'description'), 'utf-8') channel_community.modifyChannel(changes) return json.dumps({'modified': True})
def render_PUT(self, request): """ .. http:put:: /channels/discovered/(string: channelid)/playlists Create a new empty playlist with a given name and description. The name and description parameters are mandatory. **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered/abcd/playlists --data "name=My fancy playlist&description=This playlist contains some random movies" **Example response**: .. sourcecode:: javascript { "created": True } :statuscode 400: if you are missing the name and/or description parameter :statuscode 404: if the specified channel does not exist """ parameters = http.parse_qs(request.content.read(), 1) if 'name' not in parameters or len(parameters['name']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "name parameter missing"}) if 'description' not in parameters or len( parameters['description']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "description parameter missing"}) channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsPlaylistsEndpoint.return_404(request) channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404( request, message="the community for the specific channel cannot be found" ) channel_community.create_playlist( unicode(parameters['name'][0], 'utf-8'), unicode(parameters['description'][0], 'utf-8'), []) return json.dumps({"created": True})
def render_PUT(self, request): """ .. http:put:: /channels/discovered Create your own new channel. The passed mode and descriptions are optional. Valid modes include: 'open', 'semi-open' or 'closed'. By default, the mode of the new channel is 'closed'. **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered --data "name=fancy name&description=fancy description&mode=open" **Example response**: .. sourcecode:: javascript { "added": 23 } :statuscode 500: if a channel with the specified name already exists. """ parameters = http.parse_qs(request.content.read(), 1) if 'name' not in parameters or len(parameters['name']) == 0 or len( parameters['name'][0]) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "channel name cannot be empty"}) if 'description' not in parameters or len( parameters['description']) == 0: description = u'' else: description = unicode(parameters['description'][0], 'utf-8') if 'mode' not in parameters or len(parameters['mode']) == 0: # By default, the mode of the new channel is closed. mode = u'closed' else: mode = unicode(parameters['mode'][0], 'utf-8') try: channel_id = self.session.create_channel( unicode(parameters['name'][0], 'utf-8'), description, mode) except DuplicateChannelNameError as ex: return BaseChannelsEndpoint.return_500(self, request, ex) return json.dumps({"added": channel_id})
def render_PUT(self, request): """ .. http:put:: /channels/discovered/(string: channelid)/playlists Create a new empty playlist with a given name and description. The name and description parameters are mandatory. **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered/abcd/playlists --data "name=My fancy playlist&description=This playlist contains some random movies" **Example response**: .. sourcecode:: javascript { "created": True } :statuscode 400: if you are missing the name and/or description parameter :statuscode 404: if the specified channel does not exist """ parameters = http.parse_qs(request.content.read(), 1) if 'name' not in parameters or len(parameters['name']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "name parameter missing"}) if 'description' not in parameters or len(parameters['description']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "description parameter missing"}) channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsPlaylistsEndpoint.return_404(request) channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404(request, message="the community for the specific channel cannot be found") channel_community.create_playlist(unicode(parameters['name'][0], 'utf-8'), unicode(parameters['description'][0], 'utf-8'), []) return json.dumps({"created": True})
def __init__(self, session, cid, playlist_id): BaseChannelsEndpoint.__init__(self, session) self.cid = cid self.playlist_id = playlist_id
def render_DELETE(self, request): """ .. http:delete:: /channels/discovered/(string: channelid)/torrents/(string: comma separated torrent infohashes) Remove a single or multiple torrents with the given comma separated infohashes from a given channel. **Example request**: .. sourcecode:: none curl -X DELETE http://localhost:8085/channels/discovered/abcdefg/torrents/ 97d2d8f5d37e56cfaeaae151d55f05b077074779,971d55f05b077074779d2d8f5d37e56cfaeaae15 **Example response**: .. sourcecode:: javascript { "removed": True } .. sourcecode:: javascript { "removed": False, "failed_torrents":["97d2d8f5d37e56cfaeaae151d55f05b077074779"] } :statuscode 404: if the channel is not found """ if self.is_chant_channel: with db_session: my_key = self.session.trustchain_keypair my_channel_id = my_key.pub().key_to_bin() failed_torrents = [] if my_channel_id != self.cid: request.setResponseCode(http.NOT_ALLOWED) return json.dumps({ "error": "you can only remove torrents from your own chant channel" }) my_channel = self.session.lm.mds.get_my_channel() if not my_channel: return ChannelsTorrentsEndpoint.return_404(request) for torrent_path in self.path.split(","): infohash = torrent_path.decode('hex') if not my_channel.delete_torrent_from_channel(infohash): failed_torrents.append(torrent_path) if failed_torrents: return json.dumps({ "removed": False, "failed_torrents": failed_torrents }) return json.dumps({"removed": True}) else: channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsTorrentsEndpoint.return_404(request) channel_community = self.get_community_for_channel_id( channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404( request, message=UNKNOWN_COMMUNITY_MSG) torrent_db_columns = [ 'Torrent.torrent_id', 'infohash', 'Torrent.name', 'length', 'Torrent.category', 'num_seeders', 'num_leechers', 'last_tracker_check', 'ChannelTorrents.dispersy_id' ] failed_torrents = [] for torrent_path in self.path.split(","): torrent_info = self.channel_db_handler.getTorrentFromChannelId( channel_info[0], torrent_path.decode('hex'), torrent_db_columns) if torrent_info is None: failed_torrents.append(torrent_path) else: # the 8th index is the dispersy id of the channel torrent channel_community.remove_torrents([torrent_info[8]]) if failed_torrents: return json.dumps({ "removed": False, "failed_torrents": failed_torrents }) return json.dumps({"removed": True})
def render_PUT(self, request): """ .. http:put:: /channels/discovered/(string: channelid)/torrents/http%3A%2F%2Ftest.com%2Ftest.torrent Add a torrent by magnet or url to your channel. Returns error 500 if something is wrong with the torrent file and DuplicateTorrentFileError if already added to your channel (except with magnet links). **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered/abcdefg/torrents/ http%3A%2F%2Ftest.com%2Ftest.torrent --data "description=nice video" **Example response**: .. sourcecode:: javascript { "added": "http://test.com/test.torrent" } :statuscode 404: if your channel does not exist. :statuscode 500: if the specified torrent is already in your channel. """ my_key = self.session.trustchain_keypair my_channel_id = my_key.pub().key_to_bin() if self.is_chant_channel: if my_channel_id != self.cid: request.setResponseCode(http.NOT_ALLOWED) return json.dumps({ "error": "you can only add torrents to your own chant channel" }) channel = self.session.lm.mds.ChannelMetadata.get_channel_with_id( my_channel_id) else: channel = self.get_channel_from_db(self.cid) if channel is None: return BaseChannelsEndpoint.return_404(request) parameters = http.parse_qs(request.content.read(), 1) if 'description' not in parameters or len( parameters['description']) == 0: extra_info = {} else: extra_info = {'description': parameters['description'][0]} def _on_url_fetched(data): return TorrentDef.load_from_memory(data) def _on_magnet_fetched(meta_info): return TorrentDef.load_from_dict(meta_info) def _on_torrent_def_loaded(torrent_def): if self.is_chant_channel: # We have to get my channel again since we are in a different database session now with db_session: channel = self.session.lm.mds.get_my_channel() channel.add_torrent_to_channel(torrent_def, extra_info) else: channel = self.get_channel_from_db(self.cid) self.session.add_torrent_def_to_channel(channel[0], torrent_def, extra_info, forward=True) return self.path def _on_added(added): request.write(json.dumps({"added": added})) request.finish() def _on_add_failed(failure): failure.trap(ValueError, DuplicateTorrentFileError, SchemeNotSupported) self._logger.exception(failure.value) request.write( BaseChannelsEndpoint.return_500(self, request, failure.value)) request.finish() def _on_timeout(_): request.write( BaseChannelsEndpoint.return_500( self, request, RuntimeError("Metainfo timeout"))) request.finish() if self.path.startswith("http:") or self.path.startswith("https:"): self.deferred = http_get(self.path) self.deferred.addCallback(_on_url_fetched) if self.path.startswith("magnet:"): try: self.session.lm.ltmgr.get_metainfo( self.path, callback=self.deferred.callback, timeout=30, timeout_callback=_on_timeout, notify=True) except Exception as ex: self.deferred.errback(ex) self.deferred.addCallback(_on_magnet_fetched) self.deferred.addCallback(_on_torrent_def_loaded) self.deferred.addCallback(_on_added) self.deferred.addErrback(_on_add_failed) return NOT_DONE_YET
def render_PUT(self, request): """ .. http:put:: /channels/discovered/(string: channelid)/torrents Add a torrent file to your own channel. Returns error 500 if something is wrong with the torrent file and DuplicateTorrentFileError if already added to your channel. The torrent data is passed as base-64 encoded string. The description is optional. **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered/abcd/torrents --data "torrent=...&description=funny video" **Example response**: .. sourcecode:: javascript { "added": True } :statuscode 404: if your channel does not exist. :statuscode 500: if the passed torrent data is corrupt. """ key = self.session.trustchain_keypair my_channel_id = key.pub().key_to_bin() # First check whether the channel actually exists if self.is_chant_channel: if my_channel_id != self.cid: request.setResponseCode(http.NOT_ALLOWED) return json.dumps({ "error": "you can only add torrents to your own chant channel" }) channel = self.session.lm.mds.ChannelMetadata.get_channel_with_id( my_channel_id) if not channel: return ChannelsTorrentsEndpoint.return_404(request) else: channel = self.get_channel_from_db(self.cid) if channel is None: return ChannelsTorrentsEndpoint.return_404(request) parameters = http.parse_qs(request.content.read(), 1) if 'torrent' not in parameters or len(parameters['torrent']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "torrent parameter missing"}) if 'description' not in parameters or len( parameters['description']) == 0: extra_info = {} else: extra_info = {'description': parameters['description'][0]} # Try to parse the torrent data try: torrent = base64.b64decode(parameters['torrent'][0]) torrent_def = TorrentDef.load_from_memory(torrent) except ValueError as exc: return BaseChannelsEndpoint.return_500(self, request, exc) if self.is_chant_channel: try: channel.add_torrent_to_channel(torrent_def, extra_info) except DuplicateTorrentFileError as exc: return BaseChannelsEndpoint.return_500(self, request, exc) else: try: self.session.add_torrent_def_to_channel(channel[0], torrent_def, extra_info, forward=True) except (DuplicateTorrentFileError, HttpError) as ex: return BaseChannelsEndpoint.return_500(self, request, ex) return json.dumps({"added": True})
def render_PUT(self, request): """ .. http:put:: /channels/discovered/(string: channelid)/torrents/http%3A%2F%2Ftest.com%2Ftest.torrent Add a torrent by magnet or url to your channel. Returns error 500 if something is wrong with the torrent file and DuplicateTorrentFileError if already added to your channel (except with magnet links). **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered/abcdefg/torrents/ http%3A%2F%2Ftest.com%2Ftest.torrent --data "description=nice video" **Example response**: .. sourcecode:: javascript { "added": "http://test.com/test.torrent" } :statuscode 404: if your channel does not exist. :statuscode 500: if the specified torrent is already in your channel. """ channel = self.get_channel_from_db(self.cid) if channel is None: return BaseChannelsEndpoint.return_404(request) parameters = http.parse_qs(request.content.read(), 1) if 'description' not in parameters or len(parameters['description']) == 0: extra_info = {} else: extra_info = {'description': parameters['description'][0]} def _on_url_fetched(data): return TorrentDef.load_from_memory(data) def _on_magnet_fetched(meta_info): return TorrentDef.load_from_dict(meta_info) @blocking_call_on_reactor_thread def _on_torrent_def_loaded(torrent_def): self.session.add_torrent_def_to_channel(channel[0], torrent_def, extra_info, forward=True) return self.path def _on_added(added): request.write(json.dumps({"added": added})) request.finish() def _on_add_failed(failure): failure.trap(ValueError, DuplicateTorrentFileError) self._logger.exception(failure.value) request.write(BaseChannelsEndpoint.return_500(self, request, failure.value)) request.finish() if self.path.startswith("http:") or self.path.startswith("https:"): self.deferred = http_get(self.path) self.deferred.addCallback(_on_url_fetched) if self.path.startswith("magnet:"): try: self.session.lm.ltmgr.get_metainfo(self.path, callback=self.deferred.callback, timeout=30, timeout_callback=self.deferred.errback, notify=True) except Exception as ex: self.deferred.errback(ex) self.deferred.addCallback(_on_magnet_fetched) self.deferred.addCallback(_on_torrent_def_loaded) self.deferred.addCallback(_on_added) self.deferred.addErrback(_on_add_failed) return NOT_DONE_YET
def __init__(self, session, cid, playlist_id): BaseChannelsEndpoint.__init__(self, session) self.cid = cid self.playlist_id = playlist_id
def __init__(self, session, cid): BaseChannelsEndpoint.__init__(self, session) self.cid = bytes(cid.decode('hex'))
def render_DELETE(self, request): """ .. http:delete:: /channels/discovered/(string: channelid)/torrents/(string: comma separated torrent infohashes) Remove a single or multiple torrents with the given comma separated infohashes from a given channel. **Example request**: .. sourcecode:: none curl -X DELETE http://localhost:8085/channels/discovered/abcdefg/torrents/ 97d2d8f5d37e56cfaeaae151d55f05b077074779,971d55f05b077074779d2d8f5d37e56cfaeaae15 **Example response**: .. sourcecode:: javascript { "removed": True } .. sourcecode:: javascript { "removed": False, "failed_torrents":["97d2d8f5d37e56cfaeaae151d55f05b077074779"] } :statuscode 404: if the channel is not found """ if self.is_chant_channel: with db_session: my_key = self.session.trustchain_keypair my_channel_id = my_key.pub().key_to_bin() failed_torrents = [] if my_channel_id != self.cid: request.setResponseCode(http.NOT_ALLOWED) return json.dumps({"error": "you can only remove torrents from your own chant channel"}) my_channel = self.session.lm.mds.get_my_channel() if not my_channel: return ChannelsTorrentsEndpoint.return_404(request) for torrent_path in self.path.split(","): infohash = torrent_path.decode('hex') if not my_channel.delete_torrent_from_channel(infohash): failed_torrents.append(torrent_path) if failed_torrents: return json.dumps({"removed": False, "failed_torrents": failed_torrents}) return json.dumps({"removed": True}) else: channel_info = self.get_channel_from_db(self.cid) if channel_info is None: return ChannelsTorrentsEndpoint.return_404(request) channel_community = self.get_community_for_channel_id(channel_info[0]) if channel_community is None: return BaseChannelsEndpoint.return_404(request, message=UNKNOWN_COMMUNITY_MSG) torrent_db_columns = ['Torrent.torrent_id', 'infohash', 'Torrent.name', 'length', 'Torrent.category', 'num_seeders', 'num_leechers', 'last_tracker_check', 'ChannelTorrents.dispersy_id'] failed_torrents = [] for torrent_path in self.path.split(","): torrent_info = self.channel_db_handler.getTorrentFromChannelId(channel_info[0], torrent_path.decode('hex'), torrent_db_columns) if torrent_info is None: failed_torrents.append(torrent_path) else: # the 8th index is the dispersy id of the channel torrent channel_community.remove_torrents([torrent_info[8]]) if failed_torrents: return json.dumps({"removed": False, "failed_torrents": failed_torrents}) return json.dumps({"removed": True})
def on_refresh_error(failure): self._logger.exception(failure.value) request.write(BaseChannelsEndpoint.return_500(self, request, failure.value)) request.finish()
def __init__(self, session, cid, path): BaseChannelsEndpoint.__init__(self, session) self.cid = cid self.path = path self.deferred = Deferred()
def __init__(self, session, cid): BaseChannelsEndpoint.__init__(self, session) self.cid = cid
def __init__(self, session, cid): BaseChannelsEndpoint.__init__(self, session) self.cid = bytes(cid.decode('hex'))
def render_PUT(self, request): """ .. http:put:: /channels/discovered/(string: channelid)/torrents Add a torrent file to your own channel. Returns error 500 if something is wrong with the torrent file and DuplicateTorrentFileError if already added to your channel. The torrent data is passed as base-64 encoded string. The description is optional. **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered/abcd/torrents --data "torrent=...&description=funny video" **Example response**: .. sourcecode:: javascript { "added": True } :statuscode 404: if your channel does not exist. :statuscode 500: if the passed torrent data is corrupt. """ key = self.session.trustchain_keypair my_channel_id = key.pub().key_to_bin() # First check whether the channel actually exists if self.is_chant_channel: if my_channel_id != self.cid: request.setResponseCode(http.NOT_ALLOWED) return json.dumps({"error": "you can only add torrents to your own chant channel"}) channel = self.session.lm.mds.ChannelMetadata.get_channel_with_id(my_channel_id) if not channel: return ChannelsTorrentsEndpoint.return_404(request) else: channel = self.get_channel_from_db(self.cid) if channel is None: return ChannelsTorrentsEndpoint.return_404(request) parameters = http.parse_qs(request.content.read(), 1) if 'torrent' not in parameters or len(parameters['torrent']) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "torrent parameter missing"}) if 'description' not in parameters or len(parameters['description']) == 0: extra_info = {} else: extra_info = {'description': parameters['description'][0]} # Try to parse the torrent data try: torrent = base64.b64decode(parameters['torrent'][0]) torrent_def = TorrentDef.load_from_memory(torrent) except ValueError as exc: return BaseChannelsEndpoint.return_500(self, request, exc) if self.is_chant_channel: try: channel.add_torrent_to_channel(torrent_def, extra_info) except DuplicateTorrentFileError as exc: return BaseChannelsEndpoint.return_500(self, request, exc) else: try: self.session.add_torrent_def_to_channel(channel[0], torrent_def, extra_info, forward=True) except (DuplicateTorrentFileError, HttpError) as ex: return BaseChannelsEndpoint.return_500(self, request, ex) return json.dumps({"added": True})
def __init__(self, session, cid, path): BaseChannelsEndpoint.__init__(self, session) self.cid = cid self.path = path self.deferred = Deferred() self.is_chant_channel = (len(cid) == 74)
def __init__(self, session, cid): BaseChannelsEndpoint.__init__(self, session) self.cid = cid
def __init__(self, session, cid): BaseChannelsEndpoint.__init__(self, session) self.cid = cid self.is_chant_channel = (len(cid) == 74)
def render_PUT(self, request): """ .. http:put:: /channels/discovered Create your own new channel. The passed mode and descriptions are optional. Valid modes include: 'open', 'semi-open' or 'closed'. By default, the mode of the new channel is 'closed'. **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered --data "name=fancy name&description=fancy description&mode=open" **Example response**: .. sourcecode:: javascript { "added": 23 } :statuscode 500: if a channel with the specified name already exists. """ parameters = http.parse_qs(request.content.read(), 1) if 'name' not in parameters or len(parameters['name']) == 0 or len( parameters['name'][0]) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "channel name cannot be empty"}) if 'description' not in parameters or len( parameters['description']) == 0: description = u'' else: description = unicode(parameters['description'][0], 'utf-8') if self.session.config.get_chant_channel_edit(): my_key = self.session.trustchain_keypair my_channel_id = my_key.pub().key_to_bin() # Do not allow to add a channel twice if self.session.lm.mds.get_my_channel(): request.setResponseCode(http.INTERNAL_SERVER_ERROR) return json.dumps({"error": "channel already exists"}) title = unicode(parameters['name'][0], 'utf-8') self.session.lm.mds.ChannelMetadata.create_channel( title, description) return json.dumps({ "added": str(my_channel_id).encode("hex"), }) if 'mode' not in parameters or len(parameters['mode']) == 0: # By default, the mode of the new channel is closed. mode = u'closed' else: mode = unicode(parameters['mode'][0], 'utf-8') try: channel_id = self.session.create_channel( unicode(parameters['name'][0], 'utf-8'), description, mode) except DuplicateChannelNameError as ex: return BaseChannelsEndpoint.return_500(self, request, ex) return json.dumps({"added": channel_id})
def _on_timeout(_): request.write( BaseChannelsEndpoint.return_500( self, request, RuntimeError("Metainfo timeout"))) request.finish()
def __init__(self, session, cid): BaseChannelsEndpoint.__init__(self, session) self.cid = cid self.is_chant_channel = (len(cid) == 74)
def render_PUT(self, request): """ .. http:put:: /channels/discovered Create your own new channel. The passed mode and descriptions are optional. Valid modes include: 'open', 'semi-open' or 'closed'. By default, the mode of the new channel is 'closed'. **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered --data "name=fancy name&description=fancy description&mode=open" **Example response**: .. sourcecode:: javascript { "added": 23 } :statuscode 500: if a channel with the specified name already exists. """ parameters = http.parse_qs(request.content.read(), 1) if 'name' not in parameters or len(parameters['name']) == 0 or len(parameters['name'][0]) == 0: request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": "channel name cannot be empty"}) if 'description' not in parameters or len(parameters['description']) == 0: description = u'' else: description = unicode(parameters['description'][0], 'utf-8') if self.session.config.get_chant_channel_edit(): my_key = self.session.trustchain_keypair my_channel_id = my_key.pub().key_to_bin() # Do not allow to add a channel twice if self.session.lm.mds.get_my_channel(): request.setResponseCode(http.INTERNAL_SERVER_ERROR) return json.dumps({"error": "channel already exists"}) title = unicode(parameters['name'][0], 'utf-8') self.session.lm.mds.ChannelMetadata.create_channel(title, description) return json.dumps({ "added": str(my_channel_id).encode("hex"), }) if 'mode' not in parameters or len(parameters['mode']) == 0: # By default, the mode of the new channel is closed. mode = u'closed' else: mode = unicode(parameters['mode'][0], 'utf-8') try: channel_id = self.session.create_channel(unicode(parameters['name'][0], 'utf-8'), description, mode) except DuplicateChannelNameError as ex: return BaseChannelsEndpoint.return_500(self, request, ex) return json.dumps({"added": channel_id})
def _on_add_failed(failure): failure.trap(ValueError, DuplicateTorrentFileError, SchemeNotSupported) self._logger.exception(failure.value) request.write(BaseChannelsEndpoint.return_500(self, request, failure.value)) request.finish()
def __init__(self, session, cid, playlist_id, infohash): BaseChannelsEndpoint.__init__(self, session) self.cid = cid self.playlist_id = playlist_id self.infohash = infohash.decode('hex')
def _on_timeout(_): request.write(BaseChannelsEndpoint.return_500(self, request, RuntimeError("Metainfo timeout"))) request.finish()
def __init__(self, session, cid, path): BaseChannelsEndpoint.__init__(self, session) self.cid = cid self.path = path self.deferred = Deferred() self.is_chant_channel = (len(cid) == 74)
def __init__(self, session, cid, playlist_id, infohash): BaseChannelsEndpoint.__init__(self, session) self.cid = cid self.playlist_id = playlist_id self.infohash = infohash.decode('hex')
def render_PUT(self, request): """ .. http:put:: /channels/discovered/(string: channelid)/torrents/http%3A%2F%2Ftest.com%2Ftest.torrent Add a torrent by magnet or url to your channel. Returns error 500 if something is wrong with the torrent file and DuplicateTorrentFileError if already added to your channel (except with magnet links). **Example request**: .. sourcecode:: none curl -X PUT http://localhost:8085/channels/discovered/abcdefg/torrents/ http%3A%2F%2Ftest.com%2Ftest.torrent --data "description=nice video" **Example response**: .. sourcecode:: javascript { "added": "http://test.com/test.torrent" } :statuscode 404: if your channel does not exist. :statuscode 500: if the specified torrent is already in your channel. """ my_key = self.session.trustchain_keypair my_channel_id = my_key.pub().key_to_bin() if self.is_chant_channel: if my_channel_id != self.cid: request.setResponseCode(http.NOT_ALLOWED) return json.dumps({"error": "you can only add torrents to your own chant channel"}) channel = self.session.lm.mds.ChannelMetadata.get_channel_with_id(my_channel_id) else: channel = self.get_channel_from_db(self.cid) if channel is None: return BaseChannelsEndpoint.return_404(request) parameters = http.parse_qs(request.content.read(), 1) if 'description' not in parameters or len(parameters['description']) == 0: extra_info = {} else: extra_info = {'description': parameters['description'][0]} def _on_url_fetched(data): return TorrentDef.load_from_memory(data) def _on_magnet_fetched(meta_info): return TorrentDef.load_from_dict(meta_info) def _on_torrent_def_loaded(torrent_def): if self.is_chant_channel: # We have to get my channel again since we are in a different database session now with db_session: channel = self.session.lm.mds.get_my_channel() channel.add_torrent_to_channel(torrent_def, extra_info) else: channel = self.get_channel_from_db(self.cid) self.session.add_torrent_def_to_channel(channel[0], torrent_def, extra_info, forward=True) return self.path def _on_added(added): request.write(json.dumps({"added": added})) request.finish() def _on_add_failed(failure): failure.trap(ValueError, DuplicateTorrentFileError, SchemeNotSupported) self._logger.exception(failure.value) request.write(BaseChannelsEndpoint.return_500(self, request, failure.value)) request.finish() def _on_timeout(_): request.write(BaseChannelsEndpoint.return_500(self, request, RuntimeError("Metainfo timeout"))) request.finish() if self.path.startswith("http:") or self.path.startswith("https:"): self.deferred = http_get(self.path) self.deferred.addCallback(_on_url_fetched) if self.path.startswith("magnet:"): try: self.session.lm.ltmgr.get_metainfo(self.path, callback=self.deferred.callback, timeout=30, timeout_callback=_on_timeout, notify=True) except Exception as ex: self.deferred.errback(ex) self.deferred.addCallback(_on_magnet_fetched) self.deferred.addCallback(_on_torrent_def_loaded) self.deferred.addCallback(_on_added) self.deferred.addErrback(_on_add_failed) return NOT_DONE_YET
def render_POST(self, request): """ .. http:post:: /mychannel Modify the name and/or the description of your channel. This endpoint returns a 404 HTTP response if you have not created a channel (yet). **Example request**: .. sourcecode:: none curl -X POST http://localhost:8085/mychannel --data "name=My fancy playlist&description=This playlist contains some random movies" **Example response**: .. sourcecode:: javascript { "modified": True } :statuscode 404: if your channel has not been created (yet). """ parameters = http.parse_qs(request.content.read(), 1) if not get_parameter(parameters, 'name') and not get_parameter(parameters, 'commit_changes'): request.setResponseCode(http.BAD_REQUEST) return json.dumps({"error": 'channel name cannot be empty'}) if self.session.config.get_chant_channel_edit(): with db_session: modified = False my_key = self.session.trustchain_keypair my_channel_id = my_key.pub().key_to_bin() my_channel = self.session.lm.mds.ChannelMetadata.get_channel_with_id(my_channel_id) if not my_channel: request.setResponseCode(http.NOT_FOUND) return json.dumps({"error": NO_CHANNEL_CREATED_RESPONSE_MSG}) if get_parameter(parameters, 'name'): my_channel.update_metadata(update_dict={ "tags": unicode(get_parameter(parameters, 'description'), 'utf-8'), "title": unicode(get_parameter(parameters, 'name'), 'utf-8') }) modified = True if get_parameter(parameters, 'commit_changes') and my_channel.staged_entries_list: # Update torrent if we have uncommitted content in the channel my_channel.commit_channel_torrent() torrent_path = os.path.join(self.session.lm.mds.channels_dir, my_channel.dir_name + ".torrent") self.session.lm.updated_my_channel(torrent_path) modified = True return json.dumps({'modified': modified}) else: my_channel_id = self.channel_db_handler.getMyChannelId() if my_channel_id is None: request.setResponseCode(http.NOT_FOUND) return json.dumps({"error": NO_CHANNEL_CREATED_RESPONSE_MSG}) channel_community = self.get_community_for_channel_id(my_channel_id) if channel_community is None: return BaseChannelsEndpoint.return_404(request, message="the community for the your channel cannot be found") my_channel = self.channel_db_handler.getChannel(my_channel_id) changes = {} if my_channel[2] != get_parameter(parameters, 'name'): changes['name'] = unicode(get_parameter(parameters, 'name'), 'utf-8') if my_channel[3] != get_parameter(parameters, 'description'): changes['description'] = unicode(get_parameter(parameters, 'description'), 'utf-8') channel_community.modifyChannel(changes) return json.dumps({'modified': True})