Add email subject line and sending newsletters

This commit is contained in:
JonnyWong16 2018-01-09 01:14:19 -08:00
parent d104ec216c
commit 5ac5b3cd29
6 changed files with 94 additions and 59 deletions

View file

@ -133,7 +133,7 @@
<div class="col-md-8"> <div class="col-md-8">
<select class="form-control" id="email_notifier" name="email_notifier"> <select class="form-control" id="email_notifier" name="email_notifier">
% for notifier in email_notifiers: % for notifier in email_notifiers:
<% selected = 'selected' if notifier['id'] == newsletter['email_notifier'] else '' %> <% selected = 'selected' if notifier['id'] == newsletter['email_config']['notifier'] else '' %>
% if notifier['friendly_name']: % if notifier['friendly_name']:
<option value="${notifier['id']}" ${selected}>${notifier['agent_label']} (${notifier['id']} - ${notifier['friendly_name']})</option> <option value="${notifier['id']}" ${selected}>${notifier['agent_label']} (${notifier['id']} - ${notifier['friendly_name']})</option>
% elif notifier['id']: % elif notifier['id']:
@ -147,8 +147,21 @@
</div> </div>
<p class="help-block">Use an exisiting Email notification agent or enter a new configuration below.</p> <p class="help-block">Use an exisiting Email notification agent or enter a new configuration below.</p>
</div> </div>
<div class="form-group">
<label for="email_subject">Email Subject</label>
<div class="row">
<div class="col-md-8">
<input type="text" class="form-control" id="email_subject" name="email_subject" value="${newsletter['email_config']['subject']}" size="30">
</div>
</div>
<p class="help-block">
Optional: Enter a subject line for the email. Leave blank for default.
<br>
Note: You may include <span class="inline-pre">{start_date}</span> and <span class="inline-pre">{end_date}</span> as parameters. The global date format under Settings > General will be used.
</p>
</div>
</div> </div>
<div id="newsletter-email-config" class="col-md-12" style="padding-top: 10px; border-top: 1px solid #444; ${'display: none;' if newsletter['email_notifier'] else ''}"> <div id="newsletter-email-config" class="col-md-12" style="padding-top: 10px; border-top: 1px solid #444; ${'display: none;' if newsletter['email_config']['notifier'] else ''}">
% for item in newsletter['email_config_options']: % for item in newsletter['email_config_options']:
% if item['input_type'] == 'help': % if item['input_type'] == 'help':
<div class="form-group"> <div class="form-group">

View file

@ -733,7 +733,7 @@
<tr> <tr>
<td class="wrapper newsletter-header"> <td class="wrapper newsletter-header">
<div class="header"></div> <div class="header"></div>
<div class="dates">${start_date} - ${end_date}</div> <div class="dates">${parameters['start_date']} - ${parameters['end_date']}</div>
</td> </td>
</tr> </tr>
% if recently_added.get('movie'): % if recently_added.get('movie'):

View file

@ -624,7 +624,7 @@ def dbcheck():
c_db.execute( c_db.execute(
'CREATE TABLE IF NOT EXISTS newsletters (id INTEGER PRIMARY KEY AUTOINCREMENT, ' 'CREATE TABLE IF NOT EXISTS newsletters (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'agent_id INTEGER, agent_name TEXT, agent_label TEXT, ' 'agent_id INTEGER, agent_name TEXT, agent_label TEXT, '
'friendly_name TEXT, newsletter_config TEXT, email_config TEXT, email_notifier INTEGER DEFAULT 0, ' 'friendly_name TEXT, newsletter_config TEXT, email_config TEXT, '
'cron TEXT NOT NULL DEFAULT "0 0 * * 0", active INTEGER DEFAULT 0)' 'cron TEXT NOT NULL DEFAULT "0 0 * * 0", active INTEGER DEFAULT 0)'
) )

View file

