예제 #1
0
def send_failure_alert(printer):
    if not settings.EMAIL_HOST:
        LOGGER.warn("Email settings are missing. Ignored send requests")
        return

    subject = 'Your print {} may be failing on {}'.format(
        printer.current_print_filename or '', printer.name)
    from_email = settings.DEFAULT_FROM_EMAIL

    ctx = {
        'printer':
        printer,
        'view_link':
        site.build_full_url('/printers/'),
        'cancel_link':
        site.build_full_url('/printers/{}/cancel/'.format(printer.id)),
        'resume_link':
        site.build_full_url('/printers/{}/resume/?mute_alert=true'.format(
            printer.id)),
    }

    message = get_template('email/failure_alert.html').render(ctx)
    msg = EmailMessage(subject,
                       message,
                       to=(printer.user.email, ),
                       from_email=from_email)
    msg.content_subtype = 'html'
    msg.send()
def send_failure_alert_email(printer, is_warning, print_paused):
    if not settings.EMAIL_HOST:
        LOGGER.warn("Email settings are missing. Ignored send requests")
        return

    subject = 'Your print {} on {} {}.'.format(
        printer.current_print.filename or '', printer.name,
        'smells fishy' if is_warning else 'is probably failing')

    ctx = {
        'printer':
        printer,
        'print_paused':
        print_paused,
        'is_warning':
        is_warning,
        'view_link':
        site.build_full_url('/printers/'),
        'cancel_link':
        site.build_full_url('/printers/{}/cancel/'.format(printer.id)),
        'resume_link':
        site.build_full_url('/printers/{}/resume/'.format(printer.id)),
    }

    unsub_url = site.build_full_url(
        f'/unsubscribe_email/?unsub_token={printer.user.unsub_token}&list=alert'
    )
    send_email(
        printer.user,
        subject,
        unsub_url,
        'email/failure_alert.html',
        ctx,
        img_url=printer.pic['img_url'],
    )
def send_print_notification_email(_print, extra_ctx={}, event_type=None):
    ctx = {
        'print': _print,
        'timelapse_link': site.build_full_url(f'/prints/{_print.id}/'),
        'user_pref_url': site.build_full_url('/user_preferences/'),
    }

    if event_type == PrintEvent.FILAMENT_CHANGE:
        subject = f'{_print.filename} requires filament change.'
        template_path = 'email/filament_change_req_notification.html'
    else:
        subject = f'{_print.filename} is canceled.' if _print.is_canceled(
        ) else f'🙌 {_print.filename} is ready.'
        template_path = 'email/print_notification.html'
        ctx['print_time'] = str(_print.ended_at() -
                                _print.started_at).split('.')[0],

    ctx.update(extra_ctx)
    send_email(
        user=_print.printer.user,
        subject=subject,
        mailing_list='print_notification',
        template_path=template_path,
        ctx=ctx,
        img_url=_print.poster_url,
    )
예제 #4
0
def send_failure_alert_email(printer, rotated_jpg_url, is_warning,
                             print_paused):
    if not settings.EMAIL_HOST:
        LOGGER.warn("Email settings are missing. Ignored send requests")
        return

    subject = 'Your print {} on {} {}.'.format(
        printer.current_print.filename or '', printer.name,
        'smells fishy' if is_warning else 'is probably failing')

    ctx = {
        'printer':
        printer,
        'print_paused':
        print_paused,
        'is_warning':
        is_warning,
        'view_link':
        site.build_full_url('/printers/'),
        'cancel_link':
        site.build_full_url('/prints/{}/cancel/'.format(
            printer.current_print_id)),
        'resume_link':
        site.build_full_url('/prints/{}/resume/'.format(
            printer.current_print_id)),
    }

    send_email(
        user=printer.user,
        subject=subject,
        mailing_list='alert',
        template_path='email/failure_alert.html',
        ctx=ctx,
        img_url=rotated_jpg_url,
    )
