comletely delete old lws, rewrite vk_sms_checker on python
This commit is contained in:
parent
952e41d594
commit
95ac1f0d67
75
bin/vk_sms_checker.py
Executable file
75
bin/vk_sms_checker.py
Executable file
@ -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()
|
@ -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'
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
||||
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 MySQLHomeCredsConfig(MySQLCredsConfig):
|
||||
NAME = 'mysql_home_creds'
|
||||
|
||||
|
||||
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()
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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"
|
||||
}
|
341
localwebsite/composer.lock
generated
341
localwebsite/composer.lock
generated
@ -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"
|
||||
}
|
@ -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' => [],
|
||||
];
|
@ -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);
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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';
|
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user