mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-03-12 04:35:40 -07:00
230 lines
10 KiB
Python
230 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# 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/>.
|
|
|
|
from io import open
|
|
import os
|
|
import shlex
|
|
|
|
from apscheduler.triggers.cron import CronTrigger
|
|
import email.utils
|
|
|
|
import plexpy
|
|
from plexpy import database
|
|
from plexpy import helpers
|
|
from plexpy import logger
|
|
from plexpy import newsletters
|
|
|
|
|
|
NEWSLETTER_SCHED = None
|
|
|
|
|
|
def add_newsletter_each(newsletter_id=None, notify_action=None, **kwargs):
|
|
if not notify_action:
|
|
logger.debug("Tautulli NewsletterHandler :: Notify called but no action received.")
|
|
return
|
|
|
|
data = {'newsletter': True,
|
|
'newsletter_id': newsletter_id,
|
|
'notify_action': notify_action}
|
|
data.update(kwargs)
|
|
plexpy.NOTIFY_QUEUE.put(data)
|
|
|
|
|
|
def schedule_newsletters(newsletter_id=None):
|
|
newsletters_list = newsletters.get_newsletters(newsletter_id=newsletter_id)
|
|
|
|
for newsletter in newsletters_list:
|
|
newsletter_job_name = '{} (newsletter_id {})'.format(newsletter['agent_label'], newsletter['id'])
|
|
|
|
if newsletter['active']:
|
|
schedule_newsletter_job('newsletter-{}'.format(newsletter['id']), name=newsletter_job_name,
|
|
func=add_newsletter_each, args=[newsletter['id'], 'on_cron'], cron=newsletter['cron'])
|
|
else:
|
|
schedule_newsletter_job('newsletter-{}'.format(newsletter['id']), name=newsletter_job_name,
|
|
remove_job=True)
|
|
|
|
|
|
def schedule_newsletter_job(newsletter_job_id, name='', func=None, remove_job=False, args=None, cron=None):
|
|
if cron:
|
|
values = shlex.split(cron)
|
|
# apscheduler day_of_week uses 0-6 = mon-sun
|
|
values[4] = str((int(values[4]) - 1) % 7) if values[4].isdigit() else values[4]
|
|
|
|
if NEWSLETTER_SCHED.get_job(newsletter_job_id):
|
|
if remove_job:
|
|
NEWSLETTER_SCHED.remove_job(newsletter_job_id)
|
|
logger.info("Tautulli NewsletterHandler :: Removed scheduled newsletter: %s" % name)
|
|
else:
|
|
try:
|
|
NEWSLETTER_SCHED.reschedule_job(
|
|
newsletter_job_id, args=args, trigger=CronTrigger(
|
|
minute=values[0], hour=values[1], day=values[2], month=values[3], day_of_week=values[4]
|
|
)
|
|
)
|
|
logger.info("Tautulli NewsletterHandler :: Re-scheduled newsletter: %s" % name)
|
|
except ValueError as e:
|
|
logger.error("Tautulli NewsletterHandler :: Failed to re-schedule newsletter: %s" % e)
|
|
elif not remove_job:
|
|
try:
|
|
NEWSLETTER_SCHED.add_job(
|
|
func, args=args, id=newsletter_job_id, trigger=CronTrigger(
|
|
minute=values[0], hour=values[1], day=values[2], month=values[3], day_of_week=values[4]
|
|
),
|
|
misfire_grace_time=None
|
|
)
|
|
logger.info("Tautulli NewsletterHandler :: Scheduled newsletter: %s" % name)
|
|
except ValueError as e:
|
|
logger.error("Tautulli NewsletterHandler :: Failed to schedule newsletter: %s" % e)
|
|
|
|
|
|
def notify(newsletter_id=None, notify_action=None, **kwargs):
|
|
logger.info("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 = kwargs.pop('subject', None) or newsletter_config['subject']
|
|
body = kwargs.pop('body', None) or newsletter_config['body']
|
|
message = kwargs.pop('message', None) or newsletter_config['message']
|
|
else:
|
|
subject = newsletter_config['subject']
|
|
body = newsletter_config['body']
|
|
message = newsletter_config['message']
|
|
|
|
email_msg_id = email.utils.make_msgid()
|
|
email_reply_msg_id = get_last_newsletter_email_msg_id(newsletter_id=newsletter_id, notify_action=notify_action)
|
|
|
|
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'],
|
|
subject=subject,
|
|
body=body,
|
|
message=message,
|
|
email_msg_id=email_msg_id,
|
|
email_reply_msg_id=email_reply_msg_id
|
|
)
|
|
|
|
# Set the newsletter state in the db
|
|
newsletter_log_id = set_notify_state(newsletter=newsletter_config,
|
|
notify_action=notify_action,
|
|
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,
|
|
end_time=newsletter_agent.end_time,
|
|
newsletter_uuid=newsletter_agent.uuid,
|
|
email_msg_id=email_msg_id)
|
|
|
|
# Send the notification
|
|
success = newsletter_agent.send()
|
|
|
|
if success:
|
|
set_notify_success(newsletter_log_id)
|
|
return True
|
|
|
|
|
|
def set_notify_state(newsletter, notify_action, subject, body, message, filename,
|
|
start_date, end_date, start_time, end_time, newsletter_uuid, email_msg_id):
|
|
|
|
if newsletter and notify_action:
|
|
db = database.MonitorDatabase()
|
|
|
|
keys = {'timestamp': helpers.timestamp(),
|
|
'uuid': newsletter_uuid}
|
|
|
|
values = {'newsletter_id': newsletter['id'],
|
|
'agent_id': newsletter['agent_id'],
|
|
'agent_name': newsletter['agent_name'],
|
|
'notify_action': notify_action,
|
|
'subject_text': subject,
|
|
'body_text': body,
|
|
'message_text': message,
|
|
'start_date': start_date,
|
|
'end_date': end_date,
|
|
'start_time': start_time,
|
|
'end_time': end_time,
|
|
'email_msg_id': email_msg_id,
|
|
'filename': filename}
|
|
|
|
db.upsert(table_name='newsletter_log', key_dict=keys, value_dict=values)
|
|
return db.last_insert_id()
|
|
else:
|
|
logger.error("Tautulli NewsletterHandler :: Unable to set notify state.")
|
|
|
|
|
|
def set_notify_success(newsletter_log_id):
|
|
keys = {'id': newsletter_log_id}
|
|
values = {'success': 1}
|
|
|
|
db = database.MonitorDatabase()
|
|
db.upsert(table_name='newsletter_log', key_dict=keys, value_dict=values)
|
|
|
|
|
|
def get_last_newsletter_email_msg_id(newsletter_id, notify_action):
|
|
db = database.MonitorDatabase()
|
|
|
|
result = db.select_single("SELECT email_msg_id FROM newsletter_log "
|
|
"WHERE newsletter_id = ? AND notify_action = ? AND success = 1 "
|
|
"ORDER BY timestamp DESC LIMIT 1", [newsletter_id, notify_action])
|
|
|
|
if result:
|
|
return result['email_msg_id']
|
|
|
|
|
|
def get_newsletter(newsletter_uuid=None, newsletter_id_name=None):
|
|
db = database.MonitorDatabase()
|
|
|
|
if newsletter_uuid:
|
|
result = db.select_single("SELECT start_date, end_date, uuid, filename FROM newsletter_log "
|
|
"WHERE uuid = ?", [newsletter_uuid])
|
|
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_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_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):
|
|
try:
|
|
with open(newsletter_file_fp, 'r', encoding='utf-8') as n_file:
|
|
newsletter = n_file.read()
|
|
return newsletter
|
|
except OSError as e:
|
|
logger.error("Tautulli NewsletterHandler :: Failed to retrieve newsletter '%s': %s" % (newsletter_uuid, e))
|
|
else:
|
|
logger.warn("Tautulli NewsletterHandler :: Newsletter file '%s' is missing." % newsletter_file)
|