def inline_markup(printer, buttons=['more_info']):
    links = {
        'cancel': {
            'text': 'Yes it failed. Cancel the print!',
            'url':
            site.build_full_url('/printers/{}/cancel/'.format(printer.id))
        },
        'resume': {
            'text': 'It is a false alarm. Resume the print!',
            'url':
            site.build_full_url('/printers/{}/resume/'.format(printer.id))
        },
        'do_not_ask': {
            'text':
            'Resume the print, and don\'t alert me for the rest of this print.',
            'url':
            site.build_full_url('/printers/{}/resume/?mute_alert=true'.format(
                printer.id))
        },
        'more_info': {
            'text': 'Go to The Spaghetti Detective to take a closer look.',
            'url': site.build_full_url('/printers/')
        }
    }

    button_list = [
        types.InlineKeyboardButton(links[button]['text'],
                                   url=links[button]['url'])
        for button in buttons
    ]
    markup = types.InlineKeyboardMarkup(row_width=1)
    markup.add(*button_list)

    return markup
def send_failure_alert_email(printer, is_warning, print_paused):
    if not settings.EMAIL_HOST:
        LOGGER.warn("Email settings are missing. Ignored send requests")
        return

    # https://github.com/TheSpaghettiDetective/TheSpaghettiDetective/issues/43
    try:
        if ipaddress.ip_address(urlparse(
                printer.pic['img_url']).hostname).is_global:
            attachments = []
        else:
            attachments = [('Detected Failure.jpg',
                            requests.get(printer.pic['img_url']).content,
                            'image/jpeg')]
    except:
        attachments = []

    subject = 'Your print {} on {} {}.'.format(
        printer.current_print.filename or '', printer.name,
        'smells fishy' if is_warning else 'is probably failing')
    from_email = settings.DEFAULT_FROM_EMAIL

    ctx = {
        'printer':
        printer,
        'print_paused':
        print_paused,
        'is_warning':
        is_warning,
        'view_link':
        site.build_full_url('/printers/'),
        'cancel_link':
        site.build_full_url('/printers/{}/cancel/'.format(printer.id)),
        'resume_link':
        site.build_full_url('/printers/{}/resume/?mute_alert=true'.format(
            printer.id)),
        'insert_img':
        len(attachments) == 0,
    }

    # By default email verification should be required for notifications but
    # maybe users will want to disable it on private servers
    if settings.ACCOUNT_EMAIL_VERIFICATION != 'none':
        emails = EmailAddress.objects.filter(user=printer.user, verified=True)
    else:
        emails = EmailAddress.objects.filter(user=printer.user)
    message = get_template('email/failure_alert.html').render(ctx)
    for email in emails:
        msg = EmailMessage(subject,
                           message,
                           to=(email.email, ),
                           from_email=from_email,
                           attachments=attachments)
        msg.content_subtype = 'html'
        msg.send()
def send_print_notification_pushbullet(_print):
    if not _print.printer.user.has_valid_pushbullet_token():
        return

    pb = Pushbullet(_print.printer.user.pushbullet_access_token)

    title = 'The Spaghetti Detective - Print job notification'
    link = site.build_full_url('/')
    body = f"Your print job {_print.filename} {'has been canceled' if _print.is_canceled() else 'is done'} on printer {_print.printer.name}."
    file_url = None
    try:
        file_url = _print.printer.pic['img_url']
        if not ipaddress.ip_address(urlparse(file_url).hostname).is_global:
            pb.upload_file(requests.get(file_url).content, 'Snapshot.jpg')
    except:
        pass

    try:
        if file_url:
            pb.push_file(file_url=file_url,
                         file_name="Snapshot.jpg",
                         file_type="image/jpeg",
                         body=body,
                         title=title)
        else:
            pb.push_link(title, link, body)
    except (PushError, PushbulletError) as e:
        LOGGER.error(e)
def send_failure_alert_pushover(printer, rotated_jpg_url, is_warning,
                                print_paused):
    if not printer.user.pushover_user_token:
        return

    try:
        photo = requests.get(rotated_jpg_url).content
    except:
        photo = None

    pausing_msg = ''
    if print_paused:
        pausing_msg = 'Printer is paused.'
    elif printer.action_on_failure == Printer.PAUSE and is_warning:
        pausing_msg = 'Printer is NOT paused because The Detective is not very sure about it.'

    title = 'The Spaghetti Detective - Failure alert!'

    msg = 'Your print {} on {} {}.'.format(
        printer.current_print.filename or '', printer.name,
        'smells fishy' if is_warning else 'is probably failing')
    link = site.build_full_url('/')
    body = '{}\n{}\nGo check it at: {}'.format(msg, pausing_msg, link)
    priority = PushoverPriority.HIGH

    try:
        pushover_notification(printer.user.pushover_user_token, body, title,
                              photo, priority)
    except (PushoverException) as e:
        LOGGER.error(e)
