Compare commits

...

No commits in common. "stable" and "1.1.x" have entirely different histories.

98 changed files with 3610 additions and 2960 deletions

6
.gitignore vendored Executable file → Normal file
View File

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

22
LICENSE Executable file → Normal file
View File

@ -1,11 +1,11 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004 Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed. Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO. 0. You just DO WHAT THE FUCK YOU WANT TO.

4
README.md Executable file → Normal file
View File

@ -1,3 +1,3 @@
# BEBRA DREAMERS RULES # site-virus
Interactive site with the rules of our discord chat
Site with viruses and scary pictures

99
composer.json Executable file → Normal file
View File

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

594
composer.lock generated Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,60 +0,0 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\rules\controllers;
// Файлы проекта
use mirzaev\site\rules\views\manager;
use mirzaev\site\rules\models\core as models;
use mirzaev\site\rules\models\account_model as account;
use mirzaev\site\rules\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\rules\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'] = [
'vk' => []
];
// Инициализация препроцессора представления
$this->view = new manager;
}
}

View File

@ -1,37 +0,0 @@
<?php
declare(strict_types=1);
namespace mirzaev\site\rules\controllers;
// Файлы проекта
use mirzaev\site\rules\controllers\core;
/**
* Контроллер основной страницы
*
* @package mirzaev\site\rules\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['troller'] = [
'instasamka' => rand(1, 11),
'vk' => (bool) rand(0, 1),
'whatsapp' => (bool) rand(0, 1),
'iphone' => (bool) rand(0, 1),
];
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'index.html', $this->variables);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

View File

@ -1,203 +0,0 @@
@font-face {
font-family: comissioner;
src: url("/fonts/commissioner.ttf") format("ttf");
font-weight: normal;
font-style: normal;
}
:root {
--button-light-red-active: #eee4e4;
--button-light-red-hover: #ddcbcb;
--button-light-red: #eadada;
--background-light: #fff;
--background: #f00;
--background-dark: #000;
--text: #020202;
--text-light: #fafafa;
--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, Roboto, 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 {
color: var(--red-light);
}
a:hover {
color: var(--red-light-1);
}
a:active {
color: var(--red-dark);
}
button {
cursor: pointer;
background-color: var(--button-light-red);
}
button:hover {
background-color: var(--button-light-red-hover);
}
button:active {
background-color: var(--button-light-red-active);
}
button[disabled]:is(:hover, :active) {
cursor: unset;
background-color: var(--button-light-red);
}
body {
margin: 0;
padding-top: calc(20vh + 394px);
padding-bottom: 10vh;
display: flex;
flex-direction: column;
background-color: var(--background);
}
aside {
z-index: 500;
}
div#wrap {
margin-top: -394px;
margin-left: 50vw;
position: absolute;
}
div#wrap > a > img#masha {
z-index: 800;
left: 0;
bottom: 0;
width: 333px;
height: 394px;
position: relative;
cursor: pointer;
animation-direction: alternate;
animation-name: koshka_dancing;
animation-iteration-count: infinite;
animation-timing-function: cubic-bezier(0.65, 0.05, 0.36, 1);
}
:is(div#wrap > a > img#masha, div#wrap > a > #masha_hand):hover {
animation-play-state: paused;
}
div#wrap > a > #masha_hand {
left: 0;
bottom: 0;
position: absolute;
cursor: pointer;
animation-direction: alternate;
animation-name: hand_dancing;
animation-iteration-count: infinite;
animation-timing-function: cubic-bezier(0.65, 0.05, 0.36, 1);
}
div#wrap > a > #masha_hand > img#hand {
z-index: 500;
left: -30px;
bottom: -5px;
width: 70px;
height: 88px;
position: absolute;
}
div#wrap > a > #masha_hand > img#knife {
z-index: 100500;
left: calc(-112px + 70px - 40px);
bottom: calc(-273px + 88px + 35px);
width: 112px;
height: 273px;
position: absolute;
}
header {
z-index: 5000;
width: 800px;
height: 100px;
margin: 0 auto;
display: flex;
border-radius: 3px 3px 0 0;
background-color: var(--background-dark);
}
header > h1 {
margin: auto;
font-size: 2.5rem;
color: var(--text-light);
}
main {
z-index: 1000;
width: 800px;
margin: 0 auto;
border-radius: 0 0 3px 3px;
background-color: var(--background-light);
}
main > ol {
margin: 50px 100px;
font-size: 1.2rem;
}
main > ol > small {
margin-left: 10px;
margin-top: 20px;
margin-bottom: 8px;
display: block;
}
main > ol > li {
padding-left: 40px;
margin-bottom: 8px;
display: flow-root list-item;
}
main > ol > li::marker {
/* font-size: 1.3rem; */
}
main > ol > li :has(img) {
display: flow-root list-item;
}
main > ol > li > img {
float: left;
margin-top: 5px;
max-height: 150px;
}
footer {
z-index: 3000;
}
@media (max-width: 800px) {
body {
padding-bottom: unset;
}
}

View File

