From 2ed674ff9bf0693cdf33653a9bceaad85b055f8b Mon Sep 17 00:00:00 2001 From: seiferta Date: Tue, 17 May 2016 17:27:12 +0200 Subject: [PATCH] communication extension added with implementation of telegram bot communication. --- emonitor.cfg.template | 2 + emonitor/app.py | 7 +- emonitor/communication.py | 273 ++++++++++++++++++ emonitor/extensions.py | 6 + emonitor/frontend/web/js/frontend.min.js | 2 +- emonitor/modules/alarms/alarm.py | 30 +- emonitor/modules/persons/content_admin.py | 2 +- .../admin.persons.uploadpreview.html | 10 +- emonitor/modules/settings/__init__.py | 4 +- emonitor/modules/settings/content_admin.py | 38 +++ .../translations/de/LC_MESSAGES/modules.mo | Bin 83518 -> 85975 bytes .../translations/de/LC_MESSAGES/modules.po | 206 ++++++++----- emonitor/modules/translations/modules.pot | 145 ++++++---- 13 files changed, 581 insertions(+), 144 deletions(-) create mode 100644 emonitor/communication.py diff --git a/emonitor.cfg.template b/emonitor.cfg.template index dd199f2..a50d86d 100644 --- a/emonitor.cfg.template +++ b/emonitor.cfg.template @@ -14,6 +14,8 @@ cachetimeout = 300 TILE_MISSING = 'load' # load|none ADMIN_DEFAULT_PASSWORD = 'admin' +TELEGRAMKEY = '' + PATH_DATA = './data/' PATH_INCOME = './data/income/' PATH_DONE = './data/done/' diff --git a/emonitor/app.py b/emonitor/app.py index 1d24201..93365e3 100644 --- a/emonitor/app.py +++ b/emonitor/app.py @@ -4,7 +4,7 @@ from alembic import util as alembicutil from sqlalchemy.exc import OperationalError from flask import Flask, request, render_template, current_app -from .extensions import alembic, db, login_manager, babel, cache, events, scheduler, monitorserver, signal, printers +from .extensions import alembic, db, login_manager, babel, cache, events, scheduler, monitorserver, signal, printers, communication from .user import User from emonitor import __version__ @@ -58,6 +58,8 @@ class DEFAULT_CONFIG(object): OBSERVERINTERVAL = 2 # interval for folderobserver MONITORPING = 2 # monitor ping in minutes + TELEGRAMKEY = "botid" + def create_app(config=None, app_name=None, blueprints=None): """ @@ -180,6 +182,9 @@ def configure_extensions(app): def load_user(id): return User.getUsers(userid=id) + # communication + communication.init_app(app) + # add global elements from emonitor.scheduler import eMonitorIntervalTrigger from emonitor.modules.settings.settings import Settings diff --git a/emonitor/communication.py b/emonitor/communication.py new file mode 100644 index 0000000..2ba67a2 --- /dev/null +++ b/emonitor/communication.py @@ -0,0 +1,273 @@ +import yaml +import logging +from emonitor.extensions import events, babel, db +from emonitor.modules.events.eventhandler import Eventhandler +from emonitor.modules.alarms.alarm import Alarm +from emonitor.modules.settings.settings import Settings +from emonitor.modules.persons.persons import Person + +logger = logging.getLogger(__name__) + + +class Communicator: + def sendMessage(self, addressee, message): + pass + + def getUsers(self): + return [] + + +class TelegramBot(Communicator): + """ + telegram connector class + """ + __personidentifier__ = 'telegramid' + app = None + logger = logging.getLogger('telegram.bot') + logger.setLevel(logging.ERROR) + users = Person + + def __init__(self, **kwargs): + # Create the EventHandler and pass it your bot's token. + from telegram.ext import Updater, CommandHandler, CallbackQueryHandler, MessageHandler, Filters + from telegram.error import InvalidToken, Unauthorized, NetworkError + + self.updater = Updater(kwargs.get('token', '')) + self.active = False + self.botname = None + + TelegramBot.app = kwargs.get('app', None) + + try: + if self.updater.bot.getMe(): + self.botname = self.updater.bot.getMe().name + # on different commands - answer in Telegram + self.updater.dispatcher.addHandler(CommandHandler("start", TelegramBot.msg_start, pass_args=True)) + self.updater.dispatcher.addHandler(CommandHandler("Start", TelegramBot.msg_start, pass_args=True)) + self.updater.dispatcher.addHandler(CommandHandler("hilfe", TelegramBot.msg_help, pass_args=True)) + self.updater.dispatcher.addHandler(CommandHandler("Hilfe", TelegramBot.msg_help, pass_args=True)) + self.updater.dispatcher.addHandler(CallbackQueryHandler(TelegramBot.msg_responder)) + self.updater.start_polling() + except InvalidToken: + self.logger.error('invalid telegram token {}'.format(kwargs.get('token', ''))) + self.updater = Updater(kwargs.get('token', '')) + except Unauthorized: + self.logger.error('unauthorized telegram token {}'.format(kwargs.get('token', ''))) + except NetworkError: + self.logger.error('network error with telegram token {}'.format(kwargs.get('token', ''))) + + def updateToken(self, token=None): + """ + update token after changes + :return: botname + """ + from telegram.ext import Updater + from telegram.error import Unauthorized, NetworkError + updater = Updater(token or Settings.get('telegramkey')) + self.updater = updater + self.botname = None + try: + if updater.bot.getMe(): + self.botname = updater.bot.getMe().name + + except Unauthorized: + self.botname = None + except NetworkError: + self.logger.error("network error") + + return self.botname + + def start(self): + """ + start update handler for telegram messages + """ + self.logger.debug('telegram bot updater started') + self.active = True + try: + self.updater.idle() + except: + self.active = True + + def stop(self): + """ + stop update handler for telegram messages + """ + self.active = False + self.updater.stop() + + def state(self): + return self.active + + def getUsers(self): + """ + get list of users for telegram messenger + :return: list of persons + """ + return Person.query.filter(self.users._options.like('%{}%'.format(self.__personidentifier__))).all() + + def sendMessage(self, addressee, message, **kwargs): + """ + send message via telegram messenger + :param addressee: id of user or group + :param message: text message + :param kwargs: additional attributes, 'reply_markup' defined + """ + self.updater.bot.sendMessage(addressee, message, parse_mode='Markdown', reply_markup=kwargs.get('reply_markup', None)) + + def sendVenue(self, addressee, message, **kwargs): + """ + send venue of current item + :param addressee: id of user or group + :param message: text message for header + :param kwargs: deliver 'lat', 'lng', 'address', 'reply_markup' + """ + self.updater.bot.sendVenue(addressee, kwargs.get('lat'), kwargs.get('lng'), message, kwargs.get('address'), reply_markup=kwargs.get('reply_markup', None)) + + def sendFile(self, addressee, document, **kwargs): + """ + send file for given parameters + :param addressee: id of user or group + :param document: document pointer to document to send + :param kwargs: additional attributes, 'filename', 'caption' + """ + self.updater.bot.sendDocument(addressee, document, filename=kwargs.get('filename', None), caption=kwargs.get('caption', None)) + + @staticmethod + def msg_start(bot, update, **kwargs): + """ + send start message and add user id to emonitor user if found + :param bot: + :param update: + :param kwargs: + """ + for person in TelegramBot.users.getPersons(): + if person.firstname == update.message.from_user['first_name'] and person.lastname == update.message.from_user['last_name']: + TelegramBot.logger.info('add telegramid {} to user {} {}'.format(update.message.from_user['id'], person.firstname, person.lastname)) + _additional = person.options + _additional['telegramid'] = update.message.from_user['id'] + person._options = yaml.safe_dump(_additional, encoding='utf-8') + db.session.commit() + + msgtext = Settings.get('telegramsettings')['welcomemsg'] or babel.gettext('telegram.default.welcomemsg') + bot.sendMessage(update.message.chat_id, text=msgtext.format(vorname=update.message.from_user.first_name, nachname=update.message.from_user.last_name)) + TelegramBot.logger.info('send message from "msg_start" to {} {}'.format(update.message.from_user.first_name, update.message.from_user.last_name)) + + @staticmethod + def msg_responder(bot, update, **kwargs): + """ + Responder for incoming messages + :param bot: + :param update: + :param kwargs: + """ + if update.callback_query.data.startswith('file_'): # send file + bot.sendDocument(update.callback_query.message.chat_id, open(TelegramBot.app.config.get('PATH_DONE') + update.callback_query.data.split('_')[-1], 'rb'), 'details.pdf', 'details') + + elif update.callback_query.data.startswith('details_'): # details_[type]_[id] + if update.callback_query.data.split('_')[1] == 'alarm': + from telegram import InlineKeyboardMarkup, InlineKeyboardButton + args = {'id': int(update.callback_query.data.split('_')[-1]), 'style': 'details', 'addressees': [update.callback_query.message.chat_id], 'keyboard': InlineKeyboardMarkup, 'button': InlineKeyboardButton} + attrs = Alarm.getExportData('telegram', **args) + for addressee in [update.callback_query.message.chat_id]: + bot.sendMessage(addressee, attrs['details'], reply_markup=attrs['reply'], parse_mode='Markdown') + return + + elif update.callback_query.data.startswith('location_'): + bot.sendLocation(update.callback_query.message.chat_id, update.callback_query.data.split('_')[1], update.callback_query.data.split('_')[2]) + + @staticmethod + def msg_help(bot, update, **kwargs): + """ + send information about the bot + :param bot: + :param update: + :param kwargs: + """ + msgtext = Settings.get('telegramsettings')['helpmsg'] or babel.gettext('telegram.default.helpmsg') + bot.sendMessage(update.message.chat_id, msgtext, parse_mode='Markdown') + TelegramBot.logger.debug("help_msg sent.") + + +class Mailer(Communicator): + + def __init__(self, **kwargs): + pass + + +class Communication(object): + """ + collector class for all communication interfaces + """ + app = None + + def __init__(self, app=None): + self.__dict__ = {} + if app is not None: + self.init_app(app) + + def init_app(self, app): + Communication.app = app + + try: # try telegram + import telegram + self.__dict__['telegram'] = TelegramBot(app=app, token=Settings.get('telegramsettings')['telegramkey'] or app.config.get('TELEGRAMKEY')) + except TypeError: + Settings.set('telegramsettings', {'telegramkey': ''}) + self.__dict__['telegram'] = None + except ImportError: + logger.error("error telegram") + self.__dict__['telegram'] = None + + try: # try mail + # TODO: add Mail communicator + pass + self.__dict__['mail'] = Mailer + except ImportError: + self.__dict__['mail'] = None + logger.error("error Mail") + # Mail = None + + app.extensions['communication'] = self + + logger.info("{} Communicator(s) loaded: {}".format(len(self.__dict__.keys()), ", ".join(self.__dict__.keys()))) + events.addHandlerClass('*', 'emonitor.communication.Communication', Communication.handleEvent, ['in.sendertype', 'in.group', 'in.id', 'in.style']) + + def updateCommunicator(self, commtype): + for key, communicator in self.__dict__.items(): + if key == commtype: + self.__dict__[key] = TelegramBot(app=Communication.app, token=Settings.get('telegramsettings')['telegramkey'] or Communication.app.config.get('TELEGRAMKEY')) + return self.__dict__[key] + + def _teardown(self, **kwargs): + pass + + @staticmethod + def handleEvent(eventname, **kwargs): + hdl = [hdl for hdl in Eventhandler.getEventhandlers(event=eventname) if hdl.handler == 'emonitor.communication.Communication'][0] + if hdl: + from emonitor.extensions import communication + params = {} + for p in hdl.getParameterValues('in'): + params[p[0].split('.')[-1]] = p[1] + if params["sendertype"] == 'telegram': + for group, members in Settings.getYaml('telegramsettings').__dict__['groups'].items(): + if group == params['group']: + from telegram import InlineKeyboardMarkup, InlineKeyboardButton + args = {'id': int(kwargs.get('alarmid')), 'style': params['style'], 'addressees': members[:-1], 'keyboard': InlineKeyboardMarkup, 'button': InlineKeyboardButton} + attrs = Alarm.getExportData('telegram', **args) + for member in members[:-1]: + if params['id'] == 'alarmid': # send alarm details with location + try: + if params.get('style') in ['text', 'details']: + communication.telegram.sendMessage(member, attrs['details'], reply_markup=attrs['reply']) + elif params.get('style') == 'venue': + communication.telegram.sendVenue(member, attrs['text'], lat=attrs['lat'], lng=attrs['lng'], address=attrs['address'], reply_markup=attrs['reply']) + except: + print "error handleEvent" + return kwargs + + elif params["sendertype"] == 'mailer': + # TODO: implement mail notification + pass + + return kwargs diff --git a/emonitor/extensions.py b/emonitor/extensions.py index 0fbdd6d..3d09b4d 100644 --- a/emonitor/extensions.py +++ b/emonitor/extensions.py @@ -46,3 +46,9 @@ def get_query(self, *entities, **kwargs): # printer from emonitor.printertype import ePrinters printers = ePrinters() + +# communication +from emonitor.communication import Communication +communication = Communication() + + diff --git a/emonitor/frontend/web/js/frontend.min.js b/emonitor/frontend/web/js/frontend.min.js index 60fd14a..14dad65 100644 --- a/emonitor/frontend/web/js/frontend.min.js +++ b/emonitor/frontend/web/js/frontend.min.js @@ -1 +1 @@ -window.WebSocket=window.WebSocket||window.MozWebSocket||false;if(!window.WebSocket){$("#ws").html("-");console.log("websockets not supportetd")}else{ws=new WebSocket("ws://"+location.host+"/ws");var reloadtimer=null;var connection_info="";$.ajax({type:"POST",url:"/data/frontpage?action=translatebaseinfo",success:function(a){connection_info=a.connection_info}});ws.onclose=function(){setTimeout(function(){$("#overlaycontent").html(connection_info);$(".overlay").show()},2000);if(!reloadtimer){reloadtimer=setInterval(tryReconnect,5000)}$("#ws").html('')};ws.onmessage=function(a){var b=JSON.parse(a.data);console.log(b);alert(b)}}function tryReconnect(){$.get(window.location.href).done(function(){location.reload()}).fail(function(){console.log("reload failed")})}function closeOverlay(){$(".overlay").toggle();return false}function showMonitorDefinition(){$.ajax({type:"POST",url:"/data/monitors?action=monitoroverview",success:function(a){$("#overlaycontent").html(a);$(".overlay").show();$(".overlay").on("hide",function(){stopMonitorPing()});return false}});return false}function stopMonitorPing(){clearTimeout(nextrun)}$(".usermenu").hover(function(){$(this).find(".dropdown-menu").stop(true,true).delay(200).fadeIn(500)},function(){$(this).find(".dropdown-menu").stop(true,true).delay(200).fadeOut(500)});(function(a){a.each(["show","hide"],function(b,d){var c=a.fn[d];a.fn[d]=function(){this.trigger(d);return c.apply(this,arguments)}})})(jQuery);function showInfo(){$.ajax({type:"POST",url:"/data/frontpage?action=info",success:function(a){$("#overlaycontent").html(a);$(".overlay").toggle();return false}});return false}function showSystemInfo(){$.ajax({type:"POST",url:"/data/frontpage?action=systeminfo",success:function(a){$("#overlaycontent").html(a);$(".overlay").toggle();return false}});return false}function restartApp(){$.ajax({type:"POST",url:"/data/frontpage?action=restart",success:function(a){return false}});return false}; \ No newline at end of file +window.WebSocket=window.WebSocket||window.MozWebSocket||false;if(!window.WebSocket){$("#ws").html("-");console.log("websockets not supportetd")}else{ws=new WebSocket("ws://"+location.host+"/ws");var reloadtimer=null;var connection_info="";$.ajax({type:"POST",url:"/data/frontpage?action=translatebaseinfo",success:function(a){connection_info=a.connection_info}});ws.onclose=function(){setTimeout(function(){$("#overlaycontent").html(connection_info);$(".overlay").show()},2000);if(!reloadtimer){reloadtimer=setInterval(tryReconnect,5000)}$("#ws").html('')};ws.onmessage=function(a){var b=JSON.parse(a.data);console.log(b)}}function tryReconnect(){$.get(window.location.href).done(function(){location.reload()}).fail(function(){console.log("reload failed")})}function closeOverlay(){$(".overlay").toggle();return false}function showMonitorDefinition(){$.ajax({type:"POST",url:"/data/monitors?action=monitoroverview",success:function(a){$("#overlaycontent").html(a);$(".overlay").show();$(".overlay").on("hide",function(){stopMonitorPing()});return false}});return false}function stopMonitorPing(){clearTimeout(nextrun)}$(".usermenu").hover(function(){$(this).find(".dropdown-menu").stop(true,true).delay(200).fadeIn(500)},function(){$(this).find(".dropdown-menu").stop(true,true).delay(200).fadeOut(500)});(function(a){a.each(["show","hide"],function(b,d){var c=a.fn[d];a.fn[d]=function(){this.trigger(d);return c.apply(this,arguments)}})})(jQuery);function showInfo(){$.ajax({type:"POST",url:"/data/frontpage?action=info",success:function(a){$("#overlaycontent").html(a);$(".overlay").toggle();return false}});return false}function showSystemInfo(){$.ajax({type:"POST",url:"/data/frontpage?action=systeminfo",success:function(a){$("#overlaycontent").html(a);$(".overlay").toggle();return false}});return false}function restartApp(){$.ajax({type:"POST",url:"/data/frontpage?action=restart",success:function(a){return false}});return false}; \ No newline at end of file diff --git a/emonitor/modules/alarms/alarm.py b/emonitor/modules/alarms/alarm.py index aec1e95..88a2486 100644 --- a/emonitor/modules/alarms/alarm.py +++ b/emonitor/modules/alarms/alarm.py @@ -310,7 +310,7 @@ def changeState(id, state): if not alarm: return [] - if alarm.state != state: # only change + if alarm.state != state and alarm.state != 0: # only change _op = 'changestate' else: _op = 'added' @@ -355,7 +355,6 @@ def changeState(id, state): pass finally: monitorserver.sendMessage('0', 'reset') # refresh monitor layout - #signal.send('alarm', 'changestate', newstate=1) return list(set(c)) elif state == 2: # close alarm @@ -377,9 +376,9 @@ def getExportData(exportformat, **params): """ Export alarm to given format - :param exportformat: *.html*, *.png* + :param exportformat: *.html*, *.png*, *telegram*, [*mail*] :param params: - - style: exportstyle: *alarmmap*, *routemap* + - style: exportstyle: *alarmmap*, *routemap*, *telegram.text*, *telegram.venue* - filename: name of exportfile @@ -423,6 +422,29 @@ def getExportData(exportformat, **params): if 'filename' in params and os.path.exists("%s/inc/%s.png" % (os.path.abspath(os.path.dirname(__file__)), params['filename'])): with open("%s/inc/%s.png" % (os.path.abspath(os.path.dirname(__file__)), params['filename']), 'rb') as f: return f.read() + + elif exportformat == 'telegram': # build telegram information for alarm + attrs = {'text': u"{}: {}".format(alarm.key.category, alarm.key.key), + 'details': u"*Alarm ({})*\n*{}: {}*\n{} {} ({})\n\n{}".format(alarm.timestamp, alarm.key.category, alarm.key.key, alarm.street.name, alarm.housenumber.number, alarm.city.name, alarm.remark), + 'address': u"{} {} ({})".format(alarm.street.name, alarm.housenumber.number, alarm.city.name), 'filename': alarm.get('filename'), + 'lat': alarm.lat, 'lng': alarm.lng, 'reply': []} + + if alarm.type == 1: # fax type can send file + attrs['reply'].append(params.get('button')("Fax", callback_data=u'file_{}'.format(attrs['filename']))) + + if params.get('style') == 'text': + attrs['reply'].append(params.get('button')("Position", callback_data=u'location_{}_{}'.format(alarm.lat, alarm.lng))) + + if params.get('style') == 'venue': + attrs['reply'].append(params.get('button')("Details", callback_data=u'details_alarm_{}'.format(alarm.id))) + + attrs['reply'] = params.get('keyboard')([attrs['reply']]) + return attrs + + elif exportformat == 'mail': + # TODO: Add mailer handler + return None + abort(404) @staticmethod diff --git a/emonitor/modules/persons/content_admin.py b/emonitor/modules/persons/content_admin.py index db04383..f8c778f 100644 --- a/emonitor/modules/persons/content_admin.py +++ b/emonitor/modules/persons/content_admin.py @@ -52,7 +52,7 @@ def getAdminContent(self, **params): person.remark = request.form.get('remark') _additional = {} for field in Settings.get('persons.settings').get('additional'): - if field.split('=')[0] in request.form.keys(): + if field.split('=')[0] in request.form.keys() and request.form.get(field.split('=')[0]).strip() != '': _additional[field.split('=')[0]] = request.form.get(field.split('=')[0]) person._options = yaml.safe_dump(_additional, encoding='utf-8') db.session.commit() diff --git a/emonitor/modules/persons/templates/admin.persons.uploadpreview.html b/emonitor/modules/persons/templates/admin.persons.uploadpreview.html index d6c914b..ad927c8 100644 --- a/emonitor/modules/persons/templates/admin.persons.uploadpreview.html +++ b/emonitor/modules/persons/templates/admin.persons.uploadpreview.html @@ -6,10 +6,11 @@