def send_failure_alert_pushbullet(printer, is_warning, print_paused):
    if not printer.user.has_valid_pushbullet_token():
        return

    pausing_msg = ''
    if print_paused:
        pausing_msg = 'Printer is paused.'
    elif printer.action_on_failure == Printer.PAUSE and is_warning:
        pausing_msg = 'Printer is NOT paused because The Detective is not very sure about it.'

    pb = Pushbullet(printer.user.pushbullet_access_token)
    title = 'The Spaghetti Detective - Your print {} on {} {}.'.format(
        printer.current_print.filename or '',
        printer.name,
        'smells fishy' if is_warning else 'is probably failing')
    link = site.build_full_url('/')
    body = '{}\nGo check it at: {}'.format(pausing_msg, link)

    try:
        file_url = None
        try:
            file_url = printer.pic['img_url']
            if not ipaddress.ip_address(urlparse(file_url).hostname).is_global:
                pb.upload_file(requests.get(file_url).content, 'Detected Failure.jpg')
        except:
            pass

        if file_url:
            pb.push_file(file_url=file_url, file_name="Detected Failure.jpg", file_type="image/jpeg", body=body, title=title)
        else:
            pb.push_link(title, link, body)
    except PushError as e:
        LOGGER.error(e)
    except PushbulletError as e:
        LOGGER.error(e)
예제 #10
0
def send_timelapse_detection_done_email(_print):
    if not settings.EMAIL_HOST:
        LOGGER.warn("Email settings are missing. Ignored send requests")
        return

    subject = 'The Detective is done looking at the time-lapse you uploaded.'
    from_email = settings.DEFAULT_FROM_EMAIL

    ctx = {
        'print':
        _print,
        'unsub_url':
        'https://app.thespaghettidetective.com/ent/email_unsubscribe/?list=notification&email={}'
        .format(_print.user.email),
        'prints_link':
        site.build_full_url('/prints/'),
    }
    emails = [
        email.email for email in EmailAddress.objects.filter(user=_print.user)
    ]
    message = get_template('email/upload_print_processed.html').render(ctx)
    msg = EmailMessage(
        subject,
        message,
        to=emails,
        from_email=from_email,
        headers={
            'List-Unsubscribe':
            '<{}>, <mailto:[email protected]?subject=Unsubscribe_notification>'
            .format(ctx['unsub_url'])
        },
    )
    msg.content_subtype = 'html'
    msg.send()
예제 #11
0
    def send_failure_alert(self, context: FailureAlertContext) -> None:
        chat_id = self.get_chat_id_from_config(context.config)
        if not chat_id:
            return

        link = site.build_full_url('/printers/')
        text = self.get_failure_alert_text(context=context, link=link)
        if not text:
            return

        buttons = ['more_info']
        if context.print_paused:
            buttons = ['cancel', 'resume', 'do_not_ask', 'more_info']
        elif context.printer.pause_on_failure and context.is_warning:
            buttons = ['cancel', 'more_info']

        message = f"Hi {context.user.first_name},\n{text}"

        try:
            file_content = requests.get(context.img_url).content
        except:
            file_content = None

        markups = self.inline_buttons(
            context, buttons) if file_content else self.default_button()

        self.call_telegram(
            chat_id=chat_id,
            message=message,
            markups=markups,
            file_content=file_content,
        )
def send_print_notification_pushbullet(_print, event_type=None):
    if not _print.printer.user.has_valid_pushbullet_token():
        return

    pb = Pushbullet(_print.printer.user.pushbullet_access_token)

    title = 'The Spaghetti Detective - Print job notification'
    link = site.build_full_url('/')
    body = get_notification_body(_print, event_type=event_type)
    file_url = None
    try:
        file_url = _print.poster_url
        if not settings.SITE_IS_PUBLIC:
            pb.upload_file(requests.get(file_url).content, 'Snapshot.jpg')
    except:
        pass

    try:
        if file_url:
            pb.push_file(file_url=file_url,
                         file_name="Snapshot.jpg",
                         file_type="image/jpeg",
                         body=body,
                         title=title)
        else:
            pb.push_link(title, link, body)
    except (PushError, PushbulletError) as e:
        LOGGER.error(e)
