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):
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'] = (
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:
makeTextValidator($('#smtpServerEntry'), true);
makeTextValidator($('#smtpAccountEntry'), true);
makeTextValidator($('#smtpPasswordEntry'), true);
+ makeTextValidator($('#webHookUrlEntry'), true);
/* number validators */
makeNumberValidator($('#streamingPortEntry'), 1024, 65535, false, false, true);
$('#preservePicturesSelect').change(updateConfigUi);
$('#motionMoviesSwitch').change(updateConfigUi);
$('#preserveMoviesSelect').change(updateConfigUi);
- $('#motionNotificationsSwitch').change(updateConfigUi);
+ $('#emailNotificationsSwitch').change(updateConfigUi);
+ $('#webHookNotificationsSwitch').change(updateConfigUi);
$('#workingScheduleSwitch').change(updateConfigUi);
$('#storageDeviceSelect').change(function () {
$('#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);
'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,
$('#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'];
</tr>
</table>
- <div class="settings-section-title advanced-setting"><input type="checkbox" class="styled section notifications" id="motionNotificationsSwitch">Motion Notifications</div>
+ <div class="settings-section-title advanced-setting">Motion Notifications</div>
<table class="settings">
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">Email Notifications</span></td>
+ <td class="settings-item-value"><input type="checkbox" class="styled notifications" id="emailNotificationsSwitch"></td>
+ <td><span class="help-mark" title="enable this if you want to receive email notifications whenever a motion event is detected">?</span></td>
+ </tr>
<tr class="settings-item advanced-setting">
<td class="settings-item-label"><span class="settings-item-label">Email Addresses</span></td>
<td class="settings-item-value"><input type="text" class="styled notifications" id="emailAddressesEntry" placeholder="email addresses..."></td>
<td><span class="help-mark" title="email addresses (separated by comma) that are added here will receive notifications whenever a motion event is detected">?</span></td>
</tr>
- <tr class="settings-item advanced-setting">
- <td colspan="100"><div class="settings-item-separator"></div></td>
- </tr>
<tr class="settings-item advanced-setting">
<td class="settings-item-label"><span class="settings-item-label">SMTP Server</span></td>
<td class="settings-item-value"><input type="text" class="styled notifications" id="smtpServerEntry" placeholder="e.g. smtp.gmail.com"></td>
<td class="settings-item-value"><input type="checkbox" class="styled notifications" id="smtpTlsSwitch"></td>
<td><span class="help-mark" title="enable this if your SMTP server requires TLS (Gmail needs this to be enabled)">?</span></td>
</tr>
+ <tr class="settings-item advanced-setting">
+ <td colspan="100"><div class="settings-item-separator"></div></td>
+ </tr>
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">Web Hook Notifications</span></td>
+ <td class="settings-item-value"><input type="checkbox" class="styled notifications" id="webHookNotificationsSwitch"></td>
+ <td><span class="help-mark" title="enable this if you want a URL to be requested whenever a motion event is detected">?</span></td>
+ </tr>
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">Web Hook URL</span></td>
+ <td class="settings-item-value"><input type="text" class="styled notifications" id="webHookUrlEntry" placeholder="e.g. http://www.example.com/notify/"></td>
+ <td><span class="help-mark" title="a URL to be requested when motion is detected; the following special tokens are accepted: %Y = year, %m = month, %d = date, %H = hour, %M = minute, %S = second, %q = frame number">?</span></td>
+ </tr>
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">HTTP Method</span></td>
+ <td class="settings-item-value">
+ <select class="styled notifications" id="webHookHttpMethod">
+ <option value="GET">GET</option>
+ <option value="POST">POST</option>
+ </select>
+ </td>
+ <td><span class="help-mark" title="the HTTP method to use when requesting the web hook URL">?</span></td>
+ </tr>
</table>
<div class="settings-section-title hidden"><input type="checkbox" class="styled section working-schedule" id="workingScheduleSwitch">Working Schedule</div>
--- /dev/null
+#!/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 <http://www.gnu.org/licenses/>.
+
+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 <method> <url>'
+
+
+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)