@ -15,14 +15,10 @@
import arrow import arrow
import json import json
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import email.utils
from itertools import groupby from itertools import groupby
from mako.lookup import TemplateLookup from mako.lookup import TemplateLookup
from mako import exceptions from mako import exceptions
import os import os
import re
import time import time
import plexpy import plexpy
@ -32,8 +28,7 @@ import libraries
import logger import logger
import notification_handler import notification_handler
import pmsconnect import pmsconnect
import request from notifiers import send_notification, EMAIL
from notifiers import EMAIL
AGENT_IDS = { AGENT_IDS = {
@ -114,8 +109,8 @@ def get_newsletter_config(newsletter_id=None):
return None return None
try: try:
config = json.loads(result.pop('newsletter_config') or '{}') config = json.loads(result.pop('newsletter_config', '{}'))
email_config = json.loads(result.pop('email_config') or '{}') email_config = json.loads(result.pop('email_config', '{}'))
newsletter_agent = get_agent_class(agent_id=result['agent_id'], config=config, email_config=email_config) newsletter_agent = get_agent_class(agent_id=result['agent_id'], config=config, email_config=email_config)
newsletter_config = newsletter_agent.return_config_options() newsletter_config = newsletter_agent.return_config_options()
newsletter_email_config = newsletter_agent.return_email_config_options() newsletter_email_config = newsletter_agent.return_email_config_options()
@ -124,6 +119,7 @@ def get_newsletter_config(newsletter_id=None):
return return
result['config'] = config result['config'] = config
result['email_config'] = email_config
result['config_options'] = newsletter_config result['config_options'] = newsletter_config
result['email_config_options'] = newsletter_email_config result['email_config_options'] = newsletter_email_config
@ -188,8 +184,6 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs):
newsletter_config = {k[len(config_prefix):]: kwargs.pop(k) newsletter_config = {k[len(config_prefix):]: kwargs.pop(k)
for k in kwargs.keys() if k.startswith(config_prefix)} for k in kwargs.keys() if k.startswith(config_prefix)}
email_notifier = kwargs.pop('email_notifier', 0)
email_config = {k[len(email_config_prefix):]: kwargs.pop(k) email_config = {k[len(email_config_prefix):]: kwargs.pop(k)
for k in kwargs.keys() if k.startswith(email_config_prefix)} for k in kwargs.keys() if k.startswith(email_config_prefix)}
@ -202,7 +196,6 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs):
'friendly_name': kwargs.get('friendly_name', ''), 'friendly_name': kwargs.get('friendly_name', ''),
'newsletter_config': json.dumps(agent_class.config), 'newsletter_config': json.dumps(agent_class.config),
'email_config': json.dumps(agent_class.email_config), 'email_config': json.dumps(agent_class.email_config),
'email_notifier': email_notifier,
'cron': kwargs.get('cron'), 'cron': kwargs.get('cron'),
'active': kwargs.get('active') 'active': kwargs.get('active')
} }
@ -245,11 +238,17 @@ def serve_template(templatename, **kwargs):
class Newsletter(object): class Newsletter(object):
NAME = '' NAME = ''
_DEFAULT_CONFIG = {} _DEFAULT_CONFIG = {}
_DEFAULT_EMAIL_CONFIG = EMAIL._DEFAULT_CONFIG
def __init__(self, config=None, email_config=None): def __init__(self, config=None, email_config=None):
self._default_email_config = EMAIL().return_default_config()
self._default_email_config['from_name'] = 'Tautulli Newsletter'
self._default_email_config['notifier'] = 0
self._default_email_config['subject'] = 'Tautulli Newsletter'
self.config = self.set_config(config=config, default=self._DEFAULT_CONFIG) self.config = self.set_config(config=config, default=self._DEFAULT_CONFIG)
self.email_config = self.set_config(config=email_config, default=self._DEFAULT_EMAIL_CONFIG) self.email_config = self.set_config(config=email_config, default=self._default_email_config)
self.parameters = {}
def set_config(self, config=None, default=None): def set_config(self, config=None, default=None):
return self._validate_config(config=config, default=default) return self._validate_config(config=config, default=default)
@ -267,33 +266,59 @@ class Newsletter(object):
return new_config return new_config
def preview(self, **kwargs): def _render_template(self, **kwargs):
return serve_template(
templatename=self._TEMPLATE,
title=self.NAME,
parameters=self.parameters,
**kwargs
)
def _format_subject(self, subject):
subject = subject or self._default_email_config['subject']
try:
subject = unicode(subject).format(**self.parameters)
except LookupError as e:
logger.error(
u"Tautulli Newsletter :: Unable to parse parameter %s in newsletter subject. Using fallback." % e)
subject = unicode(self._default_email_config['subject']).format(**self.parameters)
except Exception as e:
logger.error(
u"Tautulli Newsletter :: Unable to parse custom newsletter subject: %s. Using fallback." % e)
subject = unicode(self._default_email_config['subject']).format(**self.parameters)
return subject
def retrieve_data(self):
pass pass
def generate_newsletter(self):
pass
def preview(self):
self.retrieve_data()
return self.generate_newsletter()
def send(self, **kwargs): def send(self, **kwargs):
pass self.retrieve_data()
def make_request(self, url, method='POST', **kwargs): subject = self._format_subject(self.email_config['subject'])
response, err_msg, req_msg = request.request_response2(url, method, **kwargs) newsletter = self.generate_newsletter()
if response and not err_msg: if self.email_config['notifier']:
logger.info(u"Tautulli Newsletters :: {name} notification sent.".format(name=self.NAME)) return send_notification(
return True notifier_id=self.email_config['notifier'],
subject=subject,
body=newsletter
)
else: else:
verify_msg = "" email = EMAIL(config=self.email_config)
if response is not None and response.status_code >= 400 and response.status_code < 500: return email.notify(
verify_msg = " Verify you notification newsletter agent settings are correct." subject=subject,
body=newsletter
logger.error(u"Tautulli Newsletters :: {name} notification failed.{}".format(verify_msg, name=self.NAME)) )
if err_msg:
logger.error(u"Tautulli Newsletters :: {}".format(err_msg))
if req_msg:
logger.debug(u"Tautulli Newsletters :: Request response: {}".format(req_msg))
return False
def return_config_options(self): def return_config_options(self):
config_options = [] config_options = []
@ -321,6 +346,8 @@ class RecentlyAdded(Newsletter):
elif not isinstance(self.config['incl_libraries'], list): elif not isinstance(self.config['incl_libraries'], list):
self.config['incl_libraries'] = [self.config['incl_libraries']] self.config['incl_libraries'] = [self.config['incl_libraries']]
self._default_email_config['subject'] = 'Recently Added to Plex! ({end_date})'
date_format = helpers.momentjs_to_arrow(plexpy.CONFIG.DATE_FORMAT) date_format = helpers.momentjs_to_arrow(plexpy.CONFIG.DATE_FORMAT)
self.end_time = int(time.time()) self.end_time = int(time.time())
@ -328,6 +355,9 @@ class RecentlyAdded(Newsletter):
self.end_date = arrow.get(self.end_time).format(date_format) self.end_date = arrow.get(self.end_time).format(date_format)
self.start_date = arrow.get(self.start_time).format(date_format) self.start_date = arrow.get(self.start_time).format(date_format)
self.parameters = {'start_date': self.start_date,
'end_date': self.end_date}
self.plexpy_config = { self.plexpy_config = {
'pms_identifier': plexpy.CONFIG.PMS_IDENTIFIER, 'pms_identifier': plexpy.CONFIG.PMS_IDENTIFIER,
'pms_web_url': plexpy.CONFIG.PMS_WEB_URL 'pms_web_url': plexpy.CONFIG.PMS_WEB_URL
@ -451,32 +481,22 @@ class RecentlyAdded(Newsletter):
return recently_added return recently_added
def get_recently_added(self): def retrieve_data(self):
media_types = {s['section_type'] for s in self._get_sections() media_types = {s['section_type'] for s in self._get_sections()
if str(s['section_id']) in self.config['incl_libraries']} if str(s['section_id']) in self.config['incl_libraries']}
for media_type in media_types: for media_type in media_types:
self.recently_added[media_type] = self._get_recently_added(media_type) if media_type not in self.recently_added:
self.recently_added[media_type] = self._get_recently_added(media_type)
return self.recently_added return self.recently_added
def preview(self, **kwargs): def generate_newsletter(self):
self.get_recently_added() return self._render_template(
return serve_template(
templatename=self._TEMPLATE,
title=self.NAME,
recently_added=self.recently_added, recently_added=self.recently_added,
start_date=self.start_date,
end_date=self.end_date,
plexpy_config=self.plexpy_config plexpy_config=self.plexpy_config
) )
def send(self, **kwargs):
self.get_recently_added()
return
def _get_sections(self): def _get_sections(self):
return libraries.Libraries().get_sections() return libraries.Libraries().get_sections()

View file

@ -454,7 +454,7 @@ def get_notifier_config(notifier_id=None):
return None return None
try: try:
config = json.loads(result.pop('notifier_config') or '{}') config = json.loads(result.pop('notifier_config', '{}'))
notifier_agent = get_agent_class(agent_id=result['agent_id'], config=config) notifier_agent = get_agent_class(agent_id=result['agent_id'], config=config)
notifier_config = notifier_agent.return_config_options() notifier_config = notifier_agent.return_config_options()
except Exception as e: except Exception as e:
@ -772,6 +772,9 @@ class Notifier(object):
return new_config return new_config
def return_default_config(self):
return self._DEFAULT_CONFIG
def notify(self, subject='', body='', action='', **kwargs): def notify(self, subject='', body='', action='', **kwargs):
if self.NAME != 'Script': if self.NAME != 'Script':
if not subject and self.config.get('incl_subject', True): if not subject and self.config.get('incl_subject', True):
@ -1271,7 +1274,7 @@ class EMAIL(Notifier):
Email notifications Email notifications
""" """
NAME = 'Email' NAME = 'Email'
_DEFAULT_CONFIG = {'from_name': '', _DEFAULT_CONFIG = {'from_name': 'Tautulli',
'from': '', 'from': '',
'to': '', 'to': '',
'cc': '', 'cc': '',

View file

@ -3157,7 +3157,7 @@ class WebInterface(object):
notifier = notifiers.get_notifier_config(notifier_id=notifier_id) notifier = notifiers.get_notifier_config(notifier_id=notifier_id)
if notifier: if notifier:
logger.debug(u"Sending %s%s notification." % (test, notifier['agent_name'])) logger.debug(u"Sending %s%s notification." % (test, notifier['agent_label']))
if notification_handler.notify(notifier_id=notifier_id, if notification_handler.notify(notifier_id=notifier_id,
notify_action=notify_action, notify_action=notify_action,
subject=subject, subject=subject,
@ -5500,9 +5500,8 @@ class WebInterface(object):
newsletter = newsletters.get_newsletter_config(newsletter_id=newsletter_id) newsletter = newsletters.get_newsletter_config(newsletter_id=newsletter_id)
if newsletter: if newsletter:
logger.debug(u"Sending %s%s newsletter." % (test, newsletter['agent_name'])) logger.debug(u"Sending %s%s newsletter." % (test, newsletter['agent_label']))
if newsletter_handler.send(newsletter_id=newsletter_id, if newsletters.send_newsletter(newsletter_id=newsletter_id):
**kwargs):
return "Newsletter sent." return "Newsletter sent."
else: else:
return "Newsletter failed." return "Newsletter failed."