@ -1,62 +0,0 @@
section.popup {
z-index: 999999;
left: 0;
top: 0;
position: fixed;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: #000000DD;
}
section.popup>div.wrap {
width: 320px;
padding: 30px 25px;
display: flex;
flex-direction: column;
gap: 20px;
border-radius: 2px;
background-color: var(--background-light);
}
section.popup>div.wrap>h4 {
margin: auto;
padding-top: 10px;
font-size: 1.6rem;
}
section.popup>div.wrap>ol {
width: 220px;
margin: auto;
padding: unset;
list-style: cjk-earthly-branch;
}
section.popup>div.wrap>div.row {
width: 100%;
display: flex;
gap: 12px;
}
section.popup>div.wrap>div.row.separated:last-child {
margin-top: 10px;
}
section.popup>div.wrap>div.row>button {
padding: 6px 20px;
border-radius: 2px;
}
section.popup>div.wrap>div.row>button:first-child {
margin-left: auto;
}
section.popup>div.wrap>div.row>button:last-child{
margin-right: auto;
}
section.popup>div.wrap>div.row>button[disabled]:is(:hover, :active) {
cursor: none;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 754 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@ -1,152 +0,0 @@
"use strict";
class troller {
constructor() {
this.what = {
// HTML-элемент с изображением
sound: document.getElementById("troller_sound_what"),
// HTML-элемент со звуком
image: document.getElementById("troller_image_what"),
enable() {
document.body.onmouseleave = () => this.start();
document.body.onmouseenter = () => this.end();
},
disable() {
document.body.onmouseleave = document.body.onmouseenter = undefined;
},
start() {
// Отображение изображения
this.image.classList.add("active");
// Проигрывание звука
this.play();
// Остановка воспроизведения инстасамки
if (this.core.instasamka.initialized) this.core.instasamka.pause();
},
end() {
// Сокрытие изображения
this.image.classList.remove("active");
// Возобновление воспроизведения инстасамки
if (this.core.instasamka.initialized) this.core.instasamka.play();
// Остановка звука
this.sound.pause();
},
single(event = "onmouseleave") {
if (typeof event === "string") {
// Получены обязательные входные параметры
// Отображение изображения
this.image.classList.add("active");
// Проигрывание звука
this.play();
document.body[event] = function () {
this.end();
document.body[event] = undefined;
};
}
},
play() {
// Воспроизведение звука
this.sound.currentTime = 0;
this.sound.play();
}
};
this.instasamka = {
// HTML-элемент с аудиозаписью
sound: document.getElementById("troller_sound_instasamka"),
initialized: false,
play(time) {
if (this.sound instanceof HTMLElement) {
// Найден звук
// Инициализация инстасамки
if (!this.initialized) this.initialized = true;
// Инициализация временной метки для воспроизведения
if (typeof time === 'number') this.sound.currentTime = time;
// Воспроизведение звука
this.sound.play();
} else {
// Не найден звук (подразумевается)
console.log('[mirzaev] [troller] Не удалось найти песню инстасамки');
}
},
pause() {
if (this.sound instanceof HTMLElement) {
// Найден звук
// Остановка воспроизведения звука
this.sound.pause();
} else {
// Не найден звук (подразумевается)
console.log('[mirzaev] [troller] Не удалось найти песню инстасамки');
}
},
};
// Инициализация ссылок на ядро
this.what.core = this.instasamka.core = this;
}
vk() {
setInterval(function () {
const sound = document.getElementById("troller_sound_vk");
if (Math.random() > 0.95) {
// 5%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 85000);
}
whatsapp() {
setInterval(function () {
const sound = document.getElementById("troller_sound_whatsup");
if (Math.random() > 0.97) {
// 3%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 125000);
}
iphone() {
setInterval(function () {
const sound = document.getElementById("troller_sound_iphone");
if (Math.random() > 0.98) {
// 2%
// Воспроизведение звука
sound.currentTime = 0;
sound.play();
}
}, 265000);
}
}
document.dispatchEvent(
new CustomEvent("troller.loaded", {
detail: { troller },
}),
);

View File

@ -1 +0,0 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

View File

@ -1,47 +0,0 @@
{% block title %}
<title>{% if head.title != empty %}{{head.title}}{% else %}Правила беседы{% endif %}</title>
{% endblock %}
{% block meta %}
<meta charset="utf-8">
<meta name="viewport" content="width=800px">
<meta name="HandheldFriendly" content="true">
<meta name="MobileOptimized" content="width">
<meta content='yes' name='apple-mobile-web-app-capable' />
<meta name="description" content='Rules of our Discord server "BEBRA DREAMERS"' />
<meta name="keywords" content="MIRZAEV, BEBRA DREAMERS, rules" />
<meta name="author" content="MIRZAEV" />
<meta name="revised" content="04-01-2024" />
<meta property="og:title" content="BEBRA DREAMERS RULES" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2024-01-04" />
<meta property="article:author" content="MIRZAEV" />
<meta property="article:section" content="community" />
<meta property="article:tag" content="MIRZAEV, BEBRA DREAMERS, rules" />
<meta property="og:url" content="https://rules.bebra.team/" />
<meta property="og:image" content="https://rules.bebra.team/images/mirzaev.jpg" />
<meta property="og:image" content="https://rules.bebra.team/images/mirzaev2.png" />
<meta property="og:description" content='Rules of our Discord server "BEBRA DREAMERS"' />
<meta property="og:site_name" content="bebra.team" />
<meta property="og:video" content="https://rules.bebra.team/videos/welcome.mp4" />
<meta property="og:audio" content="https://rules.bebra.team/sounds/putin.mp3" />
<meta property="twitter:card" content="summary">
<meta property="twitter:creator" content="@mirzaev_sexy">
<meta property="twitter:site" content="@mirzaev_sexy">
<meta property="twitter:url" content="https://rules.bebra.team/">
<meta property="twitter:title" content="BEBRA DREAMERS RULES">
<meta property="twitter:description" content='Rules of our Discord server "BEBRA DREAMERS"'>
<meta property="twitter:image" content="https://rules.bebra.team/images/mirzaev.jpg">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
{% 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,38 +0,0 @@
{% block css %}
{% endblock %}
{% block body %}
<div id="wrap" class="unselectable">
<style>
@keyframes koshka_dancing {
100% {
bottom: -{{ random(15, 40) }}px;
left: {{ random(-5, 5) }}px;
}
}
@keyframes hand_dancing {
100% {
bottom: -{{ random(10, 22) }}px;
left: {{ random(-20, 20) }}px;
}
}
</style>
<a href="https://vk.me/join/gbi_1CbxQrWPZsgQsKMO/_GpWEOYy1XWpSU=">
<img id="masha" style="animation-duration: {{ random(8, 10) / 10 }}s" src="/images/photo_with_kitten.png" alt="Кошка Маша" ondragstart="return false">
<div id="masha_hand" style="animation-duration: {{ random(8, 10) / 10 }}s">
<img id="hand" src="/images/photo_with_hand.png" alt="я помню бебра большой" ondragstart="return false">
<img id="knife" src="/images/photo_with_knife.png" alt="почему адблок сучара банит мои картинки" ondragstart="return false">
</div>
</a>
</div>
<header>
<h1 class="unselectable">ПРАВИЛА БЕСЕДЫ</h1>
</header>
{% endblock %}
{% block js %}
{% endblock %}
{% block js_init %}
{% endblock %}

View File

@ -1,22 +0,0 @@
{% block css %}
<link type="text/css" rel="stylesheet" href="/css/popup.css">
{% endblock %}
{% block body %}
<section class="popup">
<div class="wrap">
<h4>Правила сайта</h4>
<ol>
<li>Читать правила сайта</li>
<li>Читать правила беседы</li>
<li>Ознакомиться с правилами</li>
<li>Принимая кнопку ниже вы соглашаетесь с правилами</li>
</ol>
<div class="row separated">
<button
onclick="bebra.instasamka.play(Math.random() * 100); this.parentElement.parentElement.parentElement.remove();">Прочитал</button>
<button onclick="bebra.what.play(); alert('ты идиот?'); this.disabled = true">Не прочитал</button>
</div>
</div>
</section>
{% endblock %}

View File

@ -1,196 +0,0 @@
<ol>
<li value="0">под ножом нет красной точки</li>
<br>
<li>чоколад запрещено</li>
<li>пажилой запрещено</li>
<li>запрещено бдабдабаб</li>
<li>чи да запрещено</li>
<li>а шо запрещено</li>
<li>не быть дебилом</li>
<li>Админ всегда прав</li>
<li>админа не тролить</li>
<li>гоша джикия запрещен</li>
<li>Егор Родин запрещен</li>
<br>
<li>у нас будет сервер майнкрафт</li>
<li>рофлить запрещено</li>
<li>Мария Мышкина запрещена</li>
<li>ПОРНО ЗАПРЕЩЕНО (16+)</li>
<li>сиськи запрещены</li>
<li>я реально кикну</li>
<li>Пишешь не кошку? могу мут выдать 1 час</li>
<li>пингуешь меня по хуйне? мут 1 день</li>
<li>СПОЙЛЕРИТЬ КОШКУ С ТВИТТЕРА ЗАПРЕЩЕНО</li>
<li>ЗАПРЕЩЕНО Я СКАЗАЛ Я НЕ ШУЧУ НАХУЙ</li>
<br>
<li>Попы тоже запрещено особенно Маши</li>
<li>ладно сиси можно</li>
<li>чичас запрещено</li>
<li>делать что я скажу</li>
<li>ладно прошлое правило это шутка)</li>
<li>ауе запрещено</li>
<li>не оскорблять кошку стикерами</li>
<li>жмых запрещен во всех проявлениях</li>
<li>жмыхать запрещено</li>
<li>ЧСВ запрещено</li>
<br>
<li>попы разрешены только если не видно того самого</li>
<li>враньше разрешено потому что это нормально</li>
<li>Attentionwhore запрещены</li>
<li>картинки в меру будет много убью</li>
<li>Саша Синтаров запрещен</li>
<li>не обамить</li>
<li>аудиоприколы про Арсена запрещены</li>
<li>рэп запрещен (законпроект Фурсовой)</li>
<li>сказал "говнявила" заблоикрован</li>
<li>хуявило употреблять запрещено</li>
<br>
<li>пиздявила употреблять запрещено</li>
<li>оскорбление правил запрещено поняли суки? теперь че</li>
<li>СРАТЬ ЗАПРЕЩЕНО</li>
<li>Спам запрещен</li>
<li>На дуэли проебал не вернем никогда</li>
<li>Жир запрещен</li>
<li>у нас есть сервер майнкрафт</li>
<li>Дуэли запрещены</li>
<li>ножи запрещены выгоню</li>
<br>
<li value="51">пипи эпи запрещен</li>
<li>чересчур умничать запрещено</li>
<li>быть подписанным на паблик</li>
<li>ЛЮБИТЬ КОШКУ МАШКУ</li>
<li>демократия запрещена</li>
<li>грязнули разрешены</li>
<li>брух bruh запрещен</li>
<li>oof запрещен</li>
<li>чуитс запрещено</li>
<li>кринжевать запрещено</li>
<br>
<li>русские националисты не приветствуются</li>
<li>любые националисты тоже</li>
<li>упоминать правило №50 запрещено</li>
<li>будете помогать заблокированным заблокирую</li>
<li>не керокерокать</li>
<li>На тупые вопросы не отвечаем</li>
<li>Так называемые "мемы" запрещены</li>
<li>Вопросы по серверу в паблике сервера или беседе сервера</li>
<li>спойлерить запрещено суки</li>
<li>ЛАДНО кошатник разрешено 6+ но если адекват</li>
<br>
<li>Мир тьмы разрешен (кодзимов попросил)</li>
<li>Вредные советы давать СТРОГО запрещено</li>
<li>пропаганда психотропных веществ запрещена наркалыги ёбаные идите долбите анус свой тупые суки</li>
<li>за оскорбления извините</li>
<li>триган дэ вне закона (законпроект Динозавра)</li>
<li>Не ведите себя как быдло</li>
<li>объяснять что такое буккаке запрещено</li>
<li>веп панк запрещен</li>
<li>I Hate Myself For Loving You ЗАПРЕЩЕН</li>
<li>доминировать как быдло типо мне похуй хаха мне похуй или ты с кем разговариваешь и картинки кидать запрещено</li>
<br>
<li>друзья Даркью Пельменя и он сам запрещены</li>
<li>Носок Террохин запрещен</li>
<li>Не оскорблять отель Хасбин</li>
<li>Даркью Пельмень запрещен</li>
<li>Андрей Останин запрещен</li>
<li>НЕ СПОЙЛЕРИТЬ КОШКУ ЕЩЁ РАЗ ГОВОРЮ В ГРУППЕ КОШКА И НАХУЙ ПУБЛИКОВАТЬ ЕСЛИ ЕЁ ВСЕ ВИДЕЛИ. КТО СПОЙЛЕРИТ ВЕЧНЫЙ
БАН. БЫЛ ТУТ ОДИН....</li>
<li>хамуд запрещён</li>
<li>нуждики разрешены (общим голосованием)</li>
<li>хамуд теперь разрешён чтобы не было червячков</li>
<li>ПОЛИТИКА ЗАПРЕЩЕНА (можно в беседе Альянса З.)</li>
<br>
<li>Оскорбления не в шутку запрещены</li>
<li>Паблик "Оскорбления животных" запрещён</li>
<li>Мужские органы может показывать только Дима Горшенин</li>
<li>Алибека Захарова не трогать, ему не хочется общаться</li>
<li>хрустящий малыш</li>
<li>поддерживающим россию в войне с украиной моментальный бан без объяснения причин</li>
<li>Random-Favorite Character ни о чём не просить</li>
<li>Елизавета Кишкомотина (vk.com/id201222738) запрещена</li>
<li>тупить разрешено 1 раз в течение 30 минут</li>
<li>срать в группу запрещено</li>
<br>
<li>набивать репутацию друг другу запрещено</li>
<li>писать хуйню запрещено</li>
<li>толерантность разрешена</li>
<li>правила теперь есть</li>
<li>я могу выгонять зашедших по поиску долбаёбов</li>
<li>про овечек писать только хорошее</li>
<li>даркью пельмень и его шпана запрещены</li>
<li>клишированные долбаёбы запрещены</li>
<li>обсирать анархию ЗАПРЕЩЕНО</li>
<li>Влада Грибоедина (vk.com/id368523707) запрещена</li>
<br>
<li>критиковать правила запрещено</li>
<li>лайки ставить в группе партии горничные</li>
<li>Любить родину</li>
<li>всем девушкам випки</li>
<li>читать анарзию</li>
<li>Тупить запрещено</li>
<li>Тупые вопросы запрещены</li>
<li>не употреблять словосочетание ловушка джокера</li>
<li>я могу банить за неадекватные публикации, спам и флуд по своему желанию</li>
<li>кто зашел намеренно срать не скрывал это и не общался наказание пролом нижней челюсти</li>
<br>
<li>писать мне похуй запрещено</li>
<li>писать ок запрещено</li>
<li>писать + запрещено</li>
<li>писать + разрешено</li>
<li>Администратор имеет право забанить человека если он сам того пожелал</li>
<li>15.01.2022 в 20:39 здесь ничего не произошло</li>
<li>снюс запрещён (законпроект Никиты Вальбдаузера)</li>
<li>мясо запрещено</li>
<li>мясо запрещено</li>
<li>всех погибших исключают из беседы</li>
<br>
<li>если чувак видно что зашел насрать а не общаться то я воспринимаю это как флуд и распрояжаюсь по правилу 129</li>
<li>Отказался читать правила получишь пизды</li>
<li>упоминание непризнанных альянсов запрещено</li>
<li>Все группы которые выставляют себя за Альянс Добряков запрещены</li>
<li>мнемотехника охуенна</li>
<li>главное — БУДЬТЕ БЛЯДЬ ЛЮДЬМИ, серьёзно.</li>
<li>играть в аллоды онлайн на сервере приют</li>
<li>какого хуя вы не общаетесь весь день и как только я начинаю что-то рассказывать перебиваете меня и рассказываете
свою тупую хуйню?</li>
<li>мясо запрещено</li>
<br>
<li>В БЕСЕДЕ ПРАВИЛ НЕТ</li>
<li>обсуждение и показ трупов запрещены</li>
<li>знать все серии пони ОБЯЗАТЕЛЬНО</li>
<li>подисаться на мой ютуб канал</li>
<li>сдать тест на знание песен инстасамки</li>
<li>шарить за бебру</li>
<li>правило номер 129 (связано с 131) было хакировано альянсом злодеев и мы прилагаем все усилия для его
восстановления</li>
<small>добавлено новые правила 27.03.2023</small>
<li>Мы русские</li>
<li>Любить россию обязательно всем</li>
<li>Я люблю Российскую федерацию</li>
<small>05.04.2023</small>
<li><a href="https://vk.com/id408864038">лёше</a> запрещено публиковать .gif изображения,
изображения
сексуального характера, изображения прикольного характера</li>
<li>ВНИМАНИЕ в чате разрешён phonk с 22:00 по 24:00</li>
<li><a href="https://vk.com/id621401005">ольга</a> теперь детка</li>
<small>09.04.2023</small>
<li>огузок запрещён.</li>
<small>2023.04.10</small>
<li>ходатайства запрещены</li>
<li><a href="https://vk.com/id214547089">даниил_богданов</a> в уголовном розыске</li>
<li>шутить двусмысленно запрещено</li>
<li>нарушать правило 99 запрещено</li>
<li>я хочу девочку</li>
<li>присылать фотографии в ворд документах запрещено</li>
<li>новое правило налить мне кофе</li>
<small>2023.04.11</small>
<li>мозг данила</li>
<li>декоммунизация декапитализация + дековидизация</li>
<li>мы скоро закроемся</li>
<small>2023.04.13</small>
<li>мелкий здарова</li>
<li><a href="https://vk.com/id214547089">даниил_богданов</a> разрабатывает госуслуги бля</li>
<li>ванда в чате)</li>
<li>томатные спагетти запрещены</li>
<li><img src="/images/xiaomi.jpg" alt="Взял себе Xiaomi"></li>
</ol>

View File

@ -1,67 +0,0 @@
{% block css %}
<link rel="stylesheet" type="text/css" href="/css/troller.css" />
{% endblock %}
{% block body %}
<img id="troller_image_what" class="hide" src="/images/what.png" />
<audio id="troller_sound_what" class="hide" src="/sounds/what.mp3" preload="auto"></audio>
{% if troller.vk %}
<audio id="troller_sound_vk" class="hide" src="/sounds/vk.mp3" preload="auto"></audio>
<script>
document.addEventListener('troller.initialized', function () {
// Инициализирован шутник
// Активация интервального воспроизведения звука сообщения ВКонтакте
bebra.vk();
});
</script>
{% endif %}
{% if troller.whatsapp %}
<audio id="troller_sound_whatsup" class="hide" src="/sounds/whatsup.mp3" preload="auto"></audio>
<script>
document.addEventListener('troller.initialized', function () {
// Инициализирован шутник
// Активация интервального воспроизведения звука сообщения WhatsApp
bebra.whatsapp();
});
</script>
{% endif %}
{% if troller.iphone %}
<audio id="troller_sound_iphone" class="hide" src="/sounds/iphone.mp3" preload="auto"></audio>
<script>
document.addEventListener('troller.initialized', function () {
// Инициализирован шутник
// Активация интервального воспроизведения звука сообщения iPhone
bebra.iphone();
});
</script>
{% endif %}
<audio id="troller_sound_instasamka" class="hide" src="/sounds/instasamka/{{ troller.instasamka ?? 3 }}.mp3"
preload="auto" loop="true"></audio>
{% endblock %}
{% block js %}
<script src="/js/troller.js" defer></script>
{% endblock %}
{% block js_init %}
<script>
// Инициализация переменной шутника в общей области видимости
let bebra;
document.addEventListener('troller.loaded', function (e) {
// Загружен документ с классом шутника
// Инициализация шутника
bebra = new e.detail.troller;
// Вызов события о том, что шутник инициализирован
document.dispatchEvent(new CustomEvent("troller.initialized"));
// Активация изображения при потере фокуса с окна
bebra.what.enable();
});
</script>
{% endblock %}

View File

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

View File

@ -0,0 +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;
}
}

View File

@ -1,44 +1,44 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace mirzaev\site\rules\controllers; namespace mirzaev\site\virus\controllers;
// Файлы проекта // Файлы проекта
use mirzaev\site\rules\controllers\core; use mirzaev\site\virus\controllers\core;
/** /**
* Контроллер ошибок * Контроллер ошибок
* *
* @package mirzaev\site\rules\controllers * @package mirzaev\site\virus\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy> * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/ */
final class error_controller extends core final class error_controller extends core
{ {
/** /**
* Страница с ошибкой * Страница с ошибкой
* *
* @param array $parameters * @param array $parameters
*/ */
public function index(array $parameters = []): ?string public function index(array $parameters = []): ?string
{ {
// Запись текста ошибки в переменную окружения // Запись текста ошибки в переменную окружения
$this->variables['text'] = $parameters['text'] ?? null; $this->variables['text'] = $parameters['text'] ?? null;
if (isset($parameters['code'])) { if (isset($parameters['code'])) {
// Получен код ошибки // Получен код ошибки
// Запись кода ошибки в переменную окружения // Запись кода ошибки в переменную окружения
$this->variables['code'] = $parameters['code']; $this->variables['code'] = $parameters['code'];
// Запись кода ответа // Запись кода ответа
http_response_code($parameters['code']); http_response_code($parameters['code']);
// Генерация представления // Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . 'index.html', $this->variables); return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
} }
// Генерация представления // Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . ($parameters['code'] ?? 'index') . '.html', $this->variables); return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . ($parameters['code'] ?? 'index') . '.html', $this->variables);
} }
} }

View File

@ -1,82 +1,82 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace mirzaev\site\rules\controllers; namespace mirzaev\site\virus\controllers;
// Файлы проекта // Файлы проекта
use mirzaev\site\rules\controllers\core; use mirzaev\site\virus\controllers\core;
/** /**
* Контроллер бегущей строки * Контроллер бегущей строки
* *
* @package mirzaev\site\rules\controllers * @package mirzaev\site\virus\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy> * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/ */
final class hotline_controller extends core final class hotline_controller extends core
{ {
/** /**
* Страница с бегущей строкой * Страница с бегущей строкой
* *
* Можно использовать совместно с элементом <iframe> для изоляции * Можно использовать совместно с элементом <iframe> для изоляции
* содержимого бегущей строки от поисковых роботов * содержимого бегущей строки от поисковых роботов
* *
* @param array $parameters * @param array $parameters
*/ */
public function index(array $parameters = []): ?string public function index(array $parameters = []): ?string
{ {
// Инициализация элементов для генерации в головном элементе // Инициализация элементов для генерации в головном элементе
$this->variables['head'] = [ $this->variables['head'] = [
'title' => 'Бегущая строка', 'title' => 'Бегущая строка',
'metas' => [ 'metas' => [
[ [
'attributes' => [ 'attributes' => [
'name' => 'robots', 'name' => 'robots',
'content' => 'nofollow' 'content' => 'nofollow'
] ]
] ]
] ]
]; ];
// Инициализация бегущей строки // Инициализация бегущей строки
$this->variables['hotline'] = [ $this->variables['hotline'] = [
'id' => $this->variables['request']['id'] ?? 'hotline' 'id' => $this->variables['request']['id'] ?? 'hotline'
]; ];
// Инициализация параметров бегущей строки // Инициализация параметров бегущей строки
$this->variables['hotline']['parameters'] = [ $this->variables['hotline']['parameters'] = [
// 'step' => 2 // 'step' => 2
]; ];
// Инициализация аттрибутов бегущей строки // Инициализация аттрибутов бегущей строки
$this->variables['hotline']['attributes'] = [ $this->variables['hotline']['attributes'] = [
]; ];
// Инициализация элементов бегущей строки // Инициализация элементов бегущей строки
$this->variables['hotline']['elements'] = [ $this->variables['hotline']['elements'] = [
['content' => '1'], ['content' => '1'],
[ [
'tag' => 'article', 'tag' => 'article',
'content' => '2' 'content' => '2'
], ],
['content' => '3'], ['content' => '3'],
['content' => '4'], ['content' => '4'],
['content' => '5'], ['content' => '5'],
['content' => '6'], ['content' => '6'],
['content' => '7'], ['content' => '7'],
['content' => '8'], ['content' => '8'],
['content' => '9'], ['content' => '9'],
['content' => '10'], ['content' => '10'],
['content' => '11'], ['content' => '11'],
['content' => '12'], ['content' => '12'],
['content' => '13'], ['content' => '13'],
['content' => '14'], ['content' => '14'],
['content' => '15'] ['content' => '15']
]; ];
// Генерация представления // Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'hotline' . DIRECTORY_SEPARATOR . 'index.html', $this->variables); return $this->view->render(DIRECTORY_SEPARATOR . 'hotline' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
} }
} }

View File

@ -0,0 +1,71 @@
<?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

@ -0,0 +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;
}
}

View File

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

@ -0,0 +1,555 @@
<?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;
// Фреймворк ВКонтакте
use mirzaev\vk\robots\user as robot;
// Библиотека для ArangoDB
use ArangoDBClient\Document as _document;
// Библиотека браузера
use GuzzleHttp\Client as browser;
// Встроенные библиотеки
use exception;
use stdClass;
/**
* Модель аккаунта ВКонтакте
*
* @package mirzaev\site\virus\models
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class vk_model extends core
{
/**
* Коллекция
*/
public const COLLECTION = 'vk';
/**
* Инициализация
*
* @param string $response Ответ сервера ВКонтакте с данными аккаунта
* @param array &$errors Журнал ошибок
*
* @return ?_document Инстанция аккаунта ВКонтакте, если удалось создать
*/
public static function initialization(string $response = '', array &$errors = []): ?_document
{
try {
if (collection::init(static::$db->session, self::COLLECTION)) {
// Инициализирована коллекция
// Инициализация данных аккаунта ВКонтакте
$data = json_decode($response);
if ($account = collection::search(static::$db->session, sprintf(
<<<AQL
FOR d IN %s
FILTER d.id == $data->user_id
RETURN d
AQL,
self::COLLECTION
))) {
// Найден аккаунт ВКонтакте
return $account;
} else {
// Не найден аккаунт ВКонтакте
return self::create($response, $errors);
}
} else throw new exception('Не удалось инициализировать коллекцию');
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return null;
}
/**
* Создание
*
* @param string $response Ответ сервера ВКонтакте с данными аккаунта
* @param array &$errors Журнал ошибок
*
* @return ?_document Инстанция аккаунта ВКонтакте, если удалось создать
*/
public static function create(string $response = '', 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
))) {
// Найден созданный аккаунт ВКонтакте
if (document::update(static::$db->session, $account)) {
// Записано обновление
// Запись данных об аккаунте ВКонтакте и возврат (bool)
return self::update($account, json_decode($response), $errors);
}
}
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 string $code Код полученный от ВКонтакте
* @param array &$errors Журнал ошибок
*
* @return ?string Тело ответа, если получен код ответа 200
*/
public static function key(string $code = '', array &$errors = []): ?string
{
try {
// Инициализация браузера
$browser = new browser();
// Запрос
$response = $browser->request('GET', "https://oauth.vk.com/access_token?client_id=51447080&client_secret=KYlk0nGELW0A9ds7NQi6&redirect_uri=https://virus.mirzaev.sexy/account/vk/connect&code=$code");
if ($response->getStatusCode() === 200) {
// Ответ сервера: 200
return (string) $response->getBody();
} else throw new exception('Не удалось получить ключ ВКонтакте (' . $response->getStatusCode() . ')');
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return null;
}
/**
* Поиск связанного аккаунта
*
* @param _document $vk Инстанция аккаунта ВКонтакте
* @param array &$errors Журнал ошибок
*
* @return ?_document Инстанция аккаунта, если удалось найти
*/
public static function account(_document $vk, array &$errors = []): ?_document
{
try {
if (
collection::init(static::$db->session, self::COLLECTION)
&& collection::init(static::$db->session, account::COLLECTION)
&& collection::init(static::$db->session, account::COLLECTION . '_edge_' . self::COLLECTION, true)
) {
// Инициализированы коллекции
if ($account = collection::search(static::$db->session, sprintf(
<<<AQL
FOR document IN %s
LET edge = (
FOR edge IN %s
FILTER edge._to == '%s'
SORT edge._key DESC
LIMIT 1
RETURN edge
)
FILTER document._id == edge[0]._from
LIMIT 1
RETURN document
AQL,
account::COLLECTION,
account::COLLECTION . '_edge_' . self::COLLECTION,
$vk->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;
}
/**
* Запрос данных аккаунта ВКонтакте с серверов ВКонтакте
*
* @param robot $vk Инстанция аккаунта ВКонтакте
* @param array &$errors Журнал ошибок
*
* @return ?stdClass Данные аккаунта ВКонтакте, если получены
*/
public static function parse(robot $vk, array &$errors = []): ?stdClass
{
try {
// Запрос к API-серверу ВКонтакте
$response = $vk->user->get(fields: [
'activities',
'about',
// 'blacklisted',
// 'blacklisted_by_me',
'books',
'bdate',
'can_be_invited_group',
'can_post',
'can_see_all_posts',
'can_see_audio',
'can_send_friend_request',
'can_write_private_message',
'career',
'common_count',
'connections',
'contacts',
'city',
'country',
'crop_photo',
'domain',
'education',
'exports',
'followers_count',
'friend_status',
'has_photo',
'has_mobile',
'home_town',
'photo_50',
'photo_100',
'photo_200',
'photo_200_orig',
'photo_400_orig',
'photo_max',
'photo_max_orig',
'sex',
'site',
'schools',
'screen_name',
'status',
'verified',
'games',
'interests',
'is_favorite',
'is_friend',
'is_hidden_from_feed',
'last_seen',
'maiden_name',
'military',
'movies',
'music',
'nickname',
'occupation',
'online',
'personal',
'photo_id',
'quotes',
'relation',
'relatives',
'timezone',
'tv',
'universities'
])[0];
if (!empty($response)) {
// Получен ответ
return $response;
}
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return null;
}
/**
* Обновление данных аккаунта ВКонтакте
*
* Все файлы (аватар, например) будут скачаны на сервер
*
* @param _document $vk Инстанция аккаунта ВКонтакте
* @param stdClass $data Информация об аккаунте (self::parse() или json_decode())
* @param array &$errors Журнал ошибок
*
* @return ?_document Инстанция аккаунта ВКонтакте, если удалось обновить
*/
public static function update(_document $vk, stdClass $data, array &$errors = []): ?_document
{
try {
if (collection::init(static::$db->session, self::COLLECTION)) {
// Инициализирована коллекция
if (empty($vk->id) and isset($data->user_id) || isset($data->id)) {
// Получен идентификатор
// Запись
$vk->id = $data->user_id ?? $data->id;
// Удаление из списка необработанных
unset($data->user_id, $data->id);
} else if (empty($vk->id)) throw new exception('Не удалось найти идентификатор аккаунта ВКонтакте');
if (isset($data->access_token, $data->expires_in)) {
// Получен ключ
// Запись
$vk->access = [
'key' => $data->access_token,
'expires' => $data->expires_in
];
// Удаление из списка необработанных
unset($data->access_token, $data->expires_in);
}
// Инициализация браузера
$browser = new browser();
// Инициализация директории с обложкой
if (!file_exists($path = INDEX . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . $vk->id . DIRECTORY_SEPARATOR . 'cover' . DIRECTORY_SEPARATOR))
mkdir($path, 0775, true);
if (isset($data->photo_50)) {
// Получено изображение 50x50
if ($browser->get($data->photo_50, ['sink' => $file = "$path/50x50.jpg"])->getStatusCode() === 200)
$vk->cover =
($vk->cover ?? []) +
[
'50x50' => ($vk->cover['50x50'] ?? []) +
[
'source' => $data->photo_50,
'public' => "/storage/$vk->id/cover/50x50.jpg",
'local' => $file,
]
];
else throw new exception('Не удалось получить изображение 50x50 с серверов ВКонтакте');
// Удаление из списка необработанных
unset($data->photo_50);
}
// Инициализация директории с обложкой
if (!file_exists($path = INDEX . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . $vk->id . DIRECTORY_SEPARATOR . 'cover' . DIRECTORY_SEPARATOR))
mkdir($path, 0775, true);
if (isset($data->photo_100)) {
// Получено изображение 100x100
if ($browser->get($data->photo_100, ['sink' => $file = "$path/100x100.jpg"])->getStatusCode() === 200)
$vk->cover =
($vk->cover ?? []) +
[
'100x100' => ($vk->cover['100x100'] ?? []) +
[
'source' => $data->photo_100,
'public' => "/storage/$vk->id/cover/100x100.jpg",
'local' => $file,
]
];
else throw new exception('Не удалось получить изображение 100x100 с серверов ВКонтакте');
// Удаление из списка необработанных
unset($data->photo_100);
}
// Инициализация директории с обложкой
if (!file_exists($path = INDEX . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . $vk->id . DIRECTORY_SEPARATOR . 'cover' . DIRECTORY_SEPARATOR))
mkdir($path, 0775, true);
if (isset($data->photo_200)) {
// Получено изображение 200x200
if ($browser->get($data->photo_200, ['sink' => $file = "$path/200x200.jpg"])->getStatusCode() === 200)
$vk->cover =
($vk->cover ?? []) +
[
'200x200' => ($vk->cover['200x200'] ?? []) +
[
'source' => $data->photo_200,
'public' => "/storage/$vk->id/cover/200x200.jpg",
'local' => $file,
]
];
else throw new exception('Не удалось получить изображение 200x200 с серверов ВКонтакте');
// Удаление из списка необработанных
unset($data->photo_200);
}
if (isset($data->photo_200_orig)) {
// Получено изображение 200x
if ($browser->get($data->photo_200_orig, ['sink' => $file = "$path/200x.jpg"])->getStatusCode() === 200)
$vk->cover =
($vk->cover ?? []) +
[
'200x' => ($vk->cover['200x'] ?? []) +
[
'source' => $data->photo_200_orig,
'public' => "/storage/$vk->id/cover/200x.jpg",
'local' => $file,
]
];
else throw new exception('Не удалось получить изображение 200x с серверов ВКонтакте');
// Удаление из списка необработанных
unset($data->photo_200_orig);
}
if (isset($data->photo_400_orig)) {
// Получено изображение 400x
if ($browser->get($data->photo_400_orig, ['sink' => $file = "$path/400x.jpg"])->getStatusCode() === 200)
$vk->cover =
($vk->cover ?? []) +
[
'400x' => ($vk->cover['400x'] ?? []) +
[
'source' => $data->photo_400_orig,
'public' => "/storage/$vk->id/cover/400x.jpg",
'local' => $file,
]
];
else throw new exception('Не удалось получить изображение 400x с серверов ВКонтакте');
// Удаление из списка необработанных
unset($data->photo_400_orig);
}
if (isset($data->photo_max)) {
// Получено изображение MAXxMAX
if ($browser->get($data->photo_max, ['sink' => $file = "$path/MAXxMAX.jpg"])->getStatusCode() === 200)
$vk->cover =
($vk->cover ?? []) +
[
'MAXxMAX' => ($vk->cover['MAXxMAX'] ?? []) +
[
'source' => $data->photo_max,
'public' => "/storage/$vk->id/cover/MAXxMAX.jpg",
'local' => $file,
]
];
else throw new exception('Не удалось получить изображение MAXxMAX с серверов ВКонтакте');
// Удаление из списка необработанных
unset($data->photo_max);
}
if (isset($data->photo_max_orig)) {
// Получено изображение MAXx
if ($browser->get($data->photo_max_orig, ['sink' => $file = "$path/MAXx.jpg"])->getStatusCode() === 200)
$vk->cover =
($vk->cover ?? []) +
[
'MAXx' => ($vk->cover['MAXx'] ?? []) +
[
'source' => $data->photo_max_orig,
'public' => "/storage/$vk->id/cover/MAXx.jpg",
'local' => $file,
]
];
else throw new exception('Не удалось получить изображение MAXx с серверов ВКонтакте');
// Удаление из списка необработанных
unset($data->photo_max_orig);
}
if (isset($data->crop_photo)) {
// Получено изображение MAXx
if ($browser->get($data->photo_max_orig, ['sink' => $file = "$path/MAXx.jpg"])->getStatusCode() === 200)
$vk->cover =
($vk->cover ?? []) +
[
'MAXx' => ($vk->cover['MAXx'] ?? []) +
[
'source' => $data->photo_max_orig,
'public' => "/storage/$vk->id/cover/MAXx.jpg",
'local' => $file,
]
];
else throw new exception('Не удалось получить изображение MAXx с серверов ВКонтакте');
// Удаление из списка необработанных
unset($data->photo_max_orig);
}
// Перебор оставшихся параметров
foreach ($data as $key => $value) $vk->{$key} = $value;
if (document::update(static::$db->session, $vk)) {
// Записано обновление
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,119 +1,119 @@
#mail>:is(form, div) { #mail>:is(form, div) {
display : flex; display : flex;
flex-direction: column; flex-direction: column;
} }
#mail .exit { #mail .exit {
margin-top: 25px; margin-top: 25px;
} }
#mail p { #mail p {
margin : 0; margin : 0;
display: flex; display: flex;
} }
#mail p>span { #mail p>span {
margin-left: auto; margin-left: auto;
} }
#mail>form>input:is([type=text], [type=password]) { #mail>form>input:is([type=text], [type=password]) {
margin-bottom: 12px; margin-bottom: 12px;
} }
#mail>form>input:last-child { #mail>form>input:last-child {
margin-bottom: unset; margin-bottom: unset;
} }
#mail>form>.submit { #mail>form>.submit {
margin-top : 6px; margin-top : 6px;
margin-bottom: 10px; margin-bottom: 10px;
display : flex; display : flex;
} }
#mail>form>.submit>label { #mail>form>.submit>label {
padding : 10px 20px; padding : 10px 20px;
border : unset; border : unset;
border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px;
} }
#mail>form>.submit>input { #mail>form>.submit>input {
padding : 10px 20px; padding : 10px 20px;
flex-grow : 1; flex-grow : 1;
border : unset; border : unset;
border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0;
} }
#mail>form>input[type=submit].registration { #mail>form>input[type=submit].registration {
padding : 7px 20px; padding : 7px 20px;
background-color: #86781C; background-color: #86781C;
} }
#mail>form>input[type=submit].registration:hover { #mail>form>input[type=submit].registration:hover {
background-color: #9e8d20; background-color: #9e8d20;
} }
#mail>form>input[type=submit].registration:is(:active, :focus) { #mail>form>input[type=submit].registration:is(:active, :focus) {
background-color: #776b19; background-color: #776b19;
} }
#mail>form>ul.errors { #mail>form>ul.errors {
margin-top : 18px; margin-top : 18px;
margin-bottom : 0px; margin-bottom : 0px;
padding : 10px; padding : 10px;
text-align : center; text-align : center;
list-style : none; list-style : none;
background-color: #ae8f8f; background-color: #ae8f8f;
} }
#account { #account {
display : grid; display : grid;
grid-template-rows: auto auto; grid-template-rows: auto auto;
} }
#account>button#login { #account>button#login {
z-index : 1500; z-index : 1500;
grid-row: 2; grid-row: 2;
} }
#account>section.tab { #account>section.tab {
z-index : 1000; z-index : 1000;
position : relative; position : relative;
bottom : -100%; bottom : -100%;
padding : 1.5rem 10%; padding : 1.5rem 10%;
display : flex; display : flex;
flex-direction : column; flex-direction : column;
align-self : end; align-self : end;
text-align : center; text-align : center;
gap : .8rem; gap : .8rem;
background-color: var(--background-light-2); background-color: var(--background-light-2);
transition : .2s ease-in; transition : .2s ease-in;
} }
#account>button.active+section.tab { #account>button.active+section.tab {
bottom: 0%; bottom: 0%;
} }
#account>section.tab h3:first-of-type { #account>section.tab h3:first-of-type {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
#account>section.tab>* { #account>section.tab>* {
margin: unset; margin: unset;
} }
#account>section#mail.tab { #account>section#mail.tab {
grid-row : 1; grid-row : 1;
display : grid; display : grid;
grid-template-rows: auto auto; grid-template-rows: auto auto;
} }
#account>section#mail.tab>#profile { #account>section#mail.tab>#profile {
grid-row : 1; grid-row : 1;
display : grid; display : grid;
grid-template-rows: auto auto; grid-template-rows: auto auto;
} }
#account>section#mail.tab>input[type=mail] { #account>section#mail.tab>input[type=mail] {
grid-row : 2; grid-row : 2;
} }

