summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/vk_sms_checker.py75
-rw-r--r--include/py/homekit/database/__init__.py10
-rw-r--r--include/py/homekit/database/__init__.pyi4
-rw-r--r--include/py/homekit/database/bots.py5
-rw-r--r--include/py/homekit/database/mysql.py77
-rw-r--r--include/py/homekit/modem/e3372.py20
-rw-r--r--include/py/homekit/telegram/telegram.py2
-rw-r--r--localwebsite/classes/TelegramBotClient.php37
-rw-r--r--localwebsite/composer.json16
-rw-r--r--localwebsite/composer.lock341
-rw-r--r--localwebsite/config.php95
-rwxr-xr-xlocalwebsite/cron/check-vk-sms.php44
-rw-r--r--localwebsite/engine/database.php131
-rw-r--r--localwebsite/functions.php300
-rw-r--r--localwebsite/init.php71
-rwxr-xr-xlocalwebsite/utils.php66
16 files changed, 151 insertions, 1143 deletions
diff --git a/bin/vk_sms_checker.py b/bin/vk_sms_checker.py
new file mode 100755
index 0000000..07d9953
--- /dev/null
+++ b/bin/vk_sms_checker.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+import __py_include
+import re
+
+from html import escape
+from typing import Optional
+from homekit.config import AppConfigUnit, config
+from homekit.modem import ModemsConfig, E3372
+from homekit.database import MySQLHomeDatabase
+from homekit.telegram import send_message
+
+db: Optional[MySQLHomeDatabase] = None
+
+
+class VkSmsCheckerConfig(AppConfigUnit):
+ NAME = 'vk_sms_checker'
+
+ @classmethod
+ def schema(cls) -> Optional[dict]:
+ return {
+ 'modem': {'type': 'string', 'required': True}
+ }
+
+ @staticmethod
+ def custom_validator(data):
+ if data['modem'] not in ModemsConfig():
+ raise ValueError('invalid modem')
+
+
+def get_last_time() -> int:
+ cur = db.cursor()
+ cur.execute("SELECT last_message_time FROM vk_sms LIMIT 1")
+ return int(cur.fetchone()[0])
+
+
+def set_last_time(timestamp: int) -> None:
+ cur = db.cursor()
+ cur.execute("UPDATE vk_sms SET last_message_time=%s", (timestamp,))
+ db.commit()
+
+
+def check_sms():
+ modem = ModemsConfig()[config.app_config['modem']]
+ cl = E3372(modem['ip'], legacy_token_auth=modem['legacy_auth'])
+ messages = cl.sms_list()
+ messages.reverse()
+
+ last_time = get_last_time()
+ new_last_time = None
+ results = []
+
+ if not messages:
+ return
+
+ for m in messages:
+ if m['UnixTime'] <= last_time:
+ continue
+ new_last_time = m['UnixTime']
+ if re.match(r'^vk', m['Phone'], flags=re.IGNORECASE) or re.match(r'vk', m['Content'], flags=re.IGNORECASE):
+ results.append(m)
+
+ if results:
+ for m in results:
+ text = '<b>'+escape(m['Phone'])+'</b> ('+m['Date']+')'
+ text += "\n"+escape(m['Content'])
+ send_message(text=text, chat='vk_sms_checker')
+
+ if new_last_time:
+ set_last_time(new_last_time)
+
+
+if __name__ == '__main__':
+ db = MySQLHomeDatabase()
+ config.load_app(VkSmsCheckerConfig)
+ check_sms() \ No newline at end of file
diff --git a/include/py/homekit/database/__init__.py b/include/py/homekit/database/__init__.py
index b50cbce..c958959 100644
--- a/include/py/homekit/database/__init__.py
+++ b/include/py/homekit/database/__init__.py
@@ -6,6 +6,7 @@ __all__ = [
'get_clickhouse',
'SimpleState',
+ 'MySQLHomeDatabase',
'SensorsDatabase',
'InverterDatabase',
'BotsDatabase'
@@ -14,12 +15,13 @@ __all__ = [
def __getattr__(name: str):
if name in __all__:
- if name.endswith('Database'):
- file = name[:-8].lower()
- elif 'mysql' in name:
+ ln = name.lower()
+ if 'mysql' in ln:
file = 'mysql'
- elif 'clickhouse' in name:
+ elif 'clickhouse' in ln:
file = 'clickhouse'
+ elif name.endswith('Database'):
+ file = name[:-8].lower()
else:
file = 'simple_state'
diff --git a/include/py/homekit/database/__init__.pyi b/include/py/homekit/database/__init__.pyi
index 31aae5d..3c057dc 100644
--- a/include/py/homekit/database/__init__.pyi
+++ b/include/py/homekit/database/__init__.pyi
@@ -1,6 +1,6 @@
from .mysql import (
- get_mysql as get_mysql,
- mysql_now as mysql_now
+ mysql_now as mysql_now,
+ MySQLHomeDatabase as MySQLHomeDatabase
)
from .clickhouse import get_clickhouse as get_clickhouse
diff --git a/include/py/homekit/database/bots.py b/include/py/homekit/database/bots.py
index fb5f326..fae8fb6 100644
--- a/include/py/homekit/database/bots.py
+++ b/include/py/homekit/database/bots.py
@@ -1,6 +1,6 @@
import pytz
-from .mysql import mysql_now, MySQLDatabase, datetime_fmt
+from .mysql import mysql_now, MySQLDatabase, datetime_fmt, MySQLCredsConfig, MySQLCloudCredsConfig
from ..api.types import (
SoundSensorLocation
)
@@ -26,6 +26,9 @@ class OpenwrtLogRecord:
class BotsDatabase(MySQLDatabase):
+ def creds(self) -> MySQLCredsConfig:
+ return MySQLCloudCredsConfig()
+
def add_openwrt_logs(self,
lines: List[Tuple[datetime, str]],
access_point: int):
diff --git a/include/py/homekit/database/mysql.py b/include/py/homekit/database/mysql.py
index fe97cd4..a0b73fa 100644
--- a/include/py/homekit/database/mysql.py
+++ b/include/py/homekit/database/mysql.py
@@ -1,47 +1,74 @@
import time
import logging
+from abc import ABC, abstractmethod
from mysql.connector import connect, MySQLConnection, Error
from typing import Optional
-from ..config import config
+from ..config import ConfigUnit
-link: Optional[MySQLConnection] = None
logger = logging.getLogger(__name__)
-
datetime_fmt = '%Y-%m-%d %H:%M:%S'
-def get_mysql() -> MySQLConnection:
- global link
+class MySQLCredsConfig(ConfigUnit, ABC):
+ @classmethod
+ def schema(cls) -> Optional[dict]:
+ schema = {}
+ for k in ('host', 'database', 'user', 'password'):
+ schema[k] = dict(type='string', required=True)
+ return schema
+
- if link is not None:
- return link
+class MySQLHomeCredsConfig(MySQLCredsConfig):
+ NAME = 'mysql_home_creds'
- link = connect(
- host=config['mysql']['host'],
- user=config['mysql']['user'],
- password=config['mysql']['password'],
- database=config['mysql']['database'],
- )
- link.time_zone = '+01:00'
- return link
+
+class MySQLCloudCredsConfig(MySQLCredsConfig):
+ NAME = 'mysql_cloud_creds'
def mysql_now() -> str:
return time.strftime('%Y-%m-%d %H:%M:%S')
-class MySQLDatabase:
- def __init__(self):
- self.db = get_mysql()
+class MySQLDatabase(ABC):
+ _enable_pings: bool
+ _link: MySQLConnection
+ _time_zone: Optional[str]
+
+ @abstractmethod
+ def creds(self) -> MySQLCredsConfig:
+ pass
+
+ def __init__(self, enable_pings=False, time_zone='+01:00'):
+ self._enable_pings = enable_pings
+ self._time_zone = time_zone
+ self._connect()
+
+ def _connect(self):
+ c = self.creds()
+ self._link = connect(
+ host=c['host'],
+ user=c['user'],
+ password=c['password'],
+ database=c['database'],
+ )
+ if self._time_zone:
+ self._link.time_zone = self._time_zone
def cursor(self, **kwargs):
- try:
- self.db.ping(reconnect=True, attempts=2)
- except Error as e:
- logger.exception(e)
- self.db = get_mysql()
- return self.db.cursor(**kwargs)
+ if self._enable_pings:
+ try:
+ self._link.ping(reconnect=True, attempts=2)
+ except Error as e:
+ logger.exception(e)
+ self._connect()
+ return self._link.cursor(**kwargs)
def commit(self):
- self.db.commit()
+ self._link.commit()
+
+
+class MySQLHomeDatabase(MySQLDatabase):
+ def creds(self) -> MySQLCredsConfig:
+ return MySQLHomeCredsConfig() \ No newline at end of file
diff --git a/include/py/homekit/modem/e3372.py b/include/py/homekit/modem/e3372.py
index f68db5a..8164b88 100644
--- a/include/py/homekit/modem/e3372.py
+++ b/include/py/homekit/modem/e3372.py
@@ -1,6 +1,7 @@
import requests
import xml.etree.ElementTree as ElementTree
+from datetime import datetime
from ..util import Addr
from enum import Enum
from ..http import HTTPMethod
@@ -21,14 +22,14 @@ class Error(Enum):
ERROR_WRONG_TOKEN = 125001
ERROR_WRONG_SESSION = 125002
ERROR_WRONG_SESSION_TOKEN = 125003
-
-
+
+
class WifiStatus(Enum):
WIFI_CONNECTING = '900'
WIFI_CONNECTED = '901'
WIFI_DISCONNECTED = '902'
WIFI_DISCONNECTING = '903'
-
+
class Cradle(Enum):
CRADLE_CONNECTING = '900'
@@ -38,8 +39,8 @@ class Cradle(Enum):
CRADLE_CONNECTFAILED = '904'
CRADLE_CONNECTSTATUSNULL = '905'
CRANDLE_CONNECTSTATUSERRO = '906'
-
-
+
+
class MacroEVDOLevel(Enum):
MACRO_EVDO_LEVEL_ZERO = '0'
MACRO_EVDO_LEVEL_ONE = '1'
@@ -47,8 +48,8 @@ class MacroEVDOLevel(Enum):
MACRO_EVDO_LEVEL_THREE = '3'
MACRO_EVDO_LEVEL_FOUR = '4'
MACRO_EVDO_LEVEL_FIVE = '5'
-
-
+
+
class MacroNetWorkType(Enum):
MACRO_NET_WORK_TYPE_NOSERVICE = 0
MACRO_NET_WORK_TYPE_GSM = 1
@@ -127,7 +128,7 @@ class E3372:
_get_raw_data: bool
_headers: dict[str, str]
_authorized: bool
-
+
def __init__(self,
addr: Addr,
need_auth: bool = True,
@@ -174,7 +175,7 @@ class E3372:
def sms_count(self):
self.auth()
return self.request('sms/sms-count')
-
+
def sms_send(self, phone: str, text: str):
self.auth()
return self.request('sms/send-sms', HTTPMethod.POST, {
@@ -204,6 +205,7 @@ class E3372:
messages = []
for message_elem in root.find('Messages').findall('Message'):
message_dict = {child.tag: child.text for child in message_elem}
+ message_dict['UnixTime'] = int(datetime.strptime(message_dict['Date'], '%Y-%m-%d %H:%M:%S').timestamp())
messages.append(message_dict)
return messages
diff --git a/include/py/homekit/telegram/telegram.py b/include/py/homekit/telegram/telegram.py
index f42363e..7d7471b 100644
--- a/include/py/homekit/telegram/telegram.py
+++ b/include/py/homekit/telegram/telegram.py
@@ -11,7 +11,7 @@ _logger = logging.getLogger(__name__)
def send_message(text: str,
chat: str,
parse_mode: str = 'HTML',
- disable_web_page_preview: bool = False,):
+ disable_web_page_preview: bool = False):
data, token = _send_telegram_data(text, chat, parse_mode, disable_web_page_preview)
req = requests.post('https://api.telegram.org/bot%s/sendMessage' % token, data=data)
return req.json()
diff --git a/localwebsite/classes/TelegramBotClient.php b/localwebsite/classes/TelegramBotClient.php
deleted file mode 100644
index b9583ee..0000000
--- a/localwebsite/classes/TelegramBotClient.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-class TelegramBotClient {
-
- protected string $token;
-
- public function __construct(string $token) {
- $this->token = $token;
- }
-
- public function sendMessage(int $chat_id, string $text): bool {
- $ch = curl_init();
- $url = 'https://api.telegram.org/bot'.$this->token.'/sendMessage';
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_POST, true);
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
- curl_setopt($ch, CURLOPT_TIMEOUT, 10);
- curl_setopt($ch, CURLOPT_POSTFIELDS, [
- 'chat_id' => $chat_id,
- 'text' => $text,
- 'parse_mode' => 'html',
- 'disable_web_page_preview' => 1
- ]);
- $body = curl_exec($ch);
- curl_close($ch);
-
- $resp = jsonDecode($body);
- if (!$resp['ok']) {
- debugError(__METHOD__ . ': ' . $body);
- return false;
- }
-
- return true;
- }
-
-} \ No newline at end of file
diff --git a/localwebsite/composer.json b/localwebsite/composer.json
deleted file mode 100644
index 15ba2e5..0000000
--- a/localwebsite/composer.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "name": "ch1p/localwebsite.homekit",
- "type": "project",
- "require": {
- "twig/twig": "^3.3",
- "ext-mbstring": "*",
- "ext-sockets": "*",
- "ext-simplexml": "*",
- "ext-curl": "*",
- "ext-json": "*",
- "ext-gmp": "*",
- "ext-sqlite3": "*",
- "giggsey/libphonenumber-for-php": "^8.12"
- },
- "license": "MIT"
-}
diff --git a/localwebsite/composer.lock b/localwebsite/composer.lock
deleted file mode 100644
index c09f57d..0000000
--- a/localwebsite/composer.lock
+++ /dev/null
@@ -1,341 +0,0 @@
-{
- "_readme": [
- "This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
- "This file is @generated automatically"
- ],
- "content-hash": "aad58d1c2f9900517de6f62599845b12",
- "packages": [
- {
- "name": "giggsey/libphonenumber-for-php",
- "version": "8.12.51",
- "source": {
- "type": "git",
- "url": "https://github.com/giggsey/libphonenumber-for-php.git",
- "reference": "a42d89a46797083a95aa48393485fdac22fcac94"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/a42d89a46797083a95aa48393485fdac22fcac94",
- "reference": "a42d89a46797083a95aa48393485fdac22fcac94",
- "shasum": ""
- },
- "require": {
- "giggsey/locale": "^1.7|^2.0",
- "php": ">=5.3.2",
- "symfony/polyfill-mbstring": "^1.17"
- },
- "require-dev": {
- "pear/pear-core-minimal": "^1.9",
- "pear/pear_exception": "^1.0",
- "pear/versioncontrol_git": "^0.5",
- "phing/phing": "^2.7",
- "php-coveralls/php-coveralls": "^1.0|^2.0",
- "symfony/console": "^2.8|^3.0|^v4.4|^v5.2",
- "symfony/phpunit-bridge": "^4.2 || ^5"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "8.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "libphonenumber\\": "src/"
- },
- "exclude-from-classmap": [
- "/src/data/",
- "/src/carrier/data/",
- "/src/geocoding/data/",
- "/src/timezone/data/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "Apache-2.0"
- ],
- "authors": [
- {
- "name": "Joshua Gigg",
- "email": "giggsey@gmail.com",
- "homepage": "https://giggsey.com/"
- }
- ],
- "description": "PHP Port of Google's libphonenumber",
- "homepage": "https://github.com/giggsey/libphonenumber-for-php",
- "keywords": [
- "geocoding",
- "geolocation",
- "libphonenumber",
- "mobile",
- "phonenumber",
- "validation"
- ],
- "support": {
- "irc": "irc://irc.appliedirc.com/lobby",
- "issues": "https://github.com/giggsey/libphonenumber-for-php/issues",
- "source": "https://github.com/giggsey/libphonenumber-for-php"
- },
- "time": "2022-07-11T08:12:34+00:00"
- },
- {
- "name": "giggsey/locale",
- "version": "2.2",
- "source": {
- "type": "git",
- "url": "https://github.com/giggsey/Locale.git",
- "reference": "9c1dca769253f6a3e81f9a5c167f53b6a54ab635"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/giggsey/Locale/zipball/9c1dca769253f6a3e81f9a5c167f53b6a54ab635",
- "reference": "9c1dca769253f6a3e81f9a5c167f53b6a54ab635",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2"
- },
- "require-dev": {
- "ext-json": "*",
- "pear/pear-core-minimal": "^1.9",
- "pear/pear_exception": "^1.0",
- "pear/versioncontrol_git": "^0.5",
- "phing/phing": "^2.7",
- "php-coveralls/php-coveralls": "^2.0",
- "phpunit/phpunit": "^8.5|^9.5",
- "symfony/console": "^5.0",
- "symfony/filesystem": "^5.0",
- "symfony/finder": "^5.0",
- "symfony/process": "^5.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Giggsey\\Locale\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Joshua Gigg",
- "email": "giggsey@gmail.com",
- "homepage": "https://giggsey.com/"
- }
- ],
- "description": "Locale functions required by libphonenumber-for-php",
- "support": {
- "issues": "https://github.com/giggsey/Locale/issues",
- "source": "https://github.com/giggsey/Locale/tree/2.2"
- },
- "time": "2022-04-06T07:33:59+00:00"
- },
- {
- "name": "symfony/polyfill-ctype",
- "version": "v1.23.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
- "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "suggest": {
- "ext-ctype": "For best performance"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "1.23-dev"
- },
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Polyfill\\Ctype\\": ""
- },
- "files": [
- "bootstrap.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Gert de Pagter",
- "email": "BackEndTea@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for ctype functions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "ctype",
- "polyfill",
- "portable"
- ],
- "time": "2021-02-19T12:13:01+00:00"
- },
- {
- "name": "symfony/polyfill-mbstring",
- "version": "v1.23.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
- "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "suggest": {
- "ext-mbstring": "For best performance"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "1.23-dev"
- },
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Polyfill\\Mbstring\\": ""
- },
- "files": [
- "bootstrap.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for the Mbstring extension",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "mbstring",
- "polyfill",
- "portable",
- "shim"
- ],
- "time": "2021-05-27T09:27:20+00:00"
- },
- {
- "name": "twig/twig",
- "version": "v3.3.2",
- "source": {
- "type": "git",
- "url": "https://github.com/twigphp/Twig.git",
- "reference": "21578f00e83d4a82ecfa3d50752b609f13de6790"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/21578f00e83d4a82ecfa3d50752b609f13de6790",
- "reference": "21578f00e83d4a82ecfa3d50752b609f13de6790",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2.5",
- "symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-mbstring": "^1.3"
- },
- "require-dev": {
- "psr/container": "^1.0",
- "symfony/phpunit-bridge": "^4.4.9|^5.0.9"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.3-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Twig\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com",
- "homepage": "http://fabien.potencier.org",
- "role": "Lead Developer"
- },
- {
- "name": "Twig Team",
- "role": "Contributors"
- },
- {
- "name": "Armin Ronacher",
- "email": "armin.ronacher@active-4.com",
- "role": "Project Founder"
- }
- ],
- "description": "Twig, the flexible, fast, and secure template language for PHP",
- "homepage": "https://twig.symfony.com",
- "keywords": [
- "templating"
- ],
- "time": "2021-05-16T12:14:13+00:00"
- }
- ],
- "packages-dev": [],
- "aliases": [],
- "minimum-stability": "stable",
- "stability-flags": [],
- "prefer-stable": false,
- "prefer-lowest": false,
- "platform": {
- "ext-mbstring": "*",
- "ext-sockets": "*",
- "ext-simplexml": "*",
- "ext-curl": "*",
- "ext-json": "*",
- "ext-gmp": "*",
- "ext-sqlite3": "*"
- },
- "platform-dev": [],
- "plugin-api-version": "2.0.0"
-}
diff --git a/localwebsite/config.php b/localwebsite/config.php
deleted file mode 100644
index 3c2bcf7..0000000
--- a/localwebsite/config.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-
-return [
- 'group' => 'www-data',
- 'files_mode' => 0664,
- 'dirs_mode' => 0775,
- 'is_dev' => true,
- 'static_public_path' => '/assets',
-
- 'openwrt_ip' => '192.168.1.1',
-
- 'inverterd_host' => '192.168.1.2',
- 'inverterd_port' => 8305,
-
- 'pump_host' => '192.168.1.2',
- 'pump_port' => 8307,
-
- 'temphumd_servers' => [
- // fill here, example:
- 'hall' => ['192.168.1.3', 8306, 'Big Hall'/*, optional: config::TEMPHUMD_NO_HUM */],
- ],
-
- // modem names (array keys) must match ipset names and
- // routing table names on the openwrt router
- //
- // the order of the keys in the array must be the same
- // as the order in which fwmark iptables rules are applied
- 'modems' => [
- 'modem-example' => [
- 'ip' => '1.2.3.4',
- 'label' => 'Modem Name',
- 'short_label' => 'Mname',
- 'legacy_token_auth' => false,
- ],
- ],
-
- // 'routing_smallhome_ip' => 'fill_me',
- // 'routing_default' => 'fill_me',
-
- 'debug_backtrace' => true,
- 'debug_file' => '.debug.log',
-
- 'twig_cache' => true,
- 'templates' => [
- 'web' => [
- 'root' => 'templates-web',
- 'cache' => 'cache/templates-web',
- ],
- ],
-
- 'static' => [
- 'app.css' => 12,
- 'app.js' => 7,
- 'polyfills.js' => 1,
- 'modem.js' => 2,
- 'inverter.js' => 2,
- 'h265webjs-dist/h265webjs-v20221106.js' => 3,
- 'h265webjs-dist/h265webjs-v20221106-reminified.js' => 1,
- 'h265webjs-dist/missile.js' => 1,
- ],
-
- 'cam_hls_access_key' => '',
- 'cam_hls_proto' => 'http', // bool|callable
- 'cam_hls_host' => '192.168.1.1', // bool|callable
- 'cam_list' => [
- 'low' => [
- // fill me with names
- ],
- 'high' => [
- // fill me with names
- ],
- 'labels' => [
- // assoc array
- ],
- ],
-
- 'vk_sms_checker' => [
- 'telegram_token' => '',
- 'telegram_chat_id' => '',
- 'modem_name' => '', // reference to the 'modems' array
- ],
-
- 'database_path' => getenv('HOME').'/.config/homekit.localwebsite.sqlite3',
-
- 'auth_cookie_host' => '',
- 'auth_need' => false, // bool|callable
- 'auth_pw_salt' => '',
-
- 'grafana_sensors_url' => '',
- 'grafana_inverter_url' => '',
-
- 'ipcam_server_api_addr' => '',
-
- 'dhcp_hostname_overrides' => [],
-];
diff --git a/localwebsite/cron/check-vk-sms.php b/localwebsite/cron/check-vk-sms.php
deleted file mode 100755
index 5d1095a..0000000
--- a/localwebsite/cron/check-vk-sms.php
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env php
-<?php
-
-// this scripts pulls recent inbox from e3372 modem,
-// looks for new messages from vk and re-sends them
-// to the telegram group
-
-require_once __DIR__.'/../init.php';
-global $config;
-
-$cfg = $config['modems'][$config['vk_sms_checker']['modem_name']];
-$e3372 = new E3372($cfg['ip'], $cfg['legacy_token_auth']);
-
-$db = getDB();
-
-$last_processed = $db->querySingle("SELECT last_message_time FROM vk_processed");
-$new_last_processed = 0;
-
-$messages = $e3372->getSMSList();
-$messages = array_reverse($messages);
-
-$results = [];
-if (!empty($messages)) {
- foreach ($messages as $m) {
- if ($m['timestamp'] <= $last_processed)
- continue;
-
- $new_last_processed = $m['timestamp'];
- if (preg_match('/^vk/i', $m['phone']) || preg_match('/vk/i', $m['content']))
- $results[] = $m;
- }
-}
-
-if (!empty($results)) {
- $t = new TelegramBotClient($config['vk_sms_checker']['telegram_token']);
- foreach ($results as $m) {
- $text = '<b>'.htmlescape($m['phone']).'</b> ('.$m['date'].')';
- $text .= "\n".htmlescape($m['content']);
- $t->sendMessage($config['vk_sms_checker']['telegram_chat_id'], $text);
- }
-}
-
-if ($new_last_processed != 0)
- $db->exec("UPDATE vk_processed SET last_message_time=?", $new_last_processed); \ No newline at end of file
diff --git a/localwebsite/engine/database.php b/localwebsite/engine/database.php
deleted file mode 100644
index 33f36cf..0000000
--- a/localwebsite/engine/database.php
+++ /dev/null
@@ -1,131 +0,0 @@
-<?php
-
-class database {
-
- const SCHEMA_VERSION = 2;
-
- protected SQLite3 $link;
-
- public function __construct(string $db_path) {
- $will_create = !file_exists($db_path);
- $this->link = new SQLite3($db_path);
- if ($will_create)
- setperm($db_path);
- $this->link->enableExceptions(true);
- $this->upgradeSchema();
- }
-
- protected function upgradeSchema() {
- $cur = $this->getSchemaVersion();
- if ($cur == self::SCHEMA_VERSION)
- return;
-
- if ($cur < 1) {
- $this->link->exec("CREATE TABLE users (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- username TEXT,
- password TEXT
- )");
- }
- if ($cur < 2) {
- $this->link->exec("CREATE TABLE vk_processed (
- last_message_time INTEGER
- )");
- $this->link->exec("INSERT INTO vk_processed (last_message_time) VALUES (0)");
- }
- $this->syncSchemaVersion();
- }
-
- protected function getSchemaVersion() {
- return $this->link->query("PRAGMA user_version")->fetchArray()[0];
- }
-
- protected function syncSchemaVersion() {
- $this->link->exec("PRAGMA user_version=".self::SCHEMA_VERSION);
- }
-
- protected function prepareQuery(string $sql): string {
- if (func_num_args() > 1) {
- $mark_count = substr_count($sql, '?');
- $positions = array();
- $last_pos = -1;
- for ($i = 0; $i < $mark_count; $i++) {
- $last_pos = strpos($sql, '?', $last_pos + 1);
- $positions[] = $last_pos;
- }
- for ($i = $mark_count - 1; $i >= 0; $i--) {
- $arg_val = func_get_arg($i + 1);
- if (is_null($arg_val)) {
- $v = 'NULL';
- } else {
- $v = '\''.$this->link->escapeString($arg_val) . '\'';
- }
- $sql = substr_replace($sql, $v, $positions[$i], 1);
- }
- }
-
- return $sql;
- }
-
- public function query(string $sql, ...$params): SQLite3Result {
- return $this->link->query($this->prepareQuery($sql, ...$params));
- }
-
- public function exec(string $sql, ...$params) {
- return $this->link->exec($this->prepareQuery($sql, ...$params));
- }
-
- public function querySingle(string $sql, ...$params) {
- return $this->link->querySingle($this->prepareQuery($sql, ...$params));
- }
-
- public function querySingleRow(string $sql, ...$params) {
- return $this->link->querySingle($this->prepareQuery($sql, ...$params), true);
- }
-
- protected function performInsert(string $command, string $table, array $fields): SQLite3Result {
- $names = [];
- $values = [];
- $count = 0;
- foreach ($fields as $k => $v) {
- $names[] = $k;
- $values[] = $v;
- $count++;
- }
-
- $sql = "{$command} INTO `{$table}` (`" . implode('`, `', $names) . "`) VALUES (" . implode(', ', array_fill(0, $count, '?')) . ")";
- array_unshift($values, $sql);
-
- return call_user_func_array([$this, 'query'], $values);
- }
-
- public function insert(string $table, array $fields): SQLite3Result {
- return $this->performInsert('INSERT', $table, $fields);
- }
-
- public function replace(string $table, array $fields): SQLite3Result {
- return $this->performInsert('REPLACE', $table, $fields);
- }
-
- public function insertId(): int {
- return $this->link->lastInsertRowID();
- }
-
- public function update($table, $rows, ...$cond): SQLite3Result {
- $fields = [];
- $args = [];
- foreach ($rows as $row_name => $row_value) {
- $fields[] = "`{$row_name}`=?";
- $args[] = $row_value;
- }
- $sql = "UPDATE `$table` SET " . implode(', ', $fields);
- if (!empty($cond)) {
- $sql .= " WHERE " . $cond[0];
- if (count($cond) > 1)
- $args = array_merge($args, array_slice($cond, 1));
- }
- return $this->query($sql, ...$args);
- }
-
-
-} \ No newline at end of file
diff --git a/localwebsite/functions.php b/localwebsite/functions.php
deleted file mode 100644
index 6868b0d..0000000
--- a/localwebsite/functions.php
+++ /dev/null
@@ -1,300 +0,0 @@
-<?php
-
-function param($key) {
- global $RouterInput;
-
- $val = null;
-
- if (isset($RouterInput[$key])) {
- $val = $RouterInput[$key];
- } else if (isset($_POST[$key])) {
- $val = $_POST[$key];
- } else if (isset($_GET[$key])) {
- $val = $_GET[$key];
- }
-
- if (is_array($val)) {
- $val = implode($val);
- }
- return $val;
-}
-
-function str_replace_once(string $needle, string $replace, string $haystack): string {
- $pos = strpos($haystack, $needle);
- if ($pos !== false) {
- $haystack = substr_replace($haystack, $replace, $pos, strlen($needle));
- }
- return $haystack;
-}
-
-function htmlescape($s) {
- if (is_array($s)) {
- foreach ($s as $k => $v) {
- $s[$k] = htmlescape($v);
- }
- return $s;
- }
- return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
-}
-
-function jsonEncode($obj) {
- return json_encode($obj, JSON_UNESCAPED_UNICODE);
-}
-
-function jsonDecode($json) {
- return json_decode($json, true);
-}
-
-function startsWith(string $haystack, string $needle): bool {
- return $needle === "" || strpos($haystack, $needle) === 0;
-}
-
-function endsWith(string $haystack, string $needle): bool {
- return $needle === "" || substr($haystack, -strlen($needle)) === $needle;
-}
-
-function exectime($format = null) {
- $time = round(microtime(true) - START_TIME, 4);
- if (!is_null($format)) {
- $time = sprintf($format, $time);
- }
- return $time;
-}
-
-function stransi($s) {
- static $colors = [
- 'black' => 0,
- 'red' => 1,
- 'green' => 2,
- 'yellow' => 3,
- 'blue' => 4,
- 'magenta' => 5,
- 'cyan' => 6,
- 'white' => 7
- ];
- static $valid_styles = ['bold', 'fgbright', 'bgbright'];
-
- $s = preg_replace_callback('/<(?:e ([a-z, =]+)|\/e)>/', function($match) use ($colors, $valid_styles) {
- if (empty($match[1])) {
- return "\033[0m";
- } else {
- $codes = [];
- $args = preg_split('/ +/', $match[1]);
- $fg = null;
- $bg = null;
- $styles = [];
- foreach ($args as $arg) {
- list($argname, $argvalue) = explode('=', $arg);
- $err = false;
- if ($argname == 'fg' || $argname == 'bg') {
- if (isset($colors[$argvalue])) {
- $$argname = $colors[$argvalue];
- } else {
- $err = true;
- }
- } else if ($argname == 'style') {
- $argstyles = array_filter(explode(',', $argvalue));
- foreach ($argstyles as $style) {
- if (!in_array($style, $valid_styles)) {
- $err = true;
- break;
- }
- }
- if (!$err) {
- foreach ($argstyles as $style) {
- $styles[$style] = true;
- }
- }
- } else {
- $err = true;
- }
-
- if ($err) {
- trigger_error(__FUNCTION__.": unrecognized argument {$arg}", E_USER_WARNING);
- }
- }
-
- if (!is_null($fg)) {
- $codes[] = $fg + (isset($styles['fgbright']) ? 90 : 30);
- }
- if (!is_null($bg)) {
- $codes[] = $bg + (isset($styles['bgbright']) ? 100 : 40);
- }
- if (isset($styles['bold'])) {
- $codes[] = 1;
- }
-
- return !empty($codes) ? "\033[".implode(';', $codes)."m" : '';
- }
- }, $s);
- return $s;
-}
-
-function strgen($len = 10): string {
- $buf = '';
- for ($i = 0; $i < $len; $i++) {
- $j = mt_rand(0, 61);
- if ($j >= 36) {
- $j += 13;
- } else if ($j >= 10) {
- $j += 7;
- }
- $buf .= chr(48 + $j);
- }
- return $buf;
-}
-
-function setperm($file, $is_dir = null) {
- global $config;
-
- // chgrp
- $gid = filegroup($file);
- $gname = posix_getgrgid($gid);
- if (!is_array($gname)) {
- debugError(__FUNCTION__.": posix_getgrgid() failed on $gid", $gname);
- } else {
- $gname = $gname['name'];
- }
- if ($gname != $config['group']) {
- if (!chgrp($file, $config['group'])) {
- debugError(__FUNCTION__.": chgrp() failed on $file");
- }
- }
-
- // chmod
- $perms = fileperms($file);
- $need_perms = is_dir($file) ? $config['dirs_mode'] : $config['files_mode'];
- if (($perms & $need_perms) !== $need_perms) {
- if (!chmod($file, $need_perms)) {
- debugError(__FUNCTION__.": chmod() failed on $file");
- }
- }
-}
-
-function redirect($url, $preserve_utm = true, $no_ajax = false) {
- if (PHP_SAPI != 'cli' && $_SERVER['REQUEST_METHOD'] == 'GET' && $preserve_utm) {
- $proxy_params = ['utm_source', 'utm_medium', 'utm_content', 'utm_campaign'];
- $params = [];
- foreach ($proxy_params as $p) {
- if (!empty($_GET[$p])) {
- $params[$p] = (string)$_GET[$p];
- }
- }
- if (!empty($params)) {
- if (($anchor_pos = strpos($url, '#')) !== false) {
- $anchor = substr($url, $anchor_pos+1);
- $url = substr($url, 0, $anchor_pos);
- }
- $url .= (strpos($url, '?') === false ? '?' : '&').http_build_query($params);
- if ($anchor_pos !== false) {
- $url .= '#'.$anchor;
- }
- }
- }
-
- header('Location: ' . $url);
- exit;
-}
-
-function is_xhr_request(): bool {
- return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
-}
-
-function secondsToTime(int $n): string {
- $parts = [];
-
- if ($n >= 86400) {
- $days = floor($n / 86400);
- $n %= 86400;
- $parts[] = "{$days}д";
- }
-
- if ($n >= 3600) {
- $hours = floor($n / 3600);
- $n %= 3600;
- $parts[] = "{$hours}ч";
- }
-
- if ($n >= 60) {
- $minutes = floor($n / 60);
- $n %= 60;
- $parts[] = "{$minutes}мин";
- }
-
- if ($n)
- $parts[] = "{$n}сек";
-
- return implode(' ', $parts);
-}
-
-function bytesToUnitsLabel(GMP $b): string {
- $ks = array('B', 'Kb', 'Mb', 'Gb', 'Tb');
- foreach ($ks as $i => $k) {
- if (gmp_cmp($b, gmp_pow(1024, $i + 1)) < 0) {
- if ($i == 0)
- return gmp_strval($b) . ' ' . $k;
-
- $n = gmp_intval(gmp_div_q($b, gmp_pow(1024, $i)));
- return round($n, 2).' '.$k;
- }
- }
-
- return gmp_strval($b);
-}
-
-function pwhash(string $s): string {
- return hash('sha256', config::get('auth_pw_salt').'|'.$s);
-}
-
-$ShutdownFunctions = [];
-
-function append_shutdown_function(callable $f) {
- global $ShutdownFunctions;
- $ShutdownFunctions[] = $f;
-}
-
-function prepend_shutdown_function(callable $f) {
- global $ShutdownFunctions;
- array_unshift($ShutdownFunctions, $f);
-}
-
-function getDB(): database {
- static $link = null;
-
- if (is_null($link))
- $link = new database(config::get('database_path'));
-
- return $link;
-}
-
-function to_camel_case(string $input, string $separator = '_'): string {
- return lcfirst(str_replace($separator, '', ucwords($input, $separator)));
-}
-
-function from_camel_case(string $s): string {
- $buf = '';
- $len = strlen($s);
- for ($i = 0; $i < $len; $i++) {
- if (!ctype_upper($s[$i])) {
- $buf .= $s[$i];
- } else {
- $buf .= '_'.strtolower($s[$i]);
- }
- }
- return $buf;
-}
-
-function unsetcookie(string $name) {
- global $config;
- setcookie($name, null, -1, '/', $config['auth_cookie_host']);
-}
-
-function setcookie_safe(...$args) {
- global $config;
- if (!headers_sent()) {
- if (count($args) == 2)
- setcookie($args[0], $args[1], time()+86400*365, '/', $config['auth_cookie_host']);
- else
- setcookie(...$args);
- }
-} \ No newline at end of file
diff --git a/localwebsite/init.php b/localwebsite/init.php
deleted file mode 100644
index 4620ed2..0000000
--- a/localwebsite/init.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-error_reporting(E_ALL);
-ini_set('display_errors', 1);
-
-mb_internal_encoding('UTF-8');
-mb_regex_encoding('UTF-8');
-
-register_shutdown_function(function() {
- global $ShutdownFunctions;
- if (!empty($ShutdownFunctions)) {
- foreach ($ShutdownFunctions as $f)
- $f();
- }
-});
-
-spl_autoload_register(function($class) {
- if (endsWith($class, 'Handler'))
- $path = ROOT.'/handlers/'.$class.'.php';
-
- // engine classes
- else if (in_array($class, ['request_handler', 'router', 'model', 'debug', 'database']))
- $path = ROOT.'/engine/'.$class.'.php';
-
- else if ($class == 'Lang')
- $path = ROOT.'/engine/lang.php';
-
- else if (endsWith($class, '_tpl'))
- $path = ROOT.'/engine/tpl.php';
-
- // other classes
- else
- $path = ROOT.'/classes/'.$class.'.php';
-
- if (strpos($path, '\\') !== false)
- $path = str_replace('\\', '/', $path);
-
- if (is_file($path))
- require_once $path;
-});
-
-define('ROOT', __DIR__);
-define('START_TIME', microtime(true));
-
-set_include_path(get_include_path().PATH_SEPARATOR.ROOT);
-
-require_once ROOT.'/functions.php';
-
-$config = require ROOT.'/config.php';
-if (!is_file(ROOT.'/config.local.php'))
- die('config.local.php not found');
-$config = array_merge($config, require_once ROOT.'/config.local.php');
-
-// it's better to start logging as early as possible
-$debug = debug::getInstance(
- function($errno, $errfile, $errlne, $errstr) {
- // it's not our fault that some vendor package uses something that's deprecated
- // so let's not spam our logs
- if ($errno == E_USER_DEPRECATED && startsWith($errfile, ROOT.'/vendor/'))
- return false;
-
- return true;
- }
-);
-$debug->setMessagesStoreType(debug::STORE_FILE);
-$debug->setErrorsStoreType(debug::STORE_FILE);
-$debug->enable();
-unset($debug);
-
-// composer
-require_once ROOT.'/vendor/autoload.php';
diff --git a/localwebsite/utils.php b/localwebsite/utils.php
deleted file mode 100755
index 333ebfc..0000000
--- a/localwebsite/utils.php
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env php
-<?php
-
-require_once __DIR__.'/init.php';
-
-function read_stdin(?string $prompt = null, bool $multiline = true) {
- if (!is_null($prompt))
- echo $prompt;
-
- if (!$multiline)
- return trim(fgets(STDIN));
-
- $fp = fopen('php://stdin', 'r');
- $data = stream_get_contents($fp);
- fclose($fp);
-
- return $data;
-}
-
-function usage() {
- global $argv;
- echo <<<EOF
-usage: {$argv[0]} COMMAND
-
-Supported commands:
- add-user
- change-password
-
-EOF;
- exit(1);
-}
-
-if (empty($argv[1]))
- usage();
-
-switch ($argv[1]) {
- case 'add-user':
- $username = read_stdin('enter username: ', false);
- $password = read_stdin('enter password: ', false);
-
- if (users::exists($username)) {
- fwrite(STDERR, "user already exists\n");
- exit(1);
- }
-
- $id = users::add($username, $password);
- echo "added user, id = $id\n";
-
- break;
-
- case 'change-password':
- $id = (int)read_stdin('enter ID: ', false);
- if (!$id)
- die("invalid id\n");
-
- $password = read_stdin('enter new password: ', false);
- if (!$password)
- die("invalid password\n");
-
- users::setPassword($id, $password);
- break;
-
- default:
- fwrite(STDERR, "invalid command\n");
- exit(1);
-} \ No newline at end of file