Compare commits

..

1 Commits

68 changed files with 3670 additions and 3580 deletions

6
.gitignore vendored
View File

@ -1,3 +1,3 @@
!.gitignore
composer.phar
vendor
!.gitignore
composer.phar
vendor

22
LICENSE
View File

@ -1,11 +1,11 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
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.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
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.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View File

@ -1,3 +1,3 @@
# site-virus
# site-virus
Site with viruses and scary pictures

View File

@ -1,51 +1,50 @@
{
"name": "mirzaev/site-virus",
"description": "Site with viruses and scary pictures",
"readme": "README.md",
"keywords": [
"virus",
"download",
"Evil Alliance",
"imageboard",
"site"
],
"type": "site",
"homepage": "https://git.mirzaev.sexy/mirzaev/site-virus",
"license": "WTFPL",
"authors": [
{
"name": "Arsen Mirzaev Tatyano-Muradovich",
"email": "arsen@mirzaev.sexy",
"homepage": "https://mirzaev.sexy",
"role": "Programmer"
}
],
"support": {
"docs": "https://git.mirzaev.sexy/mirzaev/site-virus/manual",
"issues": "https://git.mirzaev.sexy/mirzaev/site-virus/issues"
},
"require": {
"php": "~8.1",
"ext-sodium": "~8.1",
"mirzaev/minimal": "^2.0.x-dev",
"mirzaev/accounts": "~1.2.x-dev",
"mirzaev/arangodb": "^1.0.0",
"mirzaev/vk": "^4.0",
"triagens/arangodb": "~3.9.x-dev",
"twig/twig": "^3.4",
"guzzlehttp/guzzle": "^7.5"
},
"require-dev": {
"phpunit/phpunit": "~9.5"
},
"autoload": {
"psr-4": {
"mirzaev\\site\\virus\\": "mirzaev/site/virus/system"
}
},
"autoload-dev": {
"psr-4": {
"mirzaev\\site\\virus\\tests\\": "mirzaev/site/virus/tests"
}
}
}
{
"name": "mirzaev/site-ff",
"description": "our FUCKING.FORUM",
"readme": "README.md",
"keywords": [
"forum",
"Evil Alliance",
"imageboard",
"site"
],
"type": "site",
"homepage": "https://git.mirzaev.sexy/mirzaev/site-ff",
"license": "WTFPL",
"authors": [
{
"name": "Arsen Mirzaev Tatyano-Muradovich",
"email": "arsen@mirzaev.sexy",
"homepage": "https://mirzaev.sexy",
"role": "Programmer"
}
],
"support": {
"docs": "https://git.mirzaev.sexy/mirzaev/site-ff/manual",
"issues": "https://git.mirzaev.sexy/mirzaev/site-ff/issues"
},
"require": {
"php": "~8.2",
"ext-sodium": "~8.2",
"mirzaev/accounts": "~1.2.x-dev",
"mirzaev/arangodb": "^1.0.0",
"mirzaev/vk": "^4.0",
"triagens/arangodb": "~3.9.x-dev",
"twig/twig": "^3.4",
"guzzlehttp/guzzle": "^7.5",
"mirzaev/minimal": "^2.1"
},
"require-dev": {
"phpunit/phpunit": "~9.5"
},
"autoload": {
"psr-4": {
"mirzaev\\site\\ff\\": "mirzaev/site/ff/system"
}
},
"autoload-dev": {
"psr-4": {
"mirzaev\\site\\ff\\tests\\": "mirzaev/site/ff/tests"
}
}
}

460
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,147 +1,147 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\virus\controllers;
// Файлы проекта
use mirzaev\site\virus\controllers\core;
use mirzaev\site\virus\models\account_model as account;
use mirzaev\site\virus\models\session_model as session;
use mirzaev\site\virus\models\vk_model as vk;
// Библиотека для ArangoDB
use ArangoDBClient\Document as _document;
use SebastianBergmann\Type\ObjectType;
use stdClass;
// Фреймворк для ВКонтакте
use mirzaev\vk\core as api;
/**
* Контроллер аккаунтов
*
* @package mirzaev\site\virus\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class account_controller extends core
{
/**
* Страница профиля
*
* @param array $parameters Параметры запроса
*/
public function index(array $parameters = []): ?string
{
return null;
}
/**
* Инициализация
*
* @param array $parameters Параметры запроса
*/
public function initialization(array $parameters = []): ?string
{
if ($this->variables['account'] instanceof _document) {
// Найден аккаунт
if ($this->variables['vk'] instanceof _document) {
// Найден аккаунт ВКонтакте
// Инициализация данных аккаунта ВКонтакте
vk::parse($this->variables['vk'], $this->variables['errors']['vk']);
}
// Запись кода ответа
http_response_code(200);
return null;
} else {
// Не найден аккаунт
// Запись кода ответа
http_response_code(401);
// Запись заголовка ответа с ключом аккаунта
header('session: ' . $this->variables['session']->hash);
return null;
}
// Запись кода ответа
http_response_code(500);
return null;
}
/**
* Связь аккаунта с аккаунтом ВКонтакте
*
* @param array $parameters Параметры запроса
*/
public function connect(array $parameters = []): ?string
{
if ($this->variables['session']->hash === $parameters['state']) {
// Совпадает хеш сессии с полученным хешем из ответа ВКонтакте
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['account'] = vk::account($this->variables['vk'])) instanceof _document) {
// Найден аккаунт (существующий)
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) {
// Найден аккаунт (создан новый)
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'])) {
// Связан аккаунт с аккаунтом ВКонтакте
}
}
}
// Инициализация робота для аккаунта ВКонтакте
$this->vk = api::init()->user(key: $this->variables['vk']->access['key']);
if ($this->variables['vk'] instanceof _document) {
// Инициализирован робот для аккаунта ВКонтакте
// Инициализация данных аккаунта ВКонтакте
$data = vk::parse($this->vk, $this->variables['errors']['vk']);
var_dump($data); die;
if ($data instanceof stdClass) {
// Получены данные ВКонтакте
// Запись в базу данных
vk::update($this->variables['vk'], $data, $this->variables['errors']['vk']);
}
}
}
}
}
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'vk.html', $this->variables);
}
/**
* Генерация панели аккаунта
*
* @param array $parameters Параметры запроса
*/
public function panel(array $parameters = []): ?string
{
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'panel.html', $this->variables);
}
}
<?php
declare(strict_types=1);
namespace mirzaev\site\ff\controllers;
// Файлы проекта
use mirzaev\site\ff\controllers\core;
use mirzaev\site\ff\models\account_model as account;
use mirzaev\site\ff\models\session_model as session;
use mirzaev\site\ff\models\vk_model as vk;
// Библиотека для ArangoDB
use ArangoDBClient\Document as _document;
use SebastianBergmann\Type\ObjectType;
use stdClass;
// Фреймворк для ВКонтакте
use mirzaev\vk\core as api;
/**
* Контроллер аккаунтов
*
* @package mirzaev\site\ff\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class account_controller extends core
{
/**
* Страница профиля
*
* @param array $parameters Параметры запроса
*/
public function index(array $parameters = []): ?string
{
return null;
}
/**
* Инициализация
*
* @param array $parameters Параметры запроса
*/
public function initialization(array $parameters = []): ?string
{
if ($this->variables['account'] instanceof _document) {
// Найден аккаунт
if ($this->variables['vk'] instanceof _document) {
// Найден аккаунт ВКонтакте
// Инициализация данных аккаунта ВКонтакте
vk::parse($this->variables['vk'], $this->variables['errors']['vk']);
}
// Запись кода ответа
http_response_code(200);
return null;
} else {
// Не найден аккаунт
// Запись кода ответа
http_response_code(401);
// Запись заголовка ответа с ключом аккаунта
header('session: ' . $this->variables['session']->hash);
return null;
}
// Запись кода ответа
http_response_code(500);
return null;
}
/**
* Связь аккаунта с аккаунтом ВКонтакте
*
* @param array $parameters Параметры запроса
*/
public function connect(array $parameters = []): ?string
{
if ($this->variables['session']->hash === $parameters['state']) {
// Совпадает хеш сессии с полученным хешем из ответа ВКонтакте
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['account'] = vk::account($this->variables['vk'])) instanceof _document) {
// Найден аккаунт (существующий)
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) {
// Найден аккаунт (создан новый)
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'])) {
// Связан аккаунт с аккаунтом ВКонтакте
}
}
}
// Инициализация робота для аккаунта ВКонтакте
$this->vk = api::init()->user(key: $this->variables['vk']->access['key']);
if ($this->variables['vk'] instanceof _document) {
// Инициализирован робот для аккаунта ВКонтакте
// Инициализация данных аккаунта ВКонтакте
$data = vk::parse($this->vk, $this->variables['errors']['vk']);
var_dump($data); die;
if ($data instanceof stdClass) {
// Получены данные ВКонтакте
// Запись в базу данных
vk::update($this->variables['vk'], $data, $this->variables['errors']['vk']);
}
}
}
}
}
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'vk.html', $this->variables);
}
/**
* Генерация панели аккаунта
*
* @param array $parameters Параметры запроса
*/
public function panel(array $parameters = []): ?string
{
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'account' . DIRECTORY_SEPARATOR . 'panel.html', $this->variables);
}
}