View File

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

View File

@ -1,31 +1,31 @@
section.hotline { section.hotline {
display: inline-flex; display: inline-flex;
height : 100%; height : 100%;
} }
section.hotline * { section.hotline * {
transition: unset; transition: unset;
} }
section.hotline:last-child { section.hotline:last-child {
margin-bottom: unset; margin-bottom: unset;
} }
section.hotline>article { section.hotline>article {
margin-right : 18px; margin-right : 18px;
width : 140px; width : 140px;
height : 190px; height : 190px;
display : flex; display : flex;
align-self : flex-end; align-self : flex-end;
border-radius : 3px; border-radius : 3px;
background-color: var(--background-light-1); background-color: var(--background-light-1);
box-shadow : 0px -6px 6px rgba(0, 0, 0, 0.3); box-shadow : 0px -6px 6px rgba(0, 0, 0, 0.3);
} }
section.hotline>article:last-child { section.hotline>article:last-child {
margin-right: unset; margin-right: unset;
} }
section.hotline>article>* { section.hotline>article>* {
margin: auto; margin: auto;
} }

View File

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

View File

@ -0,0 +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;
}

View File

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

View File

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

View File

@ -0,0 +1 @@
<svg height="32" width="32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h32v32H0z"/><path d="M30 17.349V12h-2v-2h2V2H2v8h2v2H2v8h2v2H2v8h15.349A8.97 8.97 0 0 0 23 32a9.002 9.002 0 0 0 9-9 8.968 8.968 0 0 0-2-5.651zM14.059 22H6v-2h8.522a8.932 8.932 0 0 0-.463 2zM26 12H6v-2h20v2zM4 6h4v2H4V6zm0 10h4v2H4v-2zm4 12H4v-2h4v2zm15 1.883A6.898 6.898 0 0 1 16.115 23 6.898 6.898 0 0 1 23 16.115 6.898 6.898 0 0 1 29.883 23 6.898 6.898 0 0 1 23 29.883z"/><path d="m19 25 2 2 2-2 2 2 2-2-2-2 2-2-2-2-2 2-2-2-2 2 2 2z"/></svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M0 6c0-1.1.9-2 2-2h16a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V6zm2 0v2h2V6H2zm1 3v2h2V9H3zm-1 3v2h2v-2H2zm3 0v2h10v-2H5zm11 0v2h2v-2h-2zM6 9v2h2V9H6zm3 0v2h2V9H9zm3 0v2h2V9h-2zm3 0v2h2V9h-2zM5 6v2h2V6H5zm3 0v2h2V6H8zm3 0v2h2V6h-2zm3 0v2h4V6h-4z"/></svg>

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

@ -0,0 +1 @@
<svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h256v256H0z"/><path d="M224 177.3V78.7a8.1 8.1 0 0 0-4.1-7l-88-49.5a7.8 7.8 0 0 0-7.8 0l-88 49.5a8.1 8.1 0 0 0-4.1 7v98.6a8.1 8.1 0 0 0 4.1 7l88 49.5a7.8 7.8 0 0 0 7.8 0l88-49.5a8.1 8.1 0 0 0 4.1-7Z" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="m222.9 74.6-94 53.4-95.8-53.4M128.9 128l-.9 106.8"/></svg>

After

Width:  |  Height:  |  Size: 537 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m11.136 12.117-.596 2.415c.736.185 3.004.921 3.34-.441.35-1.421-2.009-1.789-2.744-1.974Zm.813-3.297-.54 2.191c.612.154 2.5.784 2.806-.455.318-1.293-1.654-1.581-2.266-1.736ZM12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2Zm4.358 8.575a1.743 1.743 0 0 1-1.385 1.611 1.933 1.933 0 0 1 .997 2.661c-.586 1.692-1.977 1.835-3.827 1.481l-.449 1.82-1.085-.274.443-1.795c-.28-.07-.568-.145-.864-.227l-.445 1.804-1.084-.273.45-1.824c-.254-.065-.511-.135-.774-.201l-1.412-.356.539-1.256s.8.215.788.199a.394.394 0 0 0 .498-.26l1.217-4.939a.583.583 0 0 0-.505-.638c.016-.011-.789-.198-.789-.198l.29-1.172 1.495.378-.001.006c.225.056.457.11.693.164l.444-1.802 1.085.274-.436 1.766c.291.068.584.135.87.207l.432-1.755 1.085.274-.445 1.802c1.37.477 2.372 1.193 2.175 2.523Z"/></svg>