def send_failure_alert_sms(printer, is_warning, print_paused):
    if not settings.TWILIO_ENABLED:
        LOGGER.warn("Twilio settings are missing. Ignored send requests")
        return

    if not printer.user.sms_eligible():
        return

    twilio_client = Client(settings.TWILIO_ACCOUNT_SID,
                           settings.TWILIO_AUTH_TOKEN)
    from_number = settings.TWILIO_FROM_NUMBER

    to_number = printer.user.phone_country_code + printer.user.phone_number

    pausing_msg = ''
    if print_paused:
        pausing_msg = 'Printer is paused. '
    elif printer.action_on_failure == Printer.PAUSE and is_warning:
        pausing_msg = 'Printer is NOT paused. '

    msg = 'The Spaghetti Detective - Your print {} on {} {}. {}Go check it at: {}'.format(
        printer.current_print.filename or '', printer.name,
        'smells fishy' if is_warning else 'is probably failing', pausing_msg,
        site.build_full_url('/'))
    twilio_client.messages.create(body=msg, to=to_number, from_=from_number)
예제 #14
0
def default_markup():
    markup = types.InlineKeyboardMarkup(row_width=1)
    markup.add(
        types.InlineKeyboardButton(
            'Go to The Spaghetti Detective to take a closer look.',
            url=site.build_full_url('/printers/')))
    return markup
def send_print_notification_email(_print, extra_ctx={}):
    subject = f'{_print.filename} is canceled.' if _print.is_canceled(
    ) else f'🙌 {_print.filename} is ready.'
    ctx = {
        'print': _print,
        'print_time': str(_print.ended_at() - _print.started_at).split('.')[0],
        'timelapse_link': site.build_full_url(f'/prints/{_print.id}/'),
        'user_pref_url': site.build_full_url(f'/user_preferences/'),
    }
    ctx.update(extra_ctx)
    send_email(
        user=_print.printer.user,
        subject=subject,
        mailing_list='print_notification',
        template_path='email/print_notification.html',
        ctx=ctx,
        img_url=_print.poster_url,
    )
 def send_test_message(self, context: TestMessageContext) -> None:
     access_token = self.get_access_token_from_config(context.config)
     link = site.build_full_url('/')
     self.call_pushbullet(
         access_token=access_token,
         title='Test Notification',
         body='It works',
         link=link,
         file_url='',
     )
def save_file_obj(dest_path, file_obj, container):
    fqp = path.join(settings.MEDIA_ROOT, container, dest_path)
    if not path.exists(path.dirname(fqp)):
        os.makedirs(path.dirname(fqp))

    with open(fqp, 'wb+') as dest_file:
        copyfileobj(file_obj, dest_file)

    uri = '{}{}/{}'.format(settings.MEDIA_URL, container, dest_path)
    return settings.INTERNAL_MEDIA_HOST + uri, site.build_full_url(uri)
def send_print_notification_email(_print):
    subject = f'{_print.filename} is canceled.' if _print.is_canceled(
    ) else f'🙌 {_print.filename} is ready.'
    ctx = {
        'print': _print,
        'print_time': str(_print.ended_at() - _print.started_at).split('.')[0],
        'timelapse_link': site.build_full_url('/prints/'),
    }
    unsub_url = site.build_full_url(
        f'/unsubscribe_email/?unsub_token={_print.printer.user.unsub_token}&list=print_notification'
    )
    send_email(
        _print.printer.user,
        subject,
        unsub_url,
        'email/print_notification.html',
        ctx,
        img_url=_print.printer.pic['img_url'] if _print.printer.pic else None,
    )
예제 #19
0
    def send_failure_alert(self, context: FailureAlertContext) -> None:
        if not settings.TWILIO_ENABLED:
            LOGGER.warn("Twilio settings are missing. Ignored send requests")
            return

        to_number = self.get_number_from_config(context.config)
        link = site.build_full_url('/printers/')
        text = self.get_failure_alert_text(context=context, link=link)
        if not text or not to_number:
            return

        return self.send_sms(body=text, to_number=to_number)