View File

@ -1,100 +1,100 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\virus\controllers;
// Файлы проекта
use mirzaev\site\virus\views\manager;
use mirzaev\site\virus\models\core as models;
use mirzaev\site\virus\models\account_model as account;
use mirzaev\site\virus\models\session_model as session;
// Библиотека для ArangoDB
use ArangoDBClient\Document as _document;
// Фреймворк PHP
use mirzaev\minimal\controller;
// Фреймворк ВКонтакте
use mirzaev\vk\core as vk;
use mirzaev\vk\robots\user as robot;
/**
* Ядро контроллеров
*
* @package mirzaev\site\virus\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class core extends controller
{
/**
* Переменные окружения
*/
protected robot $vk;
/**
* Переменные окружения
*/
protected array $variables = [];
/**
* Конструктор
*
* @return void
*/
public function __construct()
{
parent::__construct();
// Инициализация ядра моделей (соединение с базой данных...)
new models();
// Инициализация журнала ошибок
$this->variables['errors'] = [
'session' => [],
'account' => [],
'vk' => []
];
// Инициализация даты до которой будет активна сессия
$expires = time() + 604800;
// Инициализация сессии (без журналирования)
$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) {
// Изменился хеш сессии (подразумевается, что сессия устарела)
// Запись хеша новой сессии
setcookie('session', $this->variables['session']->hash, [
'expires' => $expires,
'domain' => 'virus.mirzaev.sexy',
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'strict'
]);
}
// Инициализация аккаунта (без журналирования)
$this->variables['account'] = session::account($this->variables['session']);
if ($this->variables['account'] instanceof _document) {
// Инициализирован аккаунт
// Инициализация аккаунта ВКонтакте (без журналирования)
$this->variables['vk'] = account::vk($this->variables['account']);
if ($this->variables['vk'] instanceof _document) {
// Инициализирован аккаунт ВКонтакте
// Инициализация робота для аккаунта ВКонтакте
$this->vk = vk::init()->user(key: $this->variables['vk']->access['key']);
} else unset($this->variables['account'], $this->variables['vk']);
}
// Инициализация препроцессора представления
$this->view = new manager;
}
}
<?php
declare(strict_types=1);
namespace mirzaev\site\ff\controllers;
// Файлы проекта
use mirzaev\site\ff\views\manager;
use mirzaev\site\ff\models\core as models;
use mirzaev\site\ff\models\account_model as account;
use mirzaev\site\ff\models\session_model as session;
// Библиотека для ArangoDB
use ArangoDBClient\Document as _document;
// Фреймворк PHP
use mirzaev\minimal\controller;
// Фреймворк ВКонтакте
use mirzaev\vk\core as vk;
use mirzaev\vk\robots\user as robot;
/**
* Ядро контроллеров
*
* @package mirzaev\site\ff\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class core extends controller
{
/**
* Переменные окружения
*/
protected robot $vk;
/**
* Переменные окружения
*/
protected array $variables = [];
/**
* Конструктор
*
* @return void
*/
public function __construct()
{
parent::__construct();
// Инициализация ядра моделей (соединение с базой данных...)
new models();
// Инициализация журнала ошибок
$this->variables['errors'] = [
'session' => [],
'account' => [],
'vk' => []
];
// Инициализация даты до которой будет активна сессия
$expires = time() + 604800;
// Инициализация сессии (без журналирования)
$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) {
// Изменился хеш сессии (подразумевается, что сессия устарела)
// Запись хеша новой сессии
setcookie('session', $this->variables['session']->hash, [
'expires' => $expires,
'domain' => 'ff.mirzaev.sexy',
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'strict'
]);
}
// Инициализация аккаунта (без журналирования)
$this->variables['account'] = session::account($this->variables['session']);
if ($this->variables['account'] instanceof _document) {
// Инициализирован аккаунт
// Инициализация аккаунта ВКонтакте (без журналирования)
$this->variables['vk'] = account::vk($this->variables['account']);
if ($this->variables['vk'] instanceof _document) {
// Инициализирован аккаунт ВКонтакте
// Инициализация робота для аккаунта ВКонтакте
$this->vk = vk::init()->user(key: $this->variables['vk']->access['key']);
} else unset($this->variables['account'], $this->variables['vk']);
}
// Инициализация препроцессора представления
$this->view = new manager;
}
}

View File

