mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-10 23:42:37 -07:00
Add newsletter handler
This commit is contained in:
parent
33c2315384
commit
d4d5ff9de7
6 changed files with 155 additions and 23 deletions
|
@ -439,7 +439,7 @@
|
|||
});
|
||||
|
||||
function previewNewsletter() {
|
||||
window.open('preview_newsletter?newsletter_id=${newsletter["id"]}');
|
||||
window.open('preview_newsletter?newsletter_id=' + $('#newsletter_id').val());
|
||||
}
|
||||
|
||||
function sendTestNewsletter() {
|
||||
|
@ -447,8 +447,9 @@
|
|||
$.ajax({
|
||||
url: 'send_newsletter',
|
||||
data: {
|
||||
newsletter_id: '${newsletter["id"]}',
|
||||
test: true
|
||||
newsletter_id: $('#newsletter_id').val(),
|
||||
subject: $('#email_subject').val(),
|
||||
notify_action: 'test'
|
||||
},
|
||||
cache: false,
|
||||
async: true,
|
||||
|
|
|
@ -755,7 +755,7 @@
|
|||
$.ajax({
|
||||
url: 'send_notification',
|
||||
data: {
|
||||
notifier_id: '${notifier["id"]}',
|
||||
notifier_id: $('#notifier_id').val(),
|
||||
subject: $('#test_subject').val(),
|
||||
body: $('#test_body').val(),
|
||||
script: $('#test_script').val(),
|
||||
|
|
|
@ -426,7 +426,7 @@ def initialize_scheduler():
|
|||
logger.error(e)
|
||||
|
||||
|
||||
def schedule_job(function, name, hours=0, minutes=0, seconds=0, args=None):
|
||||
def schedule_job(func, name, hours=0, minutes=0, seconds=0, args=None):
|
||||
"""
|
||||
Start scheduled job if starting or restarting plexpy.
|
||||
Reschedule job if Interval Settings have changed.
|
||||
|
@ -444,7 +444,7 @@ def schedule_job(function, name, hours=0, minutes=0, seconds=0, args=None):
|
|||
hours=hours, minutes=minutes, seconds=seconds), args=args)
|
||||
logger.info(u"Re-scheduled background task: %s", name)
|
||||
elif hours > 0 or minutes > 0 or seconds > 0:
|
||||
SCHED.add_job(function, id=name, trigger=IntervalTrigger(
|
||||
SCHED.add_job(func, id=name, trigger=IntervalTrigger(
|
||||
hours=hours, minutes=minutes, seconds=seconds), args=args)
|
||||
logger.info(u"Scheduled background task: %s", name)
|
||||
|
||||
|
@ -574,14 +574,6 @@ def dbcheck():
|
|||
'filter_music TEXT, filter_photos TEXT)'
|
||||
)
|
||||
|
||||
# notify_log table :: This is a table which logs notifications sent
|
||||
c_db.execute(
|
||||
'CREATE TABLE IF NOT EXISTS notify_log (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, '
|
||||
'session_key INTEGER, rating_key INTEGER, parent_rating_key INTEGER, grandparent_rating_key INTEGER, '
|
||||
'user_id INTEGER, user TEXT, notifier_id INTEGER, agent_id INTEGER, agent_name TEXT, notify_action TEXT, '
|
||||
'subject_text TEXT, body_text TEXT, script_args TEXT, success INTEGER DEFAULT 0)'
|
||||
)
|
||||
|
||||
# library_sections table :: This table keeps record of the servers library sections
|
||||
c_db.execute(
|
||||
'CREATE TABLE IF NOT EXISTS library_sections (id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
|
@ -620,6 +612,14 @@ def dbcheck():
|
|||
'custom_conditions TEXT, custom_conditions_logic TEXT)'
|
||||
)
|
||||
|
||||
# notify_log table :: This is a table which logs notifications sent
|
||||
c_db.execute(
|
||||
'CREATE TABLE IF NOT EXISTS notify_log (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, '
|
||||
'session_key INTEGER, rating_key INTEGER, parent_rating_key INTEGER, grandparent_rating_key INTEGER, '
|
||||
'user_id INTEGER, user TEXT, notifier_id INTEGER, agent_id INTEGER, agent_name TEXT, notify_action TEXT, '
|
||||
'subject_text TEXT, body_text TEXT, script_args TEXT, success INTEGER DEFAULT 0)'
|
||||
)
|
||||
|
||||
# newsletters table :: This table keeps record of the newsletter settings
|
||||
c_db.execute(
|
||||
'CREATE TABLE IF NOT EXISTS newsletters (id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
|
@ -628,6 +628,13 @@ def dbcheck():
|
|||
'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, success INTEGER DEFAULT 0)'
|
||||
)
|
||||
|
||||
# poster_urls table :: This table keeps record of the notification poster urls
|
||||
c_db.execute(
|
||||
'CREATE TABLE IF NOT EXISTS poster_urls (id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
|
|
102
plexpy/newsletter_handler.py
Normal file
102
plexpy/newsletter_handler.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
# This file is part of Tautulli.
|
||||
#
|
||||
# Tautulli is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Tautulli is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Tautulli. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import time
|
||||
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
|
||||
import plexpy
|
||||
import database
|
||||
import logger
|
||||
import newsletters
|
||||
|
||||
|
||||
NEWSLETTER_SCHED = BackgroundScheduler()
|
||||
|
||||
|
||||
def schedule_newsletter(newsletter_id, func=None, remove_job=False, args=None, **kwargs):
|
||||
if NEWSLETTER_SCHED.get_job(newsletter_id):
|
||||
if remove_job:
|
||||
NEWSLETTER_SCHED.remove_job(newsletter_id)
|
||||
else:
|
||||
NEWSLETTER_SCHED.reschedule_job(
|
||||
newsletter_id, args=args, trigger=CronTrigger(**kwargs))
|
||||
elif not remove_job:
|
||||
NEWSLETTER_SCHED.add_job(
|
||||
func, args=args, id=newsletter_id, trigger=CronTrigger(**kwargs))
|
||||
|
||||
|
||||
def notify(newsletter_id=None, notify_action=None, **kwargs):
|
||||
logger.info(u"Tautulli NewsletterHandler :: Preparing newsletter for newsletter_id %s." % newsletter_id)
|
||||
|
||||
newsletter_config = newsletters.get_newsletter_config(newsletter_id=newsletter_id)
|
||||
|
||||
if not newsletter_config:
|
||||
return
|
||||
|
||||
if notify_action in ('test', 'api'):
|
||||
subject_string = kwargs.pop('subject', 'Tautulli Newsletter')
|
||||
else:
|
||||
# Get the subject string
|
||||
subject_string = newsletter_config['subject']
|
||||
|
||||
newsletter_agent = newsletters.get_agent_class(agent_id=newsletter_config['agent_id'],
|
||||
config=newsletter_config['config'],
|
||||
email_config=newsletter_config['email_config'])
|
||||
subject = newsletter_agent.format_subject(subject_string)
|
||||
|
||||
# Set the newsletter state in the db
|
||||
newsletter_log_id = set_notify_state(newsletter=newsletter_config,
|
||||
notify_action=notify_action,
|
||||
subject=subject)
|
||||
|
||||
# Send the notification
|
||||
success = newsletters.send_newsletter(newsletter_id=newsletter_config['id'],
|
||||
subject=subject,
|
||||
notify_action=notify_action,
|
||||
newsletter_log_id=newsletter_log_id,
|
||||
**kwargs)
|
||||
|
||||
if success:
|
||||
set_notify_success(newsletter_log_id)
|
||||
return True
|
||||
|
||||
|
||||
def set_notify_state(newsletter, notify_action, subject):
|
||||
|
||||
if newsletter and notify_action:
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
keys = {'timestamp': int(time.time()),
|
||||
'newsletter_id': newsletter['id'],
|
||||
'agent_id': newsletter['agent_id'],
|
||||
'notify_action': notify_action}
|
||||
|
||||
values = {'agent_name': newsletter['agent_name'],
|
||||
'subject_text': subject}
|
||||
|
||||
monitor_db.upsert(table_name='newsletter_log', key_dict=keys, value_dict=values)
|
||||
return monitor_db.last_insert_id()
|
||||
else:
|
||||
logger.error(u"Tautulli NewsletterHandler :: Unable to set notify state.")
|
||||
|
||||
|
||||
def set_notify_success(newsletter_log_id):
|
||||
keys = {'id': newsletter_log_id}
|
||||
values = {'success': 1}
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
monitor_db.upsert(table_name='newsletter_log', key_dict=keys, value_dict=values)
|
|
@ -50,6 +50,19 @@ def available_newsletter_agents():
|
|||
return agents
|
||||
|
||||
|
||||
def available_notification_actions():
|
||||
actions = [{'label': 'Schedule',
|
||||
'name': 'on_cron',
|
||||
'description': 'Trigger a notification on a certain schedule.',
|
||||
'subject': 'Tautulli Newsletter',
|
||||
'icon': 'fa-calendar',
|
||||
'media_types': ('newsletter',)
|
||||
}
|
||||
]
|
||||
|
||||
return actions
|
||||
|
||||
|
||||
def get_agent_class(agent_id=None, config=None, email_config=None):
|
||||
if str(agent_id).isdigit():
|
||||
agent_id = int(agent_id)
|
||||
|
@ -213,13 +226,15 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs):
|
|||
return False
|
||||
|
||||
|
||||
def send_newsletter(newsletter_id=None, newsletter_log_id=None, **kwargs):
|
||||
def send_newsletter(newsletter_id=None, subject=None, notify_action='', 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(newsletter_log_id=newsletter_log_id, **kwargs)
|
||||
return agent.send(subject=subject,
|
||||
action=notify_action.split('on_')[-1],
|
||||
newsletter_log_id=newsletter_log_id, **kwargs)
|
||||
else:
|
||||
logger.debug(u"Tautulli Newsletters :: Notification requested but no newsletter_id received.")
|
||||
|
||||
|
@ -284,7 +299,7 @@ class Newsletter(object):
|
|||
**kwargs
|
||||
)
|
||||
|
||||
def _format_subject(self, subject):
|
||||
def format_subject(self, subject):
|
||||
subject = subject or self._DEFAULT_EMAIL_CONFIG['subject']
|
||||
|
||||
try:
|
||||
|
@ -313,10 +328,10 @@ class Newsletter(object):
|
|||
self.retrieve_data()
|
||||
return self.generate_newsletter()
|
||||
|
||||
def send(self, **kwargs):
|
||||
def send(self, subject='', **kwargs):
|
||||
self.retrieve_data()
|
||||
|
||||
subject = self._format_subject(self.email_config['subject'])
|
||||
subject = self.format_subject(subject or self.email_config['subject'])
|
||||
newsletter = self.generate_newsletter()
|
||||
|
||||
if self.email_config['notifier']:
|
||||
|
|
|
@ -39,6 +39,7 @@ import http_handler
|
|||
import libraries
|
||||
import log_reader
|
||||
import logger
|
||||
import newsletter_handler
|
||||
import newsletters
|
||||
import mobile_app
|
||||
import notification_handler
|
||||
|
@ -5478,7 +5479,7 @@ class WebInterface(object):
|
|||
@cherrypy.expose
|
||||
@requireAuth(member_of("admin"))
|
||||
@addtoapi("notify_newsletter")
|
||||
def send_newsletter(self, newsletter_id=None, test=False, **kwargs):
|
||||
def send_newsletter(self, newsletter_id=None, subject='Tautulli Newsletter', notify_action='', **kwargs):
|
||||
""" Send a newsletter using Tautulli.
|
||||
|
||||
```
|
||||
|
@ -5494,14 +5495,17 @@ class WebInterface(object):
|
|||
"""
|
||||
cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
|
||||
|
||||
test = 'test ' if test else ''
|
||||
test = 'test ' if notify_action == 'test' else ''
|
||||
|
||||
if newsletter_id:
|
||||
newsletter = newsletters.get_newsletter_config(newsletter_id=newsletter_id)
|
||||
|
||||
if newsletter:
|
||||
logger.debug(u"Sending %s%s newsletter." % (test, newsletter['agent_label']))
|
||||
if newsletters.send_newsletter(newsletter_id=newsletter_id):
|
||||
if newsletter_handler.notify(newsletter_id=newsletter_id,
|
||||
notify_action=notify_action,
|
||||
subject=subject,
|
||||
**kwargs):
|
||||
return "Newsletter sent."
|
||||
else:
|
||||
return "Newsletter failed."
|
||||
|
@ -5518,7 +5522,10 @@ class WebInterface(object):
|
|||
if newsletter_id:
|
||||
newsletter = newsletters.get_newsletter_config(newsletter_id=newsletter_id)
|
||||
newsletter_agent = newsletters.get_agent_class(agent_id=newsletter['agent_id'], config=newsletter['config'])
|
||||
|
||||
if newsletter_agent:
|
||||
return newsletter_agent.preview(master=master)
|
||||
|
||||
return
|
||||
return "Invalid newsletter id %s" % newsletter_id
|
||||
|
||||
return "Missing newsletter_id parameter"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue