ребрендинг + строка пакостей
|
@ -1,3 +1,3 @@
|
||||||
!.gitignore
|
!.gitignore
|
||||||
composer.phar
|
composer.phar
|
||||||
vendor
|
vendor
|
||||||
|
|
22
LICENSE
|
@ -1,11 +1,11 @@
|
||||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
Version 2, December 2004
|
Version 2, December 2004
|
||||||
|
|
||||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
|
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
|
||||||
|
|
||||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
# site-virus
|
# site-virus
|
||||||
|
|
||||||
Site with viruses and scary pictures
|
Site with viruses and scary pictures
|
101
composer.json
|
@ -1,51 +1,50 @@
|
||||||
{
|
{
|
||||||
"name": "mirzaev/site-virus",
|
"name": "mirzaev/site-ff",
|
||||||
"description": "Site with viruses and scary pictures",
|
"description": "our FUCKING.FORUM",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"virus",
|
"forum",
|
||||||
"download",
|
"Evil Alliance",
|
||||||
"Evil Alliance",
|
"imageboard",
|
||||||
"imageboard",
|
"site"
|
||||||
"site"
|
],
|
||||||
],
|
"type": "site",
|
||||||
"type": "site",
|
"homepage": "https://git.mirzaev.sexy/mirzaev/site-ff",
|
||||||
"homepage": "https://git.mirzaev.sexy/mirzaev/site-virus",
|
"license": "WTFPL",
|
||||||
"license": "WTFPL",
|
"authors": [
|
||||||
"authors": [
|
{
|
||||||
{
|
"name": "Arsen Mirzaev Tatyano-Muradovich",
|
||||||
"name": "Arsen Mirzaev Tatyano-Muradovich",
|
"email": "arsen@mirzaev.sexy",
|
||||||
"email": "arsen@mirzaev.sexy",
|
"homepage": "https://mirzaev.sexy",
|
||||||
"homepage": "https://mirzaev.sexy",
|
"role": "Programmer"
|
||||||
"role": "Programmer"
|
}
|
||||||
}
|
],
|
||||||
],
|
"support": {
|
||||||
"support": {
|
"docs": "https://git.mirzaev.sexy/mirzaev/site-ff/manual",
|
||||||
"docs": "https://git.mirzaev.sexy/mirzaev/site-virus/manual",
|
"issues": "https://git.mirzaev.sexy/mirzaev/site-ff/issues"
|
||||||
"issues": "https://git.mirzaev.sexy/mirzaev/site-virus/issues"
|
},
|
||||||
},
|
"require": {
|
||||||
"require": {
|
"php": "~8.2",
|
||||||
"php": "~8.1",
|
"ext-sodium": "~8.2",
|
||||||
"ext-sodium": "~8.1",
|
"mirzaev/accounts": "~1.2.x-dev",
|
||||||
"mirzaev/minimal": "^2.0.x-dev",
|
"mirzaev/arangodb": "^1.0.0",
|
||||||
"mirzaev/accounts": "~1.2.x-dev",
|
"mirzaev/vk": "^4.0",
|
||||||
"mirzaev/arangodb": "^1.0.0",
|
"triagens/arangodb": "~3.9.x-dev",
|
||||||
"mirzaev/vk": "^4.0",
|
"twig/twig": "^3.4",
|
||||||
"triagens/arangodb": "~3.9.x-dev",
|
"guzzlehttp/guzzle": "^7.5",
|
||||||
"twig/twig": "^3.4",
|
"mirzaev/minimal": "^2.1"
|
||||||
"guzzlehttp/guzzle": "^7.5"
|
},
|
||||||
},
|
"require-dev": {
|
||||||
"require-dev": {
|
"phpunit/phpunit": "~9.5"
|
||||||
"phpunit/phpunit": "~9.5"
|
},
|
||||||
},
|
"autoload": {
|
||||||
"autoload": {
|
"psr-4": {
|
||||||
"psr-4": {
|
"mirzaev\\site\\ff\\": "mirzaev/site/ff/system"
|
||||||
"mirzaev\\site\\virus\\": "mirzaev/site/virus/system"
|
}
|
||||||
}
|
},
|
||||||
},
|
"autoload-dev": {
|
||||||
"autoload-dev": {
|
"psr-4": {
|
||||||
"psr-4": {
|
"mirzaev\\site\\ff\\tests\\": "mirzaev/site/ff/tests"
|
||||||
"mirzaev\\site\\virus\\tests\\": "mirzaev/site/virus/tests"
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,147 +1,147 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\site\virus\controllers;
|
namespace mirzaev\site\ff\controllers;
|
||||||
|
|
||||||
// Файлы проекта
|
// Файлы проекта
|
||||||
use mirzaev\site\virus\controllers\core;
|
use mirzaev\site\ff\controllers\core;
|
||||||
use mirzaev\site\virus\models\account_model as account;
|
use mirzaev\site\ff\models\account_model as account;
|
||||||
use mirzaev\site\virus\models\session_model as session;
|
use mirzaev\site\ff\models\session_model as session;
|
||||||
use mirzaev\site\virus\models\vk_model as vk;
|
use mirzaev\site\ff\models\vk_model as vk;
|
||||||
|
|
||||||
// Библиотека для ArangoDB
|
// Библиотека для ArangoDB
|
||||||
use ArangoDBClient\Document as _document;
|
use ArangoDBClient\Document as _document;
|
||||||
use SebastianBergmann\Type\ObjectType;
|
use SebastianBergmann\Type\ObjectType;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
|
|
||||||
// Фреймворк для ВКонтакте
|
// Фреймворк для ВКонтакте
|
||||||
use mirzaev\vk\core as api;
|
use mirzaev\vk\core as api;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Контроллер аккаунтов
|
* Контроллер аккаунтов
|
||||||
*
|
*
|
||||||
* @package mirzaev\site\virus\controllers
|
* @package mirzaev\site\ff\controllers
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
final class account_controller extends core
|
final class account_controller extends core
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Страница профиля
|
* Страница профиля
|
||||||
*
|
*
|
||||||
* @param array $parameters Параметры запроса
|
* @param array $parameters Параметры запроса
|
||||||
*/
|
*/
|
||||||
public function index(array $parameters = []): ?string
|
public function index(array $parameters = []): ?string
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Инициализация
|
* Инициализация
|
||||||
*
|
*
|
||||||
* @param array $parameters Параметры запроса
|
* @param array $parameters Параметры запроса
|
||||||
*/
|
*/
|
||||||
public function initialization(array $parameters = []): ?string
|
public function initialization(array $parameters = []): ?string
|
||||||
{
|
{
|
||||||
if ($this->variables['account'] instanceof _document) {
|
if ($this->variables['account'] instanceof _document) {
|
||||||
// Найден аккаунт
|
// Найден аккаунт
|
||||||
|
|
||||||
if ($this->variables['vk'] instanceof _document) {
|
if ($this->variables['vk'] instanceof _document) {
|
||||||
// Найден аккаунт ВКонтакте
|
// Найден аккаунт ВКонтакте
|
||||||
|
|
||||||
// Инициализация данных аккаунта ВКонтакте
|
// Инициализация данных аккаунта ВКонтакте
|
||||||
vk::parse($this->variables['vk'], $this->variables['errors']['vk']);
|
vk::parse($this->variables['vk'], $this->variables['errors']['vk']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запись кода ответа
|
// Запись кода ответа
|
||||||
http_response_code(200);
|
http_response_code(200);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
// Не найден аккаунт
|
// Не найден аккаунт
|
||||||
|
|
||||||
// Запись кода ответа
|
// Запись кода ответа
|
||||||
http_response_code(401);
|
http_response_code(401);
|
||||||
|
|
||||||
// Запись заголовка ответа с ключом аккаунта
|
// Запись заголовка ответа с ключом аккаунта
|
||||||
header('session: ' . $this->variables['session']->hash);
|
header('session: ' . $this->variables['session']->hash);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запись кода ответа
|
// Запись кода ответа
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Связь аккаунта с аккаунтом ВКонтакте
|
* Связь аккаунта с аккаунтом ВКонтакте
|
||||||
*
|
*
|
||||||
* @param array $parameters Параметры запроса
|
* @param array $parameters Параметры запроса
|
||||||
*/
|
*/
|
||||||
public function connect(array $parameters = []): ?string
|
public function connect(array $parameters = []): ?string
|
||||||
{
|
{
|
||||||
if ($this->variables['session']->hash === $parameters['state']) {
|
if ($this->variables['session']->hash === $parameters['state']) {
|
||||||
// Совпадает хеш сессии с полученным хешем из ответа ВКонтакте
|
// Совпадает хеш сессии с полученным хешем из ответа ВКонтакте
|
||||||
|
|
||||||
if (!empty($response = vk::key($parameters['code'], $this->variables['errors']['vk']))) {
|
if (!empty($response = vk::key($parameters['code'], $this->variables['errors']['vk']))) {
|
||||||
// Получены данные аккаунта ВКонтакте
|
// Получены данные аккаунта ВКонтакте
|
||||||
|
|
||||||
if (($this->variables['vk'] = vk::initialization($response, $this->variables['errors']['vk'])) instanceof _document) {
|
if (($this->variables['vk'] = vk::initialization($response, $this->variables['errors']['vk'])) instanceof _document) {
|
||||||
// Инициализирован аккаунт ВКонтакте
|
// Инициализирован аккаунт ВКонтакте
|
||||||
|
|
||||||
if (($this->variables['account'] = vk::account($this->variables['vk'])) instanceof _document) {
|
if (($this->variables['account'] = vk::account($this->variables['vk'])) instanceof _document) {
|
||||||
// Найден аккаунт (существующий)
|
// Найден аккаунт (существующий)
|
||||||
|
|
||||||
if (session::connect($this->variables['session'], $this->variables['account'], $this->variables['errors']['session'])) {
|
if (session::connect($this->variables['session'], $this->variables['account'], $this->variables['errors']['session'])) {
|
||||||
// Связана сессия с аккаунтом
|
// Связана сессия с аккаунтом
|
||||||
}
|
}
|
||||||
} else if (($this->variables['account'] = account::create($this->variables['errors']['account'])) instanceof _document) {
|
} else if (($this->variables['account'] = account::create($this->variables['errors']['account'])) instanceof _document) {
|
||||||
// Найден аккаунт (создан новый)
|
// Найден аккаунт (создан новый)
|
||||||
|
|
||||||
if (session::connect($this->variables['session'], $this->variables['account'], $this->variables['errors']['session'])) {
|
if (session::connect($this->variables['session'], $this->variables['account'], $this->variables['errors']['session'])) {
|
||||||
// Связана сессия с аккаунтом
|
// Связана сессия с аккаунтом
|
||||||
|
|
||||||
if (account::connect($this->variables['account'], $this->variables['vk'], $this->variables['errors']['account'])) {
|
if (account::connect($this->variables['account'], $this->variables['vk'], $this->variables['errors']['account'])) {
|
||||||
// Связан аккаунт с аккаунтом ВКонтакте
|
// Связан аккаунт с аккаунтом ВКонтакте
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация робота для аккаунта ВКонтакте
|
// Инициализация робота для аккаунта ВКонтакте
|
||||||
$this->vk = api::init()->user(key: $this->variables['vk']->access['key']);
|
$this->vk = api::init()->user(key: $this->variables['vk']->access['key']);
|
||||||
|
|
||||||
if ($this->variables['vk'] instanceof _document) {
|
if ($this->variables['vk'] instanceof _document) {
|
||||||
// Инициализирован робот для аккаунта ВКонтакте
|
// Инициализирован робот для аккаунта ВКонтакте
|
||||||
|
|
||||||
// Инициализация данных аккаунта ВКонтакте
|
// Инициализация данных аккаунта ВКонтакте
|
||||||
$data = vk::parse($this->vk, $this->variables['errors']['vk']);
|
$data = vk::parse($this->vk, $this->variables['errors']['vk']);
|
||||||
var_dump($data); die;
|
var_dump($data); die;
|
||||||
|
|
||||||
if ($data instanceof stdClass) {
|
if ($data instanceof stdClass) {
|
||||||
// Получены данные ВКонтакте
|
// Получены данные ВКонтакте
|
||||||
|
|
||||||
// Запись в базу данных
|
// Запись в базу данных
|
||||||
vk::update($this->variables['vk'], $data, $this->variables['errors']['vk']);
|
vk::update($this->variables['vk'], $data, $this->variables['errors']['vk']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Генерация представления
|
// Генерация представления
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'vk.html', $this->variables);
|
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'vk.html', $this->variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Генерация панели аккаунта
|
* Генерация панели аккаунта
|
||||||
*
|
*
|
||||||
* @param array $parameters Параметры запроса
|
* @param array $parameters Параметры запроса
|
||||||
*/
|
*/
|
||||||
public function panel(array $parameters = []): ?string
|
public function panel(array $parameters = []): ?string
|
||||||
{
|
{
|
||||||
// Генерация представления
|
// Генерация представления
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'panel.html', $this->variables);
|
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'panel.html', $this->variables);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,100 +1,100 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\site\virus\controllers;
|
namespace mirzaev\site\ff\controllers;
|
||||||
|
|
||||||
// Файлы проекта
|
// Файлы проекта
|
||||||
use mirzaev\site\virus\views\manager;
|
use mirzaev\site\ff\views\manager;
|
||||||
use mirzaev\site\virus\models\core as models;
|
use mirzaev\site\ff\models\core as models;
|
||||||
use mirzaev\site\virus\models\account_model as account;
|
use mirzaev\site\ff\models\account_model as account;
|
||||||
use mirzaev\site\virus\models\session_model as session;
|
use mirzaev\site\ff\models\session_model as session;
|
||||||
|
|
||||||
// Библиотека для ArangoDB
|
// Библиотека для ArangoDB
|
||||||
use ArangoDBClient\Document as _document;
|
use ArangoDBClient\Document as _document;
|
||||||
|
|
||||||
// Фреймворк PHP
|
// Фреймворк PHP
|
||||||
use mirzaev\minimal\controller;
|
use mirzaev\minimal\controller;
|
||||||
|
|
||||||
// Фреймворк ВКонтакте
|
// Фреймворк ВКонтакте
|
||||||
use mirzaev\vk\core as vk;
|
use mirzaev\vk\core as vk;
|
||||||
use mirzaev\vk\robots\user as robot;
|
use mirzaev\vk\robots\user as robot;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ядро контроллеров
|
* Ядро контроллеров
|
||||||
*
|
*
|
||||||
* @package mirzaev\site\virus\controllers
|
* @package mirzaev\site\ff\controllers
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
class core extends controller
|
class core extends controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Переменные окружения
|
* Переменные окружения
|
||||||
*/
|
*/
|
||||||
protected robot $vk;
|
protected robot $vk;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Переменные окружения
|
* Переменные окружения
|
||||||
*/
|
*/
|
||||||
protected array $variables = [];
|
protected array $variables = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Конструктор
|
* Конструктор
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
// Инициализация ядра моделей (соединение с базой данных...)
|
// Инициализация ядра моделей (соединение с базой данных...)
|
||||||
new models();
|
new models();
|
||||||
|
|
||||||
// Инициализация журнала ошибок
|
// Инициализация журнала ошибок
|
||||||
$this->variables['errors'] = [
|
$this->variables['errors'] = [
|
||||||
'session' => [],
|
'session' => [],
|
||||||
'account' => [],
|
'account' => [],
|
||||||
'vk' => []
|
'vk' => []
|
||||||
];
|
];
|
||||||
|
|
||||||
// Инициализация даты до которой будет активна сессия
|
// Инициализация даты до которой будет активна сессия
|
||||||
$expires = time() + 604800;
|
$expires = time() + 604800;
|
||||||
|
|
||||||
// Инициализация сессии (без журналирования)
|
// Инициализация сессии (без журналирования)
|
||||||
$this->variables['session'] = session::initialization($_COOKIE["session"] ?? null, $expires) ?? header('Location: https://virus.mirzaev.sexy/error?code=500&text=Не+удалось+инициализировать+сессию');
|
$this->variables['session'] = session::initialization($_COOKIE["session"] ?? null, $expires) ?? header('Location: https://virus.mirzaev.sexy/error?code=500&text=Не+удалось+инициализировать+сессию');
|
||||||
|
|
||||||
if ($_COOKIE["session"] ?? null !== $this->variables['session']->hash) {
|
if ($_COOKIE["session"] ?? null !== $this->variables['session']->hash) {
|
||||||
// Изменился хеш сессии (подразумевается, что сессия устарела)
|
// Изменился хеш сессии (подразумевается, что сессия устарела)
|
||||||
|
|
||||||
// Запись хеша новой сессии
|
// Запись хеша новой сессии
|
||||||
setcookie('session', $this->variables['session']->hash, [
|
setcookie('session', $this->variables['session']->hash, [
|
||||||
'expires' => $expires,
|
'expires' => $expires,
|
||||||
'domain' => 'virus.mirzaev.sexy',
|
'domain' => 'ff.mirzaev.sexy',
|
||||||
'path' => '/',
|
'path' => '/',
|
||||||
'secure' => true,
|
'secure' => true,
|
||||||
'httponly' => true,
|
'httponly' => true,
|
||||||
'samesite' => 'strict'
|
'samesite' => 'strict'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация аккаунта (без журналирования)
|
// Инициализация аккаунта (без журналирования)
|
||||||
$this->variables['account'] = session::account($this->variables['session']);
|
$this->variables['account'] = session::account($this->variables['session']);
|
||||||
|
|
||||||
if ($this->variables['account'] instanceof _document) {
|
if ($this->variables['account'] instanceof _document) {
|
||||||
// Инициализирован аккаунт
|
// Инициализирован аккаунт
|
||||||
|
|
||||||
// Инициализация аккаунта ВКонтакте (без журналирования)
|
// Инициализация аккаунта ВКонтакте (без журналирования)
|
||||||
$this->variables['vk'] = account::vk($this->variables['account']);
|
$this->variables['vk'] = account::vk($this->variables['account']);
|
||||||
|
|
||||||
if ($this->variables['vk'] instanceof _document) {
|
if ($this->variables['vk'] instanceof _document) {
|
||||||
// Инициализирован аккаунт ВКонтакте
|
// Инициализирован аккаунт ВКонтакте
|
||||||
|
|
||||||
// Инициализация робота для аккаунта ВКонтакте
|
// Инициализация робота для аккаунта ВКонтакте
|
||||||
$this->vk = vk::init()->user(key: $this->variables['vk']->access['key']);
|
$this->vk = vk::init()->user(key: $this->variables['vk']->access['key']);
|
||||||
} else unset($this->variables['account'], $this->variables['vk']);
|
} else unset($this->variables['account'], $this->variables['vk']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация препроцессора представления
|
// Инициализация препроцессора представления
|
||||||
$this->view = new manager;
|
$this->view = new manager;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,44 +1,44 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\site\virus\controllers;
|
namespace mirzaev\site\ff\controllers;
|
||||||
|
|
||||||
// Файлы проекта
|
// Файлы проекта
|
||||||
use mirzaev\site\virus\controllers\core;
|
use mirzaev\site\ff\controllers\core;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Контроллер ошибок
|
* Контроллер ошибок
|
||||||
*
|
*
|
||||||
* @package mirzaev\site\virus\controllers
|
* @package mirzaev\site\ff\controllers
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
final class error_controller extends core
|
final class error_controller extends core
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Страница с ошибкой
|
* Страница с ошибкой
|
||||||
*
|
*
|
||||||
* @param array $parameters
|
* @param array $parameters
|
||||||
*/
|
*/
|
||||||
public function index(array $parameters = []): ?string
|
public function index(array $parameters = []): ?string
|
||||||
{
|
{
|
||||||
// Запись текста ошибки в переменную окружения
|
// Запись текста ошибки в переменную окружения
|
||||||
$this->variables['text'] = $parameters['text'] ?? null;
|
$this->variables['text'] = $parameters['text'] ?? null;
|
||||||
|
|
||||||
if (isset($parameters['code'])) {
|
if (isset($parameters['code'])) {
|
||||||
// Получен код ошибки
|
// Получен код ошибки
|
||||||
|
|
||||||
// Запись кода ошибки в переменную окружения
|
// Запись кода ошибки в переменную окружения
|
||||||
$this->variables['code'] = $parameters['code'];
|
$this->variables['code'] = $parameters['code'];
|
||||||
|
|
||||||
// Запись кода ответа
|
// Запись кода ответа
|
||||||
http_response_code($parameters['code']);
|
http_response_code($parameters['code']);
|
||||||
|
|
||||||
// Генерация представления
|
// Генерация представления
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Генерация представления
|
// Генерация представления
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . ($parameters['code'] ?? 'index') . '.html', $this->variables);
|
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . ($parameters['code'] ?? 'index') . '.html', $this->variables);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,82 +1,82 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\site\virus\controllers;
|
namespace mirzaev\site\ff\controllers;
|
||||||
|
|
||||||
// Файлы проекта
|
// Файлы проекта
|
||||||
use mirzaev\site\virus\controllers\core;
|
use mirzaev\site\ff\controllers\core;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Контроллер бегущей строки
|
* Контроллер бегущей строки
|
||||||
*
|
*
|
||||||
* @package mirzaev\site\virus\controllers
|
* @package mirzaev\site\ff\controllers
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
final class hotline_controller extends core
|
final class hotline_controller extends core
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Страница с бегущей строкой
|
* Страница с бегущей строкой
|
||||||
*
|
*
|
||||||
* Можно использовать совместно с элементом <iframe> для изоляции
|
* Можно использовать совместно с элементом <iframe> для изоляции
|
||||||
* содержимого бегущей строки от поисковых роботов
|
* содержимого бегущей строки от поисковых роботов
|
||||||
*
|
*
|
||||||
* @param array $parameters
|
* @param array $parameters
|
||||||
*/
|
*/
|
||||||
public function index(array $parameters = []): ?string
|
public function index(array $parameters = []): ?string
|
||||||
{
|
{
|
||||||
// Инициализация элементов для генерации в головном элементе
|
// Инициализация элементов для генерации в головном элементе
|
||||||
$this->variables['head'] = [
|
$this->variables['head'] = [
|
||||||
'title' => 'Бегущая строка',
|
'title' => 'Бегущая строка',
|
||||||
'metas' => [
|
'metas' => [
|
||||||
[
|
[
|
||||||
'attributes' => [
|
'attributes' => [
|
||||||
'name' => 'robots',
|
'name' => 'robots',
|
||||||
'content' => 'nofollow'
|
'content' => 'nofollow'
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
// Инициализация бегущей строки
|
// Инициализация бегущей строки
|
||||||
$this->variables['hotline'] = [
|
$this->variables['hotline'] = [
|
||||||
'id' => $this->variables['request']['id'] ?? 'hotline'
|
'id' => $this->variables['request']['id'] ?? 'hotline'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Инициализация параметров бегущей строки
|
// Инициализация параметров бегущей строки
|
||||||
$this->variables['hotline']['parameters'] = [
|
$this->variables['hotline']['parameters'] = [
|
||||||
// 'step' => 2
|
// 'step' => 2
|
||||||
];
|
];
|
||||||
|
|
||||||
// Инициализация аттрибутов бегущей строки
|
// Инициализация аттрибутов бегущей строки
|
||||||
$this->variables['hotline']['attributes'] = [
|
$this->variables['hotline']['attributes'] = [
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Инициализация элементов бегущей строки
|
// Инициализация элементов бегущей строки
|
||||||
$this->variables['hotline']['elements'] = [
|
$this->variables['hotline']['elements'] = [
|
||||||
['content' => '1'],
|
['content' => '1'],
|
||||||
[
|
[
|
||||||
'tag' => 'article',
|
'tag' => 'article',
|
||||||
'content' => '2'
|
'content' => '2'
|
||||||
],
|
],
|
||||||
['content' => '3'],
|
['content' => '3'],
|
||||||
['content' => '4'],
|
['content' => '4'],
|
||||||
['content' => '5'],
|
['content' => '5'],
|
||||||
['content' => '6'],
|
['content' => '6'],
|
||||||
['content' => '7'],
|
['content' => '7'],
|
||||||
['content' => '8'],
|
['content' => '8'],
|
||||||
['content' => '9'],
|
['content' => '9'],
|
||||||
['content' => '10'],
|
['content' => '10'],
|
||||||
['content' => '11'],
|
['content' => '11'],
|
||||||
['content' => '12'],
|
['content' => '12'],
|
||||||
['content' => '13'],
|
['content' => '13'],
|
||||||
['content' => '14'],
|
['content' => '14'],
|
||||||
['content' => '15']
|
['content' => '15']
|
||||||
];
|
];
|
||||||
|
|
||||||
// Генерация представления
|
// Генерация представления
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'hotline' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
return $this->view->render(DIRECTORY_SEPARATOR . 'hotline' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace mirzaev\site\ff\controllers;
|
||||||
|
|
||||||
|
// Файлы проекта
|
||||||
|
use mirzaev\site\ff\controllers\core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Контроллер основной страницы
|
||||||
|
*
|
||||||
|
* @package mirzaev\site\ff\controllers
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
final class index_controller extends core
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Главная страница
|
||||||
|
*
|
||||||
|
* @param array $parameters Параметры запроса
|
||||||
|
*/
|
||||||
|
public function index(array $parameters = []): ?string
|
||||||
|
{
|
||||||
|
// Инициализация загружаемых категорий
|
||||||
|
$this->variables['include'] = [
|
||||||
|
'head' => ['self'],
|
||||||
|
'body' => ['self']
|
||||||
|
];
|
||||||
|
|
||||||
|
// Инициализация бегущей строки
|
||||||
|
$this->variables['hotline'] = [
|
||||||
|
'id' => $this->variables['request']['id'] ?? 'hotline'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Инициализация параметров бегущей строки
|
||||||
|
$this->variables['hotline']['parameters'] = [
|
||||||
|
'step' => '0.3'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Инициализация аттрибутов бегущей строки
|
||||||
|
$this->variables['hotline']['attributes'] = [];
|
||||||
|
|
||||||
|
// Инициализация элементов бегущей строки
|
||||||
|
$this->variables['hotline']['elements'] = [
|
||||||
|
['html' => '1'],
|
||||||
|
[
|
||||||
|
'tag' => 'article',
|
||||||
|
'attributes' => [
|
||||||
|
'class' => 'trash'
|
||||||
|
],
|
||||||
|
'html' => $this->view->render(DIRECTORY_SEPARATOR . 'hotline' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . 'trash.html', [
|
||||||
|
'id' => 'trash_1',
|
||||||
|
'title' => 'Linoleum',
|
||||||
|
'main' => '<p>Do you really like the rotting smell, dull sound and disgusting greasy shine of parquet-like fake pattern on a polymer toxic film? <b>Are you fucking insane?</b></p>',
|
||||||
|
'image' => [
|
||||||
|
'src' => '/images/trash/linoleum.png',
|
||||||
|
'alt' => 'Linoleum'
|
||||||
|
]
|
||||||
|
])
|
||||||
|
],
|
||||||
|
['html' => '3'],
|
||||||
|
['html' => '4'],
|
||||||
|
['html' => '5'],
|
||||||
|
['html' => '6'],
|
||||||
|
['html' => '7'],
|
||||||
|
['html' => '8'],
|
||||||
|
['html' => '9'],
|
||||||
|
['html' => '10'],
|
||||||
|
['html' => '11'],
|
||||||
|
['html' => '12'],
|
||||||
|
['html' => '13'],
|
||||||
|
['html' => '14'],
|
||||||
|
['html' => '15']
|
||||||
|
];
|
||||||
|
|
||||||
|
// Генерация представления
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,169 +1,169 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\site\virus\models;
|
namespace mirzaev\site\ff\models;
|
||||||
|
|
||||||
// Файлы проекта
|
// Файлы проекта
|
||||||
use mirzaev\site\virus\models\vk_model as vk;
|
use mirzaev\site\ff\models\vk_model as vk;
|
||||||
|
|
||||||
// Фреймворк ArangoDB
|
// Фреймворк ArangoDB
|
||||||
use mirzaev\arangodb\collection,
|
use mirzaev\arangodb\collection,
|
||||||
mirzaev\arangodb\document;
|
mirzaev\arangodb\document;
|
||||||
|
|
||||||
// Библиотека для ArangoDB
|
// Библиотека для ArangoDB
|
||||||
use ArangoDBClient\Document as _document;
|
use ArangoDBClient\Document as _document;
|
||||||
|
|
||||||
// Встроенные библиотеки
|
// Встроенные библиотеки
|
||||||
use exception;
|
use exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Модель регистрации, аутентификации и авторизации
|
* Модель регистрации, аутентификации и авторизации
|
||||||
*
|
*
|
||||||
* @package mirzaev\site\virus\models
|
* @package mirzaev\site\ff\models
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
final class account_model extends core
|
final class account_model extends core
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Коллекция
|
* Коллекция
|
||||||
*/
|
*/
|
||||||
public const COLLECTION = 'account';
|
public const COLLECTION = 'account';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Создать
|
* Создать
|
||||||
*
|
*
|
||||||
* @param array &$errors Журнал ошибок
|
* @param array &$errors Журнал ошибок
|
||||||
*
|
*
|
||||||
* @return ?_document Инстанция аккаунта, если удалось создать
|
* @return ?_document Инстанция аккаунта, если удалось создать
|
||||||
*/
|
*/
|
||||||
public static function create(array &$errors = []): ?_document
|
public static function create(array &$errors = []): ?_document
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (collection::init(static::$db->session, self::COLLECTION)) {
|
if (collection::init(static::$db->session, self::COLLECTION)) {
|
||||||
// Инициализирована коллекция
|
// Инициализирована коллекция
|
||||||
|
|
||||||
// Запись аккаунта в базу данных
|
// Запись аккаунта в базу данных
|
||||||
$_id = document::write(static::$db->session, self::COLLECTION);
|
$_id = document::write(static::$db->session, self::COLLECTION);
|
||||||
|
|
||||||
if ($account = collection::search(static::$db->session, sprintf(
|
if ($account = collection::search(static::$db->session, sprintf(
|
||||||
<<<AQL
|
<<<AQL
|
||||||
FOR d IN %s
|
FOR d IN %s
|
||||||
FILTER d._id == '$_id'
|
FILTER d._id == '$_id'
|
||||||
RETURN d
|
RETURN d
|
||||||
AQL,
|
AQL,
|
||||||
self::COLLECTION
|
self::COLLECTION
|
||||||
))) {
|
))) {
|
||||||
// Найден созданный аккаунт
|
// Найден созданный аккаунт
|
||||||
|
|
||||||
return $account;
|
return $account;
|
||||||
} else throw new exception('Не удалось создать аккаунт');
|
} else throw new exception('Не удалось создать аккаунт');
|
||||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||||
} catch (exception $e) {
|
} catch (exception $e) {
|
||||||
// Запись в журнал ошибок
|
// Запись в журнал ошибок
|
||||||
$errors[] = [
|
$errors[] = [
|
||||||
'text' => $e->getMessage(),
|
'text' => $e->getMessage(),
|
||||||
'file' => $e->getFile(),
|
'file' => $e->getFile(),
|
||||||
'line' => $e->getLine(),
|
'line' => $e->getLine(),
|
||||||
'stack' => $e->getTrace()
|
'stack' => $e->getTrace()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Связь аккаунта с аккаунтом ВКонтакте
|
* Связь аккаунта с аккаунтом ВКонтакте
|
||||||
*
|
*
|
||||||
* @param _document $account Инстанция аккаунта
|
* @param _document $account Инстанция аккаунта
|
||||||
* @param _document $vk Инстанция аккаунта ВКонтакте
|
* @param _document $vk Инстанция аккаунта ВКонтакте
|
||||||
* @param array &$errors Журнал ошибок
|
* @param array &$errors Журнал ошибок
|
||||||
*
|
*
|
||||||
* @return bool Статус выполнения
|
* @return bool Статус выполнения
|
||||||
*/
|
*/
|
||||||
public static function connect(_document $account, _document $vk, array &$errors = []): bool
|
public static function connect(_document $account, _document $vk, array &$errors = []): bool
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
collection::init(static::$db->session, self::COLLECTION)
|
collection::init(static::$db->session, self::COLLECTION)
|
||||||
&& collection::init(static::$db->session, vk::COLLECTION)
|
&& collection::init(static::$db->session, vk::COLLECTION)
|
||||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
|
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
|
||||||
) {
|
) {
|
||||||
// Инициализированы коллекции
|
// Инициализированы коллекции
|
||||||
|
|
||||||
if (document::write(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, [
|
if (document::write(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, [
|
||||||
'_from' => $account->getId(),
|
'_from' => $account->getId(),
|
||||||
'_to' => $vk->getId()
|
'_to' => $vk->getId()
|
||||||
])) {
|
])) {
|
||||||
// Создано ребро: account -> vk
|
// Создано ребро: account -> vk
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else throw new exception('Не удалось создать ребро: account -> vk');
|
} else throw new exception('Не удалось создать ребро: account -> vk');
|
||||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||||
} catch (exception $e) {
|
} catch (exception $e) {
|
||||||
// Запись в журнал ошибок
|
// Запись в журнал ошибок
|
||||||
$errors[] = [
|
$errors[] = [
|
||||||
'text' => $e->getMessage(),
|
'text' => $e->getMessage(),
|
||||||
'file' => $e->getFile(),
|
'file' => $e->getFile(),
|
||||||
'line' => $e->getLine(),
|
'line' => $e->getLine(),
|
||||||
'stack' => $e->getTrace()
|
'stack' => $e->getTrace()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Поиск связанного аккаунта ВКонтакте
|
* Поиск связанного аккаунта ВКонтакте
|
||||||
*
|
*
|
||||||
* @param _document $account Инстанция аккаунта
|
* @param _document $account Инстанция аккаунта
|
||||||
* @param array &$errors Журнал ошибок
|
* @param array &$errors Журнал ошибок
|
||||||
*
|
*
|
||||||
* @return ?_document Инстанция аккаунта, если удалось найти
|
* @return ?_document Инстанция аккаунта, если удалось найти
|
||||||
*/
|
*/
|
||||||
public static function vk(_document $account, array &$errors = []): ?_document
|
public static function vk(_document $account, array &$errors = []): ?_document
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
collection::init(static::$db->session, self::COLLECTION)
|
collection::init(static::$db->session, self::COLLECTION)
|
||||||
&& collection::init(static::$db->session, vk::COLLECTION)
|
&& collection::init(static::$db->session, vk::COLLECTION)
|
||||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
|
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
|
||||||
) {
|
) {
|
||||||
// Инициализирована коллекция
|
// Инициализирована коллекция
|
||||||
|
|
||||||
if ($vk = collection::search(static::$db->session, sprintf(
|
if ($vk = collection::search(static::$db->session, sprintf(
|
||||||
<<<AQL
|
<<<AQL
|
||||||
FOR document IN %s
|
FOR document IN %s
|
||||||
LET edge = (
|
LET edge = (
|
||||||
FOR edge IN %s
|
FOR edge IN %s
|
||||||
FILTER edge._from == '%s'
|
FILTER edge._from == '%s'
|
||||||
SORT edge._key DESC
|
SORT edge._key DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
RETURN edge
|
RETURN edge
|
||||||
)
|
)
|
||||||
FILTER document._id == edge[0]._to
|
FILTER document._id == edge[0]._to
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
RETURN document
|
RETURN document
|
||||||
AQL,
|
AQL,
|
||||||
vk::COLLECTION,
|
vk::COLLECTION,
|
||||||
self::COLLECTION . '_edge_' . vk::COLLECTION,
|
self::COLLECTION . '_edge_' . vk::COLLECTION,
|
||||||
$account->getId()
|
$account->getId()
|
||||||
))) {
|
))) {
|
||||||
// Найден аккаунт ВКонтакте
|
// Найден аккаунт ВКонтакте
|
||||||
|
|
||||||
return $vk;
|
return $vk;
|
||||||
} else throw new exception('Не удалось найти аккаунт ВКонтакте');
|
} else throw new exception('Не удалось найти аккаунт ВКонтакте');
|
||||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||||
} catch (exception $e) {
|
} catch (exception $e) {
|
||||||
// Запись в журнал ошибок
|
// Запись в журнал ошибок
|
||||||
$errors[] = [
|
$errors[] = [
|
||||||
'text' => $e->getMessage(),
|
'text' => $e->getMessage(),
|
||||||
'file' => $e->getFile(),
|
'file' => $e->getFile(),
|
||||||
'line' => $e->getLine(),
|
'line' => $e->getLine(),
|
||||||
'stack' => $e->getTrace()
|
'stack' => $e->getTrace()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,143 +1,143 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\site\virus\models;
|
namespace mirzaev\site\ff\models;
|
||||||
|
|
||||||
use mirzaev\minimal\model;
|
use mirzaev\minimal\model;
|
||||||
|
|
||||||
use mirzaev\arangodb\connection;
|
use mirzaev\arangodb\connection;
|
||||||
|
|
||||||
use exception;
|
use exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ядро моделей
|
* Ядро моделей
|
||||||
*
|
*
|
||||||
* @package mirzaev\site\virus\models
|
* @package mirzaev\site\ff\models
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
class core extends model
|
class core extends model
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Коллекция в которой хранятся аккаунты
|
* Коллекция в которой хранятся аккаунты
|
||||||
*/
|
*/
|
||||||
public const SETTINGS = '../settings/arangodb.php';
|
public const SETTINGS = '../settings/arangodb.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Соединение с базой данных
|
* Соединение с базой данных
|
||||||
*/
|
*/
|
||||||
protected static connection $db;
|
protected static connection $db;
|
||||||
|
|
||||||
public function __construct(connection $db = null)
|
public function __construct(connection $db = null)
|
||||||
{
|
{
|
||||||
if (isset($db)) {
|
if (isset($db)) {
|
||||||
// Получена инстанция соединения с базой данных
|
// Получена инстанция соединения с базой данных
|
||||||
|
|
||||||
// Запись и инициализация соединения с базой данных
|
// Запись и инициализация соединения с базой данных
|
||||||
$this->__set('db', $db);
|
$this->__set('db', $db);
|
||||||
} else {
|
} else {
|
||||||
// Не получена инстанция соединения с базой данных
|
// Не получена инстанция соединения с базой данных
|
||||||
|
|
||||||
// Инициализация соединения с базой данных по умолчанию
|
// Инициализация соединения с базой данных по умолчанию
|
||||||
$this->__get('db');
|
$this->__get('db');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Записать свойство
|
* Записать свойство
|
||||||
*
|
*
|
||||||
* @param string $name Название
|
* @param string $name Название
|
||||||
* @param mixed $value Значение
|
* @param mixed $value Значение
|
||||||
*/
|
*/
|
||||||
public function __set(string $name, mixed $value = null): void
|
public function __set(string $name, mixed $value = null): void
|
||||||
{
|
{
|
||||||
match ($name) {
|
match ($name) {
|
||||||
'db' => (function () use ($value) {
|
'db' => (function () use ($value) {
|
||||||
if ($this->__isset('db')) {
|
if ($this->__isset('db')) {
|
||||||
// Свойство уже было инициализировано
|
// Свойство уже было инициализировано
|
||||||
|
|
||||||
// Выброс исключения (неудача)
|
// Выброс исключения (неудача)
|
||||||
throw new exception('Запрещено реинициализировать соединение с базой данных ($this->db)', 500);
|
throw new exception('Запрещено реинициализировать соединение с базой данных ($this->db)', 500);
|
||||||
} else {
|
} else {
|
||||||
// Свойство ещё не было инициализировано
|
// Свойство ещё не было инициализировано
|
||||||
|
|
||||||
if ($value instanceof connection) {
|
if ($value instanceof connection) {
|
||||||
// Передано подходящее значение
|
// Передано подходящее значение
|
||||||
|
|
||||||
// Запись свойства (успех)
|
// Запись свойства (успех)
|
||||||
self::$db = $value;
|
self::$db = $value;
|
||||||
} else {
|
} else {
|
||||||
// Передано неподходящее значение
|
// Передано неподходящее значение
|
||||||
|
|
||||||
// Выброс исключения (неудача)
|
// Выброс исключения (неудача)
|
||||||
throw new exception('Соединение с базой данных ($this->db) должен быть инстанцией mirzaev\arangodb\connection', 500);
|
throw new exception('Соединение с базой данных ($this->db) должен быть инстанцией mirzaev\arangodb\connection', 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})(),
|
})(),
|
||||||
default => parent::__set($name, $value)
|
default => parent::__set($name, $value)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Прочитать свойство
|
* Прочитать свойство
|
||||||
*
|
*
|
||||||
* @param string $name Название
|
* @param string $name Название
|
||||||
*
|
*
|
||||||
* @return mixed Содержимое
|
* @return mixed Содержимое
|
||||||
*/
|
*/
|
||||||
public function __get(string $name): mixed
|
public function __get(string $name): mixed
|
||||||
{
|
{
|
||||||
return match ($name) {
|
return match ($name) {
|
||||||
'db' => (function () {
|
'db' => (function () {
|
||||||
if (!$this->__isset('db')) {
|
if (!$this->__isset('db')) {
|
||||||
// Свойство не инициализировано
|
// Свойство не инициализировано
|
||||||
|
|
||||||
// Инициализация значения по умолчанию исходя из настроек
|
// Инициализация значения по умолчанию исходя из настроек
|
||||||
$this->__set('db', new connection(require static::SETTINGS));
|
$this->__set('db', new connection(require static::SETTINGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$db;
|
return self::$db;
|
||||||
})(),
|
})(),
|
||||||
default => parent::__get($name)
|
default => parent::__get($name)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Проверить свойство на инициализированность
|
* Проверить свойство на инициализированность
|
||||||
*
|
*
|
||||||
* @param string $name Название
|
* @param string $name Название
|
||||||
*/
|
*/
|
||||||
public function __isset(string $name): bool
|
public function __isset(string $name): bool
|
||||||
{
|
{
|
||||||
return match ($name) {
|
return match ($name) {
|
||||||
default => parent::__isset($name)
|
default => parent::__isset($name)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Удалить свойство
|
* Удалить свойство
|
||||||
*
|
*
|
||||||
* @param string $name Название
|
* @param string $name Название
|
||||||
*/
|
*/
|
||||||
public function __unset(string $name): void
|
public function __unset(string $name): void
|
||||||
{
|
{
|
||||||
match ($name) {
|
match ($name) {
|
||||||
default => parent::__isset($name)
|
default => parent::__isset($name)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Статический вызов
|
* Статический вызов
|
||||||
*
|
*
|
||||||
* @param string $name Название
|
* @param string $name Название
|
||||||
* @param array $arguments Параметры
|
* @param array $arguments Параметры
|
||||||
*/
|
*/
|
||||||
public static function __callStatic(string $name, array $arguments): mixed
|
public static function __callStatic(string $name, array $arguments): mixed
|
||||||
{
|
{
|
||||||
match ($name) {
|
match ($name) {
|
||||||
'db' => (new static)->__get('db'),
|
'db' => (new static)->__get('db'),
|
||||||
default => throw new exception("Не найдено свойство или функция: $name", 500)
|
default => throw new exception("Не найдено свойство или функция: $name", 500)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,216 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace mirzaev\site\ff\models;
|
||||||
|
|
||||||
|
// Файлы проекта
|
||||||
|
use mirzaev\site\ff\models\account_model as account;
|
||||||
|
|
||||||
|
// Фреймворк ArangoDB
|
||||||
|
use mirzaev\arangodb\collection,
|
||||||
|
mirzaev\arangodb\document;
|
||||||
|
|
||||||
|
// Библиотека для ArangoDB
|
||||||
|
use ArangoDBClient\Document as _document;
|
||||||
|
|
||||||
|
// Встроенные библиотеки
|
||||||
|
use exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Модель сессий
|
||||||
|
*
|
||||||
|
* @package mirzaev\site\ff\models
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
final class session_model extends core
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Коллекция
|
||||||
|
*/
|
||||||
|
public const COLLECTION = 'session';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Инициализация
|
||||||
|
*
|
||||||
|
* @param ?string $hash Хеш сессии в базе данных
|
||||||
|
* @param ?int $expires Дата окончания работы сессии (используется при создании новой сессии)
|
||||||
|
* @param array &$errors Журнал ошибок
|
||||||
|
*
|
||||||
|
* @return ?_document Инстанция сессии, если удалось найти или создать
|
||||||
|
*/
|
||||||
|
public static function initialization(?string $hash = null, ?int $expires = null, array &$errors = []): ?_document
|
||||||
|
{
|
||||||
|
$a = new _document();
|
||||||
|
$a->hash = 'dolboeb227';
|
||||||
|
return $a;
|
||||||
|
try {
|
||||||
|
if (collection::init(static::$db->session, self::COLLECTION)) {
|
||||||
|
// Инициализирована коллекция
|
||||||
|
|
||||||
|
if (isset($hash) && $session = collection::search(static::$db->session, sprintf(
|
||||||
|
<<<AQL
|
||||||
|
FOR d IN %s
|
||||||
|
FILTER d.hash == '$hash' && d.expires > %d
|
||||||
|
RETURN d
|
||||||
|
AQL,
|
||||||
|
self::COLLECTION,
|
||||||
|
time()
|
||||||
|
))) {
|
||||||
|
// Найдена сессия по хешу
|
||||||
|
|
||||||
|
// Возврат сессии
|
||||||
|
return $session;
|
||||||
|
} else if ($session = collection::search(static::$db->session, sprintf(
|
||||||
|
<<<AQL
|
||||||
|
FOR d IN %s
|
||||||
|
FILTER d.ip == '%s' && d.expires > %d
|
||||||
|
RETURN d
|
||||||
|
AQL,
|
||||||
|
self::COLLECTION,
|
||||||
|
$_SERVER['REMOTE_ADDR'],
|
||||||
|
time()
|
||||||
|
))) {
|
||||||
|
// Найдена сессия по данным пользователя
|
||||||
|
|
||||||
|
// Возврат сессии
|
||||||
|
return $session;
|
||||||
|
} else {
|
||||||
|
// Не найдена сессия
|
||||||
|
|
||||||
|
// Запись сессии в базу данных
|
||||||
|
$_id = document::write(static::$db->session, self::COLLECTION, [
|
||||||
|
'ip' => $_SERVER['REMOTE_ADDR'],
|
||||||
|
'expires' => $expires ?? time() + 604800
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($session = collection::search(static::$db->session, sprintf(
|
||||||
|
<<<AQL
|
||||||
|
FOR d IN %s
|
||||||
|
FILTER d._id == '$_id' && d.expires > %d
|
||||||
|
RETURN d
|
||||||
|
AQL,
|
||||||
|
self::COLLECTION,
|
||||||
|
time()
|
||||||
|
))) {
|
||||||
|
// Найдена созданная сессия
|
||||||
|
|
||||||
|
// Запись хеша
|
||||||
|
$session->hash = sodium_bin2hex(sodium_crypto_generichash($_id));
|
||||||
|
|
||||||
|
if (document::update(static::$db->session, $session)) {
|
||||||
|
// Записано обновление
|
||||||
|
|
||||||
|
return $session;
|
||||||
|
} else throw new exception('Не удалось записать данные сессии');
|
||||||
|
} else throw new exception('Не удалось создать или найти созданную сессию');
|
||||||
|
}
|
||||||
|
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||||
|
} catch (exception $e) {
|
||||||
|
// Запись в журнал ошибок
|
||||||
|
$errors[] = [
|
||||||
|
'text' => $e->getMessage(),
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'stack' => $e->getTrace()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Связь сессии с аккаунтом
|
||||||
|
*
|
||||||
|
* @param _document $session Инстанция сессии
|
||||||
|
* @param _document $account Инстанция аккаунта
|
||||||
|
* @param array &$errors Журнал ошибок
|
||||||
|
*
|
||||||
|
* @return bool Статус выполнения
|
||||||
|
*/
|
||||||
|
public static function connect(_document $session, _document $account, array &$errors = []): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
collection::init(static::$db->session, self::COLLECTION)
|
||||||
|
&& collection::init(static::$db->session, account::COLLECTION)
|
||||||
|
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, true)
|
||||||
|
) {
|
||||||
|
// Инициализирована коллекция
|
||||||
|
|
||||||
|
if (document::write(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, [
|
||||||
|
'_from' => $session->getId(),
|
||||||
|
'_to' => $account->getId()
|
||||||
|
])) {
|
||||||
|
// Создано ребро: session -> account
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else throw new exception('Не удалось создать ребро: session -> account');
|
||||||
|
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||||
|
} catch (exception $e) {
|
||||||
|
// Запись в журнал ошибок
|
||||||
|
$errors[] = [
|
||||||
|
'text' => $e->getMessage(),
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'stack' => $e->getTrace()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Поиск связанного аккаунта
|
||||||
|
*
|
||||||
|
* @param _document $session Инстанция сессии
|
||||||
|
* @param array &$errors Журнал ошибок
|
||||||
|
*
|
||||||
|
* @return ?_document Инстанция аккаунта, если удалось найти
|
||||||
|
*/
|
||||||
|
public static function account(_document $session, array &$errors = []): ?_document
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
collection::init(static::$db->session, self::COLLECTION)
|
||||||
|
&& collection::init(static::$db->session, account::COLLECTION)
|
||||||
|
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, true)
|
||||||
|
) {
|
||||||
|
// Инициализированы коллекции
|
||||||
|
|
||||||
|
if ($account = collection::search(static::$db->session, sprintf(
|
||||||
|
<<<AQL
|
||||||
|
FOR document IN %s
|
||||||
|
LET edge = (
|
||||||
|
FOR edge IN %s
|
||||||
|
FILTER edge._from == '%s'
|
||||||
|
SORT edge._key DESC
|
||||||
|
LIMIT 1
|
||||||
|
RETURN edge
|
||||||
|
)
|
||||||
|
FILTER document._id == edge[0]._to
|
||||||
|
LIMIT 1
|
||||||
|
RETURN document
|
||||||
|
AQL,
|
||||||
|
account::COLLECTION,
|
||||||
|
self::COLLECTION . '_edge_' . account::COLLECTION,
|
||||||
|
$session->getId()
|
||||||
|
))) {
|
||||||
|
// Найден аккаунт
|
||||||
|
|
||||||
|
return $account;
|
||||||
|
} else throw new exception('Не удалось найти аккаунт');
|
||||||
|
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||||
|
} catch (exception $e) {
|
||||||
|
// Запись в журнал ошибок
|
||||||
|
$errors[] = [
|
||||||
|
'text' => $e->getMessage(),
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'stack' => $e->getTrace()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,119 +1,119 @@
|
||||||
#mail>:is(form, div) {
|
#mail>:is(form, div) {
|
||||||
display : flex;
|
display : flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail .exit {
|
#mail .exit {
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail p {
|
#mail p {
|
||||||
margin : 0;
|
margin : 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail p>span {
|
#mail p>span {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail>form>input:is([type=text], [type=password]) {
|
#mail>form>input:is([type=text], [type=password]) {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail>form>input:last-child {
|
#mail>form>input:last-child {
|
||||||
margin-bottom: unset;
|
margin-bottom: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail>form>.submit {
|
#mail>form>.submit {
|
||||||
margin-top : 6px;
|
margin-top : 6px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
display : flex;
|
display : flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail>form>.submit>label {
|
#mail>form>.submit>label {
|
||||||
padding : 10px 20px;
|
padding : 10px 20px;
|
||||||
border : unset;
|
border : unset;
|
||||||
border-radius: 3px 0 0 3px;
|
border-radius: 3px 0 0 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail>form>.submit>input {
|
#mail>form>.submit>input {
|
||||||
padding : 10px 20px;
|
padding : 10px 20px;
|
||||||
flex-grow : 1;
|
flex-grow : 1;
|
||||||
border : unset;
|
border : unset;
|
||||||
border-radius: 0 3px 3px 0;
|
border-radius: 0 3px 3px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#mail>form>input[type=submit].registration {
|
#mail>form>input[type=submit].registration {
|
||||||
padding : 7px 20px;
|
padding : 7px 20px;
|
||||||
background-color: #86781C;
|
background-color: #86781C;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail>form>input[type=submit].registration:hover {
|
#mail>form>input[type=submit].registration:hover {
|
||||||
background-color: #9e8d20;
|
background-color: #9e8d20;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail>form>input[type=submit].registration:is(:active, :focus) {
|
#mail>form>input[type=submit].registration:is(:active, :focus) {
|
||||||
background-color: #776b19;
|
background-color: #776b19;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mail>form>ul.errors {
|
#mail>form>ul.errors {
|
||||||
margin-top : 18px;
|
margin-top : 18px;
|
||||||
margin-bottom : 0px;
|
margin-bottom : 0px;
|
||||||
padding : 10px;
|
padding : 10px;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
list-style : none;
|
list-style : none;
|
||||||
background-color: #ae8f8f;
|
background-color: #ae8f8f;
|
||||||
}
|
}
|
||||||
|
|
||||||
#account {
|
#account {
|
||||||
display : grid;
|
display : grid;
|
||||||
grid-template-rows: auto auto;
|
grid-template-rows: auto auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#account>button#login {
|
#account>button#login {
|
||||||
z-index : 1500;
|
z-index : 1500;
|
||||||
grid-row: 2;
|
grid-row: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#account>section.tab {
|
#account>section.tab {
|
||||||
z-index : 1000;
|
z-index : 1000;
|
||||||
position : relative;
|
position : relative;
|
||||||
bottom : -100%;
|
bottom : -100%;
|
||||||
padding : 1.5rem 10%;
|
padding : 1.5rem 10%;
|
||||||
display : flex;
|
display : flex;
|
||||||
flex-direction : column;
|
flex-direction : column;
|
||||||
align-self : end;
|
align-self : end;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
gap : .8rem;
|
gap : .8rem;
|
||||||
background-color: var(--background-light-2);
|
background-color: var(--background-light-2);
|
||||||
transition : .2s ease-in;
|
transition : .2s ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
#account>button.active+section.tab {
|
#account>button.active+section.tab {
|
||||||
bottom: 0%;
|
bottom: 0%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#account>section.tab h3:first-of-type {
|
#account>section.tab h3:first-of-type {
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#account>section.tab>* {
|
#account>section.tab>* {
|
||||||
margin: unset;
|
margin: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#account>section#mail.tab {
|
#account>section#mail.tab {
|
||||||
grid-row : 1;
|
grid-row : 1;
|
||||||
display : grid;
|
display : grid;
|
||||||
grid-template-rows: auto auto;
|
grid-template-rows: auto auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#account>section#mail.tab>#profile {
|
#account>section#mail.tab>#profile {
|
||||||
grid-row : 1;
|
grid-row : 1;
|
||||||
display : grid;
|
display : grid;
|
||||||
grid-template-rows: auto auto;
|
grid-template-rows: auto auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#account>section#mail.tab>input[type=mail] {
|
#account>section#mail.tab>input[type=mail] {
|
||||||
grid-row : 2;
|
grid-row : 2;
|
||||||
}
|
}
|
|
@ -1,52 +1,52 @@
|
||||||
main>section#books {
|
main>section#books {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
main>section#books>* {
|
main>section#books>* {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
main>section#books>form.upload {
|
main>section#books>form.upload {
|
||||||
width: calc(100% / 3 - 20px - 9px * 2);
|
width: calc(100% / 3 - 20px - 9px * 2);
|
||||||
height: calc(220px - 9px * 2);
|
height: calc(220px - 9px * 2);
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
main>section#books>form.upload>p {
|
main>section#books>form.upload>p {
|
||||||
font-size: 3rem;
|
font-size: 3rem;
|
||||||
height: 0.3rem;
|
height: 0.3rem;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
main>section#books>article.book {
|
main>section#books>article.book {
|
||||||
width: calc(100% / 3 - 20px);
|
width: calc(100% / 3 - 20px);
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
main>section#books>article.book:nth-child(3) {
|
main>section#books>article.book:nth-child(3) {
|
||||||
width: calc(100% / 3);
|
width: calc(100% / 3);
|
||||||
margin-right: unset;
|
margin-right: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
main>section#books>article.book>img {
|
main>section#books>article.book>img {
|
||||||
height: 220px;
|
height: 220px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
object-position: right;
|
object-position: right;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
clip-path: polygon(5px calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 5px, 5px 5px);
|
clip-path: polygon(5px calc(100% - 5px), calc(100% - 5px) calc(100% - 5px), calc(100% - 5px) 5px, 5px 5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
main>section#books>article.book>h4 {
|
main>section#books>article.book>h4 {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
main>section#books>article.book>p {
|
main>section#books>article.book>p {
|
||||||
margin: unset;
|
margin: unset;
|
||||||
}
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
section.hotline {
|
||||||
|
display: inline-flex;
|
||||||
|
height: 100%;
|
||||||
|
transition: unset;
|
||||||
|
/* gap нельзя */
|
||||||
|
}
|
||||||
|
|
||||||
|
section.hotline * {
|
||||||
|
transition: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
section.hotline:last-child {
|
||||||
|
margin-bottom: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.hotline > article {
|
||||||
|
position: relative;
|
||||||
|
margin-right: 18px;
|
||||||
|
width: calc(140px - var(--padding, 0px) * 2);
|
||||||
|
height: calc(190px - var(--padding, 0px) * 2);
|
||||||
|
padding: var(--padding, 0px);
|
||||||
|
display: flex;
|
||||||
|
align-self: flex-end;
|
||||||
|
overflow: clip;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: var(--background-light-1);
|
||||||
|
box-shadow: 0px -6px 6px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
section.hotline>article:last-child {
|
||||||
|
margin-right: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.hotline > article > * {
|
||||||
|
margin: auto;
|
||||||
|
}
|
|
@ -1,40 +1,40 @@
|
||||||
header>div#logo {
|
header>div#logo {
|
||||||
position : relative;
|
position : relative;
|
||||||
height : 260px;
|
height : 260px;
|
||||||
display : flex;
|
display : flex;
|
||||||
flex-direction : column;
|
flex-direction : column;
|
||||||
justify-content : center;
|
justify-content : center;
|
||||||
gap : unset;
|
gap : unset;
|
||||||
border-right : 1px solid;
|
border-right : 1px solid;
|
||||||
border-right-color: #ccc;
|
border-right-color: #ccc;
|
||||||
border-right-color: rgba(255, 255, 255, 0.2);
|
border-right-color: rgba(255, 255, 255, 0.2);
|
||||||
background-color : rgba(255, 255, 255, 0.2);
|
background-color : rgba(255, 255, 255, 0.2);
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
header>div#logo>h4 {
|
header>div#logo>h4 {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
margin : 0 20px;
|
margin : 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
header>div#logo>h1 {
|
header>div#logo>h1 {
|
||||||
z-index : 50;
|
z-index : 50;
|
||||||
margin : 0 37px;
|
margin : 0 37px;
|
||||||
margin-bottom: -5px;
|
margin-bottom: -5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
header>div#logo>#hotline_logo {
|
header>div#logo>#hotline_logo {
|
||||||
z-index : -50;
|
z-index : -50;
|
||||||
position : absolute;
|
position : absolute;
|
||||||
-webkit-filter : blur(2px) brightness(1.3);
|
-webkit-filter : blur(2px) brightness(1.3);
|
||||||
filter : blur(2px) brightness(1.3);
|
filter : blur(2px) brightness(1.3);
|
||||||
/* background-color: var(--background); */
|
/* background-color: var(--background); */
|
||||||
}
|
}
|
||||||
|
|
||||||
header>div#logo>#hotline_logo>article {
|
header>div#logo>#hotline_logo>article {
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
aside>section#hotline {
|
aside>section#hotline {
|
||||||
clip-path: inset(0 0 0 250px);
|
clip-path: inset(0 0 0 250px);
|
||||||
}
|
}
|
|
@ -1,165 +1,165 @@
|
||||||
@import url('/fonts/comissioner.ttf');
|
@import url('/fonts/comissioner.ttf');
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
@media (prefers-color-scheme: light) {
|
||||||
:root {
|
:root {
|
||||||
--background: #eee;
|
--background: #eee;
|
||||||
--text : 'dark';
|
--text : 'dark';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
:root {
|
:root {
|
||||||
--background-light-3: #403939;
|
--background-light-3: #403939;
|
||||||
--background-light-2: #322d2d;
|
--background-light-2: #322d2d;
|
||||||
--background-light-1: #2b2525;
|
--background-light-1: #2b2525;
|
||||||
--background-light : #252020;
|
--background-light : #252020;
|
||||||
--background : #221e1e;
|
--background : #221e1e;
|
||||||
--background-dark : ;
|
--background-dark : ;
|
||||||
--text : #e6e6e6;
|
--text : #e6e6e6;
|
||||||
--text-hover : #fff;
|
--text-hover : #fff;
|
||||||
--text-active : #d0d0d0;
|
--text-active : #d0d0d0;
|
||||||
--red-light-1 : #dc4343;
|
--red-light-1 : #dc4343;
|
||||||
--red-light : #bf3737;
|
--red-light : #bf3737;
|
||||||
--red : #a43333;
|
--red : #a43333;
|
||||||
--red-dark : #8d2a2a;
|
--red-dark : #8d2a2a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
outline : none;
|
outline : none;
|
||||||
border : none;
|
border : none;
|
||||||
color : var(--text);
|
color : var(--text);
|
||||||
font-family : 'Commissioner', sans-serif;
|
font-family : 'Commissioner', sans-serif;
|
||||||
transition : 0.1s ease-out;
|
transition : 0.1s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unselectable {
|
.unselectable {
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
-webkit-user-select : none;
|
-webkit-user-select : none;
|
||||||
-khtml-user-select : none;
|
-khtml-user-select : none;
|
||||||
-moz-user-select : none;
|
-moz-user-select : none;
|
||||||
-ms-user-select : none;
|
-ms-user-select : none;
|
||||||
user-select : none;
|
user-select : none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
color: var(--text-hover);
|
color: var(--text-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
a:active {
|
a:active {
|
||||||
color: var(--text-active);
|
color: var(--text-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
height : 100vh;
|
height : 100vh;
|
||||||
margin : 0;
|
margin : 0;
|
||||||
display : grid;
|
display : grid;
|
||||||
grid-template-rows : 10px 200px auto 10px;
|
grid-template-rows : 10px 200px auto 10px;
|
||||||
grid-template-columns: 250px auto 300px;
|
grid-template-columns: 250px auto 300px;
|
||||||
grid-row-gap : 20px;
|
grid-row-gap : 20px;
|
||||||
grid-column-gap : 15px;
|
grid-column-gap : 15px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color : var(--background);
|
background-color : var(--background);
|
||||||
}
|
}
|
||||||
|
|
||||||
aside {
|
aside {
|
||||||
z-index : 500;
|
z-index : 500;
|
||||||
grid-column: 1/ 4;
|
grid-column: 1/ 4;
|
||||||
grid-row : 2;
|
grid-row : 2;
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
z-index : 5000;
|
z-index : 5000;
|
||||||
grid-column : 1;
|
grid-column : 1;
|
||||||
grid-row : 1 / 5;
|
grid-row : 1 / 5;
|
||||||
display : flex;
|
display : flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
box-shadow : 2px 0 5px rgba(0, 0, 0, 0.3);
|
box-shadow : 2px 0 5px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
header>menu {
|
header>menu {
|
||||||
margin : unset;
|
margin : unset;
|
||||||
padding : 20px;
|
padding : 20px;
|
||||||
display : flex;
|
display : flex;
|
||||||
flex-direction : column;
|
flex-direction : column;
|
||||||
flex-grow : 1;
|
flex-grow : 1;
|
||||||
background-color: var(--background-light-1);
|
background-color: var(--background-light-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
header>#account>button#login {
|
header>#account>button#login {
|
||||||
z-index : 1500;
|
z-index : 1500;
|
||||||
}
|
}
|
||||||
|
|
||||||
header>menu a {
|
header>menu a {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
display : flex;
|
display : flex;
|
||||||
align-items : center;
|
align-items : center;
|
||||||
}
|
}
|
||||||
|
|
||||||
header>menu a:last-child {
|
header>menu a:last-child {
|
||||||
margin-bottom: unset;
|
margin-bottom: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
header>menu a svg {
|
header>menu a svg {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
height : 1.2rem;
|
height : 1.2rem;
|
||||||
position : relative;
|
position : relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
header>menu a:hover svg {
|
header>menu a:hover svg {
|
||||||
margin-left : -5px;
|
margin-left : -5px;
|
||||||
margin-right: 13px;
|
margin-right: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
header>menu a svg path {
|
header>menu a svg path {
|
||||||
fill: var(--text);
|
fill: var(--text);
|
||||||
}
|
}
|
||||||
|
|
||||||
header>section {
|
header>section {
|
||||||
background-color: var(--background-light-1);
|
background-color: var(--background-light-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
header :is(button, a[type="button"]) {
|
header :is(button, a[type="button"]) {
|
||||||
width : 100%;
|
width : 100%;
|
||||||
height : 40px;
|
height : 40px;
|
||||||
display : flex;
|
display : flex;
|
||||||
justify-content : center;
|
justify-content : center;
|
||||||
align-items : center;
|
align-items : center;
|
||||||
cursor : pointer;
|
cursor : pointer;
|
||||||
background-color: var(--red);
|
background-color: var(--red);
|
||||||
transition : unset;
|
transition : unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
header button {
|
header button {
|
||||||
font-weight : bold;
|
font-weight : bold;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
header :is(button, a[type="button"]):hover {
|
header :is(button, a[type="button"]):hover {
|
||||||
background-color: var(--red-light);
|
background-color: var(--red-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
header :is(button, a[type="button"]):active {
|
header :is(button, a[type="button"]):active {
|
||||||
background-color: var(--red-dark);
|
background-color: var(--red-dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
header>nav {
|
header>nav {
|
||||||
margin-top : auto;
|
margin-top : auto;
|
||||||
display : flex;
|
display : flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
z-index : 1000;
|
z-index : 1000;
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
grid-row : 3;
|
grid-row : 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
z-index : 3000;
|
z-index : 3000;
|
||||||
grid-column: 3;
|
grid-column: 3;
|
||||||
grid-row : 1 / 5;
|
grid-row : 1 / 5;
|
||||||
}
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
section.hotline > article.trash {
|
||||||
|
--padding: 12px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
cursor: zoom-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.hotline > article.trash > h1 {
|
||||||
|
z-index: 10;
|
||||||
|
margin-top: 10px;
|
||||||
|
flex-grow: 4;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.hotline > article.trash :is(p, b) {
|
||||||
|
z-index: 10;
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: 0.6rem;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.hotline > article.trash small {
|
||||||
|
z-index: 10;
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.hotline > article.trash > img {
|
||||||
|
z-index: 5;
|
||||||
|
position: absolute;
|
||||||
|
left: -5%;
|
||||||
|
top: -5%;
|
||||||
|
width: 110%;
|
||||||
|
height: 110%;
|
||||||
|
object-position: center;
|
||||||
|
object-fit: cover;
|
||||||
|
filter: blur(2px) saturate(30%) brightness(40%);
|
||||||
|
transition: 0.2s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.hotline > article.trash:is(:hover, :active) > img {
|
||||||
|
left: -20%;
|
||||||
|
top: -20%;
|
||||||
|
width: 140%;
|
||||||
|
height: 140%;
|
||||||
|
filter: blur(3px) saturate(0) brightness(60%) contrast(150%);
|
||||||
|
transition: 0.1s ease-out;
|
||||||
|
}
|
|
@ -1,17 +1,17 @@
|
||||||
#what_image {
|
#what_image {
|
||||||
z-index: 9999999;
|
z-index: 9999999;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
display: none;
|
display: none;
|
||||||
transition: unset;
|
transition: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#what_image.active {
|
#what_image.active {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide {
|
.hide {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
|
@ -1,33 +1,33 @@
|
||||||
form.upload {
|
form.upload {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
border: 4px dashed #e5ddd1;
|
border: 4px dashed #e5ddd1;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.upload:hover {
|
form.upload:hover {
|
||||||
background-color: #ccc6bd;
|
background-color: #ccc6bd;
|
||||||
border: 4px dashed #fff7ea;
|
border: 4px dashed #fff7ea;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.upload>p {
|
form.upload>p {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #eee6d9;
|
color: #eee6d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.upload:hover>p {
|
form.upload:hover>p {
|
||||||
color: #fff7ea;
|
color: #fff7ea;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.upload>input {
|
form.upload>input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.upload:hover>input {
|
form.upload:hover>input {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
Before Width: | Height: | Size: 552 B After Width: | Height: | Size: 552 B |
Before Width: | Height: | Size: 328 B After Width: | Height: | Size: 328 B |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 537 B After Width: | Height: | Size: 537 B |
Before Width: | Height: | Size: 825 B After Width: | Height: | Size: 825 B |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 397 KiB After Width: | Height: | Size: 397 KiB |
Before Width: | Height: | Size: 295 KiB After Width: | Height: | Size: 295 KiB |
|
@ -1,35 +1,35 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\site\virus;
|
namespace mirzaev\site\ff;
|
||||||
|
|
||||||
use mirzaev\minimal\core;
|
use mirzaev\minimal\core;
|
||||||
use mirzaev\minimal\router;
|
use mirzaev\minimal\router;
|
||||||
|
|
||||||
ini_set('error_reporting', E_ALL);
|
ini_set('error_reporting', E_ALL);
|
||||||
ini_set('display_errors', 1);
|
ini_set('display_errors', 1);
|
||||||
ini_set('display_startup_errors', 1);
|
ini_set('display_startup_errors', 1);
|
||||||
|
|
||||||
define('VIEWS', realpath('..' . DIRECTORY_SEPARATOR . 'views'));
|
define('VIEWS', realpath('..' . DIRECTORY_SEPARATOR . 'views'));
|
||||||
define('STORAGE', realpath('..' . DIRECTORY_SEPARATOR . 'storage'));
|
define('STORAGE', realpath('..' . DIRECTORY_SEPARATOR . 'storage'));
|
||||||
define('INDEX', __DIR__);
|
define('INDEX', __DIR__);
|
||||||
|
|
||||||
// Автозагрузка
|
// Автозагрузка
|
||||||
require __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
require __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||||
|
|
||||||
// Инициализация маршрутазитора
|
// Инициализация маршрутазитора
|
||||||
$router = new router;
|
$router = new router;
|
||||||
|
|
||||||
// Запись маршрутов
|
// Запись маршрутов
|
||||||
$router->write('/', 'index', 'index');
|
$router->write('/', 'index', 'index');
|
||||||
$router->write('/system/hotline', 'hotline', 'index');
|
$router->write('/system/hotline', 'hotline', 'index');
|
||||||
$router->write('/account/initialization', 'account', 'initialization', 'PUT');
|
$router->write('/account/initialization', 'account', 'initialization', 'PUT');
|
||||||
$router->write('/account/vk/connect', 'account', 'connect');
|
$router->write('/account/vk/connect', 'account', 'connect');
|
||||||
$router->write('/account/panel', 'account', 'panel');
|
$router->write('/account/panel', 'account', 'panel');
|
||||||
|
|
||||||
// Инициализация ядра
|
// Инициализация ядра
|
||||||
$core = new core(namespace: __NAMESPACE__, router: $router);
|
$core = new core(namespace: __NAMESPACE__, router: $router);
|
||||||
|
|
||||||
// Обработка запроса
|
// Обработка запроса
|
||||||
echo $core->start();
|
echo $core->start();
|
|
@ -1,139 +1,139 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
class account {
|
class account {
|
||||||
static async initialization() {
|
static async initialization() {
|
||||||
// Запрос
|
// Запрос
|
||||||
return fetch('https://virus.mirzaev.sexy/account/initialization', {
|
return fetch('https://virus.mirzaev.sexy/account/initialization', {
|
||||||
method: 'PUT'
|
method: 'PUT'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static authentication(button) {
|
static authentication(button) {
|
||||||
if (button instanceof HTMLElement) {
|
if (button instanceof HTMLElement) {
|
||||||
// Получены обязательные входные параметры
|
// Получены обязательные входные параметры
|
||||||
|
|
||||||
if (button.classList.contains('active')) {
|
if (button.classList.contains('active')) {
|
||||||
// Кнопка активна (подразумевается)
|
// Кнопка активна (подразумевается)
|
||||||
|
|
||||||
if (window.vk !== undefined) {
|
if (window.vk !== undefined) {
|
||||||
// Найдена инстанция окна
|
// Найдена инстанция окна
|
||||||
|
|
||||||
// Закрытие окна
|
// Закрытие окна
|
||||||
window.vk.close();
|
window.vk.close();
|
||||||
|
|
||||||
// Удаление окна
|
// Удаление окна
|
||||||
window.vk = undefined;
|
window.vk = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Генерация панели
|
// Генерация панели
|
||||||
this.panel(button.parentElement);
|
this.panel(button.parentElement);
|
||||||
|
|
||||||
// Вызов троллера
|
// Вызов троллера
|
||||||
troller.what.single();
|
troller.what.single();
|
||||||
} else {
|
} else {
|
||||||
// Кнопка неактивна (подразумевается)
|
// Кнопка неактивна (подразумевается)
|
||||||
|
|
||||||
// Инициализация активного статуса
|
// Инициализация активного статуса
|
||||||
button.classList.add('active');
|
button.classList.add('active');
|
||||||
button.innerText = 'Закрыть';
|
button.innerText = 'Закрыть';
|
||||||
|
|
||||||
// Настройка окна
|
// Настройка окна
|
||||||
const width = 500;
|
const width = 500;
|
||||||
const height = 500;
|
const height = 500;
|
||||||
const left = (window.screen.width / 2) - ((width / 2) + 10);
|
const left = (window.screen.width / 2) - ((width / 2) + 10);
|
||||||
const top = (window.screen.height / 2) - ((height / 2) + 50);
|
const top = (window.screen.height / 2) - ((height / 2) + 50);
|
||||||
|
|
||||||
// Инициализация аккаунта
|
// Инициализация аккаунта
|
||||||
this.initialization()
|
this.initialization()
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 401 && typeof response.headers.get('session') === 'string') {
|
if (response.status === 401 && typeof response.headers.get('session') === 'string') {
|
||||||
// Получен код ответа 401 (не аутентифицирован) и инициализирован аккаунт
|
// Получен код ответа 401 (не аутентифицирован) и инициализирован аккаунт
|
||||||
|
|
||||||
// Открытие окна с аунтентификацией ВКонтакте
|
// Открытие окна с аунтентификацией ВКонтакте
|
||||||
window.vk = window.open(
|
window.vk = window.open(
|
||||||
'https://oauth.vk.com/authorize?client_id=51447080&redirect_uri=https://virus.mirzaev.sexy/account/vk/connect&display=popup&response_type=code&scope=4521990&state=' + response.headers.get('session'),
|
'https://oauth.vk.com/authorize?client_id=51447080&redirect_uri=https://virus.mirzaev.sexy/account/vk/connect&display=popup&response_type=code&scope=4521990&state=' + response.headers.get('session'),
|
||||||
'virus_vk',
|
'virus_vk',
|
||||||
'left=' + left + ',top=' + top + ',width=' + width + ',height=' + height + ',resizable=no,status=no,toolbar=no,menubar=no,scrollbars=no,location=no,directories=no'
|
'left=' + left + ',top=' + top + ',width=' + width + ',height=' + height + ',resizable=no,status=no,toolbar=no,menubar=no,scrollbars=no,location=no,directories=no'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Инициализация ссылки на ядро
|
// Инициализация ссылки на ядро
|
||||||
const _this = this;
|
const _this = this;
|
||||||
|
|
||||||
// Инициализация интервала проверки закрытия окна с аунтентификацией ВКонтакте
|
// Инициализация интервала проверки закрытия окна с аунтентификацией ВКонтакте
|
||||||
const interval = setInterval(function () {
|
const interval = setInterval(function () {
|
||||||
if (window.vk.closed || window.vk === undefined) {
|
if (window.vk.closed || window.vk === undefined) {
|
||||||
// Окно с аутентификацией закрыто
|
// Окно с аутентификацией закрыто
|
||||||
|
|
||||||
// Удаление интервала
|
// Удаление интервала
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
|
|
||||||
// Генерация панели
|
// Генерация панели
|
||||||
_this.panel(button.parentElement);
|
_this.panel(button.parentElement);
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
} else if (response.status === 200) {
|
} else if (response.status === 200) {
|
||||||
// Получен код ответа 200 (аутентифицирован)
|
// Получен код ответа 200 (аутентифицирован)
|
||||||
|
|
||||||
// Генерация панели
|
// Генерация панели
|
||||||
this.panel(button.parentElement);
|
this.panel(button.parentElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static deauthentication() {
|
static deauthentication() {
|
||||||
if (shell instanceof HTMLElement) {
|
if (shell instanceof HTMLElement) {
|
||||||
// Получены обязательные входные параметры
|
// Получены обязательные входные параметры
|
||||||
|
|
||||||
fetch('https://virus.mirzaev.sexy/account/panel', {
|
fetch('https://virus.mirzaev.sexy/account/panel', {
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
}).then(
|
}).then(
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
// Получен код ответа 200
|
// Получен код ответа 200
|
||||||
|
|
||||||
response.text().then(
|
response.text().then(
|
||||||
(text) => {
|
(text) => {
|
||||||
console.log(text);
|
console.log(text);
|
||||||
|
|
||||||
// Запись панели в оболочку
|
// Запись панели в оболочку
|
||||||
shell.outerHTML = text;
|
shell.outerHTML = text;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async panel(shell) {
|
static async panel(shell) {
|
||||||
if (shell instanceof HTMLElement) {
|
if (shell instanceof HTMLElement) {
|
||||||
// Получены обязательные входные параметры
|
// Получены обязательные входные параметры
|
||||||
|
|
||||||
fetch('https://virus.mirzaev.sexy/account/panel', {
|
fetch('https://virus.mirzaev.sexy/account/panel', {
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
}).then(
|
}).then(
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
// Получен код ответа 200
|
// Получен код ответа 200
|
||||||
|
|
||||||
response.text().then(
|
response.text().then(
|
||||||
(text) => {
|
(text) => {
|
||||||
console.log(text);
|
console.log(text);
|
||||||
|
|
||||||
// Запись панели в оболочку
|
// Запись панели в оболочку
|
||||||
shell.outerHTML = text;
|
shell.outerHTML = text;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,127 +1,127 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
class troller {
|
class troller {
|
||||||
static what = {
|
static what = {
|
||||||
enable() {
|
enable() {
|
||||||
document.body.onmouseleave = function () {
|
document.body.onmouseleave = function () {
|
||||||
// if (Math.random() > 0.90) {
|
// if (Math.random() > 0.90) {
|
||||||
// 10%
|
// 10%
|
||||||
|
|
||||||
troller.what.start();
|
troller.what.start();
|
||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
document.body.onmouseenter = function () {
|
document.body.onmouseenter = function () {
|
||||||
troller.what.end();
|
troller.what.end();
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
disable() {
|
disable() {
|
||||||
document.body.onmouseleave = document.body.onmouseenter = undefined;
|
document.body.onmouseleave = document.body.onmouseenter = undefined;
|
||||||
},
|
},
|
||||||
start() {
|
start() {
|
||||||
// Отображение изображения
|
// Отображение изображения
|
||||||
document.getElementById('what_image').classList.add('active');
|
document.getElementById('what_image').classList.add('active');
|
||||||
|
|
||||||
// Инициализация элемента со звуком
|
// Инициализация элемента со звуком
|
||||||
const what_sound = document.getElementById('what_sound');
|
const what_sound = document.getElementById('what_sound');
|
||||||
|
|
||||||
// Воспроизведение звука
|
// Воспроизведение звука
|
||||||
what_sound.currentTime = 0;
|
what_sound.currentTime = 0;
|
||||||
what_sound.play();
|
what_sound.play();
|
||||||
},
|
},
|
||||||
end() {
|
end() {
|
||||||
// Сокрытие изображения
|
// Сокрытие изображения
|
||||||
document.getElementById('what_image').classList.remove('active');
|
document.getElementById('what_image').classList.remove('active');
|
||||||
|
|
||||||
// Остановка звука
|
// Остановка звука
|
||||||
document.getElementById('what_sound').pause();
|
document.getElementById('what_sound').pause();
|
||||||
},
|
},
|
||||||
single(event = 'onmouseleave') {
|
single(event = 'onmouseleave') {
|
||||||
if (typeof event === 'string') {
|
if (typeof event === 'string') {
|
||||||
// Получены обязательные входные параметры
|
// Получены обязательные входные параметры
|
||||||
// Отображение изображения
|
// Отображение изображения
|
||||||
document.getElementById('what_image').classList.add('active');
|
document.getElementById('what_image').classList.add('active');
|
||||||
|
|
||||||
// Инициализация элемента со звуком
|
// Инициализация элемента со звуком
|
||||||
const what_sound = document.getElementById('what_sound');
|
const what_sound = document.getElementById('what_sound');
|
||||||
|
|
||||||
// Воспроизведение звука
|
// Воспроизведение звука
|
||||||
what_sound.currentTime = 0;
|
what_sound.currentTime = 0;
|
||||||
what_sound.play();
|
what_sound.play();
|
||||||
|
|
||||||
document.body[event] = function () {
|
document.body[event] = function () {
|
||||||
troller.what.end();
|
troller.what.end();
|
||||||
|
|
||||||
document.body[event] = undefined;
|
document.body[event] = undefined;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static vk() {
|
static vk() {
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
const sound = document.getElementById('sound_vk');
|
const sound = document.getElementById('sound_vk');
|
||||||
|
|
||||||
if (Math.random() > 0.95) {
|
if (Math.random() > 0.95) {
|
||||||
// 5%
|
// 5%
|
||||||
|
|
||||||
// Воспроизведение звука
|
// Воспроизведение звука
|
||||||
sound.currentTime = 0;
|
sound.currentTime = 0;
|
||||||
sound.play();
|
sound.play();
|
||||||
}
|
}
|
||||||
}, 85000);
|
}, 85000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static whatsapp() {
|
static whatsapp() {
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
const sound = document.getElementById('sound_whatsup');
|
const sound = document.getElementById('sound_whatsup');
|
||||||
|
|
||||||
if (Math.random() > 0.97) {
|
if (Math.random() > 0.97) {
|
||||||
// 3%
|
// 3%
|
||||||
|
|
||||||
// Воспроизведение звука
|
// Воспроизведение звука
|
||||||
sound.currentTime = 0;
|
sound.currentTime = 0;
|
||||||
sound.play();
|
sound.play();
|
||||||
}
|
}
|
||||||
}, 125000);
|
}, 125000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static iphone() {
|
static iphone() {
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
const sound = document.getElementById('sound_iphone');
|
const sound = document.getElementById('sound_iphone');
|
||||||
|
|
||||||
if (Math.random() > 0.98) {
|
if (Math.random() > 0.98) {
|
||||||
// 2%
|
// 2%
|
||||||
|
|
||||||
// Воспроизведение звука
|
// Воспроизведение звука
|
||||||
sound.currentTime = 0;
|
sound.currentTime = 0;
|
||||||
sound.play();
|
sound.play();
|
||||||
}
|
}
|
||||||
}, 265000);
|
}, 265000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.random() > 0.90) {
|
if (Math.random() > 0.90) {
|
||||||
// 10%
|
// 10%
|
||||||
|
|
||||||
troller.what.enable();
|
troller.what.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.random() > 0.90) {
|
if (Math.random() > 0.90) {
|
||||||
// 10%
|
// 10%
|
||||||
|
|
||||||
troller.vk();
|
troller.vk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Math.random() > 0.90) {
|
if (Math.random() > 0.90) {
|
||||||
// 10%
|
// 10%
|
||||||
|
|
||||||
troller.whatsapp();
|
troller.whatsapp();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.random() > 0.90) {
|
if (Math.random() > 0.90) {
|
||||||
// 10%
|
// 10%
|
||||||
|
|
||||||
troller.iphone();
|
troller.iphone();
|
||||||
}
|
}
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
@ -1 +1 @@
|
||||||
arangodb.php
|
arangodb.php
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'endpoint' => 'unix:///var/run/arangodb3/arango.sock',
|
'endpoint' => 'unix:///var/run/arangodb3/arango.sock',
|
||||||
'database' => '',
|
'database' => '',
|
||||||
'name' => '',
|
'name' => '',
|
||||||
'password' => ''
|
'password' => ''
|
||||||
];
|
];
|
|
@ -1,14 +1,14 @@
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<section id="panel">
|
<section id="panel">
|
||||||
{% if account %}
|
{% if account %}
|
||||||
{{ account.getKey() }}
|
{{ account.getKey() }}
|
||||||
{% if vk %}
|
{% if vk %}
|
||||||
{{ vk.mail }}
|
{{ vk.mail }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<button id="login" onclick="return account.authentication(this)">
|
<button id="login" onclick="return account.authentication(this)">
|
||||||
Войти в аккаунт
|
Войти в аккаунт
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,11 +1,11 @@
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<img src="/images/truth.jpg" alt="никому не показывай" style="position: absolute; left: 0; top: 0; width: 100%; height: 100%;">
|
<img src="/images/truth.jpg" alt="никому не показывай" style="position: absolute; left: 0; top: 0; width: 100%; height: 100%;">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js_init %}
|
{% block js_init %}
|
||||||
<script>
|
<script>
|
||||||
setTimeout(fn => {
|
setTimeout(fn => {
|
||||||
window.opener.vk.close();
|
window.opener.vk.close();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,19 +1,20 @@
|
||||||
{% use 'hotline/index.html' with css as hotline_css, body as hotline_body, js as hotline_js, js_init as hotline_js_init %}
|
{% use 'hotline/index.html' with css as hotline_css, body as hotline_body, js as hotline_js, js_init as hotline_js_init %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{# {{ block('hotline_css') }} #}
|
{# {{ block('hotline_css') }} #}
|
||||||
{% endblock %}
|
<link type="text/css" rel="stylesheet" href="/css/trash.css">
|
||||||
|
{% endblock %}
|
||||||
{% block body %}
|
|
||||||
<aside>
|
{% block body %}
|
||||||
{{ block('hotline_body') }}
|
<aside>
|
||||||
</aside>
|
{{ block('hotline_body') }}
|
||||||
{% endblock %}
|
</aside>
|
||||||
|
{% endblock %}
|
||||||
{% block js %}
|
|
||||||
{# {{ block('hotline_js') }} #}
|
{% block js %}
|
||||||
{% endblock %}
|
{# {{ block('hotline_js') }} #}
|
||||||
|
{% endblock %}
|
||||||
{% block js_init %}
|
|
||||||
{# {{ block('hotline_js_init') }} #}
|
{% block js_init %}
|
||||||
{% endblock %}
|
{# {{ block('hotline_js_init') }} #}
|
||||||
|
{% endblock %}
|
|
@ -1,33 +1,33 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
|
|
||||||
<html lang="ru">
|
<html lang="ru">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
{% use 'head.html' with title as head_title, meta as head_meta, css as head_css %}
|
{% use 'head.html' with title as head_title, meta as head_meta, css as head_css %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ block('head_title') }}
|
{{ block('head_title') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block meta %}
|
{% block meta %}
|
||||||
{{ block('head_meta') }}
|
{{ block('head_meta') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{{ block('head_css') }}
|
{{ block('head_css') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{% include 'js.html' %}
|
{% include 'js.html' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js_init %}
|
{% block js_init %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -1,4 +1,4 @@
|
||||||
<footer>
|
<footer>
|
||||||
<!-- <p><a href="http://www.anybrowser.org/campaign/"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
|
<!-- <p><a href="http://www.anybrowser.org/campaign/"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
|
||||||
<!-- <p><a href="/browsers"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
|
<!-- <p><a href="/browsers"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
|
||||||
</footer>
|
</footer>
|
|
@ -1,15 +1,15 @@
|
||||||
{% block title %}
|
{% block title %}
|
||||||
<title>{% if head.title != empty %}{{head.title}}{% else %}Скачать вирусы бесплатно{% endif %}</title>
|
<title>{% if head.title != empty %}{{head.title}}{% else %}Скачать вирусы бесплатно{% endif %}</title>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block meta %}
|
{% block meta %}
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
{% for meta in head.metas %}
|
{% for meta in head.metas %}
|
||||||
<meta {% for name, value in meta.attributes %}{{name}}="{{value}}" {% endfor %}>
|
<meta {% for name, value in meta.attributes %}{{name}}="{{value}}" {% endfor %}>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
<link rel="stylesheet" type="text/css" href="/css/main.css" />
|
<link rel="stylesheet" type="text/css" href="/css/main.css" />
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,22 +1,22 @@
|
||||||
{% use 'logo.html' with css as logo_css, body as logo_body, js as logo_js, js_init as logo_js_init %}
|
{% use 'logo.html' with css as logo_css, body as logo_body, js as logo_js, js_init as logo_js_init %}
|
||||||
{% use 'account/panel.html' with body as panel_body %}
|
{% use 'account/panel.html' with body as panel_body %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{{ block('logo_css') }}
|
{{ block('logo_css') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<header>
|
<header>
|
||||||
{{ block('logo_body') }}
|
{{ block('logo_body') }}
|
||||||
{% include 'menu.html' %}
|
{% include 'menu.html' %}
|
||||||
{{ block('panel_body') }}
|
{{ block('panel_body') }}
|
||||||
</header>
|
</header>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{{ block('logo_js') }}
|
{{ block('logo_js') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js_init %}
|
{% block js_init %}
|
||||||
{{ block('logo_js_init') }}
|
{{ block('logo_js_init') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,28 +1,28 @@
|
||||||
{% block css %}
|
{% block css %}
|
||||||
<link type="text/css" rel="stylesheet" href="/css/hotline.css">
|
<link type="text/css" rel="stylesheet" href="/css/hotline.css">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{% if hotline.id != empty %}
|
{% if hotline.id != empty %}
|
||||||
<section id="{{ hotline.id }}" class="hotline unselectable" data-hotline="true" {% for name, value in hotline.parameters
|
<section id="{{ hotline.id }}" class="hotline unselectable" data-hotline="true" {% for name, value in hotline.parameters
|
||||||
%} data-hotline-{{ name }}="{{value}}" {% endfor %} {% for name, value in hotline.attributes %} {{ name
|
%} data-hotline-{{ name }}="{{value}}" {% endfor %} {% for name, value in hotline.attributes %} {{ name
|
||||||
}}="{{value}}" {% endfor %}>
|
}}="{{value}}" {% endfor %}>
|
||||||
{% for element in hotline.elements %}
|
{% for element in hotline.elements %}
|
||||||
<{{element.tag??'article'}}>{{ element.content }}</{{element.tag??'article'}}>
|
<{{element.tag??'article'}} {% for attribute, value in element.attributes %}{{ attribute }}="{{ value }}"{% endfor %}>{{ element.html|raw }}</{{element.tag??'article'}}>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<script type="text/javascript" src="/js/hotline.js" defer></script>
|
<script type="text/javascript" src="/js/hotline.js" defer></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js_init %}
|
{% block js_init %}
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('hotline.loaded', function (e) {
|
document.addEventListener('hotline.loaded', function (e) {
|
||||||
// Запуск препроцессора бегущих строк
|
// Запуск препроцессора бегущих строк
|
||||||
e.detail.hotline.preprocessing();
|
e.detail.hotline.preprocessing();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
{{ main|raw }}
|
||||||
|
{% if image is not null %}<img src="{{ image.src }}" alt="{{ image.alt }}">{% endif %}
|
||||||
|
<script>
|
||||||
|
// Initialization of the element
|
||||||
|
const element = document.getElementById('{{ id }}');
|
||||||
|
|
||||||
|
if (element instanceof HTMLElement) {
|
||||||
|
// Found the element
|
||||||
|
|
||||||
|
element.addEventListener('mouseenter', () => {
|
||||||
|
console.log('{{ id }}');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,41 +1,41 @@
|
||||||
{% extends "core.html" %}
|
{% extends "core.html" %}
|
||||||
|
|
||||||
{% use "core.html" with css as core_css, body as core_body, js as core_js, js_init as core_js_init %}
|
{% use "core.html" with css as core_css, body as core_body, js as core_js, js_init as core_js_init %}
|
||||||
{% use "trolling.html" with css as trolling_css, body as trolling_body, js as trolling_js %}
|
{% use "trolling.html" with css as trolling_css, body as trolling_body, js as trolling_js %}
|
||||||
{% use "header.html" with css as header_css, body as header_body, js as header_js, js_init as header_js_init %}
|
{% use "header.html" with css as header_css, body as header_body, js as header_js, js_init as header_js_init %}
|
||||||
{% use "aside.html" with css as aside_css, body as aside_body, js as aside_js, js_init as aside_js_init %}
|
{% use "aside.html" with css as aside_css, body as aside_body, js as aside_js, js_init as aside_js_init %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{{ block('core_css') }}
|
{{ block('core_css') }}
|
||||||
{{ block('trolling_css') }}
|
{{ block('trolling_css') }}
|
||||||
{{ block('header_css') }}
|
{{ block('header_css') }}
|
||||||
{{ block('aside_css') }}
|
{{ block('aside_css') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{{ block('core_body') }}
|
{{ block('core_body') }}
|
||||||
{{ block('trolling_body') }}
|
{{ block('trolling_body') }}
|
||||||
{{ block('aside_body') }}
|
{{ block('aside_body') }}
|
||||||
{{ block('header_body') }}
|
{{ block('header_body') }}
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<noscript>К сожалению мой сайт ещё пока не готов для работы без javascript</noscript>
|
<noscript>Весь код на JavaScript выполняется из соглашения по твоему выбору через popup-окно (cookies), смело включай</noscript>
|
||||||
{% block main %}
|
{% block main %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{# {% include 'footer.html' %} #}
|
{# {% include 'footer.html' %} #}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{{ block('core_js') }}
|
{{ block('core_js') }}
|
||||||
{{ block('trolling_js') }}
|
{{ block('trolling_js') }}
|
||||||
{{ block('header_js') }}
|
{{ block('header_js') }}
|
||||||
{{ block('aside_js') }}
|
{{ block('aside_js') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js_init %}
|
{% block js_init %}
|
||||||
{{ block('core_js_init') }}
|
{{ block('core_js_init') }}
|
||||||
{{ block('header_js_init') }}
|
{{ block('header_js_init') }}
|
||||||
{{ block('aside_js_init') }}
|
{{ block('aside_js_init') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,4 +1,4 @@
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<script type="text/javascript" src="/js/js.cookie.min.js" defer></script>
|
<script type="text/javascript" src="/js/js.cookie.min.js" defer></script>
|
||||||
<script type="text/javascript" src="/js/account.js" defer></script>
|
<script type="text/javascript" src="/js/account.js" defer></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,56 +1,56 @@
|
||||||
{% use 'hotline/index.html' with css as hotline_css, body as hotline_body, js as hotline_js %}
|
{% use 'hotline/index.html' with css as hotline_css, body as hotline_body, js as hotline_js %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
<link rel="stylesheet" type="text/css" href="/css/logo.css" />
|
<link rel="stylesheet" type="text/css" href="/css/logo.css" />
|
||||||
{{ block('hotline_css') }}
|
{{ block('hotline_css') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div id="logo" class="unselectable">
|
<div id="logo" class="unselectable">
|
||||||
<h1>VIRUS</h1>
|
<h1>VIRUS</h1>
|
||||||
<h4>Скачать вирусы бесплатно</h4>
|
<h4>Скачать вирусы бесплатно</h4>
|
||||||
|
|
||||||
{% with %}
|
{% with %}
|
||||||
{% set hotline = hotline|merge({'id': 'hotline_logo'}) %}
|
{% set hotline = hotline|merge({'id': 'hotline_logo'}) %}
|
||||||
{{ block('hotline_body') }}
|
{{ block('hotline_body') }}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{{ block('hotline_js') }}
|
{{ block('hotline_js') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js_init %}
|
{% block js_init %}
|
||||||
{{ block('hotline_js_init') }}
|
{{ block('hotline_js_init') }}
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('hotline.loaded', function (e) {
|
document.addEventListener('hotline.loaded', function (e) {
|
||||||
// Запуск препроцессора бегущих строк
|
// Запуск препроцессора бегущих строк
|
||||||
|
|
||||||
// Инициализация элемента бегущей строки
|
// Инициализация элемента бегущей строки
|
||||||
const element_hotline = document.getElementById('hotline');
|
const element_hotline = document.getElementById('hotline');
|
||||||
const element_hotline_logo = document.getElementById('hotline_logo');
|
const element_hotline_logo = document.getElementById('hotline_logo');
|
||||||
|
|
||||||
// Инициализация слушателя
|
// Инициализация слушателя
|
||||||
element_hotline.hotline.events.set('move.block', true);
|
element_hotline.hotline.events.set('move.block', true);
|
||||||
element_hotline.hotline.events.set('move.unblock', true);
|
element_hotline.hotline.events.set('move.unblock', true);
|
||||||
element_hotline.hotline.events.set('onmousemove', true);
|
element_hotline.hotline.events.set('onmousemove', true);
|
||||||
|
|
||||||
document.addEventListener(`hotline.${element_hotline.id}.move.block`, function (e) {
|
document.addEventListener(`hotline.${element_hotline.id}.move.block`, function (e) {
|
||||||
// Копирование блокировки
|
// Копирование блокировки
|
||||||
element_hotline_logo.hotline.move = false;
|
element_hotline_logo.hotline.move = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener(`hotline.${element_hotline.id}.move.unblock`, function (e) {
|
document.addEventListener(`hotline.${element_hotline.id}.move.unblock`, function (e) {
|
||||||
// Копирование блокировки
|
// Копирование блокировки
|
||||||
element_hotline_logo.hotline.move = true;
|
element_hotline_logo.hotline.move = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener(`hotline.${element_hotline.id}.onmousemove`, function (e) {
|
document.addEventListener(`hotline.${element_hotline.id}.onmousemove`, function (e) {
|
||||||
// Копирование перемещения
|
// Копирование перемещения
|
||||||
element_hotline_logo.hotline.offset(e.detail.to);
|
element_hotline_logo.hotline.offset(e.detail.to);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,25 +1,25 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\site\virus\views;
|
namespace mirzaev\site\ff\views;
|
||||||
|
|
||||||
use mirzaev\minimal\controller;
|
use mirzaev\minimal\controller;
|
||||||
|
|
||||||
use Twig\Loader\FilesystemLoader;
|
use Twig\Loader\FilesystemLoader;
|
||||||
use Twig\Environment as view;
|
use Twig\Environment as view;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Менеджер представлений
|
* Менеджер представлений
|
||||||
*
|
*
|
||||||
* @package mirzaev\site\virus\controllers
|
* @package mirzaev\site\ff\controllers
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
final class manager extends controller
|
final class manager extends controller
|
||||||
{
|
{
|
||||||
public function render(string $file, array $vars = []): ?string
|
public function render(string $file, array $vars = []): ?string
|
||||||
{
|
{
|
||||||
// Генерация представления
|
// Генерация представления
|
||||||
return (new view(new FilesystemLoader(VIEWS)))->render($file, $vars);
|
return (new view(new FilesystemLoader(VIEWS)))->render($file, $vars);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,15 @@
|
||||||
{% block css %}
|
{% block css %}
|
||||||
<link rel="stylesheet" type="text/css" href="/css/trolling.css" />
|
<link rel="stylesheet" type="text/css" href="/css/trolling.css" />
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<img id="what_image" class="hide" src="/images/what.png" />
|
<img id="what_image" class="hide" src="/images/what.png" />
|
||||||
<audio id="what_sound" class="hide" src="/sounds/what.mp3" controls></audio>
|
<audio id="what_sound" class="hide" src="/sounds/what.mp3" controls></audio>
|
||||||
<audio id="sound_vk" class="hide" src="/sounds/vk.mp3" controls></audio>
|
<audio id="sound_vk" class="hide" src="/sounds/vk.mp3" controls></audio>
|
||||||
<audio id="sound_whatsup" class="hide" src="/sounds/whatsup.mp3" controls></audio>
|
<audio id="sound_whatsup" class="hide" src="/sounds/whatsup.mp3" controls></audio>
|
||||||
<audio id="sound_iphone" class="hide" src="/sounds/iphone.mp3" controls></audio>
|
<audio id="sound_iphone" class="hide" src="/sounds/iphone.mp3" controls></audio>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<script src="/js/trolling.js" defer></script>
|
<script src="/js/trolling.js" defer></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,71 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\site\virus\controllers;
|
|
||||||
|
|
||||||
// Файлы проекта
|
|
||||||
use mirzaev\site\virus\controllers\core;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Контроллер основной страницы
|
|
||||||
*
|
|
||||||
* @package mirzaev\site\virus\controllers
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class index_controller extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Главная страница
|
|
||||||
*
|
|
||||||
* @param array $parameters Параметры запроса
|
|
||||||
*/
|
|
||||||
public function index(array $parameters = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация загружаемых категорий
|
|
||||||
$this->variables['include'] = [
|
|
||||||
'head' => ['self'],
|
|
||||||
'body' => ['self']
|
|
||||||
];
|
|
||||||
|
|
||||||
// Инициализация бегущей строки
|
|
||||||
$this->variables['hotline'] = [
|
|
||||||
'id' => $this->variables['request']['id'] ?? 'hotline'
|
|
||||||
];
|
|
||||||
|
|
||||||
// Инициализация параметров бегущей строки
|
|
||||||
$this->variables['hotline']['parameters'] = [
|
|
||||||
// 'step' => 2
|
|
||||||
];
|
|
||||||
|
|
||||||
// Инициализация аттрибутов бегущей строки
|
|
||||||
$this->variables['hotline']['attributes'] = [
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
// Инициализация элементов бегущей строки
|
|
||||||
$this->variables['hotline']['elements'] = [
|
|
||||||
['content' => '1'],
|
|
||||||
[
|
|
||||||
'tag' => 'article',
|
|
||||||
'content' => '2'
|
|
||||||
],
|
|
||||||
['content' => '3'],
|
|
||||||
['content' => '4'],
|
|
||||||
['content' => '5'],
|
|
||||||
['content' => '6'],
|
|
||||||
['content' => '7'],
|
|
||||||
['content' => '8'],
|
|
||||||
['content' => '9'],
|
|
||||||
['content' => '10'],
|
|
||||||
['content' => '11'],
|
|
||||||
['content' => '12'],
|
|
||||||
['content' => '13'],
|
|
||||||
['content' => '14'],
|
|
||||||
['content' => '15']
|
|
||||||
];
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'index.html', $this->variables);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,213 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\site\virus\models;
|
|
||||||
|
|
||||||
// Файлы проекта
|
|
||||||
use mirzaev\site\virus\models\account_model as account;
|
|
||||||
|
|
||||||
// Фреймворк ArangoDB
|
|
||||||
use mirzaev\arangodb\collection,
|
|
||||||
mirzaev\arangodb\document;
|
|
||||||
|
|
||||||
// Библиотека для ArangoDB
|
|
||||||
use ArangoDBClient\Document as _document;
|
|
||||||
|
|
||||||
// Встроенные библиотеки
|
|
||||||
use exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модель сессий
|
|
||||||
*
|
|
||||||
* @package mirzaev\site\virus\models
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class session_model extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Коллекция
|
|
||||||
*/
|
|
||||||
public const COLLECTION = 'session';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Инициализация
|
|
||||||
*
|
|
||||||
* @param ?string $hash Хеш сессии в базе данных
|
|
||||||
* @param ?int $expires Дата окончания работы сессии (используется при создании новой сессии)
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return ?_document Инстанция сессии, если удалось найти или создать
|
|
||||||
*/
|
|
||||||
public static function initialization(?string $hash = null, ?int $expires = null, array &$errors = []): ?_document
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (collection::init(static::$db->session, self::COLLECTION)) {
|
|
||||||
// Инициализирована коллекция
|
|
||||||
|
|
||||||
if (isset($hash) && $session = collection::search(static::$db->session, sprintf(
|
|
||||||
<<<AQL
|
|
||||||
FOR d IN %s
|
|
||||||
FILTER d.hash == '$hash' && d.expires > %d
|
|
||||||
RETURN d
|
|
||||||
AQL,
|
|
||||||
self::COLLECTION,
|
|
||||||
time()
|
|
||||||
))) {
|
|
||||||
// Найдена сессия по хешу
|
|
||||||
|
|
||||||
// Возврат сессии
|
|
||||||
return $session;
|
|
||||||
} else if ($session = collection::search(static::$db->session, sprintf(
|
|
||||||
<<<AQL
|
|
||||||
FOR d IN %s
|
|
||||||
FILTER d.ip == '%s' && d.expires > %d
|
|
||||||
RETURN d
|
|
||||||
AQL,
|
|
||||||
self::COLLECTION,
|
|
||||||
$_SERVER['REMOTE_ADDR'],
|
|
||||||
time()
|
|
||||||
))) {
|
|
||||||
// Найдена сессия по данным пользователя
|
|
||||||
|
|
||||||
// Возврат сессии
|
|
||||||
return $session;
|
|
||||||
} else {
|
|
||||||
// Не найдена сессия
|
|
||||||
|
|
||||||
// Запись сессии в базу данных
|
|
||||||
$_id = document::write(static::$db->session, self::COLLECTION, [
|
|
||||||
'ip' => $_SERVER['REMOTE_ADDR'],
|
|
||||||
'expires' => $expires ?? time() + 604800
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($session = collection::search(static::$db->session, sprintf(
|
|
||||||
<<<AQL
|
|
||||||
FOR d IN %s
|
|
||||||
FILTER d._id == '$_id' && d.expires > %d
|
|
||||||
RETURN d
|
|
||||||
AQL,
|
|
||||||
self::COLLECTION,
|
|
||||||
time()
|
|
||||||
))) {
|
|
||||||
// Найдена созданная сессия
|
|
||||||
|
|
||||||
// Запись хеша
|
|
||||||
$session->hash = sodium_bin2hex(sodium_crypto_generichash($_id));
|
|
||||||
|
|
||||||
if (document::update(static::$db->session, $session)) {
|
|
||||||
// Записано обновление
|
|
||||||
|
|
||||||
return $session;
|
|
||||||
} else throw new exception('Не удалось записать данные сессии');
|
|
||||||
} else throw new exception('Не удалось создать или найти созданную сессию');
|
|
||||||
}
|
|
||||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Связь сессии с аккаунтом
|
|
||||||
*
|
|
||||||
* @param _document $session Инстанция сессии
|
|
||||||
* @param _document $account Инстанция аккаунта
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return bool Статус выполнения
|
|
||||||
*/
|
|
||||||
public static function connect(_document $session, _document $account, array &$errors = []): bool
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
collection::init(static::$db->session, self::COLLECTION)
|
|
||||||
&& collection::init(static::$db->session, account::COLLECTION)
|
|
||||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, true)
|
|
||||||
) {
|
|
||||||
// Инициализирована коллекция
|
|
||||||
|
|
||||||
if (document::write(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, [
|
|
||||||
'_from' => $session->getId(),
|
|
||||||
'_to' => $account->getId()
|
|
||||||
])) {
|
|
||||||
// Создано ребро: session -> account
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else throw new exception('Не удалось создать ребро: session -> account');
|
|
||||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Поиск связанного аккаунта
|
|
||||||
*
|
|
||||||
* @param _document $session Инстанция сессии
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return ?_document Инстанция аккаунта, если удалось найти
|
|
||||||
*/
|
|
||||||
public static function account(_document $session, array &$errors = []): ?_document
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
collection::init(static::$db->session, self::COLLECTION)
|
|
||||||
&& collection::init(static::$db->session, account::COLLECTION)
|
|
||||||
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . account::COLLECTION, true)
|
|
||||||
) {
|
|
||||||
// Инициализированы коллекции
|
|
||||||
|
|
||||||
if ($account = collection::search(static::$db->session, sprintf(
|
|
||||||
<<<AQL
|
|
||||||
FOR document IN %s
|
|
||||||
LET edge = (
|
|
||||||
FOR edge IN %s
|
|
||||||
FILTER edge._from == '%s'
|
|
||||||
SORT edge._key DESC
|
|
||||||
LIMIT 1
|
|
||||||
RETURN edge
|
|
||||||
)
|
|
||||||
FILTER document._id == edge[0]._to
|
|
||||||
LIMIT 1
|
|
||||||
RETURN document
|
|
||||||
AQL,
|
|
||||||
account::COLLECTION,
|
|
||||||
self::COLLECTION . '_edge_' . account::COLLECTION,
|
|
||||||
$session->getId()
|
|
||||||
))) {
|
|
||||||
// Найден аккаунт
|
|
||||||
|
|
||||||
return $account;
|
|
||||||
} else throw new exception('Не удалось найти аккаунт');
|
|
||||||
} else throw new exception('Не удалось инициализировать коллекцию');
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
section.hotline {
|
|
||||||
display: inline-flex;
|
|
||||||
height : 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.hotline * {
|
|
||||||
transition: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.hotline:last-child {
|
|
||||||
margin-bottom: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.hotline>article {
|
|
||||||
margin-right : 18px;
|
|
||||||
width : 140px;
|
|
||||||
height : 190px;
|
|
||||||
display : flex;
|
|
||||||
align-self : flex-end;
|
|
||||||
border-radius : 3px;
|
|
||||||
background-color: var(--background-light-1);
|
|
||||||
box-shadow : 0px -6px 6px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
section.hotline>article:last-child {
|
|
||||||
margin-right: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.hotline>article>* {
|
|
||||||
margin: auto;
|
|
||||||
}
|
|