From: Calin Crisan Date: Wed, 20 Aug 2014 12:00:22 +0000 (+0300) Subject: added support for motion triggered web hooks X-Git-Url: http://www.vanbest.org/gitweb/?a=commitdiff_plain;h=6da07a2dcffbbf19f813cb0dcac0a89f35a241e3;p=motioneye-debian added support for motion triggered web hooks --- diff --git a/sendmail.py b/sendmail.py index de0dda8..4ecbcb5 100755 --- a/sendmail.py +++ b/sendmail.py @@ -159,6 +159,10 @@ if __name__ == '__main__': logging.debug('moment = %s' % moment.strftime('%Y-%m-%d %H:%M:%S')) logging.debug('smtp timeout = %d' % settings.SMTP_TIMEOUT) + if not to: + logging.info('no email address specified') + sys.exit(0) + io_loop = IOLoop.instance() def on_message(subject, message, files): diff --git a/src/config.py b/src/config.py index 1bc5668..3bbaaf7 100644 --- a/src/config.py +++ b/src/config.py @@ -695,20 +695,29 @@ def camera_ui_to_dict(ui): data['ffmpeg_bps'] = int(ui['movie_quality']) * max_val / 100 - if ui['motion_notifications']: + if ui['email_notifications_enabled']: send_mail_path = os.path.join(settings.PROJECT_PATH, 'sendmail.py') send_mail_path = os.path.abspath(send_mail_path) + emails = re.sub('\\s', '', ui['email_notifications_addresses']) - emails = re.sub('\\s', '', ui['motion_notifications_emails']) - on_event_start.append('%(script)s "%(server)s" "%(port)s" "%(account)s" "%(password)s" "%(tls)s" "%(to)s" "motion_start" "%%t" "%%Y-%%m-%%dT%%H:%%M:%%S"' % { 'script': send_mail_path, - 'server': ui['smtp_server'], - 'port': ui['smtp_port'], - 'account': ui['smtp_account'], - 'password': ui['smtp_password'], - 'tls': ui['smtp_tls'], + 'server': ui['email_notifications_smtp_server'], + 'port': ui['email_notifications_smtp_port'], + 'account': ui['email_notifications_smtp_account'], + 'password': ui['email_notifications_smtp_password'], + 'tls': ui['email_notifications_smtp_tls'], 'to': emails}) + + if ui['web_hook_notifications_enabled']: + web_hook_path = os.path.join(settings.PROJECT_PATH, 'webhook.py') + web_hook_path = os.path.abspath(web_hook_path) + url = re.sub('\\s', '+', ui['web_hook_notifications_url']) + + on_event_start.append('%(script)s "%(method)s" "%(url)s"' % { + 'script': web_hook_path, + 'method': ui['web_hook_notifications_http_method'], + 'url': url}) if ui['working_schedule']: data['@working_schedule'] = ( @@ -937,15 +946,22 @@ def camera_dict_to_ui(data): if len(e) != 10: continue - ui['motion_notifications'] = True - ui['smtp_server'] = e[1] - ui['smtp_port'] = e[2] - ui['smtp_account'] = e[3] - ui['smtp_password'] = e[4] - ui['smtp_tls'] = e[5].lower() == 'true' - ui['motion_notifications_emails'] = e[6] + ui['email_notifications_enabled'] = True + ui['email_notifications_smtp_server'] = e[1] + ui['email_notifications_smtp_port'] = e[2] + ui['email_notifications_smtp_account'] = e[3] + ui['email_notifications_smtp_password'] = e[4] + ui['email_notifications_smtp_tls'] = e[5].lower() == 'true' + ui['email_notifications_addresses'] = e[6] + + elif e.count('webhook.py'): + e = e.replace('"', '').split(' ') + if len(e) != 3: + continue - break + ui['web_hook_notifications_enabled'] = True + ui['web_hook_notifications_method'] = e[1] + ui['web_hook_notifications_url'] = e[2] working_schedule = data['@working_schedule'] if working_schedule: diff --git a/static/js/main.js b/static/js/main.js index 19c46c0..bc6855e 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -217,6 +217,7 @@ function initUI() { makeTextValidator($('#smtpServerEntry'), true); makeTextValidator($('#smtpAccountEntry'), true); makeTextValidator($('#smtpPasswordEntry'), true); + makeTextValidator($('#webHookUrlEntry'), true); /* number validators */ makeNumberValidator($('#streamingPortEntry'), 1024, 65535, false, false, true); @@ -263,7 +264,8 @@ function initUI() { $('#preservePicturesSelect').change(updateConfigUi); $('#motionMoviesSwitch').change(updateConfigUi); $('#preserveMoviesSelect').change(updateConfigUi); - $('#motionNotificationsSwitch').change(updateConfigUi); + $('#emailNotificationsSwitch').change(updateConfigUi); + $('#webHookNotificationsSwitch').change(updateConfigUi); $('#workingScheduleSwitch').change(updateConfigUi); $('#storageDeviceSelect').change(function () { @@ -471,11 +473,21 @@ function updateConfigUi() { $('#moviesLifetime').parents('tr:eq(0)').each(markHide); } - /* motion notifications switch */ - if (!$('#motionNotificationsSwitch').get(0).checked) { - $('#motionNotificationsSwitch').parent().next('table.settings').find('tr.settings-item').each(markHide); + /* email notifications switch */ + if (!$('#emailNotificationsSwitch').get(0).checked) { + $('#emailAddressesEntry').parents('tr:eq(0)').each(markHide); + $('#smtpServerEntry').parents('tr:eq(0)').each(markHide); + $('#smtpPortEntry').parents('tr:eq(0)').each(markHide); + $('#smtpAccountEntry').parents('tr:eq(0)').each(markHide); + $('#smtpPasswordEntry').parents('tr:eq(0)').each(markHide); + $('#smtpTlsSwitch').parents('tr:eq(0)').each(markHide); } + if (!$('#webHookNotificationsSwitch').get(0).checked) { + $('#webHookUrlEntry').parents('tr:eq(0)').each(markHide); + $('#webHookHttpMethod').parents('tr:eq(0)').each(markHide); + } + /* working schedule switch */ if (!$('#workingScheduleSwitch').get(0).checked) { $('#workingScheduleSwitch').parent().next('table.settings').find('tr.settings-item').each(markHide); @@ -651,13 +663,16 @@ function cameraUi2Dict() { 'post_capture': $('#postCaptureEntry').val(), /* motion notifications */ - 'motion_notifications': $('#motionNotificationsSwitch')[0].checked, - 'motion_notifications_emails': $('#emailAddressesEntry').val(), - 'smtp_server': $('#smtpServerEntry').val(), - 'smtp_port': $('#smtpPortEntry').val(), - 'smtp_account': $('#smtpAccountEntry').val(), - 'smtp_password': $('#smtpPasswordEntry').val(), - 'smtp_tls': $('#smtpTlsSwitch')[0].checked, + 'email_notifications_enabled': $('#emailNotificationsSwitch')[0].checked, + 'email_notifications_addresses': $('#emailAddressesEntry').val(), + 'email_notifications_smtp_server': $('#smtpServerEntry').val(), + 'email_notifications_smtp_port': $('#smtpPortEntry').val(), + 'email_notifications_smtp_account': $('#smtpAccountEntry').val(), + 'email_notifications_smtp_password': $('#smtpPasswordEntry').val(), + 'email_notifications_smtp_tls': $('#smtpTlsSwitch')[0].checked, + 'web_hook_notifications_enabled': $('#webHookNotificationsSwitch')[0].checked, + 'web_hook_notifications_url': $('#webHookUrlEntry').val(), + 'web_hook_notifications_http_method': $('#webHookHttpMethod').val(), /* working schedule */ 'working_schedule': $('#workingScheduleSwitch')[0].checked, @@ -827,13 +842,16 @@ function dict2CameraUi(dict) { $('#postCaptureEntry').val(dict['post_capture']); /* motion notifications */ - $('#motionNotificationsSwitch')[0].checked = dict['motion_notifications']; - $('#emailAddressesEntry').val(dict['motion_notifications_emails']); - $('#smtpServerEntry').val(dict['smtp_server']); - $('#smtpPortEntry').val(dict['smtp_port']); - $('#smtpAccountEntry').val(dict['smtp_account']); - $('#smtpPasswordEntry').val(dict['smtp_password']); - $('#smtpTlsSwitch')[0].checked = dict['smtp_tls']; + $('#emailNotificationsSwitch')[0].checked = dict['email_notifications_enabled']; + $('#emailAddressesEntry').val(dict['email_notifications_addresses']); + $('#smtpServerEntry').val(dict['email_notifications_smtp_server']); + $('#smtpPortEntry').val(dict['email_notifications_smtp_port']); + $('#smtpAccountEntry').val(dict['email_notifications_smtp_account']); + $('#smtpPasswordEntry').val(dict['email_notifications_smtp_password']); + $('#smtpTlsSwitch')[0].checked = dict['email_notifications_smtp_tls']; + $('#webHookNotificationsSwitch')[0].checked = dict['web_hook_notifications_enabled']; + $('#webHookUrlEntry').val(dict['web_hook_notifications_url']); + $('#webHookHttpMethod').val(dict['web_hook_notifications_http_method']); /* working schedule */ $('#workingScheduleSwitch')[0].checked = dict['working_schedule']; diff --git a/templates/main.html b/templates/main.html index 62484dd..7f51e49 100644 --- a/templates/main.html +++ b/templates/main.html @@ -420,16 +420,18 @@ -
Motion Notifications
+
Motion Notifications
+ + + + + - - - @@ -455,6 +457,29 @@ + + + + + + + + + + + + + + + + + +
Email Notifications?
Email Addresses ?
SMTP Server ?
Web Hook Notifications?
Web Hook URL?
HTTP Method + + ?
diff --git a/webhook.py b/webhook.py new file mode 100755 index 0000000..016a0db --- /dev/null +++ b/webhook.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +# Copyright (c) 2013 Calin Crisan +# This file is part of motionEye. +# +# motionEye 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. +# +# This program 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 this program. If not, see . + +import logging +import sys +import urllib2 +import urlparse + +import settings + +from motioneye import _configure_settings, _configure_logging + + +_configure_settings() +_configure_logging() + + +def print_usage(): + print 'Usage: webhook.py ' + + +if __name__ == '__main__': + if len(sys.argv) < 3: + print_usage() + sys.exit(-1) + + method = sys.argv[1] + url = sys.argv[2] + + logging.debug('method = %s' % method) + logging.debug('url = %s' % url) + + if method == 'POST': + parts = urlparse.urlparse(url) + data = parts.query + + else: + data = None + + request = urllib2.Request(url, data) + try: + urllib2.urlopen(request, timeout=settings.REMOTE_REQUEST_TIMEOUT) + logging.debug('webhook successfully called') + + except Exception as e: + logging.error('failed to call webhook: %s' % e)