def _request(self, op: str, request: QtNetwork.QNetworkRequest, data: typing.Union[typing.AnyStr, QtCore.QByteArray] = None) -> requests.Response: """Truly initiates the network request.""" # Initiate the request reply = self.factory.request(op, request=request, data=data) # If we're being ratelimited, wait the specified # amount of time, then reinitiate the request. if reply.code == 429: timeout = reply.headers['Ratelimit-Reset'] # Get the ratelimit reset date = datetime.datetime.fromtimestamp(timeout, tz=datetime.timezone.utc) # Convert it to a datetime object diff = date - datetime.datetime.now(tz=datetime.timezone.utc) # Get a timedelta object timer = QtCore.QTimer() # Start a timer that ends after the difference's total seconds rounded up timer.start(int(math.ceil(diff.total_seconds() * 1000, 0))) signals.wait_for_signal(timer.timeout) # Stop and delete the timer once it ticks once timer.stop() timer.deleteLater() # Redo the request return self._request(op, request, data=data) return reply
def wait_and_increment_join(self): """A utility method for waiting for the JOIN/AUTH limit to reset, and incrementing the counter. If the counter is within the limit, the method will just increment the counter.""" if self._join_sent >= self._join_limit: signals.wait_for_signal(self.on_join_limit_reset) self._join_sent += 1
def wait_and_increment_priv(self): """A utility method for waiting for the PRIVMSG limit to reset, and incrementing the counter. If the counter is within the limit, the method will just increment the counter.""" if self._priv_sent >= self._priv_limit: signals.wait_for_signal(self.on_priv_limit_reset) self._priv_sent += 1
def threaded_task(self, label: str, func: callable, *args, **kwargs): """Executes a callable in a thread, while updating the dialog. :param label: The text to display when this task is executing :param func: The callable to execute""" self.set_text(label) thread = QtCore.QThread() thread.run = functools.partial(func, *args, **kwargs) thread.start() signals.wait_for_signal(thread.finished) self.increment()
def wait_for_whisper(self, *, include_accounts: bool = None): """Waits for the whisper limit to reset. If `include_accounts` is true, this will also wait for the account limit to reset.""" if self._whispers_this_minute >= self._whisper_minute_limit: signals.wait_for_signal(self.on_whisper_minute_reset) elif self._whispers_this_second >= self._whisper_second_limit: signals.wait_for_signal(self.on_whisper_second_reset) elif include_accounts and len( self._whispered_accounts) >= self._whisper_accounts_limit: signals.wait_for_signal(self.on_whisper_account_reset)
def process_chat_message(self, platform: dataclasses.Platform, message: dataclasses.Message): """Processes a raw chat message into a command.""" if not message.content.startswith( self.settings['system']['prefix'].value): if self.command_manager.PARSER_DEBUG: self.LOGGER.debug( f'Message "{message}" ' f'does not start with the user\'s ' f'requested prefix of ' f'"{self.settings["extensions"]["platforms"]["command_prefix"].value}"!' ) return command, arguments = self.command_manager.parse(message.content, ignore_case=True) if command is not None: if self.command_manager.PARSER_DEBUG: self.LOGGER.debug( f'Located command "{command.qualified_name}"!') # Re-implement commands.Manager to tie into the signals defined above. argspec = inspect.getfullargspec(command.func) key_arguments = {} for argument in arguments.copy(): if '=' in argument and self.command_manager.is_kv_pair( argument): k, v = argument.split('=') key_arguments[k] = v if v else None arguments.pop(arguments.index(argument)) args, originals = self.command_manager.convert_args( command.func, *arguments, **key_arguments) if not argspec.varargs: final_positionals = [] for key, value in originals.items(): if key not in args: final_positionals.append(value) else: final_positionals = arguments # Build a context object try: # noinspection PyUnresolvedReferences prefix = command.prefix except AttributeError: prefix = self.settings['system']['prefix'].value context = commands.Context(prefix=prefix, message=message, platform=platform, command=command, arguments=final_positionals, kwarguments=args) # Inform listeners that a command is about to be executed self.onCommandExecuteRequested.emit(context) emitted, returnable = signals.wait_for_signal( self.denyCommandExecute, timeout=5) if emitted: returnable: typing.Union[commands.Command, commands.Group] if returnable == context: return self.LOGGER.debug( f'Command execution of "{command.qualified_name}" was denied!' ) else: try: command(*final_positionals, **args) except commands.errors.CommandsError: self.LOGGER.warning( f'Command "{command.qualified_name}" does not contain a callable!' ) else: self.onCommandExecute.emit(context)