예제 #20
0
def send_email(user,
               subject,
               mailing_list,
               template_path,
               ctx,
               img_url=None,
               verified_only=True,
               attachment=None):
    if not settings.EMAIL_HOST:
        LOGGER.warn("Email settings are missing. Ignored send requests")
        return

    attachments = []
    if img_url:
        # https://github.com/TheSpaghettiDetective/TheSpaghettiDetective/issues/43
        try:
            if not ipaddress.ip_address(urlparse(img_url).hostname).is_global:
                attachments = [('Image.jpg', requests.get(img_url).content,
                                'image/jpeg')]
        except:
            pass

        ctx['img_url'] = None if attachments else img_url

    # By default email verification should be required for notifications but
    # maybe users will want to disable it on private servers
    if settings.ACCOUNT_EMAIL_VERIFICATION != 'none' and verified_only:
        emails = EmailAddress.objects.filter(user=user, verified=True)
    else:
        emails = EmailAddress.objects.filter(user=user)

    unsub_url = site.build_full_url(
        f'/unsubscribe_email/?unsub_token={user.unsub_token}&list={mailing_list}'
    )
    for email in emails:
        ctx['unsub_url'] = unsub_url
        message = get_template(template_path).render(ctx)
        msg = EmailMessage(
            subject,
            message,
            to=(email.email, ),
            from_email=settings.DEFAULT_FROM_EMAIL,
            attachments=attachments,
            headers={
                'List-Unsubscribe':
                f'<{unsub_url}>, <mailto:[email protected]?subject=Unsubscribe_{mailing_list}>'
            },
        )
        msg.content_subtype = 'html'
        if attachment:
            msg.attach_file(attachment)
        msg.send()
예제 #21
0
def send_failure_alert_sms(printer, pause_print):
    if not settings.TWILIO_ENABLED:
        LOGGER.warn("Twilio settings are missing. Ignored send requests")
        return

    if not printer.user.sms_eligible():
        return

    twilio_client = Client(settings.TWILIO_ACCOUNT_SID,
                           settings.TWILIO_AUTH_TOKEN)
    from_number = settings.TWILIO_FROM_NUMBER

    to_number = printer.user.phone_country_code + printer.user.phone_number
    msg = 'The Spaghetti Detective - Your print {} may be failing on {}. {}Go check it at: {}'.format(
        printer.current_print_filename or '', printer.name,
        'Printer is paused. ' if pause_print else '', site.build_full_url('/'))
    twilio_client.messages.create(body=msg, to=to_number, from_=from_number)
    def send_failure_alert(self, context: FailureAlertContext) -> None:
        access_token = self.get_access_token_from_config(context.config)
        if not access_token:
            return

        link = site.build_full_url('/')
        title = self.get_failure_alert_title(context=context, link=link)
        text = self.get_failure_alert_text(context=context, link=link)
        if not title or not text:
            return

        self.call_pushbullet(
            access_token=access_token,
            title=title,
            body=text,
            link=link,
            file_url=context.img_url,
        )
    def send_printer_notification(self,
                                  context: PrinterNotificationContext) -> None:
        access_token = self.get_access_token_from_config(context.config)
        if not access_token:
            return

        title = self.get_printer_notification_title(context=context)
        text = self.get_printer_notification_text(context=context)
        if not text or not title:
            return

        link = site.build_full_url('/')

        self.call_pushbullet(
            access_token=access_token,
            title=title,
            body=text,
            link=link,
            file_url=context.img_url,
        )
예제 #24
0
def send_discord_notification(printer,
                              text,
                              color,
                              webhook_url,
                              image_url=None):
    webhook = DiscordWebhook(url=webhook_url,
                             username="******")
    embed = DiscordEmbed(title=printer.name, description=text, color=color)
    if image_url:
        embed.set_image(url=image_url)
    embed.set_author(
        name="Click Here to Examine.",
        url=site.build_full_url('/printers/'),
        icon_url=
        "https://github.com/TheSpaghettiDetective/TheSpaghettiDetective/raw/master/web/app/static/img/logo-square.png"
    )
    embed.set_timestamp()
    embed.set_footer(text="The Spaghetti Detective")
    webhook.add_embed(embed)
    webhook.execute()
    def call_webhook(self,
                     title: str,
                     text: str,
                     color: int,
                     webhook_url: str,
                     image_url: Optional[str] = None):
        webhook = DiscordWebhook(url=webhook_url,
                                 username="******")
        embed = DiscordEmbed(title=title, description=text, color=color)
        if image_url:
            embed.set_image(url=image_url)

        embed.set_author(
            name="Printer Notification",
            url=site.build_full_url('/printers/'),
            icon_url=
            "https://github.com/TheSpaghettiDetective/TheSpaghettiDetective/raw/master/frontend/static/img/logo/compact/logo-compact_light-scheme.png"
        )
        embed.set_timestamp()
        embed.set_footer(text="The Spaghetti Detective")
        webhook.add_embed(embed)
        webhook.execute()