def _get_active_threads_names():
     """May contain sensitive info (like user ids). Use with care."""
     active_threads = threading.enumerate()
     return FormattedText().join([
         FormattedText().newline().normal(" - {name}").start_format().bold(
             name=thread.name).end_format() for thread in active_threads
     ])
Exemple #2
0
 def work_error(self, error: BaseException, work: Work, worker: Worker):
     self.__error(
         FormattedText().bold(ExceptionFormatter.format(error)),
         FormattedText().normal("Work: {work}").start_format().bold(
             work=work.name).end_format(),
         FormattedText().normal("Worker: {worker}").start_format().bold(
             worker=worker.name).end_format())
 def _formatted_size(size_in_bytes):
     if size_in_bytes is not None:
         size = SizeFormatter.format(size_in_bytes)
         return FormattedText().normal(" ({size})").start_format().bold(
             size=size).end_format()
     else:
         return FormattedText()
 def __get_donation_addresses(donation_addresses: Sequence[Sequence[str]]):
     texts = []
     for name, address in donation_addresses:
         texts.append(FormattedText().normal(
             " - {name}: {address}").start_format().normal(name=name).bold(
                 address=address).end_format())
     return FormattedText().newline().join(texts)
 def __build_success_response_message(event, title, printable_messages):
     footer = FormattedText().normal("\n\nWrite ").bold(
         event.command + " help").normal(" to see more options.")
     if not isinstance(title, FormattedText):
         title = FormattedText().normal(title)
     return FormattedText().concat(title).newline().concat(
         printable_messages).concat(footer).build_message()
 def __get_authors(authors: Sequence[Sequence[str]]):
     texts = []
     for name, credit in authors:
         texts.append(FormattedText().normal(
             " - {name} ({credit})").start_format().normal(
                 name=name, credit=credit).end_format())
     return FormattedText().newline().join(texts)
 def process(self, event):
     response = FormattedText().newline().join(ConfigStatus(self.config, self.state).get_config_status())
     response.newline().newline()\
         .italic("These are the current values read from storage.").newline()\
         .italic("But please, note that most of them are being cached at startup and "
                 "changing them will not modify bot behavior until it is restarted.")
     self.api.send_message(response.build_message().to_chat_replying(event.message))
    def _get_bot_status(self):
        process_uptime_value = TimeFormatter.format(
            self.__get_process_uptime())
        process_uptime = FormattedText()\
            .normal("Uptime: {bot_uptime}").start_format().bold(bot_uptime=process_uptime_value).end_format()

        process_memory_usage_value, process_memory_usage_attribute_name = self.__get_process_memory_usage(
        )
        process_memory_usage_formatted_value = SizeFormatter.format(
            process_memory_usage_value)
        process_memory_usage = FormattedText()\
            .normal("Memory usage: {memory_usage} ({memory_usage_attribute_name})").start_format()\
            .bold(memory_usage=process_memory_usage_formatted_value)\
            .normal(memory_usage_attribute_name=process_memory_usage_attribute_name).end_format()

        thread_number = WorkersAction.get_active_threads_number()

        workers_value = self.scheduler.get_running_workers()
        workers_number = WorkersAction.get_running_workers_number(
            workers_value)

        worker_pools_value = self.scheduler.get_worker_pools()
        worker_pools_number = WorkersAction.get_worker_pools_number(
            worker_pools_value)

        return FormattedText().newline().join(
            (FormattedText().bold("Bot status"), process_uptime,
             process_memory_usage, thread_number, workers_number,
             worker_pools_number))
 def _summarized(self, field="text", max_characters=15):
     text = FormattedText()
     content = getattr(self.last_message, field)
     if content:
         summarized_content = TextSummarizer.summarize(
             content, max_number_of_characters=max_characters)
         text.normal(" [ ").italic(summarized_content).normal(" ]")
     return text
 def __init__(self, project_package_name: str, releases_url: str = None):
     super().__init__()
     version = self.get_version(project_package_name)
     self.text = FormattedText().normal("Version {version}")
     if releases_url:
         self.text.newline().newline().normal("Releases: {releases_url}")
     self.text.start_format().bold(version=version).normal(
         releases_url=releases_url).end_format()
 def get_random_in_range(start, end):
     if start > end:
         return FormattedText().bold("Sorry").normal(", for this to work the first number must be ").bold("lower")\
             .normal(" than the second number.").build_message()
     chosen = random.randint(start, end)
     return FormattedText().normal("Choosing a random number between ").bold(start).normal(" and ").bold(end).normal(" (both included).").newline().newline()\
         .normal("Chosen number: ").bold(chosen)\
         .build_message()
 def __send_throttling_warning(self, event, throttling_state):
     remaining_seconds = throttling_state.remaining_seconds(
         event.message.date)
     self.__log_throttling(event, remaining_seconds)
     message = FormattedText().bold("Ignoring repeated command.").normal(" Try again in ")\
         .code_inline(remaining_seconds).normal(" seconds.")\
         .build_message()
     message.to_chat_replying(event.message)
     self.api. async .send_message(message)
 def _item(label: str, value, additional_text: str = ""):
     text = FormattedText()\
         .normal("{label}: {value}")\
         .start_format()\
         .normal(label=label)\
         .bold(value=value)\
         .end_format()
     if additional_text:
         text.normal(" ").normal(additional_text)
     return text