@ -1,44 +1,44 @@
<?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 error_controller extends core
{
/**
* Страница с ошибкой
*
* @param array $parameters
*/
public function index(array $parameters = []): ?string
{
// Запись текста ошибки в переменную окружения
$this->variables['text'] = $parameters['text'] ?? null;
if (isset($parameters['code'])) {
// Получен код ошибки
// Запись кода ошибки в переменную окружения
$this->variables['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 . ($parameters['code'] ?? 'index') . '.html', $this->variables);
}
}
<?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 error_controller extends core
{
/**
* Страница с ошибкой
*
* @param array $parameters
*/
public function index(array $parameters = []): ?string
{
// Запись текста ошибки в переменную окружения
$this->variables['text'] = $parameters['text'] ?? null;
if (isset($parameters['code'])) {
// Получен код ошибки
// Запись кода ошибки в переменную окружения
$this->variables['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 . ($parameters['code'] ?? 'index') . '.html', $this->variables);
}
}

View File

@ -1,82 +1,82 @@
<?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 hotline_controller extends core
{
/**
* Страница с бегущей строкой
*
* Можно использовать совместно с элементом <iframe> для изоляции
* содержимого бегущей строки от поисковых роботов
*
* @param array $parameters
*/
public function index(array $parameters = []): ?string
{
// Инициализация элементов для генерации в головном элементе
$this->variables['head'] = [
'title' => 'Бегущая строка',
'metas' => [
[
'attributes' => [
'name' => 'robots',
'content' => 'nofollow'
]
]
]
];
// Инициализация бегущей строки
$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 . 'hotline' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
}
}
<?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 hotline_controller extends core
{
/**
* Страница с бегущей строкой
*
* Можно использовать совместно с элементом <iframe> для изоляции
* содержимого бегущей строки от поисковых роботов
*
* @param array $parameters
*/
public function index(array $parameters = []): ?string
{
// Инициализация элементов для генерации в головном элементе
$this->variables['head'] = [
'title' => 'Бегущая строка',
'metas' => [
[
'attributes' => [
'name' => 'robots',
'content' => 'nofollow'
]
]
]
];
// Инициализация бегущей строки
$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 . 'hotline' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
}
}

View File

@ -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);
}
}

View File

@ -1,169 +1,169 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\virus\models;
// Файлы проекта
use mirzaev\site\virus\models\vk_model as vk;
// Фреймворк 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 account_model extends core
{
/**
* Коллекция
*/
public const COLLECTION = 'account';
/**
* Создать
*
* @param array &$errors Журнал ошибок
*
* @return ?_document Инстанция аккаунта, если удалось создать
*/
public static function create(array &$errors = []): ?_document
{
try {
if (collection::init(static::$db->session, self::COLLECTION)) {
// Инициализирована коллекция
// Запись аккаунта в базу данных
$_id = document::write(static::$db->session, self::COLLECTION);
if ($account = collection::search(static::$db->session, sprintf(
<<<AQL
FOR d IN %s
FILTER d._id == '$_id'
RETURN d
AQL,
self::COLLECTION
))) {
// Найден созданный аккаунт
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;
}
/**
* Связь аккаунта с аккаунтом ВКонтакте
*
* @param _document $account Инстанция аккаунта
* @param _document $vk Инстанция аккаунта ВКонтакте
* @param array &$errors Журнал ошибок
*
* @return bool Статус выполнения
*/
public static function connect(_document $account, _document $vk, array &$errors = []): bool
{
try {
if (
collection::init(static::$db->session, self::COLLECTION)
&& collection::init(static::$db->session, vk::COLLECTION)
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
) {
// Инициализированы коллекции
if (document::write(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, [
'_from' => $account->getId(),
'_to' => $vk->getId()
])) {
// Создано ребро: account -> vk
return true;
} else throw new exception('Не удалось создать ребро: account -> vk');
} else throw new exception('Не удалось инициализировать коллекцию');
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return false;
}
/**
* Поиск связанного аккаунта ВКонтакте
*
* @param _document $account Инстанция аккаунта
* @param array &$errors Журнал ошибок
*
* @return ?_document Инстанция аккаунта, если удалось найти
*/
public static function vk(_document $account, array &$errors = []): ?_document
{
try {
if (
collection::init(static::$db->session, self::COLLECTION)
&& collection::init(static::$db->session, vk::COLLECTION)
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
) {
// Инициализирована коллекция
if ($vk = 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,
vk::COLLECTION,
self::COLLECTION . '_edge_' . vk::COLLECTION,
$account->getId()
))) {
// Найден аккаунт ВКонтакте
return $vk;
} 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;
}
}
<?php
declare(strict_types=1);
namespace mirzaev\site\ff\models;
// Файлы проекта
use mirzaev\site\ff\models\vk_model as vk;
// Фреймворк 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 account_model extends core
{
/**
* Коллекция
*/
public const COLLECTION = 'account';
/**
* Создать
*
* @param array &$errors Журнал ошибок
*
* @return ?_document Инстанция аккаунта, если удалось создать
*/
public static function create(array &$errors = []): ?_document
{
try {
if (collection::init(static::$db->session, self::COLLECTION)) {
// Инициализирована коллекция
// Запись аккаунта в базу данных
$_id = document::write(static::$db->session, self::COLLECTION);
if ($account = collection::search(static::$db->session, sprintf(
<<<AQL
FOR d IN %s
FILTER d._id == '$_id'
RETURN d
AQL,
self::COLLECTION
))) {
// Найден созданный аккаунт
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;
}
/**
* Связь аккаунта с аккаунтом ВКонтакте
*
* @param _document $account Инстанция аккаунта
* @param _document $vk Инстанция аккаунта ВКонтакте
* @param array &$errors Журнал ошибок
*
* @return bool Статус выполнения
*/
public static function connect(_document $account, _document $vk, array &$errors = []): bool
{
try {
if (
collection::init(static::$db->session, self::COLLECTION)
&& collection::init(static::$db->session, vk::COLLECTION)
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
) {
// Инициализированы коллекции
if (document::write(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, [
'_from' => $account->getId(),
'_to' => $vk->getId()
])) {
// Создано ребро: account -> vk
return true;
} else throw new exception('Не удалось создать ребро: account -> vk');
} else throw new exception('Не удалось инициализировать коллекцию');
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return false;
}
/**
* Поиск связанного аккаунта ВКонтакте
*
* @param _document $account Инстанция аккаунта
* @param array &$errors Журнал ошибок
*
* @return ?_document Инстанция аккаунта, если удалось найти
*/
public static function vk(_document $account, array &$errors = []): ?_document
{
try {
if (
collection::init(static::$db->session, self::COLLECTION)
&& collection::init(static::$db->session, vk::COLLECTION)
&& collection::init(static::$db->session, self::COLLECTION . '_edge_' . vk::COLLECTION, true)
) {
// Инициализирована коллекция
if ($vk = 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,
vk::COLLECTION,
self::COLLECTION . '_edge_' . vk::COLLECTION,
$account->getId()
))) {
// Найден аккаунт ВКонтакте
return $vk;
} 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;
}
}

View File

@ -1,143 +1,143 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\virus\models;
use mirzaev\minimal\model;
use mirzaev\arangodb\connection;
use exception;
/**
* Ядро моделей
*
* @package mirzaev\site\virus\models
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class core extends model
{
/**
* Коллекция в которой хранятся аккаунты
*/
public const SETTINGS = '../settings/arangodb.php';
/**
* Соединение с базой данных
*/
protected static connection $db;
public function __construct(connection $db = null)
{
if (isset($db)) {
// Получена инстанция соединения с базой данных
// Запись и инициализация соединения с базой данных
$this->__set('db', $db);
} else {
// Не получена инстанция соединения с базой данных
// Инициализация соединения с базой данных по умолчанию
$this->__get('db');
}
}
/**
* Записать свойство
*
* @param string $name Название
* @param mixed $value Значение
*/
public function __set(string $name, mixed $value = null): void
{
match ($name) {
'db' => (function () use ($value) {
if ($this->__isset('db')) {
// Свойство уже было инициализировано
// Выброс исключения (неудача)
throw new exception('Запрещено реинициализировать соединение с базой данных ($this->db)', 500);
} else {
// Свойство ещё не было инициализировано
if ($value instanceof connection) {
// Передано подходящее значение
// Запись свойства (успех)
self::$db = $value;
} else {
// Передано неподходящее значение
// Выброс исключения (неудача)
throw new exception('Соединение с базой данных ($this->db) должен быть инстанцией mirzaev\arangodb\connection', 500);
}
}
})(),
default => parent::__set($name, $value)
};
}
/**
* Прочитать свойство
*
* @param string $name Название
*
* @return mixed Содержимое
*/
public function __get(string $name): mixed
{
return match ($name) {
'db' => (function () {
if (!$this->__isset('db')) {
// Свойство не инициализировано
// Инициализация значения по умолчанию исходя из настроек
$this->__set('db', new connection(require static::SETTINGS));
}
return self::$db;
})(),
default => parent::__get($name)
};
}
/**
* Проверить свойство на инициализированность
*
* @param string $name Название
*/
public function __isset(string $name): bool
{
return match ($name) {
default => parent::__isset($name)
};
}
/**
* Удалить свойство
*
* @param string $name Название
*/
public function __unset(string $name): void
{
match ($name) {
default => parent::__isset($name)
};
}
/**
* Статический вызов
*
* @param string $name Название
* @param array $arguments Параметры
*/
public static function __callStatic(string $name, array $arguments): mixed
{
match ($name) {
'db' => (new static)->__get('db'),
default => throw new exception("Не найдено свойство или функция: $name", 500)
};
}
}
<?php
declare(strict_types=1);
namespace mirzaev\site\ff\models;
use mirzaev\minimal\model;
use mirzaev\arangodb\connection;
use exception;
/**
* Ядро моделей
*
* @package mirzaev\site\ff\models
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class core extends model
{
/**
* Коллекция в которой хранятся аккаунты
*/
public const SETTINGS = '../settings/arangodb.php';
/**
* Соединение с базой данных
*/
protected static connection $db;
public function __construct(connection $db = null)
{
if (isset($db)) {
// Получена инстанция соединения с базой данных
// Запись и инициализация соединения с базой данных
$this->__set('db', $db);
} else {
// Не получена инстанция соединения с базой данных
// Инициализация соединения с базой данных по умолчанию
$this->__get('db');
}
}
/**
* Записать свойство
*
* @param string $name Название
* @param mixed $value Значение
*/
public function __set(string $name, mixed $value = null): void
{
match ($name) {
'db' => (function () use ($value) {
if ($this->__isset('db')) {
// Свойство уже было инициализировано
// Выброс исключения (неудача)
throw new exception('Запрещено реинициализировать соединение с базой данных ($this->db)', 500);
} else {
// Свойство ещё не было инициализировано
if ($value instanceof connection) {
// Передано подходящее значение
// Запись свойства (успех)
self::$db = $value;
} else {
// Передано неподходящее значение
// Выброс исключения (неудача)
throw new exception('Соединение с базой данных ($this->db) должен быть инстанцией mirzaev\arangodb\connection', 500);
}
}
})(),
default => parent::__set($name, $value)
};
}
/**
* Прочитать свойство
*
* @param string $name Название
*
* @return mixed Содержимое
*/
public function __get(string $name): mixed
{
return match ($name) {
'db' => (function () {
if (!$this->__isset('db')) {
// Свойство не инициализировано
// Инициализация значения по умолчанию исходя из настроек
$this->__set('db', new connection(require static::SETTINGS));
}
return self::$db;
})(),
default => parent::__get($name)
};
}
/**
* Проверить свойство на инициализированность
*
* @param string $name Название
*/
public function __isset(string $name): bool
{
return match ($name) {
default => parent::__isset($name)
};
}
/**
* Удалить свойство
*
* @param string $name Название
*/
public function __unset(string $name): void
{
match ($name) {
default => parent::__isset($name)
};
}
/**
* Статический вызов
*
* @param string $name Название
* @param array $arguments Параметры
*/
public static function __callStatic(string $name, array $arguments): mixed
{
match ($name) {
'db' => (new static)->__get('db'),
default => throw new exception("Не найдено свойство или функция: $name", 500)
};
}
}

View File

@ -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;
}
}

View File

@ -1,119 +1,119 @@
#mail>:is(form, div) {
display : flex;
flex-direction: column;
}
#mail .exit {
margin-top: 25px;
}
#mail p {
margin : 0;
display: flex;
}
#mail p>span {
margin-left: auto;
}
#mail>form>input:is([type=text], [type=password]) {
margin-bottom: 12px;
}
#mail>form>input:last-child {
margin-bottom: unset;
}
#mail>form>.submit {
margin-top : 6px;
margin-bottom: 10px;
display : flex;
}
#mail>form>.submit>label {
padding : 10px 20px;
border : unset;
border-radius: 3px 0 0 3px;
}
#mail>form>.submit>input {
padding : 10px 20px;
flex-grow : 1;
border : unset;
border-radius: 0 3px 3px 0;
}
#mail>form>input[type=submit].registration {
padding : 7px 20px;
background-color: #86781C;
}
#mail>form>input[type=submit].registration:hover {
background-color: #9e8d20;
}
#mail>form>input[type=submit].registration:is(:active, :focus) {
background-color: #776b19;
}
#mail>form>ul.errors {
margin-top : 18px;
margin-bottom : 0px;
padding : 10px;
text-align : center;
list-style : none;
background-color: #ae8f8f;
}
#account {
display : grid;
grid-template-rows: auto auto;
}
#account>button#login {
z-index : 1500;
grid-row: 2;
}
#account>section.tab {
z-index : 1000;
position : relative;
bottom : -100%;
padding : 1.5rem 10%;
display : flex;
flex-direction : column;
align-self : end;
text-align : center;
gap : .8rem;
background-color: var(--background-light-2);
transition : .2s ease-in;
}
#account>button.active+section.tab {
bottom: 0%;
}
#account>section.tab h3:first-of-type {
margin-bottom: 0.5rem;
}
#account>section.tab>* {
margin: unset;
}
#account>section#mail.tab {
grid-row : 1;
display : grid;
grid-template-rows: auto auto;
}
#account>section#mail.tab>#profile {
grid-row : 1;
display : grid;
grid-template-rows: auto auto;
}
#account>section#mail.tab>input[type=mail] {
grid-row : 2;
}
#mail>:is(form, div) {
display : flex;
flex-direction: column;
}
#mail .exit {
margin-top: 25px;
}
#mail p {
margin : 0;
display: flex;
}
#mail p>span {
margin-left: auto;
}
#mail>form>input:is([type=text], [type=password]) {
margin-bottom: 12px;
}
#mail>form>input:last-child {
margin-bottom: unset;
}
#mail>form>.submit {
margin-top : 6px;
margin-bottom: 10px;
display : flex;
}
#mail>form>.submit>label {
padding : 10px 20px;
border : unset;
border-radius: 3px 0 0 3px;
}
#mail>form>.submit>input {
padding : 10px 20px;
flex-grow : 1;
border : unset;
border-radius: 0 3px 3px 0;
}
#mail>form>input[type=submit].registration {
padding : 7px 20px;
background-color: #86781C;
}
#mail>form>input[type=submit].registration:hover {
background-color: #9e8d20;
}
#mail>form>input[type=submit].registration:is(:active, :focus) {
background-color: #776b19;
}
#mail>form>ul.errors {
margin-top : 18px;
margin-bottom : 0px;
padding : 10px;
text-align : center;
list-style : none;
background-color: #ae8f8f;
}
#account {
display : grid;
grid-template-rows: auto auto;
}
#account>button#login {
z-index : 1500;
grid-row: 2;
}
#account>section.tab {
z-index : 1000;
position : relative;
bottom : -100%;
padding : 1.5rem 10%;
display : flex;
flex-direction : column;
align-self : end;
text-align : center;
gap : .8rem;
background-color: var(--background-light-2);
transition : .2s ease-in;
}
#account>button.active+section.tab {
bottom: 0%;
}
#account>section.tab h3:first-of-type {
margin-bottom: 0.5rem;
}
#account>section.tab>* {
margin: unset;
}
#account>section#mail.tab {
grid-row : 1;
display : grid;
grid-template-rows: auto auto;
}
#account>section#mail.tab>#profile {
grid-row : 1;
display : grid;
grid-template-rows: auto auto;
}
#account>section#mail.tab>input[type=mail] {
grid-row : 2;
}

View File

@ -1,52 +1,52 @@
main>section#books {
display: flex;
flex-flow: row wrap;
}
main>section#books>* {
margin-bottom: 20px;
}
main>section#books>form.upload {
width: calc(100% / 3 - 20px - 9px * 2);
height: calc(220px - 9px * 2);
margin: 5px;
margin-right: 20px;
}
main>section#books>form.upload>p {
font-size: 3rem;
height: 0.3rem;
line-height: 0;
}
main>section#books>article.book {
width: calc(100% / 3 - 20px);
margin-right: 20px;
display: flex;
flex-direction: column;
}
main>section#books>article.book:nth-child(3) {
width: calc(100% / 3);
margin-right: unset;
}
main>section#books>article.book>img {
height: 220px;
object-fit: cover;
object-position: right;
overflow: hidden;
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 {
margin-top: 5px;
margin-bottom: 10px;
height: 50px;
text-align: center;
}
main>section#books>article.book>p {
margin: unset;
}
main>section#books {
display: flex;
flex-flow: row wrap;
}
main>section#books>* {
margin-bottom: 20px;
}
main>section#books>form.upload {
width: calc(100% / 3 - 20px - 9px * 2);
height: calc(220px - 9px * 2);
margin: 5px;
margin-right: 20px;
}
main>section#books>form.upload>p {
font-size: 3rem;
height: 0.3rem;
line-height: 0;
}
main>section#books>article.book {
width: calc(100% / 3 - 20px);
margin-right: 20px;
display: flex;
flex-direction: column;
}
main>section#books>article.book:nth-child(3) {
width: calc(100% / 3);
margin-right: unset;
}
main>section#books>article.book>img {
height: 220px;
object-fit: cover;
object-position: right;
overflow: hidden;
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 {
margin-top: 5px;
margin-bottom: 10px;
height: 50px;
text-align: center;
}
main>section#books>article.book>p {
margin: unset;
}

View File

@ -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;
}

View File

@ -1,40 +1,40 @@
header>div#logo {
position : relative;
height : 260px;
display : flex;
flex-direction : column;
justify-content : center;
gap : unset;
border-right : 1px solid;
border-right-color: #ccc;
border-right-color: rgba(255, 255, 255, 0.2);
background-color : rgba(255, 255, 255, 0.2);
overflow : hidden;
}
header>div#logo>h4 {
z-index: 10;
margin : 0 20px;
}
header>div#logo>h1 {
z-index : 50;
margin : 0 37px;
margin-bottom: -5px;
}
header>div#logo>#hotline_logo {
z-index : -50;
position : absolute;
-webkit-filter : blur(2px) brightness(1.3);
filter : blur(2px) brightness(1.3);
/* background-color: var(--background); */
}
header>div#logo>#hotline_logo>article {
margin-bottom: 30px;
}
aside>section#hotline {
clip-path: inset(0 0 0 250px);
}
header>div#logo {
position : relative;
height : 260px;
display : flex;
flex-direction : column;
justify-content : center;
gap : unset;
border-right : 1px solid;
border-right-color: #ccc;
border-right-color: rgba(255, 255, 255, 0.2);
background-color : rgba(255, 255, 255, 0.2);
overflow : hidden;
}
header>div#logo>h4 {
z-index: 10;
margin : 0 20px;
}
header>div#logo>h1 {
z-index : 50;
margin : 0 37px;
margin-bottom: -5px;
}
header>div#logo>#hotline_logo {
z-index : -50;
position : absolute;
-webkit-filter : blur(2px) brightness(1.3);
filter : blur(2px) brightness(1.3);
/* background-color: var(--background); */
}
header>div#logo>#hotline_logo>article {
margin-bottom: 30px;
}
aside>section#hotline {
clip-path: inset(0 0 0 250px);
}

View File

@ -1,165 +1,165 @@
@import url('/fonts/comissioner.ttf');
@media (prefers-color-scheme: light) {
:root {
--background: #eee;
--text : 'dark';
}
}
@media (prefers-color-scheme: dark) {
:root {
--background-light-3: #403939;
--background-light-2: #322d2d;
--background-light-1: #2b2525;
--background-light : #252020;
--background : #221e1e;
--background-dark : ;
--text : #e6e6e6;
--text-hover : #fff;
--text-active : #d0d0d0;
--red-light-1 : #dc4343;
--red-light : #bf3737;
--red : #a43333;
--red-dark : #8d2a2a;
}
}
* {
text-decoration: none;
outline : none;
border : none;
color : var(--text);
font-family : 'Commissioner', sans-serif;
transition : 0.1s ease-out;
}
.unselectable {
-webkit-touch-callout: none;
-webkit-user-select : none;
-khtml-user-select : none;
-moz-user-select : none;
-ms-user-select : none;
user-select : none;
}
a:hover {
color: var(--text-hover);
}
a:active {
color: var(--text-active);
}
body {
height : 100vh;
margin : 0;
display : grid;
grid-template-rows : 10px 200px auto 10px;
grid-template-columns: 250px auto 300px;
grid-row-gap : 20px;
grid-column-gap : 15px;
overflow: hidden;
background-color : var(--background);
}
aside {
z-index : 500;
grid-column: 1/ 4;
grid-row : 2;
overflow : hidden;
}
header {
z-index : 5000;
grid-column : 1;
grid-row : 1 / 5;
display : flex;
flex-direction: column;
box-shadow : 2px 0 5px rgba(0, 0, 0, 0.3);
}
header>menu {
margin : unset;
padding : 20px;
display : flex;
flex-direction : column;
flex-grow : 1;
background-color: var(--background-light-1);
}
header>#account>button#login {
z-index : 1500;
}
header>menu a {
margin-bottom: 8px;
display : flex;
align-items : center;
}
header>menu a:last-child {
margin-bottom: unset;
}
header>menu a svg {
margin-right: 8px;
height : 1.2rem;
position : relative;
}
header>menu a:hover svg {
margin-left : -5px;
margin-right: 13px;
}
header>menu a svg path {
fill: var(--text);
}
header>section {
background-color: var(--background-light-1);
}
header :is(button, a[type="button"]) {
width : 100%;
height : 40px;
display : flex;
justify-content : center;
align-items : center;
cursor : pointer;
background-color: var(--red);
transition : unset;
}
header button {
font-weight : bold;
text-transform: uppercase;
}
header :is(button, a[type="button"]):hover {
background-color: var(--red-light);
}
header :is(button, a[type="button"]):active {
background-color: var(--red-dark);
}
header>nav {
margin-top : auto;
display : flex;
flex-direction: column;
}
main {
z-index : 1000;
grid-column: 2;
grid-row : 3;
}
footer {
z-index : 3000;
grid-column: 3;
grid-row : 1 / 5;
}
@import url('/fonts/comissioner.ttf');
@media (prefers-color-scheme: light) {
:root {
--background: #eee;
--text : 'dark';
}
}
@media (prefers-color-scheme: dark) {
:root {
--background-light-3: #403939;
--background-light-2: #322d2d;
--background-light-1: #2b2525;
--background-light : #252020;
--background : #221e1e;
--background-dark : ;
--text : #e6e6e6;
--text-hover : #fff;
--text-active : #d0d0d0;
--red-light-1 : #dc4343;
--red-light : #bf3737;
--red : #a43333;
--red-dark : #8d2a2a;
}
}
* {
text-decoration: none;
outline : none;
border : none;
color : var(--text);
font-family : 'Commissioner', sans-serif;
transition : 0.1s ease-out;
}
.unselectable {
-webkit-touch-callout: none;
-webkit-user-select : none;
-khtml-user-select : none;
-moz-user-select : none;
-ms-user-select : none;
user-select : none;
}
a:hover {
color: var(--text-hover);
}
a:active {
color: var(--text-active);
}
body {
height : 100vh;
margin : 0;
display : grid;
grid-template-rows : 10px 200px auto 10px;
grid-template-columns: 250px auto 300px;
grid-row-gap : 20px;
grid-column-gap : 15px;
overflow: hidden;
background-color : var(--background);
}
aside {
z-index : 500;
grid-column: 1/ 4;
grid-row : 2;
overflow : hidden;
}
header {
z-index : 5000;
grid-column : 1;
grid-row : 1 / 5;
display : flex;
flex-direction: column;
box-shadow : 2px 0 5px rgba(0, 0, 0, 0.3);
}
header>menu {
margin : unset;
padding : 20px;
display : flex;
flex-direction : column;
flex-grow : 1;
background-color: var(--background-light-1);
}
header>#account>button#login {
z-index : 1500;
}
header>menu a {
margin-bottom: 8px;
display : flex;
align-items : center;
}
header>menu a:last-child {
margin-bottom: unset;
}
header>menu a svg {
margin-right: 8px;
height : 1.2rem;
position : relative;
}
header>menu a:hover svg {
margin-left : -5px;
margin-right: 13px;
}
header>menu a svg path {
fill: var(--text);
}
header>section {
background-color: var(--background-light-1);
}
header :is(button, a[type="button"]) {
width : 100%;
height : 40px;
display : flex;
justify-content : center;
align-items : center;
cursor : pointer;
background-color: var(--red);
transition : unset;
}
header button {
font-weight : bold;
text-transform: uppercase;
}
header :is(button, a[type="button"]):hover {
background-color: var(--red-light);
}
header :is(button, a[type="button"]):active {
background-color: var(--red-dark);
}
header>nav {
margin-top : auto;
display : flex;
flex-direction: column;
}
main {
z-index : 1000;
grid-column: 2;
grid-row : 3;
}
footer {
z-index : 3000;
grid-column: 3;
grid-row : 1 / 5;
}

View File

@ -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;
}

View File

@ -1,17 +1,17 @@
#what_image {
z-index: 9999999;
position: absolute;
width: 100vw;
height: 100vh;
display: none;
transition: unset;
}
#what_image.active {
display: block;
}
.hide {
position: absolute;
display: none;
}
#what_image {
z-index: 9999999;
position: absolute;
width: 100vw;
height: 100vh;
display: none;
transition: unset;
}
#what_image.active {
display: block;
}
.hide {
position: absolute;
display: none;
}

View File

@ -1,33 +1,33 @@
form.upload {
width: 100%;
height: 100px;
position: relative;
display: flex;
border: 4px dashed #e5ddd1;
}
form.upload:hover {
background-color: #ccc6bd;
border: 4px dashed #fff7ea;
}
form.upload>p {
margin: auto;
font-weight: bold;
color: #eee6d9;
}
form.upload:hover>p {
color: #fff7ea;
}
form.upload>input {
width: 100%;
height: 100%;
position: absolute;
opacity: 0;
}
form.upload:hover>input {
cursor: pointer;
}
form.upload {
width: 100%;
height: 100px;
position: relative;
display: flex;
border: 4px dashed #e5ddd1;
}
form.upload:hover {
background-color: #ccc6bd;
border: 4px dashed #fff7ea;
}
form.upload>p {
margin: auto;
font-weight: bold;
color: #eee6d9;
}
form.upload:hover>p {
color: #fff7ea;
}
form.upload>input {
width: 100%;
height: 100%;
position: absolute;
opacity: 0;
}
form.upload:hover>input {
cursor: pointer;
}

View File

Before

Width:  |  Height:  |  Size: 552 B

After

Width:  |  Height:  |  Size: 552 B

View File

Before

Width:  |  Height:  |  Size: 328 B

After

Width:  |  Height:  |  Size: 328 B

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 537 B

After

Width:  |  Height:  |  Size: 537 B

View File

Before

Width:  |  Height:  |  Size: 825 B

After

Width:  |  Height:  |  Size: 825 B

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

Before

Width:  |  Height:  |  Size: 397 KiB

After

Width:  |  Height:  |  Size: 397 KiB

View File

Before

Width:  |  Height:  |  Size: 295 KiB

After

