def send_failure_alert(printer, is_warning=True, print_paused=False):
    LOGGER.info(
        f'Printer {printer.user.id} {"smells fishy" if is_warning else "is probably failing"}. Sending Alerts'
    )
    if not printer.current_print:
        LOGGER.warn(
            f'Trying to alert on printer without current print. printer_id: {printer.id}'
        )
        return

    rotated_jpg_url = save_print_snapshot(
        printer,
        last_pic_of_print(printer.current_print, 'tagged'),
        f'snapshots/{printer.id}/{printer.current_print.id}/{str(timezone.now().timestamp())}_rotated.jpg',
        rotated=True,
        to_long_term_storage=False)

    # Calls wrapped in individual try/except because anyone of them could fail, and we still want the flow to continue
    try:
        mobile_notifications.send_failure_alert(printer, rotated_jpg_url,
                                                is_warning, print_paused)
    except:
        sentryClient.captureException()

    try:
        if printer.user.alert_by_email:
            send_failure_alert_email(printer, rotated_jpg_url, is_warning,
                                     print_paused)
    except:
        sentryClient.captureException()

    try:
        send_failure_alert_pushbullet(printer, rotated_jpg_url, is_warning,
                                      print_paused)
    except:
        sentryClient.captureException()

    try:
        send_failure_alert_pushover(printer, rotated_jpg_url, is_warning,
                                    print_paused)
    except:
        sentryClient.captureException()

    try:
        send_failure_alert_telegram(printer, rotated_jpg_url, is_warning,
                                    print_paused)
    except:
        sentryClient.captureException()

    try:
        if printer.user.is_pro and printer.user.alert_by_sms:
            send_failure_alert_sms(printer, is_warning, print_paused)
    except:
        sentryClient.captureException()

    try:
        if printer.user.is_pro:
            send_failure_alert_slack(printer, rotated_jpg_url, is_warning,
                                     print_paused)
    except:
        sentryClient.captureException()

    try:
        send_failure_alert_discord(printer, rotated_jpg_url, is_warning,
                                   print_paused)
    except:
        capture_exception()
    def send_failure_alerts(
        self,
        is_warning: bool,
        print_paused: bool,
        printer: Printer,
        print_: Print,
        img_url: str,
        extra_context: Optional[Dict] = None,
        plugin_names: Tuple[str, ...] = (),
        fail_silently: bool = True,
    ) -> None:
        try:
            mobile_notifications.send_failure_alert(printer, img_url, is_warning, print_paused)
        except Exception:
            capture_exception()

        if plugin_names:
            names = list(set(self.notification_plugin_names()) & set(plugin_names))
        else:
            names = self.notification_plugin_names()

        # select matching, enabled & configured
        nsettings = list(NotificationSetting.objects.filter(
            user_id=printer.user_id,
            enabled=True,
            name__in=names,
            notify_on_failure_alert=True
        ))

        if not nsettings:
            LOGGER.debug("no matching NotificationSetting objects, ignoring failure alert")
            return

        user_ctx = self.get_user_context(printer.user)
        printer_ctx = self.get_printer_context(printer)
        print_ctx = self.get_print_context(print_)
        
        for nsetting in nsettings:
            LOGGER.debug(f'forwarding failure alert to plugin "{nsetting.name}" (pk: {nsetting.pk})')
            try:
                plugin = self.notification_plugin_by_name(nsetting.name)
                if not plugin:
                    continue

                context = FailureAlertContext(
                    config=nsetting.config,
                    user=user_ctx,
                    printer=printer_ctx,
                    print=print_ctx,
                    is_warning=is_warning,
                    print_paused=print_paused,
                    extra_context=extra_context,
                    img_url=img_url,
                )

                self._send_failure_alert(nsetting=nsetting, context=context)
            except NotImplementedError:
                pass
            except Exception:
                if fail_silently:
                    LOGGER.exception('send_failure_alert plugin error')
                    capture_exception()
                else:
                    raise