{{ _('persons.upload.step5header') }}

{{ _('persons.upload.firstname') }}
{{ _('persons.upload.lastname') }}
-
{{ _('persons.upload.salutation') }}
+
{{ _('persons.upload.birthday') }}
+
{{ _('persons.upload.salutation') }}
{{ _('persons.upload.grade') }}
{{ _('persons.upload.position') }}
-
{{ _('persons.upload.identifier') }}
+
{{ _('persons.upload.identifier') }}
@@ -19,10 +20,11 @@

{{ _('persons.upload.step5header') }}

{{ val['firstname']|safe }}
{{ val['lastname']|safe }}
-
{{ val['salutation']|safe }}
+
{{ val['birthdate']|safe }}
+
{{ val['salutation']|safe }}
{{ val['grade']|safe }}
{{ val['position']|safe }}
-
{{ val['identifier']|safe }}
+
{{ val['identifier']|safe }}
{%- if val['state']=='0' %} diff --git a/emonitor/modules/settings/__init__.py b/emonitor/modules/settings/__init__.py index c3a6bea..8cbae08 100644 --- a/emonitor/modules/settings/__init__.py +++ b/emonitor/modules/settings/__init__.py @@ -26,7 +26,7 @@ def __init__(self, app): self.widgets = [CrestWidget('departmentcrest')] # subnavigation - self.adminsubnavigation = [('/admin/settings', 'settings.main'), ('/admin/settings/department', 'module.settings.department'), ('/admin/settings/cars', 'module.settings.cars'), ('/admin/settings/start', 'module.settings.start')] + self.adminsubnavigation = [('/admin/settings', 'settings.main'), ('/admin/settings/department', 'module.settings.department'), ('/admin/settings/cars', 'module.settings.cars'), ('/admin/settings/communication', 'module.settings.communication'), ('/admin/settings/start', 'module.settings.start')] # static folders @app.route('/settings/inc/') @@ -38,6 +38,7 @@ def settings_static(filename): babel.gettext(u'settings.main') babel.gettext(u'module.settings.department') babel.gettext(u'module.settings.cars') + babel.gettext(u'module.settings.communication') babel.gettext(u'module.settings.start') babel.gettext(u'settings.pathtype.pathdone') @@ -46,6 +47,7 @@ def settings_static(filename): babel.gettext(u'settings.pathtype.pathincome') babel.gettext(u'departmentcrest') + babel.gettext(u'telegram.default.welcomemsg') # add default values if Settings.query.count() == 0: # add default values diff --git a/emonitor/modules/settings/content_admin.py b/emonitor/modules/settings/content_admin.py index cd390d5..4a871e7 100644 --- a/emonitor/modules/settings/content_admin.py +++ b/emonitor/modules/settings/content_admin.py @@ -88,6 +88,39 @@ def chunks(l, n): params.update({'cartypes': Settings.getCarTypes()}) return render_template('admin.settings.cars.html', **params) + elif module[1] == 'communication': + from emonitor.extensions import communication + if request.method == 'POST': + if request.form.get('action') == 'telegramsettings': + vals = Settings.get('telegramsettings') + vals['telegramkey'] = request.form.get('telegrambot') + vals['welcomemsg'] = request.form.get('welcometext') + vals['helpmsg'] = request.form.get('helptext') + Settings.set('telegramsettings', vals) + db.session.commit() + tb = communication.telegram + if not tb: + communication.init_app(app=communication.app) + tb = communication.telegram + else: + tb.stop() + tb.updateToken(vals['telegramkey']) + + elif request.form.get('action') == 'telegramgroups': + vals = Settings.get('telegramsettings') + g = {} + for f in filter(lambda x: x.startswith('groupname_'), request.form): + _id = f.split('_')[-1] # fieldname in form + if request.form.get('groupname_' + _id) in ['newgroup', '']: + continue + g[request.form.get('groupname_' + _id)] = request.form.get('members_selectable_' + _id).split(';') + vals['groups'] = g + Settings.set('telegramsettings', vals) + db.session.commit() + + params.update({'bot': communication.telegram, 'settings': Settings.getYaml('telegramsettings'), 'configtelegramkey': current_app.config.get('TELEGRAMKEY', '')}) + return render_template('admin.settings.communication.html', **params) + elif module[1] == 'start': if request.method == 'POST': @@ -152,4 +185,9 @@ def getAdminData(self, **params): elif request.args.get('action') == 'downgradedb': return alembic.downgrade() or "done" + elif request.args.get('action') == 'sendtelegramtest': + from emonitor.extensions import communication + communication.telegram.sendMessage(addressee=int(request.args.get('user')), message=request.args.get('msg')) + return babel.gettext(u'admin.settings.telegramtest.done') + return "" diff --git a/emonitor/modules/translations/de/LC_MESSAGES/modules.mo b/emonitor/modules/translations/de/LC_MESSAGES/modules.mo index a134a65cc8cd9ade474bc6c1c979750ca0ce2356..34b54d67ce2170122a0f5005c8205fb84fc9023e 100644 GIT binary patch delta 25334 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 HlN|pK?2qE2 delta 22922 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 diff --git a/emonitor/modules/translations/de/LC_MESSAGES/modules.po b/emonitor/modules/translations/de/LC_MESSAGES/modules.po index b553ce4..0283ac6 100644 --- a/emonitor/modules/translations/de/LC_MESSAGES/modules.po +++ b/emonitor/modules/translations/de/LC_MESSAGES/modules.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-05-04 20:12+0200\n" -"PO-Revision-Date: 2016-05-04 20:15+0200\n" +"POT-Creation-Date: 2016-05-17 16:54+0200\n" +"PO-Revision-Date: 2016-05-17 17:18+0200\n" "Last-Translator: Arne Seifert \n" "Language-Team: de \n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -833,49 +833,49 @@ msgid "trigger.alarm_changestate_sub" msgstr "Einsatz-Status geändert (%(sub)s)" #: emonitor/modules/alarms/__init__.py:141 -#: emonitor/modules/alarms/alarmutils.py:320 +#: emonitor/modules/alarms/alarmutils.py:372 msgid "alarms.print.slightleft" msgstr "leicht links" #: emonitor/modules/alarms/__init__.py:142 -#: emonitor/modules/alarms/alarmutils.py:320 +#: emonitor/modules/alarms/alarmutils.py:372 msgid "alarms.print.slightright" msgstr "leicht rechts" #: emonitor/modules/alarms/__init__.py:143 -#: emonitor/modules/alarms/alarmutils.py:320 +#: emonitor/modules/alarms/alarmutils.py:372 msgid "alarms.print.right" msgstr "rechts" #: emonitor/modules/alarms/__init__.py:144 -#: emonitor/modules/alarms/alarmutils.py:320 +#: emonitor/modules/alarms/alarmutils.py:372 msgid "alarms.print.left" msgstr "links" #: emonitor/modules/alarms/__init__.py:145 -#: emonitor/modules/alarms/alarmutils.py:320 -#: emonitor/modules/alarms/alarmutils.py:335 +#: emonitor/modules/alarms/alarmutils.py:372 +#: emonitor/modules/alarms/alarmutils.py:387 msgid "alarms.print.straight" msgstr "weiterfahren" #: emonitor/modules/alarms/__init__.py:146 -#: emonitor/modules/alarms/alarmutils.py:320 -#: emonitor/modules/alarms/alarmutils.py:335 +#: emonitor/modules/alarms/alarmutils.py:372 +#: emonitor/modules/alarms/alarmutils.py:387 msgid "alarms.print.exit" msgstr "ausfahrt" #: emonitor/modules/alarms/__init__.py:147 -#: emonitor/modules/alarms/alarmutils.py:319 +#: emonitor/modules/alarms/alarmutils.py:371 msgid "alarms.print.bus" msgstr "bus" #: emonitor/modules/alarms/__init__.py:148 -#: emonitor/modules/alarms/alarmutils.py:337 +#: emonitor/modules/alarms/alarmutils.py:389 msgid "alarms.print.positive" msgstr "Fahrtrichtung SÜD" #: emonitor/modules/alarms/__init__.py:149 -#: emonitor/modules/alarms/alarmutils.py:338 +#: emonitor/modules/alarms/alarmutils.py:390 msgid "alarms.print.negative" msgstr "Fahrtrichtung NORD" @@ -1024,28 +1024,28 @@ msgstr "Uhrzeit" msgid "list" msgstr "" -#: emonitor/modules/alarms/alarmutils.py:329 -#: emonitor/modules/alarms/alarmutils.py:331 +#: emonitor/modules/alarms/alarmutils.py:381 +#: emonitor/modules/alarms/alarmutils.py:383 msgid "alarms.print.highwaylong" msgstr "Bundesautobahn" -#: emonitor/modules/alarms/alarmutils.py:331 +#: emonitor/modules/alarms/alarmutils.py:383 msgid "alarms.print.highwayshort" msgstr "A" -#: emonitor/modules/alarms/alarmutils.py:335 +#: emonitor/modules/alarms/alarmutils.py:387 msgid "alarms.print.exitstart" msgstr "Auf" -#: emonitor/modules/alarms/alarmutils.py:335 +#: emonitor/modules/alarms/alarmutils.py:387 msgid "alarms.print.straightexit" msgstr "nehmen" -#: emonitor/modules/alarms/content_admin.py:246 +#: emonitor/modules/alarms/content_admin.py:247 msgid "admin.alarms.checkernotvalid" msgstr "Datei nicht passend" -#: emonitor/modules/alarms/content_admin.py:313 +#: emonitor/modules/alarms/content_admin.py:335 msgid "admin.alarms.list" msgstr "Liste" @@ -1340,12 +1340,12 @@ msgid "alarms.type.delcheckerquestion" msgstr "Soll der gewählte Einsatztyp wirklich gelöscht werden?" #: emonitor/modules/alarms/templates/admin.alarms.type.html:24 -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:18 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:22 msgid "alarms.type.header.overview" msgstr "Einsatztypen" #: emonitor/modules/alarms/templates/admin.alarms.type.html:25 -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:19 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:23 msgid "alarms.type.info" msgstr "" "Anhand angegebener Stichworte kann die Faxerkennung für verschiedene Faxe " @@ -1354,12 +1354,12 @@ msgstr "" "Faxe können abhängig vom Einsatztyp definiert werden." #: emonitor/modules/alarms/templates/admin.alarms.type.html:30 -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:32 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:36 msgid "alarms.type.name" msgstr "Typname" #: emonitor/modules/alarms/templates/admin.alarms.type.html:31 -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:37 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:41 msgid "alarms.type.keywords" msgstr "Stichwörter" @@ -1453,31 +1453,37 @@ msgid "alarms.upload.checkerfile" msgstr "Interpreter-Datei hochladen" #: emonitor/modules/alarms/templates/admin.alarms.type.html:137 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:66 msgid "alarms.test.checkerstart" msgstr "Datei hochladen" -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:23 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:27 msgid "alarms.type.interpreter" msgstr "Interpreter/Auswerter" -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:42 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:46 msgid "alarms.type.variables" msgstr "Variablen" -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:43 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:47 msgid "alarms.type.variableinfo" msgstr "" "Für die automatische Faxauswertung werden einige Schlüsselworte verwendet, die " "als Variable definiert, für jeden Einsatztyp unterschiedlich heißen können." -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:49 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:53 msgid "alarms.type.save" msgstr "Speichern" -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:50 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:54 msgid "alarms.type.cancel" msgstr "Abbrechen" +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:62 +#, fuzzy +msgid "alarms.upload.definitionfile" +msgstr "Einsatz-Felddefinition" + #: emonitor/modules/alarms/templates/admin.alarms_alarm.html:13 #: emonitor/modules/alarms/templates/frontend.alarms_alarm.html:45 msgid "alarms.showfax" @@ -3836,9 +3842,8 @@ msgid "module.settings.cars" msgstr "Fahrzeuge/Material" #: emonitor/modules/settings/__init__.py:41 -#, fuzzy msgid "module.settings.communication" -msgstr "Fahrzeuge/Material" +msgstr "Messenger/Mail" #: emonitor/modules/settings/__init__.py:42 msgid "module.settings.start" @@ -3864,14 +3869,19 @@ msgstr "Pfad Eingang" msgid "departmentcrest" msgstr "Wappen" -#: emonitor/modules/settings/content_admin.py:168 +#: emonitor/modules/settings/__init__.py:50 +msgid "telegram.default.welcomemsg" +msgstr "" +"Hi {vorname} {nachname}\n" +"Du wurdest zum Telegram-Alarmgeber der Feuerwehr Haar hinzugefügt" + +#: emonitor/modules/settings/content_admin.py:183 msgid "admin.settings.updatedberror" msgstr "Aktualisierung fehlgeschlagen!" -#: emonitor/modules/settings/content_admin.py:176 -#, fuzzy +#: emonitor/modules/settings/content_admin.py:191 msgid "admin.settings.telegramtest.done" -msgstr "Aktualisierung fehlgeschlagen!" +msgstr "Telegram Mitteilung gesendet." #: emonitor/modules/settings/templates/admin.settings.cars.html:19 msgid "settings.cars.listtitle" @@ -3895,69 +3905,107 @@ msgstr "Hintergrundfarbe" msgid "settings.cars.save" msgstr "Speichern" -#: emonitor/modules/settings/templates/admin.settings.communication.html:28 -#, fuzzy -msgid "settings.communication.mail.title" -msgstr "Karte bearbeiten" - -#: emonitor/modules/settings/templates/admin.settings.communication.html:29 -#, fuzzy -msgid "settings.communication.mail.info" -msgstr "" -"Wenn für eine Kartenanzeige keine Koordinaten definiert worden sind, wird die " -"Standardposition verwendet. Richten Sie die Mitte der Karte auf den gewünschten " -"Punkt aus und bestätigen Sie mit 'Position speichern'." - -#: emonitor/modules/settings/templates/admin.settings.communication.html:31 -#, fuzzy -msgid "settings.communiaction.mail.server" -msgstr "Kartenserver" - -#: emonitor/modules/settings/templates/admin.settings.communication.html:34 -#: emonitor/modules/settings/templates/admin.settings.communication.html:55 -#: emonitor/modules/settings/templates/admin.settings.html:51 -#: emonitor/modules/settings/templates/admin.settings.html:62 -msgid "settings.save" -msgstr "Speichern" +#: emonitor/modules/settings/templates/admin.settings.communication.html:5 +msgid "settings.communication.telegram.groupname" +msgstr "Name" -#: emonitor/modules/settings/templates/admin.settings.communication.html:40 -#, fuzzy +#: emonitor/modules/settings/templates/admin.settings.communication.html:72 +#: emonitor/modules/settings/templates/admin.settings.communication.html:82 msgid "settings.communication.telegram.title" -msgstr "Karte löschen" +msgstr "Telegram Einstellungen" -#: emonitor/modules/settings/templates/admin.settings.communication.html:41 -#, fuzzy +#: emonitor/modules/settings/templates/admin.settings.communication.html:75 +#: emonitor/modules/settings/templates/admin.settings.communication.html:158 +msgid "settings.communication.mail.title" +msgstr "E-Mail Einstellungen" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:83 msgid "settings.communication.telegram.info" msgstr "" -"Der Kartenserver kann entweder ein lokaler Server sein oder online die Kacheln " -"laden.
Beispiele:
lokal: /tileserver/osm/{z}/{x}/{y}
Bing: //ak.t2.tiles.virtualearth.net/tiles/a{q}?g=1236
Google:" -" //khm2.googleapis.com/kh?v=142&x={x}&y={y}&z={z}" +"Der Telegram Messenger kann eingebunden werden. Dafür muss ein BOT in " +"Telegram erstellt werden, der Mitteilungen der Applikation übermitteln kann. " +"Jeder Bot besitzt eine Identifikations-Kennung, die gespeichert werden muss, um " +"eine Kommunikation zu starten." -#: emonitor/modules/settings/templates/admin.settings.communication.html:43 +#: emonitor/modules/settings/templates/admin.settings.communication.html:89 msgid "settings.communication.telegram.botname" -msgstr "" +msgstr "Telegram Bot Identifikator" -#: emonitor/modules/settings/templates/admin.settings.communication.html:50 +#: emonitor/modules/settings/templates/admin.settings.communication.html:96 msgid "settings.communication.telegram.boterror" msgstr "" +"Telegram Bot nicht verfügbar: Entweder steht das Python-Modul nicht zur " +"Verfügung oder der angegebene Bot-Schlüssel ist falsch" -#: emonitor/modules/settings/templates/admin.settings.communication.html:58 -#: emonitor/modules/settings/templates/admin.settings.communication.html:70 -msgid "settings.communication.telegram.testmessage" +#: emonitor/modules/settings/templates/admin.settings.communication.html:101 +msgid "settings.communication.telegram.welcometext" +msgstr "Bot Willkommensnachricht" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:103 +msgid "settings.communication.telegram.welcomeinfo" msgstr "" +"Der Text wird dem Benutzer geschickt, der sich am Bot anmeldet. Dabei können " +"folgende Variablen genutzt werden:
\n" +"- {vorname}
- {nachname}
- /hilfe" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:106 +msgid "settings.communication.telegram.helptext" +msgstr "Bot Hilfenachricht" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:109 +#: emonitor/modules/settings/templates/admin.settings.communication.html:150 +#: emonitor/modules/settings/templates/admin.settings.communication.html:164 +#: emonitor/modules/settings/templates/admin.settings.html:51 +#: emonitor/modules/settings/templates/admin.settings.html:62 +msgid "settings.save" +msgstr "Speichern" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:115 +msgid "settings.communication.telegram.testmessage" +msgstr "Telegram Testmitteilung senden" -#: emonitor/modules/settings/templates/admin.settings.communication.html:60 +#: emonitor/modules/settings/templates/admin.settings.communication.html:117 msgid "settings.communication.telegram.testuser" -msgstr "" +msgstr "Benutzer" -#: emonitor/modules/settings/templates/admin.settings.communication.html:62 +#: emonitor/modules/settings/templates/admin.settings.communication.html:119 msgid "settings.communication.telegram.userselection" -msgstr "" +msgstr "- Empfänger auswählen -" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:128 +msgid "settings.communication.telegram.testtext" +msgstr "Test-Mitteilung" -#: emonitor/modules/settings/templates/admin.settings.communication.html:73 +#: emonitor/modules/settings/templates/admin.settings.communication.html:132 msgid "settings.communication.telegram.sendtest" +msgstr "Testnachricht senden" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:141 +msgid "settings.communication.telegram.grouptitle" +msgstr "Telegram Gruppen" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:142 +msgid "settings.communication.telegram.groupinfo" +msgstr "" +"Es können beliebig viele Gruppen aus Telegram Benutzern gebildet werden, die " +"bei bestimmten Events benachrichtigt werden. Die Namen der Gruppen dürfen nur " +"aus Buchstaben ohne Leerzeichen bestehen. Gruppen können gelöscht werden, indem " +"der Name leer gelassen wird. Durch markieren der Namen in den Kästen wird der " +"Benutzer zur Gruppe hinzugefügt, grau hinterlegte Benutzer sind Mitglieder der " +"Gruppe." + +#: emonitor/modules/settings/templates/admin.settings.communication.html:159 +#, fuzzy +msgid "settings.communication.mail.info" msgstr "" +"Wenn für eine Kartenanzeige keine Koordinaten definiert worden sind, wird die " +"Standardposition verwendet. Richten Sie die Mitte der Karte auf den gewünschten " +"Punkt aus und bestätigen Sie mit 'Position speichern'." + +#: emonitor/modules/settings/templates/admin.settings.communication.html:161 +#, fuzzy +msgid "settings.communiaction.mail.server" +msgstr "Kartenserver" #: emonitor/modules/settings/templates/admin.settings.department.html:16 msgid "settings.department.listtitle" diff --git a/emonitor/modules/translations/modules.pot b/emonitor/modules/translations/modules.pot index e6191fc..7b76b28 100644 --- a/emonitor/modules/translations/modules.pot +++ b/emonitor/modules/translations/modules.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-05-04 20:12+0200\n" +"POT-Creation-Date: 2016-05-17 16:54+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -802,49 +802,49 @@ msgid "trigger.alarm_changestate_sub" msgstr "" #: emonitor/modules/alarms/__init__.py:141 -#: emonitor/modules/alarms/alarmutils.py:320 +#: emonitor/modules/alarms/alarmutils.py:372 msgid "alarms.print.slightleft" msgstr "" #: emonitor/modules/alarms/__init__.py:142 -#: emonitor/modules/alarms/alarmutils.py:320 +#: emonitor/modules/alarms/alarmutils.py:372 msgid "alarms.print.slightright" msgstr "" #: emonitor/modules/alarms/__init__.py:143 -#: emonitor/modules/alarms/alarmutils.py:320 +#: emonitor/modules/alarms/alarmutils.py:372 msgid "alarms.print.right" msgstr "" #: emonitor/modules/alarms/__init__.py:144 -#: emonitor/modules/alarms/alarmutils.py:320 +#: emonitor/modules/alarms/alarmutils.py:372 msgid "alarms.print.left" msgstr "" #: emonitor/modules/alarms/__init__.py:145 -#: emonitor/modules/alarms/alarmutils.py:320 -#: emonitor/modules/alarms/alarmutils.py:335 +#: emonitor/modules/alarms/alarmutils.py:372 +#: emonitor/modules/alarms/alarmutils.py:387 msgid "alarms.print.straight" msgstr "" #: emonitor/modules/alarms/__init__.py:146 -#: emonitor/modules/alarms/alarmutils.py:320 -#: emonitor/modules/alarms/alarmutils.py:335 +#: emonitor/modules/alarms/alarmutils.py:372 +#: emonitor/modules/alarms/alarmutils.py:387 msgid "alarms.print.exit" msgstr "" #: emonitor/modules/alarms/__init__.py:147 -#: emonitor/modules/alarms/alarmutils.py:319 +#: emonitor/modules/alarms/alarmutils.py:371 msgid "alarms.print.bus" msgstr "" #: emonitor/modules/alarms/__init__.py:148 -#: emonitor/modules/alarms/alarmutils.py:337 +#: emonitor/modules/alarms/alarmutils.py:389 msgid "alarms.print.positive" msgstr "" #: emonitor/modules/alarms/__init__.py:149 -#: emonitor/modules/alarms/alarmutils.py:338 +#: emonitor/modules/alarms/alarmutils.py:390 msgid "alarms.print.negative" msgstr "" @@ -993,28 +993,28 @@ msgstr "" msgid "list" msgstr "" -#: emonitor/modules/alarms/alarmutils.py:329 -#: emonitor/modules/alarms/alarmutils.py:331 +#: emonitor/modules/alarms/alarmutils.py:381 +#: emonitor/modules/alarms/alarmutils.py:383 msgid "alarms.print.highwaylong" msgstr "" -#: emonitor/modules/alarms/alarmutils.py:331 +#: emonitor/modules/alarms/alarmutils.py:383 msgid "alarms.print.highwayshort" msgstr "" -#: emonitor/modules/alarms/alarmutils.py:335 +#: emonitor/modules/alarms/alarmutils.py:387 msgid "alarms.print.exitstart" msgstr "" -#: emonitor/modules/alarms/alarmutils.py:335 +#: emonitor/modules/alarms/alarmutils.py:387 msgid "alarms.print.straightexit" msgstr "" -#: emonitor/modules/alarms/content_admin.py:246 +#: emonitor/modules/alarms/content_admin.py:247 msgid "admin.alarms.checkernotvalid" msgstr "" -#: emonitor/modules/alarms/content_admin.py:313 +#: emonitor/modules/alarms/content_admin.py:335 msgid "admin.alarms.list" msgstr "" @@ -1275,22 +1275,22 @@ msgid "alarms.type.delcheckerquestion" msgstr "" #: emonitor/modules/alarms/templates/admin.alarms.type.html:24 -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:18 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:22 msgid "alarms.type.header.overview" msgstr "" #: emonitor/modules/alarms/templates/admin.alarms.type.html:25 -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:19 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:23 msgid "alarms.type.info" msgstr "" #: emonitor/modules/alarms/templates/admin.alarms.type.html:30 -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:32 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:36 msgid "alarms.type.name" msgstr "" #: emonitor/modules/alarms/templates/admin.alarms.type.html:31 -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:37 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:41 msgid "alarms.type.keywords" msgstr "" @@ -1376,29 +1376,34 @@ msgid "alarms.upload.checkerfile" msgstr "" #: emonitor/modules/alarms/templates/admin.alarms.type.html:137 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:66 msgid "alarms.test.checkerstart" msgstr "" -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:23 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:27 msgid "alarms.type.interpreter" msgstr "" -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:42 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:46 msgid "alarms.type.variables" msgstr "" -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:43 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:47 msgid "alarms.type.variableinfo" msgstr "" -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:49 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:53 msgid "alarms.type.save" msgstr "" -#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:50 +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:54 msgid "alarms.type.cancel" msgstr "" +#: emonitor/modules/alarms/templates/admin.alarms.type_actions.html:62 +msgid "alarms.upload.definitionfile" +msgstr "" + #: emonitor/modules/alarms/templates/admin.alarms_alarm.html:13 #: emonitor/modules/alarms/templates/frontend.alarms_alarm.html:45 msgid "alarms.showfax" @@ -3646,11 +3651,15 @@ msgstr "" msgid "departmentcrest" msgstr "" -#: emonitor/modules/settings/content_admin.py:168 +#: emonitor/modules/settings/__init__.py:50 +msgid "telegram.default.welcomemsg" +msgstr "" + +#: emonitor/modules/settings/content_admin.py:183 msgid "admin.settings.updatedberror" msgstr "" -#: emonitor/modules/settings/content_admin.py:176 +#: emonitor/modules/settings/content_admin.py:191 msgid "admin.settings.telegramtest.done" msgstr "" @@ -3674,58 +3683,88 @@ msgstr "" msgid "settings.cars.save" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:28 +#: emonitor/modules/settings/templates/admin.settings.communication.html:5 +msgid "settings.communication.telegram.groupname" +msgstr "" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:72 +#: emonitor/modules/settings/templates/admin.settings.communication.html:82 +msgid "settings.communication.telegram.title" +msgstr "" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:75 +#: emonitor/modules/settings/templates/admin.settings.communication.html:158 msgid "settings.communication.mail.title" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:29 -msgid "settings.communication.mail.info" +#: emonitor/modules/settings/templates/admin.settings.communication.html:83 +msgid "settings.communication.telegram.info" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:31 -msgid "settings.communiaction.mail.server" +#: emonitor/modules/settings/templates/admin.settings.communication.html:89 +msgid "settings.communication.telegram.botname" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:34 -#: emonitor/modules/settings/templates/admin.settings.communication.html:55 -#: emonitor/modules/settings/templates/admin.settings.html:51 -#: emonitor/modules/settings/templates/admin.settings.html:62 -msgid "settings.save" +#: emonitor/modules/settings/templates/admin.settings.communication.html:96 +msgid "settings.communication.telegram.boterror" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:40 -msgid "settings.communication.telegram.title" +#: emonitor/modules/settings/templates/admin.settings.communication.html:101 +msgid "settings.communication.telegram.welcometext" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:41 -msgid "settings.communication.telegram.info" +#: emonitor/modules/settings/templates/admin.settings.communication.html:103 +msgid "settings.communication.telegram.welcomeinfo" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:43 -msgid "settings.communication.telegram.botname" +#: emonitor/modules/settings/templates/admin.settings.communication.html:106 +msgid "settings.communication.telegram.helptext" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:50 -msgid "settings.communication.telegram.boterror" +#: emonitor/modules/settings/templates/admin.settings.communication.html:109 +#: emonitor/modules/settings/templates/admin.settings.communication.html:150 +#: emonitor/modules/settings/templates/admin.settings.communication.html:164 +#: emonitor/modules/settings/templates/admin.settings.html:51 +#: emonitor/modules/settings/templates/admin.settings.html:62 +msgid "settings.save" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:58 -#: emonitor/modules/settings/templates/admin.settings.communication.html:70 +#: emonitor/modules/settings/templates/admin.settings.communication.html:115 msgid "settings.communication.telegram.testmessage" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:60 +#: emonitor/modules/settings/templates/admin.settings.communication.html:117 msgid "settings.communication.telegram.testuser" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:62 +#: emonitor/modules/settings/templates/admin.settings.communication.html:119 msgid "settings.communication.telegram.userselection" msgstr "" -#: emonitor/modules/settings/templates/admin.settings.communication.html:73 +#: emonitor/modules/settings/templates/admin.settings.communication.html:128 +msgid "settings.communication.telegram.testtext" +msgstr "" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:132 msgid "settings.communication.telegram.sendtest" msgstr "" +#: emonitor/modules/settings/templates/admin.settings.communication.html:141 +msgid "settings.communication.telegram.grouptitle" +msgstr "" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:142 +msgid "settings.communication.telegram.groupinfo" +msgstr "" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:159 +msgid "settings.communication.mail.info" +msgstr "" + +#: emonitor/modules/settings/templates/admin.settings.communication.html:161 +msgid "settings.communiaction.mail.server" +msgstr "" + #: emonitor/modules/settings/templates/admin.settings.department.html:16 msgid "settings.department.listtitle" msgstr ""