Width:  |  Height:  |  Size: 295 KiB

View File

@ -1,35 +1,35 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\virus;
use mirzaev\minimal\core;
use mirzaev\minimal\router;
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
define('VIEWS', realpath('..' . DIRECTORY_SEPARATOR . 'views'));
define('STORAGE', realpath('..' . DIRECTORY_SEPARATOR . 'storage'));
define('INDEX', __DIR__);
// Автозагрузка
require __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
// Инициализация маршрутазитора
$router = new router;
// Запись маршрутов
$router->write('/', 'index', 'index');
$router->write('/system/hotline', 'hotline', 'index');
$router->write('/account/initialization', 'account', 'initialization', 'PUT');
$router->write('/account/vk/connect', 'account', 'connect');
$router->write('/account/panel', 'account', 'panel');
// Инициализация ядра
$core = new core(namespace: __NAMESPACE__, router: $router);
// Обработка запроса
echo $core->start();
<?php
declare(strict_types=1);
namespace mirzaev\site\ff;
use mirzaev\minimal\core;
use mirzaev\minimal\router;
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
define('VIEWS', realpath('..' . DIRECTORY_SEPARATOR . 'views'));
define('STORAGE', realpath('..' . DIRECTORY_SEPARATOR . 'storage'));
define('INDEX', __DIR__);
// Автозагрузка
require __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
// Инициализация маршрутазитора
$router = new router;
// Запись маршрутов
$router->write('/', 'index', 'index');
$router->write('/system/hotline', 'hotline', 'index');
$router->write('/account/initialization', 'account', 'initialization', 'PUT');
$router->write('/account/vk/connect', 'account', 'connect');
$router->write('/account/panel', 'account', 'panel');
// Инициализация ядра
$core = new core(namespace: __NAMESPACE__, router: $router);
// Обработка запроса
echo $core->start();

View File

@ -1,139 +1,139 @@
"use strict";
class account {
static async initialization() {
// Запрос
return fetch('https://virus.mirzaev.sexy/account/initialization', {
method: 'PUT'
});
}
static authentication(button) {
if (button instanceof HTMLElement) {
// Получены обязательные входные параметры
if (button.classList.contains('active')) {
// Кнопка активна (подразумевается)
if (window.vk !== undefined) {
// Найдена инстанция окна
// Закрытие окна
window.vk.close();
// Удаление окна
window.vk = undefined;
}
// Генерация панели
this.panel(button.parentElement);
// Вызов троллера
troller.what.single();
} else {
// Кнопка неактивна (подразумевается)
// Инициализация активного статуса
button.classList.add('active');
button.innerText = 'Закрыть';
// Настройка окна
const width = 500;
const height = 500;
const left = (window.screen.width / 2) - ((width / 2) + 10);
const top = (window.screen.height / 2) - ((height / 2) + 50);
// Инициализация аккаунта
this.initialization()
.then(
(response) => {
if (response.status === 401 && typeof response.headers.get('session') === 'string') {
// Получен код ответа 401 (не аутентифицирован) и инициализирован аккаунт
// Открытие окна с аунтентификацией ВКонтакте
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'),
'virus_vk',
'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 interval = setInterval(function () {
if (window.vk.closed || window.vk === undefined) {
// Окно с аутентификацией закрыто
// Удаление интервала
clearInterval(interval);
// Генерация панели
_this.panel(button.parentElement);
}
}, 100);
} else if (response.status === 200) {
// Получен код ответа 200 (аутентифицирован)
// Генерация панели
this.panel(button.parentElement);
}
}
);
}
return true;
}
}
static deauthentication() {
if (shell instanceof HTMLElement) {
// Получены обязательные входные параметры
fetch('https://virus.mirzaev.sexy/account/panel', {
method: 'GET'
}).then(
(response) => {
if (response.status === 200) {
// Получен код ответа 200
response.text().then(
(text) => {
console.log(text);
// Запись панели в оболочку
shell.outerHTML = text;
}
);
}
}
);
}
}
static async panel(shell) {
if (shell instanceof HTMLElement) {
// Получены обязательные входные параметры
fetch('https://virus.mirzaev.sexy/account/panel', {
method: 'GET'
}).then(
(response) => {
if (response.status === 200) {
// Получен код ответа 200
response.text().then(
(text) => {
console.log(text);
// Запись панели в оболочку
shell.outerHTML = text;
}
);
}
}
);
}
}
}
"use strict";
class account {
static async initialization() {
// Запрос
return fetch('https://virus.mirzaev.sexy/account/initialization', {
method: 'PUT'
});
}
static authentication(button) {
if (button instanceof HTMLElement) {
// Получены обязательные входные параметры
if (button.classList.contains('active')) {
// Кнопка активна (подразумевается)
if (window.vk !== undefined) {
// Найдена инстанция окна
// Закрытие окна
window.vk.close();
// Удаление окна
window.vk = undefined;
}
// Генерация панели
this.panel(button.parentElement);
// Вызов троллера
troller.what.single();
} else {
// Кнопка неактивна (подразумевается)
// Инициализация активного статуса
button.classList.add('active');
button.innerText = 'Закрыть';
// Настройка окна
const width = 500;
const height = 500;
const left = (window.screen.width / 2) - ((width / 2) + 10);
const top = (window.screen.height / 2) - ((height / 2) + 50);
// Инициализация аккаунта
this.initialization()
.then(
(response) => {
if (response.status === 401 && typeof response.headers.get('session') === 'string') {
// Получен код ответа 401 (не аутентифицирован) и инициализирован аккаунт
// Открытие окна с аунтентификацией ВКонтакте
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'),
'virus_vk',
'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 interval = setInterval(function () {
if (window.vk.closed || window.vk === undefined) {
// Окно с аутентификацией закрыто
// Удаление интервала
clearInterval(interval);
// Генерация панели
_this.panel(button.parentElement);
}
}, 100);
} else if (response.status === 200) {
// Получен код ответа 200 (аутентифицирован)
// Генерация панели
this.panel(button.parentElement);
}
}
);
}
return true;
}
}
static deauthentication() {
if (shell instanceof HTMLElement) {
// Получены обязательные входные параметры
fetch('https://virus.mirzaev.sexy/account/panel', {
method: 'GET'
}).then(
(response) => {
if (response.status === 200) {
// Получен код ответа 200
response.text().then(
(text) => {
console.log(text);
// Запись панели в оболочку
shell.outerHTML = text;
}
);
}
}
);
}
}
static async panel(shell) {
if (shell instanceof HTMLElement) {
// Получены обязательные входные параметры
fetch('https://virus.mirzaev.sexy/account/panel', {
method: 'GET'
}).then(
(response) => {
if (response.status === 200) {
// Получен код ответа 200
response.text().then(
(text) => {
console.log(text);
// Запись панели в оболочку
shell.outerHTML = text;
}
);
}
}
);
}
}
}

View File