Exemple #14
0
 def get_response_mod(self, event, action_params, handler):
     alias = action_params[0]
     success = self.set_timezone_data(action_params, handler)
     if not success:
         return FormattedText().bold("ERROR while modifying timezone").normal(", check name and offset are valid.")\
             .normal(" See help for more info")\
             .build_message()
     return FormattedText().normal("Timezone ").bold(alias).normal(" updated!").newline().newline()\
         .concat(self.get_timezone_info_text(handler.get_timezone_state(alias)))\
         .build_message()
 def process(self, event):
     api = self.api.no_async
     error = NotARealError("simulated error")
     response = FormattedText().bold("Simulating bot error...")
     args = event.command_args.split()
     if "fatal" in args:
         error = NotARealFatalError("simulated fatal error")
         response.newline().normal(" - ").bold("FATAL")
     if "async" in args:
         api = self.api. async
         response.newline().normal(" - ").bold("async")
 def get_response_whereis(self, event, message_id):
     return FormattedText().bold("👆 Here is message ").code_inline(message_id).bold(".")\
         .build_message().reply_to_message(message_id=message_id)\
         .with_error_callback(lambda e: self.api.send_message(
             FormattedText().bold("❌ Sorry, message ").code_inline(message_id).bold(" cannot be located.")
             .newline().newline().normal("Possible causes:").newline()
             .normal("· The message may have been deleted.").newline()
             .normal("· The message ID you entered may not be valid. They should be positive numbers.").newline()
             .normal("· If you recently converted the group to a supergroup, messages sent before the conversion"
                     " took place cannot be replied to.")
             .build_message().to_chat_replying(event.message)))
Exemple #17
0
 def __send_traceback(self):
     try:
         self.traceback_logger.log(
             TRACEBACK_TAG,
             FormattedText().code_block(traceback.format_exc()))
     except ApiException:
         # tracebacks can be very long and reach message length limit
         # retry with a shorter traceback
         self.traceback_logger.log(
             TRACEBACK_TAG,
             FormattedText().code_block(traceback.format_exc(limit=1)))
Exemple #18
0
 def do_enable(self, event):
     disable_command = UnderscoredCommandBuilder.build_command(
         event.command, "off")
     message = FormattedText().normal("Activating #silence mode. I won't send anything here until you ")\
         .normal(disable_command).normal(" me.")\
         .build_message()
     # sending reply before activating silence mode, so that it is actually sent
     message.to_chat_replying(event.message)
     self.api.send_message(message)
     event.state.silenced = "yes"
     # returning a message to avoid caller failing, but message should not be sent, as silence mode is now enabled
     return message
Exemple #19
0
 def __log_command_execution(event, elapsed_seconds: float):
     event.logger.log(
         COMMAND_LOG_TAG,
         FormattedText().normal("{command} {args}").start_format().bold(
             command=event.command, args=event.command_args).end_format(),
         FormattedText().normal("User: {user}").start_format().bold(
             user=UserFormatter(
                 event.message.from_).full_data).end_format(),
         FormattedText().normal("Chat: {chat}").start_format().bold(
             chat=ChatFormatter(event.chat).full_data).end_format(),
         FormattedText().normal("Execution time: {time}").start_format().
         bold(time=TimeFormatter.format(elapsed_seconds)).end_format())
 def _full_content_header(self):
     text = FormattedText()\
         .normal(self.bullet)\
         .normal("Message ").bold(self.message_id)\
         .normal(" sent on ").bold(self.full_date)\
         .normal(" by ").bold(self.full_user)\
         .normal(".").newline()
     self.__add_reply_info_if_needed(text)
     self.__add_forwarded_info_if_needed(text)
     self.__add_edit_info_if_needed(text)
     self.__add_incomplete_info_if_needed(text)
     return text.newline()
 def __log_throttling(event, remaining_seconds):
     event.logger.log(
         LOG_TAG,
         FormattedText().normal("{command} {args}").start_format().bold(
             command=event.command, args=event.command_args).end_format(),
         FormattedText().normal("User: {user}").start_format().bold(
             user=UserFormatter(
                 event.message.from_).full_data).end_format(),
         FormattedText().normal("Chat: {chat}").start_format().bold(
             chat=ChatFormatter(event.chat).full_data).end_format(),
         FormattedText().normal("Throttling for {seconds} seconds.").
         start_format().bold(seconds=remaining_seconds).end_format())
