def callback_stream(self, stream: Stream) -> None: """ Triggered asynchronously (in a different thread context) on every incoming stream request or file transfert requests. You can block this call until you are done with the stream. To signal that you accept / reject the file, simply call stream.accept() or stream.reject() and return. :param stream: the incoming stream request. """ stream.reject() # by default, reject the file as the plugin doesn't want it.
def callback_stream(self, stream: Stream) -> None: """ Triggered asynchronously (in a different thread context) on every incoming stream request or file transfert requests. You can block this call until you are done with the stream. To signal that you accept / reject the file, simply call stream.accept() or stream.reject() and return. :param stream: the incoming stream request. """ stream.reject( ) # by default, reject the file as the plugin doesn't want it.
def test_streaming(): canary = b'this is my test' * 1000 source = Stream(SimpleIdentifier("*****@*****.**"), BytesIO(canary)) clients = [StreamingClient() for i in range(50)] Tee(source, clients).run() for client in clients: assert client.response == canary
def send_stream_request(self, identifier, fsource, name='file', size=None, stream_type=None): """Starts a file transfer. :param identifier: ZulipPerson or ZulipRoom Identifier of the Person or Room to send the stream to. :param fsource: str, dict or binary data File URL or binary content from a local file. Optionally a dict with binary content plus metadata can be given. See `stream_type` for more details. :param name: str, optional Name of the file. Not sure if this works always. :param size: str, optional Size of the file obtained with os.path.getsize. This is only used for debug logging purposes. :param stream_type: str, optional Type of the stream. Choices: 'document', 'photo', 'audio', 'video', 'sticker', 'location'. Right now used for debug logging purposes only. :return stream: str or Stream If `fsource` is str will return str, else return Stream. """ def _metadata(fsource): if isinstance(fsource, dict): return fsource.pop('content'), fsource else: return fsource, None def _is_valid_url(url): try: from urlparse import urlparse except Exception: from urllib.parse import urlparse return bool(urlparse(url).scheme) content, meta = _metadata(fsource) if isinstance(content, str): if not _is_valid_url(content): raise ValueError("Not valid URL: {}".format(content)) else: raise NotImplementedError( "The Zulip backend does not yet support URL stream requests." ) else: stream = Stream(identifier, content, name, size, stream_type) log.debug( "Requesting upload of {0} to {1} (size hint: {2}, stream type: {3})" .format(name, identifier, size, stream_type)) self.thread_pool.apply_async(self._zulip_upload_stream, (stream, )) return stream
def send_stream_request(self, identifier, fsource, name='file', size=None, stream_type=None): """Starts a file transfer. For Slack, the size and stream_type are unsupported""" stream = Stream(identifier, fsource, name, size, stream_type) log.debug("Requesting upload of {0} to {1} (size hint: {2}, stream type: {3})".format(name, identifier.channelname, size, stream_type)) self.thread_pool.putRequest(WorkRequest(self._slack_upload, args=(stream,))) return stream
def send_stream_request( self, identifier: Identifier, fsource: BinaryIO, name: Optional[str] = None, size: Optional[int] = None, stream_type: Optional[str] = None, ) -> Stream: # Creates a new connection dcc = self.dcc_listen("raw") msg_parts = map( str, ( "SEND", name, irc.client.ip_quad_to_numstr(dcc.localaddress), dcc.localport, size, ), ) msg = subprocess.list2cmdline(msg_parts) self.connection.ctcp("DCC", identifier.nick, msg) stream = Stream(identifier, fsource, name, size, stream_type) self.transfers[dcc] = stream return stream
def send_stream_request(self, identifier, fsource, name='file', size=None, stream_type=None): """Starts a file transfer. For Slack, the size and stream_type are unsupported""" stream = Stream(identifier, fsource, name, size, stream_type) log.debug('Requesting upload of %s to %s (size hint: %d, stream type: %s).', name, identifier.channelname, size, stream_type) self.thread_pool.apply_async(self._slack_upload, (stream,)) return stream
def send_stream_request( self, user: Identifier, fsource: BinaryIO, name: str = None, size: int = None, stream_type: str = None, ) -> Stream: """ Starts a file transfer. For Slack, the size and stream_type are unsupported :param user: is the identifier of the person you want to send it to. :param fsource: is a file object you want to send. :param name: is an optional filename for it. :param size: not supported in Slack backend :param stream_type: not supported in Slack backend :return Stream: object on which you can monitor the progress of it. """ stream = Stream(user, fsource, name, size, stream_type) log.debug( "Requesting upload of %s to %s (size hint: %d, stream type: %s).", name, user.channelname, size, stream_type, ) self.thread_pool.apply_async(self._slack_upload, (stream, )) return stream
def test_streaming(): canary = b"this is my test" * 1000 source = Stream(TestPerson("*****@*****.**"), BytesIO(canary)) clients = [StreamingClient() for _ in range(50)] Tee(source, clients).run() for client in clients: assert client.response == canary
def send_stream_request(self, identifier, fsource, name=None, size=None, stream_type=None): s = Stream(identifier, fsource, name, size, stream_type) self.conn.send_stream_request(s) return s
def on_file_send_request(self, friend_number, file_number, file_size, filename): logging.debug("TOX: incoming file transfer %s : %s", friend_number, filename) # make a pipe on which we will be able to write from tox pipe = ToxStreamer() # make the original stream with all the info stream = Stream(self.friend_to_idd(friend_number), pipe, filename, file_size) # store it for tracking purposes self.incoming_streams[(friend_number, file_number)] = (pipe, stream) # callback err so it will duplicate the stream and send it to all the plugins self.backend.callback_stream(stream) # always say ok, and kill it later if finally we don't want it self.file_send_control(friend_number, 1, file_number, Tox.FILECONTROL_ACCEPT)
def send_stream_request(self, identifier, fsource, name='file', size=None, stream_type=None): """ Send a file to Cisco Webex Teams :param user: is the identifier of the person you want to send it to. :param fsource: is a file object you want to send. :param name: is an optional filename for it. :param size: not supported in Webex Teams backend :param stream_type: not supported in Webex Teams backend """ log.debug(f'Requesting upload of {fsource.name} to {identifier}.') stream = Stream(identifier, fsource, name, size, stream_type) # self.thread_pool.apply_async(self._teams_upload, (stream,)) self._teams_upload(stream) return stream
def send_stream_request( self, identifier, fsource, name="file.txt", size=None, stream_type=None ): """Starts a file transfer. note, fsource used to make the stream needs to be in open/rb state """ stream = Stream( identifier=identifier, fsource=fsource, name=name, size=size, stream_type=stream_type, ) result = self.thread_pool.apply_async(self._hipchat_upload, (stream,)) log.debug("Response from server: %s", result.get(timeout=10)) return stream
def _slack_upload(self, stream: Stream) -> None: """ Performs an upload defined in a stream :param stream: Stream object :return: None """ try: stream.accept() resp = self.webclient.files_upload(channels=stream.identifier.channelid, filename=stream.name, file=stream) if 'ok' in resp and resp['ok']: stream.success() else: stream.error() except Exception: log.exception(f'Upload of {stream.name} to {stream.identifier.channelname} failed.')
def _slack_upload(self, stream: Stream) -> None: """ Performs an upload defined in a stream :param stream: Stream object :return: None """ try: stream.accept() resp = self.api_call('files.upload', data={ 'channels': stream.identifier.channelid, 'filename': stream.name, 'file': stream }) if 'ok' in resp and resp['ok']: stream.success() else: stream.error() except Exception: log.exception(f'Upload of {stream.name} to {stream.identifier.channelname} failed.')
def _telegram_upload_stream(self, stream: Stream, **kwargs) -> None: """Perform upload defined in a stream.""" msg = None try: stream.accept() msg = self._telegram_special_message( chat_id=stream.identifier.id, content=stream.raw, msg_type=stream.stream_type, **kwargs, ) except Exception: log.exception( f"Upload of {stream.name} to {stream.identifier} failed.") else: if msg is None: stream.error() else: stream.success()
def _slack_upload(self, stream: Stream) -> None: """ Performs an upload defined in a stream :param stream: Stream object :return: None """ try: stream.accept() resp = self.api_call('files.upload', data={ 'channels': stream.identifier.channelid, 'filename': stream.name, 'file': stream }) if 'ok' in resp and resp['ok']: stream.success() else: stream.error() except Exception: log.exception(f'Upload of {stream.name} to {stream.identifier.channelname} failed.')
def _slack_upload(self, stream: Stream) -> None: """ Performs an upload defined in a stream :param stream: Stream object :return: None """ try: stream.accept() resp = self.api_call( "files.upload", data={ "channels": stream.identifier.channelid, "filename": stream.name, "file": stream, }, ) if "ok" in resp and resp["ok"]: stream.success() else: stream.error() except Exception: log.exception( f"Upload of {stream.name} to {stream.identifier.channelname} failed." )
def send_stream_request(self, identifier, fsource, name='file', size=None, stream_type=None): """Starts a file transfer. :param identifier: TelegramPerson or TelegramMUCOccupant Identifier of the Person or Room to send the stream to. :param fsource: str, dict or binary data File URL or binary content from a local file. Optionally a dict with binary content plus metadata can be given. See `stream_type` for more details. :param name: str, optional Name of the file. Not sure if this works always. :param size: str, optional Size of the file obtained with os.path.getsize. This is only used for debug logging purposes. :param stream_type: str, optional Type of the stream. Choices: 'document', 'photo', 'audio', 'video', 'sticker', 'location'. If 'video', a dict is optional as {'content': fsource, 'duration': str}. If 'voice', a dict is optional as {'content': fsource, 'duration': str}. If 'audio', a dict is optional as {'content': fsource, 'duration': str, 'performer': str, 'title': str}. For 'location' a dict is mandatory as {'latitude': str, 'longitude': str}. For 'venue': TODO # see: https://core.telegram.org/bots/api#sendvenue :return stream: str or Stream If `fsource` is str will return str, else return Stream. """ def _telegram_metadata(fsource): if isinstance(fsource, dict): return fsource.pop('content'), fsource else: return fsource, None def _is_valid_url(url): try: from urlparse import urlparse except Exception: from urllib.parse import urlparse return bool(urlparse(url).scheme) content, meta = _telegram_metadata(fsource) if isinstance(content, str): if not _is_valid_url(content): raise ValueError("Not valid URL: {}".format(content)) self._telegram_special_message(chat_id=identifier.id, content=content, msg_type=stream_type, **meta) log.debug( "Requesting upload of {0} to {1} (size hint: {2}, stream type: {3})" .format(name, identifier.username, size, stream_type)) stream = content else: stream = Stream(identifier, content, name, size, stream_type) log.debug( "Requesting upload of {0} to {1} (size hint: {2}, stream type: {3})" .format(name, identifier, size, stream_type)) self.thread_pool.apply_async(self._telegram_upload_stream, (stream, )) return stream