@ -1,127 +1,127 @@
"use strict";
class troller {
static what = {
enable() {
document.body.onmouseleave = function () {
// if (Math.random() > 0.90) {
// 10%
troller.what.start();
// }
};
document.body.onmouseenter = function () {
troller.what.end();
};
},
disable() {
document.body.onmouseleave = document.body.onmouseenter = undefined;
},
start() {
// Отображение изображения
document.getElementById('what_image').classList.add('active');
// Инициализация элемента со звуком
const what_sound = document.getElementById('what_sound');
// Воспроизведение звука
what_sound.currentTime = 0;
what_sound.play();
},
end() {
// Сокрытие изображения
document.getElementById('what_image').classList.remove('active');
// Остановка звука
document.getElementById('what_sound').pause();
},
single(event = 'onmouseleave') {
if (typeof event === 'string') {
// Получены обязательные входные параметры
// Отображение изображения
document.getElementById('what_image').classList.add('active');
// Инициализация элемента со звуком
const what_sound = document.getElementById('what_sound');
// Воспроизведение звука
what_sound.currentTime = 0;
what_sound.play();
document.body[event] = function () {
troller.what.end();
document.body[event] = undefined;
};
}
}
}
static vk() {
setInterval(function () {
const sound = document.getElementById('sound_vk');
if (Math.random() > 0.95) {
// 5%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 85000);
}
static whatsapp() {
setInterval(function () {
const sound = document.getElementById('sound_whatsup');
if (Math.random() > 0.97) {
// 3%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 125000);
}
static iphone() {
setInterval(function () {
const sound = document.getElementById('sound_iphone');
if (Math.random() > 0.98) {
// 2%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 265000);
}
}
if (Math.random() > 0.90) {
// 10%
troller.what.enable();
}
if (Math.random() > 0.90) {
// 10%
troller.vk();
}
if (Math.random() > 0.90) {
// 10%
troller.whatsapp();
}
if (Math.random() > 0.90) {
// 10%
troller.iphone();
}
"use strict";
class troller {
static what = {
enable() {
document.body.onmouseleave = function () {
// if (Math.random() > 0.90) {
// 10%
troller.what.start();
// }
};
document.body.onmouseenter = function () {
troller.what.end();
};
},
disable() {
document.body.onmouseleave = document.body.onmouseenter = undefined;
},
start() {
// Отображение изображения
document.getElementById('what_image').classList.add('active');
// Инициализация элемента со звуком
const what_sound = document.getElementById('what_sound');
// Воспроизведение звука
what_sound.currentTime = 0;
what_sound.play();
},
end() {
// Сокрытие изображения
document.getElementById('what_image').classList.remove('active');
// Остановка звука
document.getElementById('what_sound').pause();
},
single(event = 'onmouseleave') {
if (typeof event === 'string') {
// Получены обязательные входные параметры
// Отображение изображения
document.getElementById('what_image').classList.add('active');
// Инициализация элемента со звуком
const what_sound = document.getElementById('what_sound');
// Воспроизведение звука
what_sound.currentTime = 0;
what_sound.play();
document.body[event] = function () {
troller.what.end();
document.body[event] = undefined;
};
}
}
}
static vk() {
setInterval(function () {
const sound = document.getElementById('sound_vk');
if (Math.random() > 0.95) {
// 5%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 85000);
}
static whatsapp() {
setInterval(function () {
const sound = document.getElementById('sound_whatsup');
if (Math.random() > 0.97) {
// 3%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 125000);
}
static iphone() {
setInterval(function () {
const sound = document.getElementById('sound_iphone');
if (Math.random() > 0.98) {
// 2%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 265000);
}
}
if (Math.random() > 0.90) {
// 10%
troller.what.enable();
}
if (Math.random() > 0.90) {
// 10%
troller.vk();
}
if (Math.random() > 0.90) {
// 10%
troller.whatsapp();
}
if (Math.random() > 0.90) {
// 10%
troller.iphone();
}

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,8 +1,8 @@
<?php
return [
'endpoint' => 'unix:///var/run/arangodb3/arango.sock',
'database' => '',
'name' => '',
'password' => ''
];
<?php
return [
'endpoint' => 'unix:///var/run/arangodb3/arango.sock',
'database' => '',
'name' => '',
'password' => ''
];

View File

@ -1,14 +1,14 @@
{% block body %}
<section id="panel">
{% if account %}
{{ account.getKey() }}
{% if vk %}
{{ vk.mail }}
{% endif %}
{% else %}
<button id="login" onclick="return account.authentication(this)">
Войти в аккаунт
</button>
{% endif %}
</section>
{% endblock %}
{% block body %}
<section id="panel">
{% if account %}
{{ account.getKey() }}
{% if vk %}
{{ vk.mail }}
{% endif %}
{% else %}
<button id="login" onclick="return account.authentication(this)">
Войти в аккаунт
</button>
{% endif %}
</section>
{% endblock %}

View File

@ -1,11 +1,11 @@
{% block body %}
<img src="/images/truth.jpg" alt="никому не показывай" style="position: absolute; left: 0; top: 0; width: 100%; height: 100%;">
{% endblock %}
{% block js_init %}
<script>
setTimeout(fn => {
window.opener.vk.close();
}, 2000);
</script>
{% endblock %}
{% block body %}
<img src="/images/truth.jpg" alt="никому не показывай" style="position: absolute; left: 0; top: 0; width: 100%; height: 100%;">
{% endblock %}
{% block js_init %}
<script>
setTimeout(fn => {
window.opener.vk.close();
}, 2000);
</script>
{% endblock %}

View File

@ -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 %}
{% block css %}
{# {{ block('hotline_css') }} #}
{% endblock %}
{% block body %}
<aside>
{{ block('hotline_body') }}
</aside>
{% endblock %}
{% block js %}
{# {{ block('hotline_js') }} #}
{% endblock %}
{% block js_init %}
{# {{ block('hotline_js_init') }} #}
{% endblock %}
{% 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('hotline_css') }} #}
<link type="text/css" rel="stylesheet" href="/css/trash.css">
{% endblock %}
{% block body %}
<aside>
{{ block('hotline_body') }}
</aside>
{% endblock %}
{% block js %}
{# {{ block('hotline_js') }} #}
{% endblock %}
{% block js_init %}
{# {{ block('hotline_js_init') }} #}
{% endblock %}

View File

@ -1,33 +1,33 @@
<!doctype html>
<html lang="ru">
<head>
{% use 'head.html' with title as head_title, meta as head_meta, css as head_css %}
{% block title %}
{{ block('head_title') }}
{% endblock %}
{% block meta %}
{{ block('head_meta') }}
{% endblock %}
{% block css %}
{{ block('head_css') }}
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
{% block js %}
{% include 'js.html' %}
{% endblock %}
{% block js_init %}
{% endblock %}
</body>
</html>
<!doctype html>
<html lang="ru">
<head>
{% use 'head.html' with title as head_title, meta as head_meta, css as head_css %}
{% block title %}
{{ block('head_title') }}
{% endblock %}
{% block meta %}
{{ block('head_meta') }}
{% endblock %}
{% block css %}
{{ block('head_css') }}
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
{% block js %}
{% include 'js.html' %}
{% endblock %}
{% block js_init %}
{% endblock %}
</body>
</html>

View File

@ -1,4 +1,4 @@
<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="/browsers"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
</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="/browsers"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
</footer>

View File

@ -1,15 +1,15 @@
{% block title %}
<title>{% if head.title != empty %}{{head.title}}{% else %}Скачать вирусы бесплатно{% endif %}</title>
{% endblock %}
{% block meta %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{% for meta in head.metas %}
<meta {% for name, value in meta.attributes %}{{name}}="{{value}}" {% endfor %}>
{% endfor %}
{% endblock %}
{% block css %}
<link rel="stylesheet" type="text/css" href="/css/main.css" />
{% endblock %}
{% block title %}
<title>{% if head.title != empty %}{{head.title}}{% else %}Скачать вирусы бесплатно{% endif %}</title>
{% endblock %}
{% block meta %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{% for meta in head.metas %}
<meta {% for name, value in meta.attributes %}{{name}}="{{value}}" {% endfor %}>
{% endfor %}
{% endblock %}
{% block css %}
<link rel="stylesheet" type="text/css" href="/css/main.css" />
{% endblock %}

View File

@ -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 'account/panel.html' with body as panel_body %}
{% block css %}
{{ block('logo_css') }}
{% endblock %}
{% block body %}
<header>
{{ block('logo_body') }}
{% include 'menu.html' %}
{{ block('panel_body') }}
</header>
{% endblock %}
{% block js %}
{{ block('logo_js') }}
{% endblock %}
{% block js_init %}
{{ block('logo_js_init') }}
{% endblock %}
{% 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 %}
{% block css %}
{{ block('logo_css') }}
{% endblock %}
{% block body %}
<header>
{{ block('logo_body') }}
{% include 'menu.html' %}
{{ block('panel_body') }}
</header>
{% endblock %}
{% block js %}
{{ block('logo_js') }}
{% endblock %}
{% block js_init %}
{{ block('logo_js_init') }}
{% endblock %}

View File

@ -1,28 +1,28 @@
{% block css %}
<link type="text/css" rel="stylesheet" href="/css/hotline.css">
{% endblock %}
{% block body %}
{% if hotline.id != empty %}
<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
}}="{{value}}" {% endfor %}>
{% for element in hotline.elements %}
<{{element.tag??'article'}}>{{ element.content }}</{{element.tag??'article'}}>
{% endfor %}
</section>
{% endif %}
{% endblock %}
{% block js %}
<script type="text/javascript" src="/js/hotline.js" defer></script>
{% endblock %}
{% block js_init %}
<script>
document.addEventListener('hotline.loaded', function (e) {
// Запуск препроцессора бегущих строк
e.detail.hotline.preprocessing();
});
</script>
{% endblock %}
{% block css %}
<link type="text/css" rel="stylesheet" href="/css/hotline.css">
{% endblock %}
{% block body %}
{% if hotline.id != empty %}
<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
}}="{{value}}" {% endfor %}>
{% for element in hotline.elements %}
<{{element.tag??'article'}} {% for attribute, value in element.attributes %}{{ attribute }}="{{ value }}"{% endfor %}>{{ element.html|raw }}</{{element.tag??'article'}}>
{% endfor %}
</section>
{% endif %}
{% endblock %}
{% block js %}
<script type="text/javascript" src="/js/hotline.js" defer></script>
{% endblock %}
{% block js_init %}
<script>
document.addEventListener('hotline.loaded', function (e) {
// Запуск препроцессора бегущих строк
e.detail.hotline.preprocessing();
});
</script>
{% endblock %}

View File

@ -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>

View File

@ -1,41 +1,41 @@
{% 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 "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 "aside.html" with css as aside_css, body as aside_body, js as aside_js, js_init as aside_js_init %}
{% block css %}
{{ block('core_css') }}
{{ block('trolling_css') }}
{{ block('header_css') }}
{{ block('aside_css') }}
{% endblock %}
{% block body %}
{{ block('core_body') }}
{{ block('trolling_body') }}
{{ block('aside_body') }}
{{ block('header_body') }}
<main>
<noscript>К сожалению мой сайт ещё пока не готов для работы без javascript</noscript>
{% block main %}
{% endblock %}
</main>
{# {% include 'footer.html' %} #}
{% endblock %}
{% block js %}
{{ block('core_js') }}
{{ block('trolling_js') }}
{{ block('header_js') }}
{{ block('aside_js') }}
{% endblock %}
{% block js_init %}
{{ block('core_js_init') }}
{{ block('header_js_init') }}
{{ block('aside_js_init') }}
{% endblock %}
{% 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 "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 "aside.html" with css as aside_css, body as aside_body, js as aside_js, js_init as aside_js_init %}
{% block css %}
{{ block('core_css') }}
{{ block('trolling_css') }}
{{ block('header_css') }}
{{ block('aside_css') }}
{% endblock %}
{% block body %}
{{ block('core_body') }}
{{ block('trolling_body') }}
{{ block('aside_body') }}
{{ block('header_body') }}
<main>
<noscript>Весь код на JavaScript выполняется из соглашения по твоему выбору через popup-окно (cookies), смело включай</noscript>
{% block main %}
{% endblock %}
</main>
{# {% include 'footer.html' %} #}
{% endblock %}
{% block js %}
{{ block('core_js') }}
{{ block('trolling_js') }}
{{ block('header_js') }}
{{ block('aside_js') }}
{% endblock %}
{% block js_init %}
{{ block('core_js_init') }}
{{ block('header_js_init') }}
{{ block('aside_js_init') }}
{% endblock %}

View File

@ -1,4 +1,4 @@
{% block js %}
<script type="text/javascript" src="/js/js.cookie.min.js" defer></script>
<script type="text/javascript" src="/js/account.js" defer></script>
{% endblock %}
{% block js %}
<script type="text/javascript" src="/js/js.cookie.min.js" defer></script>
<script type="text/javascript" src="/js/account.js" defer></script>
{% endblock %}

View File

@ -1,56 +1,56 @@
{% use 'hotline/index.html' with css as hotline_css, body as hotline_body, js as hotline_js %}
{% block css %}
<link rel="stylesheet" type="text/css" href="/css/logo.css" />
{{ block('hotline_css') }}
{% endblock %}
{% block body %}
<div id="logo" class="unselectable">
<h1>VIRUS</h1>
<h4>Скачать вирусы бесплатно</h4>
{% with %}
{% set hotline = hotline|merge({'id': 'hotline_logo'}) %}
{{ block('hotline_body') }}
{% endwith %}
</div>
{% endblock %}
{% block js %}
{{ block('hotline_js') }}
{% endblock %}
{% block js_init %}
{{ block('hotline_js_init') }}
<script>
document.addEventListener('hotline.loaded', function (e) {
// Запуск препроцессора бегущих строк
// Инициализация элемента бегущей строки
const element_hotline = document.getElementById('hotline');
const element_hotline_logo = document.getElementById('hotline_logo');
// Инициализация слушателя
element_hotline.hotline.events.set('move.block', true);
element_hotline.hotline.events.set('move.unblock', true);
element_hotline.hotline.events.set('onmousemove', true);
document.addEventListener(`hotline.${element_hotline.id}.move.block`, function (e) {
// Копирование блокировки
element_hotline_logo.hotline.move = false;
});
document.addEventListener(`hotline.${element_hotline.id}.move.unblock`, function (e) {
// Копирование блокировки
element_hotline_logo.hotline.move = true;
});
document.addEventListener(`hotline.${element_hotline.id}.onmousemove`, function (e) {
// Копирование перемещения
element_hotline_logo.hotline.offset(e.detail.to);
});
});
</script>
{% endblock %}
{% use 'hotline/index.html' with css as hotline_css, body as hotline_body, js as hotline_js %}
{% block css %}
<link rel="stylesheet" type="text/css" href="/css/logo.css" />
{{ block('hotline_css') }}
{% endblock %}
{% block body %}
<div id="logo" class="unselectable">
<h1>VIRUS</h1>
<h4>Скачать вирусы бесплатно</h4>
{% with %}
{% set hotline = hotline|merge({'id': 'hotline_logo'}) %}
{{ block('hotline_body') }}
{% endwith %}
</div>
{% endblock %}
{% block js %}
{{ block('hotline_js') }}
{% endblock %}
{% block js_init %}
{{ block('hotline_js_init') }}
<script>
document.addEventListener('hotline.loaded', function (e) {
// Запуск препроцессора бегущих строк
// Инициализация элемента бегущей строки
const element_hotline = document.getElementById('hotline');
const element_hotline_logo = document.getElementById('hotline_logo');
// Инициализация слушателя
element_hotline.hotline.events.set('move.block', true);
element_hotline.hotline.events.set('move.unblock', true);
element_hotline.hotline.events.set('onmousemove', true);
document.addEventListener(`hotline.${element_hotline.id}.move.block`, function (e) {
// Копирование блокировки
element_hotline_logo.hotline.move = false;
});
document.addEventListener(`hotline.${element_hotline.id}.move.unblock`, function (e) {
// Копирование блокировки
element_hotline_logo.hotline.move = true;
});
document.addEventListener(`hotline.${element_hotline.id}.onmousemove`, function (e) {
// Копирование перемещения
element_hotline_logo.hotline.offset(e.detail.to);
});
});
</script>
{% endblock %}

View File

@ -1,25 +1,25 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\virus\views;
use mirzaev\minimal\controller;
use Twig\Loader\FilesystemLoader;
use Twig\Environment as view;
/**
* Менеджер представлений
*
* @package mirzaev\site\virus\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class manager extends controller
{
public function render(string $file, array $vars = []): ?string
{
// Генерация представления
return (new view(new FilesystemLoader(VIEWS)))->render($file, $vars);
}
}
<?php
declare(strict_types=1);
namespace mirzaev\site\ff\views;
use mirzaev\minimal\controller;
use Twig\Loader\FilesystemLoader;
use Twig\Environment as view;
/**
* Менеджер представлений
*
* @package mirzaev\site\ff\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class manager extends controller
{
public function render(string $file, array $vars = []): ?string
{
// Генерация представления
return (new view(new FilesystemLoader(VIEWS)))->render($file, $vars);
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,15 +1,15 @@
{% block css %}
<link rel="stylesheet" type="text/css" href="/css/trolling.css" />
{% endblock %}
{% block body %}
<img id="what_image" class="hide" src="/images/what.png" />
<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_whatsup" class="hide" src="/sounds/whatsup.mp3" controls></audio>
<audio id="sound_iphone" class="hide" src="/sounds/iphone.mp3" controls></audio>
{% endblock %}
{% block js %}
<script src="/js/trolling.js" defer></script>
{% endblock %}
{% block css %}
<link rel="stylesheet" type="text/css" href="/css/trolling.css" />
{% endblock %}
{% block body %}
<img id="what_image" class="hide" src="/images/what.png" />
<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_whatsup" class="hide" src="/sounds/whatsup.mp3" controls></audio>
<audio id="sound_iphone" class="hide" src="/sounds/iphone.mp3" controls></audio>
{% endblock %}
{% block js %}
<script src="/js/trolling.js" defer></script>
{% endblock %}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}