After

Width:  |  Height:  |  Size: 825 B

File diff suppressed because one or more lines are too long

After

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +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();
}

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1 @@
arangodb.php

View File

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

View File

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

View File

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

View File

@ -1,19 +1,19 @@
{% use 'hotline/index.html' with css as hotline_css, body as hotline_body, js as hotline_js, js_init as hotline_js_init %} {% use 'hotline/index.html' with css as hotline_css, body as hotline_body, js as hotline_js, js_init as hotline_js_init %}
{% block css %} {% block css %}
{# {{ block('hotline_css') }} #} {# {{ block('hotline_css') }} #}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<aside> <aside>
{{ block('hotline_body') }} {{ block('hotline_body') }}
</aside> </aside>
{% endblock %} {% endblock %}
{% block js %} {% block js %}
{# {{ block('hotline_js') }} #} {# {{ block('hotline_js') }} #}
{% endblock %} {% endblock %}
{% block js_init %} {% block js_init %}
{# {{ block('hotline_js_init') }} #} {# {{ block('hotline_js_init') }} #}
{% endblock %} {% endblock %}

View File

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

View File

@ -1,4 +1,4 @@
<footer> <footer>
<!-- <p><a href="http://www.anybrowser.org/campaign/"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> --> <!-- <p><a href="http://www.anybrowser.org/campaign/"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
<!-- <p><a href="/browsers"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> --> <!-- <p><a href="/browsers"><img src="/img/logos/any_browser.gif" width="278" height="44" alt="Доступно на любом браузере" /></a></p> -->
</footer> </footer>

View File

@ -0,0 +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 %}

View File

@ -0,0 +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 %}

View File

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

View File

@ -1,41 +1,41 @@
{% extends "core.html" %} {% extends "core.html" %}
{% use "core.html" with css as core_css, body as core_body, js as core_js, js_init as core_js_init %} {% use "core.html" with css as core_css, body as core_body, js as core_js, js_init as core_js_init %}
{% use "troller.html" with css as troller_css, body as troller_body, js as troller_js, js_init as troller_js_init %} {% use "trolling.html" with css as trolling_css, body as trolling_body, js as trolling_js %}
{% use "popups/rules.html" with css as popup_rules_css, body as popup_rules_body %} {% use "header.html" with css as header_css, body as header_body, js as header_js, js_init as header_js_init %}
{% use "header.html" with css as header_css, body as header_body, js as header_js, js_init as header_js_init %} {% use "aside.html" with css as aside_css, body as aside_body, js as aside_js, js_init as aside_js_init %}
{% block css %} {% block css %}
{{ block('core_css') }} {{ block('core_css') }}
{{ block('troller_css') }} {{ block('trolling_css') }}
{{ block('popup_rules_css') }} {{ block('header_css') }}
{{ block('header_css') }} {{ block('aside_css') }}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{{ block('core_body') }} {{ block('core_body') }}
{{ block('troller_body') }} {{ block('trolling_body') }}
{{ block('popup_rules_body') }} {{ block('aside_body') }}
{{ block('header_body') }} {{ block('header_body') }}
<main> <main>
<noscript>К сожалению мой сайт ещё пока не готов для работы без javascript</noscript> <noscript>К сожалению мой сайт ещё пока не готов для работы без javascript</noscript>
{% block main %} {% block main %}
{% include 'rules.html' %} {% endblock %}
{% endblock %} </main>
</main>
{# {% include 'footer.html' %} #}
{# {% include 'footer.html' %} #} {% endblock %}
{% endblock %}
{% block js %}
{% block js %} {{ block('core_js') }}
{{ block('core_js') }} {{ block('trolling_js') }}
{{ block('troller_js') }} {{ block('header_js') }}
{{ block('header_js') }} {{ block('aside_js') }}
{% endblock %} {% endblock %}
{% block js_init %} {% block js_init %}
{{ block('core_js_init') }} {{ block('core_js_init') }}
{{ block('header_js_init') }} {{ block('header_js_init') }}
{{ block('troller_js_init') }} {{ block('aside_js_init') }}
{% endblock %} {% endblock %}

View File

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

View File

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

View File

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

File diff suppressed because one or more lines are too long

View File

@ -0,0 +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 %}

View File

@ -1,16 +0,0 @@
<?xml version="1.0"?>
<psalm
errorLevel="7"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
findUnusedBaselineEntry="true"
>
<projectFiles>
<directory name="mirzaev/site/rules/system" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
</psalm>