diff --git a/data/interfaces/default/js/tables/newsletter_logs.js b/data/interfaces/default/js/tables/newsletter_logs.js
index 166fc22e..6375bec3 100644
--- a/data/interfaces/default/js/tables/newsletter_logs.js
+++ b/data/interfaces/default/js/tables/newsletter_logs.js
@@ -48,7 +48,7 @@ newsletter_log_table_options = {
$(td).html(cellData);
}
},
- "width": "10%",
+ "width": "5%",
"className": "no-wrap"
},
{
@@ -67,43 +67,53 @@ newsletter_log_table_options = {
"data": "subject_text",
"createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== '') {
- $(td).html('' + cellData + '');
+ $(td).html(cellData);
}
},
- "width": "38%"
+ "width": "25%"
},
{
"targets": [5],
+ "data": "body_text",
+ "createdCell": function (td, cellData, rowData, row, col) {
+ if (cellData !== '') {
+ $(td).html(cellData);
+ }
+ },
+ "width": "33%"
+ },
+ {
+ "targets": [6],
"data": "start_date",
"createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== '') {
$(td).html(cellData);
}
},
- "width": "10%"
+ "width": "5%"
},
{
- "targets": [6],
+ "targets": [7],
"data": "end_date",
"createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== '') {
$(td).html(cellData);
}
},
- "width": "10%"
- },
- {
- "targets": [7],
- "data": "uuid",
- "createdCell": function (td, cellData, rowData, row, col) {
- if (cellData !== '') {
- $(td).html(cellData);
- }
- },
- "width": "10%"
+ "width": "5%"
},
{
"targets": [8],
+ "data": "uuid",
+ "createdCell": function (td, cellData, rowData, row, col) {
+ if (cellData !== '') {
+ $(td).html('' + cellData + '');
+ }
+ },
+ "width": "5%"
+ },
+ {
+ "targets": [9],
"data": "success",
"createdCell": function (td, cellData, rowData, row, col) {
if (cellData === 1) {
diff --git a/data/interfaces/default/logs.html b/data/interfaces/default/logs.html
index 38d88ab5..22a5df0c 100644
--- a/data/interfaces/default/logs.html
+++ b/data/interfaces/default/logs.html
@@ -152,6 +152,7 @@
Agent |
Action |
Subject Text |
+ Body Text |
Start Date |
End Date |
UUID |
diff --git a/data/interfaces/default/newsletter_config.html b/data/interfaces/default/newsletter_config.html
index c4f3aad3..0d2f783a 100644
--- a/data/interfaces/default/newsletter_config.html
+++ b/data/interfaces/default/newsletter_config.html
@@ -176,10 +176,10 @@
Use an existing Email notification agent or enter a new configuration below.
+
% for item in newsletter['email_config_options']:
diff --git a/plexpy/__init__.py b/plexpy/__init__.py
index 4d0a491d..907521b2 100644
--- a/plexpy/__init__.py
+++ b/plexpy/__init__.py
@@ -638,14 +638,15 @@ def dbcheck():
'CREATE TABLE IF NOT EXISTS newsletters (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'agent_id INTEGER, agent_name TEXT, agent_label TEXT, '
'friendly_name TEXT, newsletter_config TEXT, email_config TEXT, '
- 'cron TEXT NOT NULL DEFAULT "0 0 * * 0", active INTEGER DEFAULT 0)'
+ 'subject TEXT, body TEXT, cron TEXT NOT NULL DEFAULT "0 0 * * 0", active INTEGER DEFAULT 0)'
)
# newsletter_log table :: This is a table which logs newsletters sent
c_db.execute(
'CREATE TABLE IF NOT EXISTS newsletter_log (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, '
'newsletter_id INTEGER, agent_id INTEGER, agent_name TEXT, notify_action TEXT, '
- 'subject_text TEXT, start_date TEXT, end_date TEXT, uuid TEXT UNIQUE, success INTEGER DEFAULT 0)'
+ 'subject_text TEXT, body_text TEXT, start_date TEXT, end_date TEXT, '
+ 'uuid TEXT UNIQUE, success INTEGER DEFAULT 0)'
)
# poster_urls table :: This table keeps record of the notification poster urls
diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py
index b2e56eb4..2608e99d 100644
--- a/plexpy/datafactory.py
+++ b/plexpy/datafactory.py
@@ -1573,6 +1573,7 @@ class DataFactory(object):
'newsletter_log.agent_name',
'newsletter_log.notify_action',
'newsletter_log.subject_text',
+ 'newsletter_log.body_text',
'newsletter_log.start_date',
'newsletter_log.end_date',
'newsletter_log.uuid',
@@ -1606,6 +1607,7 @@ class DataFactory(object):
'agent_name': item['agent_name'],
'notify_action': item['notify_action'],
'subject_text': item['subject_text'],
+ 'body_text': item['body_text'],
'start_date': item['start_date'],
'end_date': item['end_date'],
'uuid': item['uuid'],
diff --git a/plexpy/newsletter_handler.py b/plexpy/newsletter_handler.py
index 1164db87..8f48cc98 100644
--- a/plexpy/newsletter_handler.py
+++ b/plexpy/newsletter_handler.py
@@ -65,19 +65,24 @@ def notify(newsletter_id=None, notify_action=None, **kwargs):
if not newsletter_config:
return
+ if notify_action in ('test', 'api'):
+ subject = kwargs.pop('subject', newsletter_config['subject'])
+ body = kwargs.pop('body', newsletter_config['subject'])
+ else:
+ subject = newsletter_config['subject']
+ body = newsletter_config['body']
+
newsletter_agent = newsletters.get_agent_class(agent_id=newsletter_config['agent_id'],
config=newsletter_config['config'],
- email_config=newsletter_config['email_config'])
-
- if notify_action in ('test', 'api'):
- subject_string = kwargs.pop('subject', None)
- if subject_string:
- newsletter_agent.subject = newsletter_agent.format_subject(subject_string)
+ email_config=newsletter_config['email_config'],
+ subject=subject,
+ body=body)
# Set the newsletter state in the db
newsletter_log_id = set_notify_state(newsletter=newsletter_config,
notify_action=notify_action,
- subject=newsletter_agent.subject,
+ subject=newsletter_agent.subject_formatted,
+ body=newsletter_agent.body_formatted,
start_date=newsletter_agent.start_date.format('YYYY-MM-DD'),
end_date=newsletter_agent.end_date.format('YYYY-MM-DD'),
newsletter_uuid=newsletter_agent.uuid)
@@ -90,7 +95,7 @@ def notify(newsletter_id=None, notify_action=None, **kwargs):
return True
-def set_notify_state(newsletter, notify_action, subject, start_date, end_date, newsletter_uuid):
+def set_notify_state(newsletter, notify_action, subject, body, start_date, end_date, newsletter_uuid):
if newsletter and notify_action:
db = database.MonitorDatabase()
@@ -103,6 +108,7 @@ def set_notify_state(newsletter, notify_action, subject, start_date, end_date, n
'agent_name': newsletter['agent_name'],
'notify_action': notify_action,
'subject_text': subject,
+ 'body_text': body,
'start_date': start_date,
'end_date': end_date}
@@ -149,3 +155,4 @@ def get_newsletter(newsletter_uuid):
return "Newsletter no longer exists"
else:
return "Newsletter does not exist"
+
diff --git a/plexpy/newsletters.py b/plexpy/newsletters.py
index e61e016d..d8daac2a 100644
--- a/plexpy/newsletters.py
+++ b/plexpy/newsletters.py
@@ -29,7 +29,7 @@ import logger
import newsletter_handler
import notification_handler
import pmsconnect
-from notification_handler import get_poster_info
+from notification_handler import get_poster_info, CustomFormatter
from notifiers import send_notification, EMAIL
@@ -55,6 +55,7 @@ def available_notification_actions():
'name': 'on_cron',
'description': 'Trigger a notification on a certain schedule.',
'subject': 'Tautulli Newsletter',
+ 'body': 'Tautulli Newsletter',
'icon': 'fa-calendar',
'media_types': ('newsletter',)
}
@@ -63,14 +64,17 @@ def available_notification_actions():
return actions
-def get_agent_class(agent_id=None, config=None, email_config=None, start_date=None, end_date=None):
+def get_agent_class(agent_id=None, config=None, email_config=None, start_date=None, end_date=None,
+ subject=None, body=None):
if str(agent_id).isdigit():
agent_id = int(agent_id)
kwargs = {'config': config,
'email_config': email_config,
'start_date': start_date,
- 'end_date': end_date}
+ 'end_date': end_date,
+ 'subject': subject,
+ 'body': body}
if agent_id == 0:
return RecentlyAdded(**kwargs)
@@ -131,13 +135,18 @@ def get_newsletter_config(newsletter_id=None):
try:
config = json.loads(result.pop('newsletter_config', '{}'))
email_config = json.loads(result.pop('email_config', '{}'))
- newsletter_agent = get_agent_class(agent_id=result['agent_id'], config=config, email_config=email_config)
+ subject = result.pop('subject')
+ body = result.pop('body')
+ newsletter_agent = get_agent_class(agent_id=result['agent_id'], config=config, email_config=email_config,
+ subject=subject, body=body)
newsletter_config = newsletter_agent.return_config_options()
newsletter_email_config = newsletter_agent.return_email_config_options()
except Exception as e:
logger.error(u"Tautulli Newsletters :: Failed to get newsletter config options: %s." % e)
return
+ result['subject'] = newsletter_agent.subject
+ result['body'] = newsletter_agent.body
result['config'] = config
result['email_config'] = email_config
result['config_options'] = newsletter_config
@@ -169,7 +178,9 @@ def add_newsletter_config(agent_id=None, **kwargs):
'agent_label': agent['label'],
'friendly_name': '',
'newsletter_config': json.dumps(agent_class.config),
- 'email_config': json.dumps(agent_class.email_config)
+ 'email_config': json.dumps(agent_class.email_config),
+ 'subject': agent_class.subject,
+ 'body': agent_class.body
}
db = database.MonitorDatabase()
@@ -207,7 +218,11 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs):
email_config = {k[len(email_config_prefix):]: kwargs.pop(k)
for k in kwargs.keys() if k.startswith(email_config_prefix)}
- agent_class = get_agent_class(agent_id=agent['id'], config=newsletter_config, email_config=email_config)
+ subject = kwargs.pop('subject')
+ body = kwargs.pop('body')
+
+ agent_class = get_agent_class(agent_id=agent['id'], config=newsletter_config, email_config=email_config,
+ subject=subject, body=body)
keys = {'id': newsletter_id}
values = {'agent_id': agent['id'],
@@ -216,6 +231,8 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs):
'friendly_name': kwargs.get('friendly_name', ''),
'newsletter_config': json.dumps(agent_class.config),
'email_config': json.dumps(agent_class.email_config),
+ 'subject': agent_class.subject,
+ 'body': agent_class.body,
'cron': kwargs.get('cron'),
'active': kwargs.get('active')
}
@@ -232,16 +249,15 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs):
return False
-def send_newsletter(newsletter_id=None, subject=None, notify_action='', newsletter_log_id=None, **kwargs):
+def send_newsletter(newsletter_id=None, subject=None, body=None, newsletter_log_id=None, **kwargs):
newsletter_config = get_newsletter_config(newsletter_id=newsletter_id)
if newsletter_config:
agent = get_agent_class(agent_id=newsletter_config['agent_id'],
config=newsletter_config['config'],
- email_config=newsletter_config['email_config'])
- return agent.send(subject=subject,
- action=notify_action.split('on_')[-1],
- newsletter_log_id=newsletter_log_id,
- **kwargs)
+ email_config=newsletter_config['email_config'],
+ subject=subject,
+ body=body)
+ return agent.send()
else:
logger.debug(u"Tautulli Newsletters :: Notification requested but no newsletter_id received.")
@@ -279,15 +295,16 @@ class Newsletter(object):
_DEFAULT_EMAIL_CONFIG = EMAIL().return_default_config()
_DEFAULT_EMAIL_CONFIG['from_name'] = 'Tautulli Newsletter'
_DEFAULT_EMAIL_CONFIG['notifier'] = 0
- _DEFAULT_EMAIL_CONFIG['subject'] = 'Tautulli Newsletter'
+ _DEFAULT_SUBJECT = 'Tautulli Newsletter'
+ _DEFAULT_BODY = 'Tautulli Newsletter'
_TEMPLATE_MASTER = ''
_TEMPLATE = ''
- def __init__(self, config=None, email_config=None, start_date=None, end_date=None):
+ def __init__(self, config=None, email_config=None, start_date=None, end_date=None, subject=None, body=None):
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)
- date_format = helpers.momentjs_to_arrow(plexpy.CONFIG.DATE_FORMAT)
+ self.uuid = generate_newsletter_uuid()
self.start_date = None
self.end_date = None
@@ -313,22 +330,19 @@ class Newsletter(object):
self.end_time = self.end_date.timestamp
self.start_time = self.start_date.timestamp
- self.parameters = {
- 'start_date': self.start_date.format(date_format),
- 'end_date': self.end_date.format(date_format),
- 'server_name': plexpy.CONFIG.PMS_NAME
- }
-
- self.subject = self.format_subject(self.email_config['subject'])
-
- self.uuid = generate_newsletter_uuid()
-
- self.is_preview = False
+ self.parameters = self.build_params()
+ self.subject = subject or self._DEFAULT_SUBJECT
+ self.body = body or self._DEFAULT_BODY
+ self.subject_formatted, self.body_formatted = self.build_text()
self.data = {}
self.newsletter = None
+ self.is_preview = False
+
def set_config(self, config=None, default=None):
+ self._add_config()
+
return self._validate_config(config=config, default=default)
def _validate_config(self, config=None, default=None):
@@ -344,6 +358,9 @@ class Newsletter(object):
return new_config
+ def _add_config(self):
+ pass
+
def retrieve_data(self):
pass
@@ -372,7 +389,7 @@ class Newsletter(object):
return serve_template(
templatename=template,
- title=self.subject,
+ title=self.subject_formatted,
parameters=self.parameters,
data=self.data,
preview=self.is_preview
@@ -412,32 +429,62 @@ class Newsletter(object):
if self.email_config['notifier']:
return send_notification(
notifier_id=self.email_config['notifier'],
- subject=self.subject,
+ subject=self.subject_formatted,
body=self.newsletter
)
else:
email = EMAIL(config=self.email_config)
return email.notify(
- subject=self.subject,
+ subject=self.subject_formatted,
body=self.newsletter
)
- def format_subject(self, subject=None):
- subject = subject or self._DEFAULT_EMAIL_CONFIG['subject']
+ def build_params(self):
+ parameters = self._build_params()
+
+ return parameters
+
+ def _build_params(self):
+ date_format = helpers.momentjs_to_arrow(plexpy.CONFIG.DATE_FORMAT)
+
+ parameters = {
+ 'server_name': plexpy.CONFIG.PMS_NAME,
+ 'start_date': self.start_date.format(date_format),
+ 'end_date': self.end_date.format(date_format),
+ 'newsletter_days': self.config['last_days'],
+ 'newsletter_url': 'http://localhost:8181/dev'.rstrip('/') + '/newsletter/' + self.uuid,
+ 'newsletter_uuid': self.uuid
+ }
+
+ return parameters
+
+ def build_text(self):
+ custom_formatter = CustomFormatter()
try:
- subject = unicode(subject).format(**self.parameters)
+ subject = custom_formatter.format(unicode(self.subject), **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)
+ subject = unicode(self._DEFAULT_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)
+ subject = unicode(self._DEFAULT_SUBJECT).format(**self.parameters)
- return subject
+ try:
+ body = custom_formatter.format(unicode(self.body), **self.parameters)
+ except LookupError as e:
+ logger.error(
+ u"Tautulli Newsletter :: Unable to parse parameter %s in newsletter body. Using fallback." % e)
+ body = unicode(self._DEFAULT_BODY).format(**self.parameters)
+ except Exception as e:
+ logger.error(
+ u"Tautulli Newsletter :: Unable to parse custom newsletter body: %s. Using fallback." % e)
+ body = unicode(self._DEFAULT_BODY).format(**self.parameters)
+
+ return subject, body
def return_config_options(self):
config_options = []
@@ -455,23 +502,22 @@ class RecentlyAdded(Newsletter):
_DEFAULT_CONFIG = {'last_days': 7,
'incl_libraries': None
}
+ _DEFAULT_SUBJECT = 'Recently Added to {server_name}! ({end_date})'
+ _DEFAULT_BODY = 'View the newsletter here: {newsletter_url}'
_TEMPLATE_MASTER = 'recently_added_master.html'
_TEMPLATE = 'recently_added.html'
- def __init__(self, config=None, email_config=None, start_date=None, end_date=None):
+ def __init__(self, config=None, email_config=None, start_date=None, end_date=None, subject=None, body=None):
super(RecentlyAdded, self).__init__(config=config, email_config=email_config,
- start_date=start_date, end_date=end_date)
+ start_date=start_date, end_date=end_date,
+ subject=subject, body=body)
+ def _add_config(self):
if self.config['incl_libraries'] is None:
self.config['incl_libraries'] = []
elif not isinstance(self.config['incl_libraries'], list):
self.config['incl_libraries'] = [self.config['incl_libraries']]
- self._DEFAULT_EMAIL_CONFIG['subject'] = 'Recently Added to Plex ({server_name})! ({end_date})'
-
- self.parameters['pms_identifier'] = plexpy.CONFIG.PMS_IDENTIFIER
- self.parameters['pms_web_url'] = plexpy.CONFIG.PMS_WEB_URL
-
def _get_recently_added(self, media_type=None):
pms_connect = pmsconnect.PmsConnect()
@@ -656,6 +702,20 @@ class RecentlyAdded(Newsletter):
sections[library_type] = group
return sections
+ def build_params(self):
+ parameters = self._build_params()
+
+ newsletter_libraries = []
+ for s in self._get_sections():
+ if str(s['section_id']) in self.config['incl_libraries']:
+ newsletter_libraries.append(s['section_name'])
+
+ parameters['newsletter_libraries'] = ', '.join(sorted(newsletter_libraries))
+ parameters['pms_identifier'] = plexpy.CONFIG.PMS_IDENTIFIER
+ parameters['pms_web_url'] = plexpy.CONFIG.PMS_WEB_URL
+
+ return parameters
+
def return_config_options(self):
config_option = [{'label': 'Number of Days',
'value': self.config['last_days'],
diff --git a/plexpy/webserve.py b/plexpy/webserve.py
index f840beae..63b78895 100644
--- a/plexpy/webserve.py
+++ b/plexpy/webserve.py
@@ -2495,6 +2495,7 @@ class WebInterface(object):
("agent_name", True, True),
("notify_action", True, True),
("subject_text", True, True),
+ ("body_text", True, True),
("start_date", True, True),
("end_date", True, True),
("uuid", True, True)]
@@ -5482,13 +5483,11 @@ class WebInterface(object):
"cron": "0 0 * * 1",
"active": 1
"config": {"last_days": 7,
- "incl_movies": 1,
- "incl_shows": 1,
- "incl_artists": 1,
+ "incl_libraries": [1, 2]
},
+ "email_config": {...},
"config_options": [{...}, ...],
- "email_config_options": [{...}, ...],
- "email_notifier": 0
+ "email_config_options": [{...}, ...]
}
```
"""
@@ -5561,7 +5560,7 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth(member_of("admin"))
@addtoapi("notify_newsletter")
- def send_newsletter(self, newsletter_id=None, subject='', notify_action='', **kwargs):
+ def send_newsletter(self, newsletter_id=None, subject='', body='', notify_action='', **kwargs):
""" Send a newsletter using Tautulli.
```
@@ -5587,6 +5586,7 @@ class WebInterface(object):
if newsletter_handler.notify(newsletter_id=newsletter_id,
notify_action=notify_action,
subject=subject,
+ body=body,
**kwargs):
return "Newsletter sent."
else: