lws: sms page rewrite
This commit is contained in:
parent
a9a241ad19
commit
d237e81873
@ -5,6 +5,7 @@ import aiohttp_jinja2
|
||||
import json
|
||||
import re
|
||||
import inverterd
|
||||
import phonenumbers
|
||||
import __py_include
|
||||
|
||||
from io import StringIO
|
||||
@ -27,6 +28,8 @@ class WebKbnConfig(AppConfigUnit):
|
||||
'listen_addr': cls._addr_schema(required=True),
|
||||
'assets_public_path': {'type': 'string'},
|
||||
'pump_addr': cls._addr_schema(required=True),
|
||||
'inverter_grafana_url': {'type': 'string'},
|
||||
'sensors_grafana_url': {'type': 'string'},
|
||||
}
|
||||
|
||||
|
||||
@ -69,8 +72,12 @@ def get_head_static() -> str:
|
||||
return buf.getvalue()
|
||||
|
||||
|
||||
def get_modem_client(modem_cfg: dict) -> E3372:
|
||||
return E3372(modem_cfg['ip'], legacy_token_auth=modem_cfg['legacy_auth'])
|
||||
|
||||
|
||||
def get_modem_data(modem_cfg: dict, get_raw=False) -> Union[dict, tuple]:
|
||||
cl = E3372(modem_cfg['ip'], legacy_token_auth=modem_cfg['legacy_auth'])
|
||||
cl = get_modem_client(modem_cfg)
|
||||
|
||||
signal = cl.device_signal
|
||||
status = cl.monitoring_status
|
||||
@ -190,6 +197,8 @@ class WebSite(http.HTTPServer):
|
||||
self.get('/inverter.cgi', self.inverter)
|
||||
self.get('/inverter.ajx', self.inverter_ajx)
|
||||
self.get('/pump.cgi', self.pump)
|
||||
self.get('/sms.cgi', self.sms)
|
||||
self.post('/sms.cgi', self.sms_post)
|
||||
|
||||
async def render_page(self,
|
||||
req: http.Request,
|
||||
@ -208,8 +217,12 @@ class WebSite(http.HTTPServer):
|
||||
return response
|
||||
|
||||
async def index(self, req: http.Request):
|
||||
ctx = {}
|
||||
for k in 'inverter', 'sensors':
|
||||
ctx[f'{k}_grafana_url'] = config.app_config[f'{k}_grafana_url']
|
||||
return await self.render_page(req, 'index',
|
||||
title="Home web site")
|
||||
title="Home web site",
|
||||
context=ctx)
|
||||
|
||||
async def modems(self, req: http.Request):
|
||||
return await self.render_page(req, 'modems',
|
||||
@ -218,7 +231,7 @@ class WebSite(http.HTTPServer):
|
||||
|
||||
async def modems_ajx(self, req: http.Request):
|
||||
modem = req.query.get('id', None)
|
||||
if modem not in self._modems_config.getkeys():
|
||||
if modem not in self._modems_config.keys():
|
||||
raise ValueError('invalid modem id')
|
||||
|
||||
modem_cfg = self._modems_config.get(modem)
|
||||
@ -234,7 +247,7 @@ class WebSite(http.HTTPServer):
|
||||
|
||||
async def modems_verbose(self, req: http.Request):
|
||||
modem = req.query.get('id', None)
|
||||
if modem not in self._modems_config.getkeys():
|
||||
if modem not in self._modems_config.keys():
|
||||
raise ValueError('invalid modem id')
|
||||
|
||||
modem_cfg = self._modems_config.get(modem)
|
||||
@ -253,6 +266,49 @@ class WebSite(http.HTTPServer):
|
||||
title=f'Подробная информация о модеме "{modem_name}"',
|
||||
context=dict(data=data, modem_name=modem_name))
|
||||
|
||||
async def sms(self, req: http.Request):
|
||||
modem = req.query.get('id', list(self._modems_config.keys())[0])
|
||||
is_outbox = int(req.query.get('outbox', 0)) == 1
|
||||
error = req.query.get('error', None)
|
||||
sent = int(req.query.get('sent', 0)) == 1
|
||||
|
||||
cl = get_modem_client(self._modems_config[modem])
|
||||
messages = cl.sms_list(1, 20, is_outbox)
|
||||
return await self.render_page(req, 'sms',
|
||||
title=f"SMS-сообщения ({'исходящие' if is_outbox else 'входящие'}, {modem})",
|
||||
context=dict(
|
||||
modems=self._modems_config,
|
||||
selected_modem=modem,
|
||||
is_outbox=is_outbox,
|
||||
error=error,
|
||||
is_sent=sent,
|
||||
messages=messages
|
||||
))
|
||||
|
||||
async def sms_post(self, req: http.Request):
|
||||
modem = req.query.get('id', list(self._modems_config.keys())[0])
|
||||
is_outbox = int(req.query.get('outbox', 0)) == 1
|
||||
|
||||
fd = await req.post()
|
||||
phone = fd.get('phone', None)
|
||||
text = fd.get('text', None)
|
||||
|
||||
return_url = f'/sms.cgi?id={modem}&outbox={int(is_outbox)}'
|
||||
phone = re.sub('\s+', '', phone)
|
||||
|
||||
if len(phone) > 4:
|
||||
country = None
|
||||
if not phone.startswith('+'):
|
||||
country = 'RU'
|
||||
number = phonenumbers.parse(phone, country)
|
||||
if not phonenumbers.is_valid_number(number):
|
||||
raise HTTPFound(f'{return_url}&error=Неверный+номер')
|
||||
phone = phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164)
|
||||
|
||||
cl = get_modem_client(self._modems_config[modem])
|
||||
cl.sms_send(phone, text)
|
||||
raise HTTPFound(return_url)
|
||||
|
||||
async def inverter(self, req: http.Request):
|
||||
action = req.query.get('do', None)
|
||||
if action == 'set-osp':
|
||||
|
@ -78,8 +78,14 @@ class BaseConfigUnit(ABC):
|
||||
|
||||
raise KeyError(f'option {key} not found')
|
||||
|
||||
def getkeys(self):
|
||||
return list(self._data.keys())
|
||||
def values(self):
|
||||
return self._data.values()
|
||||
|
||||
def keys(self):
|
||||
return self._data.keys()
|
||||
|
||||
def items(self):
|
||||
return self._data.items()
|
||||
|
||||
|
||||
class ConfigUnit(BaseConfigUnit):
|
||||
|
@ -95,85 +95,6 @@ class ModemHandler extends RequestHandler
|
||||
$this->tpl->render_page('routing_dhcp_page.twig');
|
||||
}
|
||||
|
||||
public function GET_sms() {
|
||||
global $config;
|
||||
|
||||
list($selected, $is_outbox, $error, $sent) = $this->input('modem, b:outbox, error, b:sent');
|
||||
if (!$selected)
|
||||
$selected = array_key_first($config['modems']);
|
||||
|
||||
$cfg = $config['modems'][$selected];
|
||||
$e3372 = new E3372($cfg['ip'], $cfg['legacy_token_auth']);
|
||||
$messages = $e3372->getSMSList(1, 20, $is_outbox);
|
||||
|
||||
$this->tpl->set([
|
||||
'modems_list' => array_keys($config['modems']),
|
||||
'modems' => $config['modems'],
|
||||
'selected_modem' => $selected,
|
||||
'messages' => $messages,
|
||||
'is_outbox' => $is_outbox,
|
||||
'error' => $error,
|
||||
'is_sent' => $sent
|
||||
]);
|
||||
|
||||
$direction = $is_outbox ? 'исходящие' : 'входящие';
|
||||
$this->tpl->set_title('SMS-сообщения ('.$direction.', '.$selected.')');
|
||||
$this->tpl->render_page('sms_page.twig');
|
||||
}
|
||||
|
||||
public function POST_sms() {
|
||||
global $config;
|
||||
|
||||
list($selected, $is_outbox, $phone, $text) = $this->input('modem, b:outbox, phone, text');
|
||||
if (!$selected)
|
||||
$selected = array_key_first($config['modems']);
|
||||
|
||||
$return_url = '/sms/?modem='.$selected;
|
||||
if ($is_outbox)
|
||||
$return_url .= '&outbox=1';
|
||||
|
||||
$go_back = function(?string $error = null) use ($return_url) {
|
||||
if (!is_null($error))
|
||||
$return_url .= '&error='.urlencode($error);
|
||||
else
|
||||
$return_url .= '&sent=1';
|
||||
redirect($return_url);
|
||||
};
|
||||
|
||||
$phone = preg_replace('/\s+/', '', $phone);
|
||||
|
||||
// при отправке смс на короткие номера не надо использовать libphonenumber и вот это вот всё
|
||||
if (strlen($phone) > 4) {
|
||||
$country = null;
|
||||
if (!startsWith($phone, '+'))
|
||||
$country = 'RU';
|
||||
|
||||
$phoneUtil = PhoneNumberUtil::getInstance();
|
||||
try {
|
||||
$number = $phoneUtil->parse($phone, $country);
|
||||
} catch (NumberParseException $e) {
|
||||
debugError(__METHOD__.': failed to parse number '.$phone.': '.$e->getMessage());
|
||||
$go_back('Неверный номер ('.$e->getMessage().')');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$phoneUtil->isValidNumber($number)) {
|
||||
$go_back('Неверный номер');
|
||||
return;
|
||||
}
|
||||
|
||||
$phone = $phoneUtil->format($number, PhoneNumberFormat::E164);
|
||||
}
|
||||
|
||||
$cfg = $config['modems'][$selected];
|
||||
$e3372 = new E3372($cfg['ip'], $cfg['legacy_token_auth']);
|
||||
|
||||
$result = $e3372->sendSMS($phone, $text);
|
||||
debugLog($result);
|
||||
|
||||
$go_back();
|
||||
}
|
||||
|
||||
protected static function getCurrentUpstream() {
|
||||
global $config;
|
||||
|
||||
|
@ -14,6 +14,7 @@ psutil~=5.9.1
|
||||
aioshutil~=1.1
|
||||
scikit-image==0.21.0
|
||||
cerberus~=1.3.4
|
||||
phonenumbers~=8.13.28
|
||||
# following can be installed from debian repositories
|
||||
# matplotlib~=3.5.0
|
||||
|
||||
|
@ -23,9 +23,9 @@
|
||||
|
||||
<h6 class="mt-4">Другое</h6>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item"><a href="/inverter.cgi">Инвертор</a> (<a href="{{ grafana_inverter_url }}">Grafana</a>)</li>
|
||||
<li class="list-group-item"><a href="/inverter.cgi">Инвертор</a> (<a href="{{ inverter_grafana_url }}">Grafana</a>)</li>
|
||||
<li class="list-group-item"><a href="/pump.cgi">Насос</a></li>
|
||||
<li class="list-group-item"><a href="/sensors.cgi">Датчики</a> (<a href="{{ grafana_sensors_url }}">Grafana</a>)</li>
|
||||
<li class="list-group-item"><a href="/sensors.cgi">Датчики</a> (<a href="{{ sensors_grafana_url }}">Grafana</a>)</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="mt-4"><a href="/cams/"><b>Все камеры</b></a> (<a href="/cams/?high=1">HQ</a>)</h6>
|
||||
|
@ -1,14 +1,13 @@
|
||||
{% include 'bc.twig' with {
|
||||
history: [
|
||||
{text: "SMS-сообщения" }
|
||||
]
|
||||
} %}
|
||||
{% extends "base.j2" %}
|
||||
|
||||
{% block content %}
|
||||
{{ breadcrumbs([{'text': 'SMS-сообщения'}]) }}
|
||||
|
||||
<nav>
|
||||
<div class="nav nav-tabs" id="nav-tab">
|
||||
{% for modem in modems_list %}
|
||||
{% if selected_modem != modem %}<a href="/sms/?modem={{ modem }}" class="text-decoration-none">{% endif %}
|
||||
<button class="nav-link{% if modem == selected_modem %} active{% endif %}" type="button">{{ modems[modem].short_label }}</button>
|
||||
{% for modem in modems.keys() %}
|
||||
{% if selected_modem != modem %}<a href="/sms.cgi?id={{ modem }}" class="text-decoration-none">{% endif %}
|
||||
<button class="nav-link{% if modem == selected_modem %} active{% endif %}" type="button">{{ modems.getshortname(modem) }}</button>
|
||||
{% if selected_modem != modem %}</a>{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
@ -20,14 +19,14 @@
|
||||
<div class="alert alert-success" role="alert">
|
||||
Сообщение отправлено.
|
||||
</div>
|
||||
{% elseif error %}
|
||||
{% elif error %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
<form method="post" action="/sms/">
|
||||
<form method="post" action="/sms.cgi">
|
||||
<input type="hidden" name="modem" value="{{ selected_modem }}">
|
||||
<div class="form-floating mb-3">
|
||||
<input type="text" name="phone" class="form-control" id="inputPhone" placeholder="+7911xxxyyzz">
|
||||
@ -46,17 +45,19 @@
|
||||
<h6 class="text-primary mt-4">
|
||||
Последние
|
||||
{% if not is_outbox %}
|
||||
<b>входящие</b> <span class="text-black-50">|</span> <a href="/sms/?modem={{ selected_modem }}&outbox=1">исходящие</a>
|
||||
<b>входящие</b> <span class="text-black-50">|</span> <a href="/sms.cgi?id={{ selected_modem }}&outbox=1">исходящие</a>
|
||||
{% else %}
|
||||
<a href="/sms/?modem={{ selected_modem }}">входящие</a> <span class="text-black-50">|</span> <b>исходящие</b>
|
||||
<a href="/sms.cgi?id={{ selected_modem }}">входящие</a> <span class="text-black-50">|</span> <b>исходящие</b>
|
||||
{% endif %}
|
||||
</h6>
|
||||
|
||||
{% for m in messages %}
|
||||
<div class="mt-3">
|
||||
<b>{{ m.phone }}</b> <span class="text-secondary">({{ m.date }})</span><br/>
|
||||
{{ m.content }}
|
||||
<b>{{ m.Phone }}</b> <span class="text-secondary">({{ m.Date }})</span><br/>
|
||||
{{ m.Content }}
|
||||
</div>
|
||||
{% else %}
|
||||
<span class="text-secondary">Сообщений нет.</span>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user