diff --git a/data/interfaces/default/newsletter_config.html b/data/interfaces/default/newsletter_config.html index 19893299..2817916f 100644 --- a/data/interfaces/default/newsletter_config.html +++ b/data/interfaces/default/newsletter_config.html @@ -166,6 +166,15 @@ % endfor
+
+ +
+
+ +
+
+

Enter a unique ID name to create a static URL to the last sent scheduled newsletter at /newsletter/id/<id_name>. Only letters (a-z), numbers (0-9), underscores (_) and hyphens (-) are allowed. Leave blank to disable.

+
@@ -483,6 +492,17 @@ return true; } } + + function validateIDName() { + var id_name = $('#id_name').val(); + if (/^[a-zA-Z0-9_-]*$/.test(id_name)) { + return true; + } else { + showMsg(' Failed to save newsletter. Invalid unique ID name.', false, true, 5000, true); + return false; + } + } + var $incl_libraries = $('#newsletter_config_incl_libraries').selectize({ plugins: ['remove_button'], maxItems: null, @@ -668,7 +688,7 @@ if ($('#custom_cron').val() === '0'){ $("#cron_value").val(cron_widget.cron('value')); } - if (validateFilename()){ + if (validateFilename() && validateIDName()){ doAjaxCall('set_newsletter_config', $(this), 'tabs', true, true, saveCallback); } } diff --git a/data/interfaces/default/settings.html b/data/interfaces/default/settings.html index 3f7c38dc..e26280d7 100644 --- a/data/interfaces/default/settings.html +++ b/data/interfaces/default/settings.html @@ -969,13 +969,6 @@ Note: The ${http_root}newsletter endpoint on your domain must be publicly accessible from the internet.

Warning: Public Tautulli domain not set under Web Interface.

- -
- -

Enable static newsletter URLs to the last sent scheduled newsletter at ${http_root}newsletter/id/<newsletter_id>.

-
diff --git a/plexpy/__init__.py b/plexpy/__init__.py index 70fa45e5..a5f8f7ab 100644 --- a/plexpy/__init__.py +++ b/plexpy/__init__.py @@ -637,7 +637,7 @@ def dbcheck(): # newsletters table :: This table keeps record of the newsletter settings c_db.execute( '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, id_name TEXT NOT NULL DEFAULT "", ' 'friendly_name TEXT, newsletter_config TEXT, email_config TEXT, ' 'subject TEXT, body TEXT, message TEXT, ' 'cron TEXT NOT NULL DEFAULT "0 0 * * 0", active INTEGER DEFAULT 0)' @@ -1504,6 +1504,15 @@ def dbcheck(): 'ALTER TABLE newsletter_log ADD COLUMN filename TEXT' ) + # Upgrade newsletters table from earlier versions + try: + c_db.execute('SELECT id_name FROM newsletters') + except sqlite3.OperationalError: + logger.debug(u"Altering database. Updating database table newsletters.") + c_db.execute( + 'ALTER TABLE newsletters ADD COLUMN id_name TEXT NOT NULL DEFAULT ""' + ) + # 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/common.py b/plexpy/common.py index f80e9e6e..fc5db6de 100644 --- a/plexpy/common.py +++ b/plexpy/common.py @@ -527,7 +527,8 @@ NEWSLETTER_PARAMETERS = [ {'name': 'Newsletter URL', 'type': 'str', 'value': 'newsletter_url', 'description': 'The self-hosted URL to the newsletter.'}, {'name': 'Newsletter Static URL', 'type': 'str', 'value': 'newsletter_static_url', 'description': 'The static self-hosted URL to the latest scheduled newsletter for the agent.'}, {'name': 'Newsletter UUID', 'type': 'str', 'value': 'newsletter_uuid', 'description': 'The unique identifier for the newsletter.'}, - {'name': 'Newsletter ID', 'type': 'int', 'value': 'newsletter_id', 'description': 'The ID number for the newsletter agent.'}, + {'name': 'Newsletter ID', 'type': 'int', 'value': 'newsletter_id', 'description': 'The unique ID number for the newsletter agent.'}, + {'name': 'Newsletter ID Name', 'type': 'int', 'value': 'newsletter_id_name', 'description': 'The unique ID name for the newsletter agent.'}, ] }, { diff --git a/plexpy/newsletter_handler.py b/plexpy/newsletter_handler.py index c30b58e6..3ff0db8c 100644 --- a/plexpy/newsletter_handler.py +++ b/plexpy/newsletter_handler.py @@ -87,6 +87,7 @@ def notify(newsletter_id=None, notify_action=None, **kwargs): message = newsletter_config['message'] newsletter_agent = newsletters.get_agent_class(newsletter_id=newsletter_id, + newsletter_id_name=newsletter_config['id_name'], agent_id=newsletter_config['agent_id'], config=newsletter_config['config'], email_config=newsletter_config['email_config'], @@ -152,21 +153,21 @@ def set_notify_success(newsletter_log_id): db.upsert(table_name='newsletter_log', key_dict=keys, value_dict=values) -def get_newsletter(newsletter_uuid=None, newsletter_id=None): +def get_newsletter(newsletter_uuid=None, newsletter_id_name=None): db = database.MonitorDatabase() if newsletter_uuid: - result = db.select_single('SELECT newsletter_id, start_date, end_date, uuid, filename FROM newsletter_log ' + result = db.select_single('SELECT start_date, end_date, uuid, filename FROM newsletter_log ' 'WHERE uuid = ?', [newsletter_uuid]) - elif newsletter_id: - result = db.select_single('SELECT newsletter_id, start_date, end_date, uuid, filename FROM newsletter_log ' - 'WHERE newsletter_id = ? AND notify_action != "test" ' - 'ORDER BY timestamp DESC LIMIT 1', [newsletter_id]) + elif newsletter_id_name: + result = db.select_single('SELECT start_date, end_date, uuid, filename FROM newsletter_log ' + 'JOIN newsletters ON newsletters.id = newsletter_log.newsletter_id ' + 'WHERE id_name = ? AND notify_action != "test" ' + 'ORDER BY timestamp DESC LIMIT 1', [newsletter_id_name]) else: result = None if result: - newsletter_id = result['newsletter_id'] newsletter_uuid = result['uuid'] start_date = result['start_date'] end_date = result['end_date'] diff --git a/plexpy/newsletters.py b/plexpy/newsletters.py index 922a4b77..bd4e7ce9 100644 --- a/plexpy/newsletters.py +++ b/plexpy/newsletters.py @@ -63,12 +63,13 @@ def available_notification_actions(): return actions -def get_agent_class(newsletter_id=None, agent_id=None, config=None, email_config=None, start_date=None, end_date=None, - subject=None, body=None, message=None): +def get_agent_class(newsletter_id=None, newsletter_id_name=None, agent_id=None, config=None, email_config=None, + start_date=None, end_date=None, subject=None, body=None, message=None): if str(agent_id).isdigit(): agent_id = int(agent_id) kwargs = {'newsletter_id': newsletter_id, + 'newsletter_id_name': newsletter_id_name, 'config': config, 'email_config': email_config, 'start_date': start_date, @@ -139,7 +140,8 @@ def get_newsletter_config(newsletter_id=None): subject = result.pop('subject') body = result.pop('body') message = result.pop('message') - newsletter_agent = get_agent_class(newsletter_id=newsletter_id, agent_id=result['agent_id'], + newsletter_agent = get_agent_class(newsletter_id=newsletter_id, newsletter_id_name=result['id_name'], + agent_id=result['agent_id'], config=config, email_config=email_config, subject=subject, body=body, message=message) except Exception as e: @@ -178,6 +180,7 @@ def add_newsletter_config(agent_id=None, **kwargs): values = {'agent_id': agent['id'], 'agent_name': agent['name'], 'agent_label': agent['label'], + 'id_name': '', 'friendly_name': '', 'newsletter_config': json.dumps(agent_class.config), 'email_config': json.dumps(agent_class.email_config), @@ -225,7 +228,7 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs): body = kwargs.pop('body') message = kwargs.pop('message') - agent_class = get_agent_class(newsletter_id=newsletter_id, agent_id=agent['id'], + agent_class = get_agent_class(agent_id=agent['id'], config=newsletter_config, email_config=email_config, subject=subject, body=body, message=message) @@ -233,6 +236,7 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs): values = {'agent_id': agent['id'], 'agent_name': agent['name'], 'agent_label': agent['label'], + 'id_name': kwargs.get('id_name', ''), 'friendly_name': kwargs.get('friendly_name', ''), 'newsletter_config': json.dumps(agent_class.config), 'email_config': json.dumps(agent_class.email_config), @@ -318,13 +322,14 @@ class Newsletter(object): _TEMPLATE_MASTER = '' _TEMPLATE = '' - def __init__(self, newsletter_id=None, config=None, email_config=None, start_date=None, end_date=None, - subject=None, body=None, message=None): + def __init__(self, newsletter_id=None, newsletter_id_name=None, config=None, email_config=None, + start_date=None, end_date=None, subject=None, body=None, message=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) self.uuid = generate_newsletter_uuid() self.newsletter_id = newsletter_id + self.newsletter_id_name = newsletter_id_name self.start_date = None self.end_date = None @@ -506,9 +511,10 @@ class Newsletter(object): 'newsletter_time_frame': self.config['time_frame'], 'newsletter_time_frame_units': self.config['time_frame_units'], 'newsletter_url': base_url + self.uuid, - 'newsletter_static_url': base_url + 'id/' + str(self.newsletter_id), + 'newsletter_static_url': base_url + 'id/' + self.newsletter_id_name, 'newsletter_uuid': self.uuid, - 'newsletter_id': self.newsletter_id + 'newsletter_id': self.newsletter_id, + 'newsletter_id_name': self.newsletter_id_name } return parameters diff --git a/plexpy/webserve.py b/plexpy/webserve.py index 2da3a5c7..f096a34c 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -2756,7 +2756,6 @@ class WebInterface(object): "show_advanced_settings": plexpy.CONFIG.SHOW_ADVANCED_SETTINGS, "newsletter_dir": plexpy.CONFIG.NEWSLETTER_DIR, "newsletter_self_hosted": checked(plexpy.CONFIG.NEWSLETTER_SELF_HOSTED), - "newsletter_static_url": checked(plexpy.CONFIG.NEWSLETTER_STATIC_URL), "newsletter_custom_dir": plexpy.CONFIG.NEWSLETTER_CUSTOM_DIR } @@ -2779,7 +2778,7 @@ class WebInterface(object): "allow_guest_access", "cache_images", "http_proxy", "http_basic_auth", "notify_concurrent_by_ip", "history_table_activity", "plexpy_auto_update", "themoviedb_lookup", "tvmaze_lookup", "http_plex_admin", - "newsletter_self_hosted", "newsletter_static_url" + "newsletter_self_hosted" ] for checked_config in checked_configs: if checked_config not in kwargs: @@ -5666,15 +5665,15 @@ class WebInterface(object): cherrypy.response.headers['Cache-Control'] = 'max-age=2592000' # 30 days return self.image(args[1], refresh=True) - if plexpy.CONFIG.NEWSLETTER_STATIC_URL and len(args) >= 2 and args[0] == 'id': - newsletter_id = args[1] + if len(args) >= 2 and args[0] == 'id': + newsletter_id_name = args[1] newsletter_uuid = None else: - newsletter_id = None + newsletter_id_name = None newsletter_uuid = args[0] newsletter = newsletter_handler.get_newsletter(newsletter_uuid=newsletter_uuid, - newsletter_id=newsletter_id) + newsletter_id_name=newsletter_id_name) return newsletter @cherrypy.expose @@ -5694,6 +5693,7 @@ class WebInterface(object): if newsletter: newsletter_agent = newsletters.get_agent_class(newsletter_id=newsletter_id, + newsletter_id_name=newsletter['id_name'], agent_id=newsletter['agent_id'], config=newsletter['config'], start_date=start_date,