Exemple #22
0
 def poll_completed(self, message: MessageViewModel, poll_id: PollIdViewModel, full_poll: FullPollViewModel):
     text = FormattedText()\
         .normal("Poll #{id}:\n\n{poll}")\
         .start_format()\
         .normal(
             id=poll_id.id
         ).concat(
             poll=self.poll_formatter.format_poll(full_poll)
     ).end_format()
     inline_keyboard = self.inline_keyboard_formatter.poll_creation_inline_keyboard(poll_id)
     api_message = text.build_message().with_reply_markup(inline_keyboard)
     self._send_message(api_message, message)
 def _full_content(self,
                   content_field="text",
                   prepend_newlines_if_content=False):
     text = FormattedText()
     content = getattr(self.message, content_field)
     if content is not None:
         if prepend_newlines_if_content:
             text.newline().newline()
         text.normal(self.start_content).bold(
             content_field.capitalize()).bold(":").newline()
         text.normal(content)
     text.concat(self._full_edits_content(content_field))
     return text
    def _get_system_status(self):
        system_uptime_value = TimeFormatter.format(
            self.__get_elapsed_seconds_since(psutil.boot_time()))
        system_uptime = FormattedText()\
            .normal("Uptime: {system_uptime}").start_format().bold(system_uptime=system_uptime_value).end_format()

        cpu_usage_value = str(
            psutil.cpu_percent(interval=self.cpu_usage_sample_seconds)) + " %"
        cpu_usage = FormattedText()\
            .normal("CPU usage: {cpu_usage} ({sample_interval} sec. sample)").start_format()\
            .bold(cpu_usage=cpu_usage_value).normal(sample_interval=self.cpu_usage_sample_seconds).end_format()

        return FormattedText().newline().join(
            (FormattedText().bold("System status"), system_uptime, cpu_usage))
Exemple #25
0
 def get_response_del(event, action_params, handler):
     alias = action_params[0]
     if alias not in handler.get_timezones():
         return FormattedText().bold("ERROR").normal(", no ").bold(alias).normal(" timezone found.")\
             .build_message()
     if alias == "main":
         return FormattedText().normal("Sorry, main timezone cannot be removed")\
             .build_message()
     handler.del_timezone(alias)
     return FormattedText().normal("Timezone ").bold(alias).normal(" removed.").newline().newline()\
         .normal("Ranking in that timezone is still accessible, but no new poles will be added.").newline()\
         .normal("If you add a timezone with the same alias in the future,"
                 " new poles will be added to the ranking again.").newline()\
         .normal("Contact the bot admin if you want the ranking to be wiped.")\
         .build_message()
Exemple #26
0
 def set_new_value(self, settings, key, new_value):
     previous_value = self.__get_current_value(settings, key)
     try:
         settings.set(key, new_value)
     except Exception as e:
         return FormattedText().bold("Setting could not be updated").newline().newline()\
             .normal("Please, input a valid value.").newline().newline()\
             .normal("Error was: ").code_inline(e)\
             .build_message()
     current_value = self.__get_current_value(settings, key)
     return FormattedText().bold("Setting updated!").newline().newline()\
         .bold("Name").normal(":").newline().code_block(key).newline().newline()\
         .bold("Previous value").normal(":").newline().concat(previous_value).newline().newline()\
         .bold("Current value").normal(":").newline().concat(current_value)\
         .build_message()
Exemple #27
0
 def get_response_list(event, action_params, handler):
     text = FormattedText().normal("List of pole timezones:").newline()
     for alias in handler.get_timezones():
         state = handler.get_timezone_state(alias)
         name = state.get_value("timezone", DEFAULT_TIMEZONE)
         text.bold(alias).normal(" → ").bold(name)
         offset_seconds = state.offset_seconds
         if offset_seconds is not None:
             text.normal(" (with ").bold(offset_seconds).normal(
                 " seconds offset)")
         text.newline()
     return text.build_message()
Exemple #28
0
 def __add_grouped_pole(self, text, grouped_pole):
     user_id, count = grouped_pole
     formatted_user = UserFormatter.retrieve_and_format(
         user_id, self.user_storage_handler)
     formatted_grouped_pole = FormattedText().normal(text).start_format()\
         .bold(user=formatted_user).normal(pole_count=count).end_format()
     self.printable_poles.append(formatted_grouped_pole)
Exemple #29
0
 def get_response_add(self, event, action_params, handler):
     timezone_alias = action_params[0]
     if timezone_alias in handler.get_timezones():
         return FormattedText().bold("ERROR").normal(", a timezone called ").bold(timezone_alias)\
             .normal(" already exists. Modify it instead of trying to add it again.")\
             .build_message()
     success = self.set_timezone_data(action_params, handler)
     if not success:
         return FormattedText().bold("ERROR while adding timezone").normal(", check name and offset are valid.")\
             .normal(" See help for more info")\
             .build_message()
     handler.add_timezone(timezone_alias)
     return FormattedText().bold("New timezone added!").newline().newline()\
         .normal("Alias: ").bold(timezone_alias).newline()\
         .concat(self.get_timezone_info_text(handler.get_timezone_state(timezone_alias)))\
         .build_message()
 def get_random_choice(choices):
     number_of_elements = len(choices)
     chosen = random.choice(choices)
     return FormattedText().normal("Choosing a random element from the ones you provided.").newline().newline()\
         .normal("Number of elements: ").normal(number_of_elements).newline().newline()\
         .normal("Chosen option: ").bold(chosen)\
         .build_message()