From 19cf56736693aae8ff7a5038c723be16ff1a5322 Mon Sep 17 00:00:00 2001 From: JonnyWong16 Date: Mon, 7 May 2018 20:02:04 -0700 Subject: [PATCH] Add option to change the newsletter filename --- .../interfaces/default/newsletter_config.html | 22 +++++++++++- data/interfaces/default/settings.html | 17 ++++----- plexpy/__init__.py | 11 +++++- plexpy/newsletter_handler.py | 16 +++++---- plexpy/newsletters.py | 35 +++++++++++++++---- 5 files changed, 78 insertions(+), 23 deletions(-) diff --git a/data/interfaces/default/newsletter_config.html b/data/interfaces/default/newsletter_config.html index aa928eb8..ab6aa878 100644 --- a/data/interfaces/default/newsletter_config.html +++ b/data/interfaces/default/newsletter_config.html @@ -166,6 +166,15 @@ % endfor
+
+ +
+
+ +
+
+

The filename to use when saving the newsletter (ending with .html). You may use any of the newsletter text parameters. Leave blank for default.

+
@@ -458,6 +467,15 @@ toggleCustomCron(); }); + function validateFilename() { + var filename = $('#newsletter_config_filename').val(); + if (filename !== '' && !(filename.endsWith('.html'))) { + showMsg(' Failed to save newsletter. Invalid filename.', false, true, 5000, true); + return false; + } else { + return true; + } + } var $incl_libraries = $('#newsletter_config_incl_libraries').selectize({ plugins: ['remove_button'], maxItems: null, @@ -643,7 +661,9 @@ if ($('#custom_cron').val() === '0'){ $("#cron_value").val(cron_widget.cron('value')); } - doAjaxCall('set_newsletter_config', $(this), 'tabs', true, true, saveCallback); + if (validateFilename()){ + doAjaxCall('set_newsletter_config', $(this), 'tabs', true, true, saveCallback); + } } $('#delete-newsletter-item').click(function () { diff --git a/data/interfaces/default/settings.html b/data/interfaces/default/settings.html index 0dd044aa..81aa0a40 100644 --- a/data/interfaces/default/settings.html +++ b/data/interfaces/default/settings.html @@ -980,6 +980,15 @@

Optional: Enter the full path to your custom newsletter templates folder. Leave blank for default.

+
+ +
+
+ +
+
+

Enter the full path to where newsletter files will be saved.

+

3rd Party APIs

@@ -1192,14 +1201,6 @@
-
- -
-
- -
-
-

diff --git a/plexpy/__init__.py b/plexpy/__init__.py index 4b5b3ea5..70fa45e5 100644 --- a/plexpy/__init__.py +++ b/plexpy/__init__.py @@ -648,7 +648,7 @@ def dbcheck(): '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, body_text TEXT, message_text TEXT, start_date TEXT, end_date TEXT, ' - 'start_time INTEGER, end_time INTEGER, uuid TEXT UNIQUE, success INTEGER DEFAULT 0)' + 'start_time INTEGER, end_time INTEGER, uuid TEXT UNIQUE, filename TEXT, success INTEGER DEFAULT 0)' ) # recently_added table :: This table keeps record of recently added items @@ -1495,6 +1495,15 @@ def dbcheck(): 'ALTER TABLE newsletter_log ADD COLUMN end_time INTEGER' ) + # Upgrade newsletter_log table from earlier versions + try: + c_db.execute('SELECT filename FROM newsletter_log') + except sqlite3.OperationalError: + logger.debug(u"Altering database. Updating database table newsletter_log.") + c_db.execute( + 'ALTER TABLE newsletter_log ADD COLUMN filename TEXT' + ) + # Upgrade library_sections table from earlier versions (remove UNIQUE constraint on section_id) try: result = c_db.execute('SELECT SQL FROM sqlite_master WHERE type="table" AND name="library_sections"').fetchone() diff --git a/plexpy/newsletter_handler.py b/plexpy/newsletter_handler.py index 6f80fd26..c30b58e6 100644 --- a/plexpy/newsletter_handler.py +++ b/plexpy/newsletter_handler.py @@ -101,6 +101,7 @@ def notify(newsletter_id=None, notify_action=None, **kwargs): subject=newsletter_agent.subject_formatted, body=newsletter_agent.body_formatted, message=newsletter_agent.message_formatted, + filename=newsletter_agent.filename_formatted, start_date=newsletter_agent.start_date.format('YYYY-MM-DD'), end_date=newsletter_agent.end_date.format('YYYY-MM-DD'), start_time=newsletter_agent.start_time, @@ -115,7 +116,7 @@ def notify(newsletter_id=None, notify_action=None, **kwargs): return True -def set_notify_state(newsletter, notify_action, subject, body, message, +def set_notify_state(newsletter, notify_action, subject, body, message, filename, start_date, end_date, start_time, end_time, newsletter_uuid): if newsletter and notify_action: @@ -134,7 +135,8 @@ def set_notify_state(newsletter, notify_action, subject, body, message, 'start_date': start_date, 'end_date': end_date, 'start_time': start_time, - 'end_time': end_time} + 'end_time': end_time, + 'filename': filename} db.upsert(table_name='newsletter_log', key_dict=keys, value_dict=values) return db.last_insert_id() @@ -168,11 +170,11 @@ def get_newsletter(newsletter_uuid=None, newsletter_id=None): newsletter_uuid = result['uuid'] start_date = result['start_date'] end_date = result['end_date'] + newsletter_file = result['filename'] or 'newsletter_%s-%s_%s.html' % (start_date.replace('-', ''), + end_date.replace('-', ''), + newsletter_uuid) - newsletter_file = 'newsletter_%s-%s_%s.html' % (start_date.replace('-', ''), - end_date.replace('-', ''), - newsletter_uuid) - newsletter_folder = plexpy.CONFIG.NEWSLETTER_DIR + newsletter_folder = plexpy.CONFIG.NEWSLETTER_DIR or os.path.join(plexpy.DATA_DIR, 'newsletters') newsletter_file_fp = os.path.join(newsletter_folder, newsletter_file) if newsletter_file in os.listdir(newsletter_folder): @@ -183,4 +185,4 @@ def get_newsletter(newsletter_uuid=None, newsletter_id=None): except OSError as e: logger.error(u"Tautulli NewsletterHandler :: Failed to retrieve newsletter '%s': %s" % (newsletter_uuid, e)) else: - logger.warn(u"Tautulli NewsletterHandler :: Newsletter '%s' file is missing." % newsletter_uuid) + logger.warn(u"Tautulli NewsletterHandler :: Newsletter file '%s' is missing." % newsletter_file) diff --git a/plexpy/newsletters.py b/plexpy/newsletters.py index de3aaa17..115448ca 100644 --- a/plexpy/newsletters.py +++ b/plexpy/newsletters.py @@ -305,13 +305,15 @@ class Newsletter(object): 'time_frame': 7, 'time_frame_units': 'days', 'formatted': 1, - 'notifier_id': 0} + 'notifier_id': 0, + 'filename': ''} _DEFAULT_EMAIL_CONFIG = EMAIL().return_default_config() _DEFAULT_EMAIL_CONFIG['from_name'] = 'Tautulli Newsletter' _DEFAULT_EMAIL_CONFIG['notifier_id'] = 0 _DEFAULT_SUBJECT = 'Tautulli Newsletter' _DEFAULT_BODY = 'View the newsletter here: {newsletter_url}' _DEFAULT_MESSAGE = '' + _DEFAULT_FILENAME = 'newsletter_{newsletter_uuid}.html' _TEMPLATE_MASTER = '' _TEMPLATE = '' @@ -353,7 +355,13 @@ class Newsletter(object): self.subject = subject or self._DEFAULT_SUBJECT self.body = body or self._DEFAULT_BODY self.message = message or self._DEFAULT_MESSAGE + self.filename = self.config['filename'] or self._DEFAULT_FILENAME + + if not self.filename.endswith('.html'): + self.filename += '.html' + self.subject_formatted, self.body_formatted, self.message_formatted = self.build_text() + self.filename_formatted = self.build_filename() self.data = {} self.newsletter = None @@ -431,10 +439,8 @@ class Newsletter(object): return self._send() def _save(self): - newsletter_file = 'newsletter_%s-%s_%s.html' % (self.start_date.format('YYYYMMDD'), - self.end_date.format('YYYYMMDD'), - self.uuid) - newsletter_folder = plexpy.CONFIG.NEWSLETTER_DIR + newsletter_file = self.filename_formatted + newsletter_folder = plexpy.CONFIG.NEWSLETTER_DIR or os.path.join(plexpy.DATA_DIR, 'newsletters') newsletter_file_fp = os.path.join(newsletter_folder, newsletter_file) # In case the user has deleted it manually @@ -541,6 +547,23 @@ class Newsletter(object): return subject, body, message + def build_filename(self): + from notification_handler import CustomFormatter + custom_formatter = CustomFormatter() + + try: + filename = custom_formatter.format(unicode(self.filename), **self.parameters) + except LookupError as e: + logger.error( + u"Tautulli Newsletter :: Unable to parse parameter %s in newsletter filename. Using fallback." % e) + filename = unicode(self._DEFAULT_FILENAME).format(**self.parameters) + except Exception as e: + logger.error( + u"Tautulli Newsletter :: Unable to parse custom newsletter subject: %s. Using fallback." % e) + filename = unicode(self._DEFAULT_FILENAME).format(**self.parameters) + + return filename + def return_config_options(self): return self._return_config_options() @@ -809,4 +832,4 @@ class RecentlyAdded(Newsletter): } ] - return config_options + additional_config + return additional_config + config_options