Compare commits
	
		
			14 Commits
		
	
	
		
			0.0.0
			...
			4d6df00dc9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4d6df00dc9 | |||
| 16d5924320 | |||
| b7e26f01ca | |||
| 0b236a672c | |||
| e2e5635cd3 | |||
| 4fc8e011d0 | |||
| 
						 | 
					4b0a1a1c34 | ||
| 
						 | 
					4963f62103 | ||
| 
						 | 
					2f2b5f832c | ||
| 
						 | 
					42c3987bbf | ||
| 
						 | 
					32c329efde | ||
| 
						 | 
					ef4a79a1f7 | ||
| 
						 | 
					493c7ee87d | ||
| 
						 | 
					e27f93d885 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,2 +1,2 @@
 | 
			
		||||
cookie.txt
 | 
			
		||||
/vendor
 | 
			
		||||
!.gitignore
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								LICENSE
									
									
									
									
									
								
							@@ -1,22 +0,0 @@
 | 
			
		||||
This program is free software: you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License
 | 
			
		||||
along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
Это свободная программа: вы можете перераспространять ее и/или изменять
 | 
			
		||||
ее на условиях Стандартной общественной лицензии GNU в том виде, в каком
 | 
			
		||||
она была опубликована Фондом свободного программного обеспечения; либо
 | 
			
		||||
версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
 | 
			
		||||
 | 
			
		||||
Эта программа распространяется в надежде, что она будет полезной,
 | 
			
		||||
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
 | 
			
		||||
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
 | 
			
		||||
общественной лицензии GNU <https://www.gnu.org/licenses/>.
 | 
			
		||||
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.md
									
									
									
									
									
								
							@@ -1,21 +1,7 @@
 | 
			
		||||
# Менеджер аккаунтов
 | 
			
		||||
Инициализирует аккаунты для их использования в колпачных фреймворках и библеотеках
 | 
			
		||||
Инициализирует аккаунты для использования в фреймворках
 | 
			
		||||
 | 
			
		||||
### Установка:
 | 
			
		||||
```sh
 | 
			
		||||
$ composer install hood/accounts
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Пример использования:
 | 
			
		||||
```php
 | 
			
		||||
use hood\accounts\vk;
 | 
			
		||||
 | 
			
		||||
// Подключение библеотек
 | 
			
		||||
require_once './vendor/autoload.php';
 | 
			
		||||
 | 
			
		||||
// Инициализация пользователя ВКонтакте
 | 
			
		||||
$account = (new vk($id))->auth('login', 'password')->key($project_id);
 | 
			
		||||
 | 
			
		||||
// Вывести сгенерированный ключ
 | 
			
		||||
echo $account->key;
 | 
			
		||||
$ composer install mirzaev/accounts
 | 
			
		||||
```
 | 
			
		||||
@@ -1,31 +1,36 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "hood/accounts",
 | 
			
		||||
    "name": "mirzaev/accounts",
 | 
			
		||||
    "type": "library",
 | 
			
		||||
    "description": "Менеджер аккаунтов",
 | 
			
		||||
    "description": "Simple accounts manager",
 | 
			
		||||
    "readme": "README.md",
 | 
			
		||||
    "keywords": [
 | 
			
		||||
        "hood",
 | 
			
		||||
        "accounts",
 | 
			
		||||
        "vk"
 | 
			
		||||
        "accounts"
 | 
			
		||||
    ],
 | 
			
		||||
    "homepage": "https://git.hood.su/hood/accounts",
 | 
			
		||||
    "license": "AGPL-3.0-or-later",
 | 
			
		||||
    "homepage": "https://git.mirzaev.sexy/mirzaev/accounts",
 | 
			
		||||
    "license": "WTFPL",
 | 
			
		||||
    "authors": [
 | 
			
		||||
        {
 | 
			
		||||
            "name": "Arsen Mirzaev",
 | 
			
		||||
            "email": "red@hood.su",
 | 
			
		||||
            "homepage": "https://hood.su/sex",
 | 
			
		||||
            "role": "Developer"
 | 
			
		||||
            "name": "Arsen Mirzaev Tatyano-Muradovich",
 | 
			
		||||
            "email": "arsen@mirzaev.sexy",
 | 
			
		||||
            "homepage": "https://mirzaev.sexy",
 | 
			
		||||
            "role": "Programmer"
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
    "support": {
 | 
			
		||||
        "docs": "https://git.hood.su/hood/accounts/manual",
 | 
			
		||||
        "issues": "https://git.hood.su/hood/accounts/issues",
 | 
			
		||||
        "chat": "https://vk.me/darkweb228"
 | 
			
		||||
        "email": "arsen@mirzaev.sexy",
 | 
			
		||||
        "wiki": "https://git.mirzaev.sexy/mirzaev/accounts/wiki",
 | 
			
		||||
        "issues": "https://git.mirzaev.sexy/mirzaev/accounts/issues"
 | 
			
		||||
    },
 | 
			
		||||
    "funding": [
 | 
			
		||||
        {
 | 
			
		||||
            "type": "funding",
 | 
			
		||||
            "url": "https://fund.mirzaev.sexy"
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
    "require": {
 | 
			
		||||
        "php": ">=7.4.0",
 | 
			
		||||
        "php": "~8.1",
 | 
			
		||||
        "ext-dom": "20031129",
 | 
			
		||||
        "ext-libxml": "^7.4",
 | 
			
		||||
        "ext-libxml": "~8.1.1",
 | 
			
		||||
        "guzzlehttp/guzzle": "^7.2"
 | 
			
		||||
    },
 | 
			
		||||
    "require-dev": {
 | 
			
		||||
@@ -34,18 +39,12 @@
 | 
			
		||||
    },
 | 
			
		||||
    "autoload": {
 | 
			
		||||
        "psr-4": {
 | 
			
		||||
            "hood\\accounts\\": "hood/accounts/system"
 | 
			
		||||
            "mirzaev\\accounts\\": "mirzaev/accounts/system"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "autoload-dev": {
 | 
			
		||||
        "psr-4": {
 | 
			
		||||
            "hood\\accounts\\tests\\": "hood/accounts/tests"
 | 
			
		||||
            "mirzaev\\accounts\\tests\\": "mirzaev/accounts/tests"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "funding": [
 | 
			
		||||
        {
 | 
			
		||||
            "type": "Hood",
 | 
			
		||||
            "url": "https://git.hood.su/hood/accounts/thanks"
 | 
			
		||||
    }
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5056
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5056
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,396 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace hood\accounts;
 | 
			
		||||
 | 
			
		||||
use hood\accounts\auth\basic;
 | 
			
		||||
 | 
			
		||||
use GuzzleHttp\Client as browser,
 | 
			
		||||
    GuzzleHttp\Cookie\FileCookieJar,
 | 
			
		||||
    GuzzleHttp\TransferStats;
 | 
			
		||||
 | 
			
		||||
use DOMDocument,
 | 
			
		||||
    DOMXPath;
 | 
			
		||||
use Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Попка
 | 
			
		||||
 * 
 | 
			
		||||
 * @todo 
 | 
			
		||||
 * 1. Вернуть внутреннее хранение cookies, а выгрузку в файл сделать отдельным методом: "dump();". 
 | 
			
		||||
 * $this->cookies - строка cookie, $this->root_path - корневая директория (которая сейчас $this->path), $this->cookies_path - путь до файла хранящего cookies
 | 
			
		||||
 * 2. Сделать возможность авторизации без входного и пароля, указав место хранения файла cookies
 | 
			
		||||
 * 4. Добавить возможность авторизации через сторонний браузер, который более походит на настоящий (низкий приоритет)
 | 
			
		||||
 * 5. Создать debug-режим в котором будут сохранены обрабатываемые html страницы и действия будут записываться по PSR-7 в журнал (низкий приоритет)
 | 
			
		||||
 */
 | 
			
		||||
final class vk extends account implements basic
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var int $id Идентификатор
 | 
			
		||||
     */
 | 
			
		||||
    private int $id;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var string $login Входной [псевдоним]
 | 
			
		||||
     */
 | 
			
		||||
    private string $login;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var string $password Пароль
 | 
			
		||||
     */
 | 
			
		||||
    private string $password;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var string $key Ключ доступа
 | 
			
		||||
     */
 | 
			
		||||
    private string $key;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Конструктор
 | 
			
		||||
     * 
 | 
			
		||||
     * @param int $id Идентификатор
 | 
			
		||||
     * @param string|null $path Корневой каталог аккаунтов
 | 
			
		||||
     * 
 | 
			
		||||
     * @return self
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct(int $id, string $path = null)
 | 
			
		||||
    {
 | 
			
		||||
        // Идентификатор
 | 
			
		||||
        $this->id = $id;
 | 
			
		||||
 | 
			
		||||
        // Инициализация директории пользователя
 | 
			
		||||
        if (isset($path)) {
 | 
			
		||||
            // Если передан путь и он существует
 | 
			
		||||
            $this->path = $path . DIRECTORY_SEPARATOR . $id;
 | 
			
		||||
        } else {
 | 
			
		||||
            // Иначе путь по умолчанию
 | 
			
		||||
            $this->path = __DIR__ . DIRECTORY_SEPARATOR . 'accounts' . DIRECTORY_SEPARATOR . $id;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Проверка и создание директории
 | 
			
		||||
        if (!file_exists($this->path)) {
 | 
			
		||||
            mkdir($this->path, 0775, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Инициализация браузера
 | 
			
		||||
        $this->browser();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Аутентификация
 | 
			
		||||
     * 
 | 
			
		||||
     * @param string $login Входной
 | 
			
		||||
     * @param string $password Пароль
 | 
			
		||||
     * @param int $mode Режим
 | 
			
		||||
     * 
 | 
			
		||||
     * @return self
 | 
			
		||||
     * 
 | 
			
		||||
     * @todo 
 | 
			
		||||
     * 1. Добавить проверку требования двухэтапной аутентификации
 | 
			
		||||
     * 2. Добавить проверку требования ввода капчи
 | 
			
		||||
     * 3. Добавить проверку неудачного ввода пароля
 | 
			
		||||
     * 4. Добавить аутентификацию через версию для ПК
 | 
			
		||||
     * 5. Добавить идентификацию капчи, решение капчи и тесты с капчей
 | 
			
		||||
     */
 | 
			
		||||
    public function auth(string $login, string $password, int $mode = 0): self
 | 
			
		||||
    {
 | 
			
		||||
        if (isset($this->login, $this->password)) {
 | 
			
		||||
            throw new Exception('Повторная аутентификация запрещена');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Инициализация свойств
 | 
			
		||||
        $this->login = $login;
 | 
			
		||||
        $this->password = $password;
 | 
			
		||||
 | 
			
		||||
        // Переход на страницу аутентификации и обработка формы
 | 
			
		||||
        if ($mode === 0) {
 | 
			
		||||
            // Если установлен режим мобильной версии (по умолчанию)
 | 
			
		||||
 | 
			
		||||
            // Запрос страницы с аутентификацией
 | 
			
		||||
            $response = $this->browser->request('GET', 'https://m.vk.com');
 | 
			
		||||
 | 
			
		||||
            // Проверка
 | 
			
		||||
            $body = $this->check((string) $response->getBody());
 | 
			
		||||
 | 
			
		||||
            if ($response->getStatusCode() === 200) {
 | 
			
		||||
                // Инициализация DOM
 | 
			
		||||
                $dom = new DOMDocument;
 | 
			
		||||
                @$dom->loadHTML($body);
 | 
			
		||||
 | 
			
		||||
                // Ссылка для отправки формы (аутентификация)
 | 
			
		||||
                $action = $dom->getElementsByTagName('form')[0]->getAttribute('action');
 | 
			
		||||
            } else {
 | 
			
		||||
                throw new Exception('Не удалось получить страницу аутентификации: ' . $response->getReasonPhrase(), $response->getStatusCode());
 | 
			
		||||
            }
 | 
			
		||||
        } else if ($mode === 1) {
 | 
			
		||||
            // Иначе, если установлен режим аутентификации через обычную версию
 | 
			
		||||
            // $this->browser->post('http://login.vk.com/?act=login');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Аутентификация
 | 
			
		||||
        $response = $this->browser->request(
 | 
			
		||||
            'POST',
 | 
			
		||||
            $action,
 | 
			
		||||
            [
 | 
			
		||||
                'form_params' => [
 | 
			
		||||
                    'email' => $login,
 | 
			
		||||
                    'pass'  => $password
 | 
			
		||||
                ]
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Поиск уведомления с ошибкой
 | 
			
		||||
        $warning = $this->xpath((string) $response->getBody(), "//div[contains(@class, 'service_msg_box')]/div[contains(@class, 'service_msg service_msg_warning')]/text()");
 | 
			
		||||
 | 
			
		||||
        if (!empty($warning[0]->textContent)) {
 | 
			
		||||
            // Если аутентификация не прошла и появилось окно с ошибкой
 | 
			
		||||
            throw new Exception('ВКонтакте: "' . trim($warning[0]->textContent) . '"');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @todo Сделать
 | 
			
		||||
     */
 | 
			
		||||
    public function deauth(): self
 | 
			
		||||
    {
 | 
			
		||||
        // Очистка cookie
 | 
			
		||||
        if (file_exists($this->path . DIRECTORY_SEPARATOR . 'cookie.txt')) {
 | 
			
		||||
            // Если сущестуют cookie, то удалить
 | 
			
		||||
            unlink($this->path . DIRECTORY_SEPARATOR . 'cookie.txt');
 | 
			
		||||
 | 
			
		||||
            // Ренициализация браузера
 | 
			
		||||
            $this->browser();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function key(int $project_id = null, string ...$rights): string
 | 
			
		||||
    {
 | 
			
		||||
        if (!is_null($project_id)) {
 | 
			
		||||
            // Если переданы параметры
 | 
			
		||||
 | 
			
		||||
            // Инициализация
 | 
			
		||||
            $uri = '';
 | 
			
		||||
 | 
			
		||||
            // Запрос и обработка страницы подтверждения генерации ключа
 | 
			
		||||
            $response = $this->browser->request(
 | 
			
		||||
                'POST',
 | 
			
		||||
                'https://oauth.vk.com/authorize?client_id=' . $project_id . '&redirect_uri=https://oauth.vk.com/blank.html&display=mobile&scope=' . (empty($rights) ? 140488159 : implode(',', $rights)) . '&response_type=token',
 | 
			
		||||
                [
 | 
			
		||||
                    'http_errors' => false,
 | 
			
		||||
                    'on_stats' => function (TransferStats $stats) use (&$uri) {
 | 
			
		||||
                        $uri = $stats->getEffectiveUri();
 | 
			
		||||
                    }
 | 
			
		||||
                ]
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Проверка
 | 
			
		||||
            $body = $this->check((string) $response->getBody());
 | 
			
		||||
 | 
			
		||||
            if ($response->getStatusCode() === 200) {
 | 
			
		||||
                // Поиск текста
 | 
			
		||||
                $text = $this->xpath($body, "/html/body/text()|/html/body/b/text()");
 | 
			
		||||
 | 
			
		||||
                // Инкрементация найденных строк в одну
 | 
			
		||||
                for ($body = '', $i = 1; $i < count($text); $body .= $text[$i++]->textContent);
 | 
			
		||||
 | 
			
		||||
                // Обрезка переносов строки и пробелов
 | 
			
		||||
                $body = trim($body);
 | 
			
		||||
 | 
			
		||||
                if ($body !== "Пожалуйста, не копируйте данные из адресной строки для сторонних сайтов. Таким образом Вы можете потерять доступ к Вашему аккаунту.") {
 | 
			
		||||
                    // Если показывает страницу подтверждения генерации токена (после генерации подтверждать не просит и сразу выдаёт токен)
 | 
			
		||||
 | 
			
		||||
                    // Инициализация DOM
 | 
			
		||||
                    $dom = new DOMDocument;
 | 
			
		||||
                    @$dom->loadHTML((string) $response->getBody());
 | 
			
		||||
 | 
			
		||||
                    // Ссылка для отправки формы (подтверждение выдачи ключа)
 | 
			
		||||
                    $action = $dom->getElementsByTagName('form')[0]->getAttribute('action');
 | 
			
		||||
 | 
			
		||||
                    // Запрос ключа
 | 
			
		||||
                    $response = $this->browser->request(
 | 
			
		||||
                        'POST',
 | 
			
		||||
                        $action,
 | 
			
		||||
                        [
 | 
			
		||||
                            'http_errors' => false,
 | 
			
		||||
                            'on_stats' => function (TransferStats $stats) use (&$uri) {
 | 
			
		||||
                                $uri = $stats->getEffectiveUri();
 | 
			
		||||
                            }
 | 
			
		||||
                        ]
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                    // Проверка ответа на наличие json с ошибкой
 | 
			
		||||
                    $this->check((string) $response->getBody());
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Извлечение ключа из URI
 | 
			
		||||
                $parts = parse_url((string) $uri);
 | 
			
		||||
                parse_str($parts['fragment'], $fragments);
 | 
			
		||||
 | 
			
		||||
                // Запись ключа
 | 
			
		||||
                $this->key = $fragments['access_token'];
 | 
			
		||||
            } else {
 | 
			
		||||
                throw new Exception('ВКонтакте: "' . json_decode((string) $response->getBody())->error_description . '"');
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->key;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function browser(): browser
 | 
			
		||||
    {
 | 
			
		||||
        return $this->browser = new browser([
 | 
			
		||||
            'verify' => $this->ssl,
 | 
			
		||||
            'cookies' => (new FileCookieJar($this->path . DIRECTORY_SEPARATOR . 'cookie.txt'))
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function xpath(string $html, string $query): ?object
 | 
			
		||||
    {
 | 
			
		||||
        // DOM
 | 
			
		||||
        $dom = new DOMDocument;
 | 
			
		||||
        @$dom->loadHTML($html);
 | 
			
		||||
 | 
			
		||||
        // XPATH 1.0
 | 
			
		||||
        $xpath = new DOMXPath($dom);
 | 
			
		||||
        return $xpath->query($query);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function check(string $response): ?string
 | 
			
		||||
    {
 | 
			
		||||
        $json = json_decode($response);
 | 
			
		||||
 | 
			
		||||
        if (json_last_error() === JSON_ERROR_NONE) {
 | 
			
		||||
            // Если это JSON
 | 
			
		||||
 | 
			
		||||
            if (isset($json->error)) {
 | 
			
		||||
                // Если есть ошибки
 | 
			
		||||
                throw new Exception('ВКонтакте: "' . ($json->error['error_msg'] ?? $json->error_description) . '"', $json->error['error_code'] ?? 0);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $response;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Магический метод: установить свойство
 | 
			
		||||
     * 
 | 
			
		||||
     * @param mixed $name Название
 | 
			
		||||
     * @param mixed $value Значение
 | 
			
		||||
     * 
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function __set($name, $value): void
 | 
			
		||||
    {
 | 
			
		||||
        if ($name === 'id') {
 | 
			
		||||
            throw new Exception('Запрещено инициализировать идентификатор');
 | 
			
		||||
        } else if ($name === 'login' || $name === 'name' || $name === 'email' || $name === 'phone' || $name === 'number' || $name === 'nick' || $name === 'nickname') {
 | 
			
		||||
            throw new Exception('Запрещено инициализировать входной');
 | 
			
		||||
        } else if ($name === 'password' || $name === 'pswd' || $name === 'pass') {
 | 
			
		||||
            throw new Exception('Запрещено инициализировать пароль');
 | 
			
		||||
        } else if ($name === 'key' || $name === 'token') {
 | 
			
		||||
            $this->key = $value;
 | 
			
		||||
        } else if ($name === 'browser') {
 | 
			
		||||
            throw new Exception('Запрещено инициализировать браузер');
 | 
			
		||||
        } else if ($name === 'path') {
 | 
			
		||||
            $this->path = $value. DIRECTORY_SEPARATOR . $this->id;
 | 
			
		||||
 | 
			
		||||
            // Проверка и создание директории
 | 
			
		||||
            if (!file_exists($this->path)) {
 | 
			
		||||
                mkdir($this->path, 0775, true);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Реинициализация браузера с новым значением
 | 
			
		||||
            $this->browser();
 | 
			
		||||
        } else if ($name === 'ssl') {
 | 
			
		||||
            $this->ssl = $value;
 | 
			
		||||
            // Реинициализация браузера с новым значением
 | 
			
		||||
            $this->browser();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Магический метод: получить свойство
 | 
			
		||||
     * 
 | 
			
		||||
     * @param mixed $name Название
 | 
			
		||||
     * 
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
    public function __get($name)
 | 
			
		||||
    {
 | 
			
		||||
        if ($name === 'id') {
 | 
			
		||||
            return $this->id;
 | 
			
		||||
        } else if ($name === 'login' || $name === 'name' || $name === 'email' || $name === 'phone' || $name === 'number' || $name === 'nick' || $name === 'nickname') {
 | 
			
		||||
            return $this->login;
 | 
			
		||||
        } else if ($name === 'password' || $name === 'pswd' || $name === 'pass') {
 | 
			
		||||
            return $this->password;
 | 
			
		||||
        } else if ($name === 'key') {
 | 
			
		||||
            return $this->key;
 | 
			
		||||
        } else if ($name === 'browser') {
 | 
			
		||||
            return $this->browser;
 | 
			
		||||
        } else  if ($name === 'path') {
 | 
			
		||||
            return $this->path;
 | 
			
		||||
        } else if ($name === 'ssl') {
 | 
			
		||||
            return $this->ssl ?? $this->ssl = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Магический метод: проверка на инициализированность
 | 
			
		||||
     * 
 | 
			
		||||
     * @param mixed $name Название
 | 
			
		||||
     * 
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
    public function __isset($name)
 | 
			
		||||
    {
 | 
			
		||||
        if ($name === 'id') {
 | 
			
		||||
            return isset($this->id);
 | 
			
		||||
        } else if ($name === 'login' || $name === 'name' || $name === 'email' || $name === 'phone' || $name === 'number' || $name === 'nick' || $name === 'nickname') {
 | 
			
		||||
            return isset($this->login);
 | 
			
		||||
        } else if ($name === 'password' || $name === 'pswd' || $name === 'pass') {
 | 
			
		||||
            return isset($this->password);
 | 
			
		||||
        } else if ($name === 'key') {
 | 
			
		||||
            return isset($this->key);
 | 
			
		||||
        } else if ($name === 'browser') {
 | 
			
		||||
            return isset($this->browser);
 | 
			
		||||
        } else if ($name === 'path') {
 | 
			
		||||
            return isset($this->path);
 | 
			
		||||
        } else if ($name === 'ssl') {
 | 
			
		||||
            return isset($this->ssl);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Магический метод: удаление
 | 
			
		||||
     * 
 | 
			
		||||
     * @param mixed $name Название
 | 
			
		||||
     * 
 | 
			
		||||
     * @return mixed
 | 
			
		||||
     */
 | 
			
		||||
    public function __unset($name)
 | 
			
		||||
    {
 | 
			
		||||
        if ($name === 'id') {
 | 
			
		||||
            throw new Exception('Запрещено деинициализировать идентификатор');
 | 
			
		||||
        } else if ($name === 'login' || $name === 'name' || $name === 'email' || $name === 'phone' || $name === 'number' || $name === 'nick' || $name === 'nickname') {
 | 
			
		||||
            throw new Exception('Запрещено деинициализировать входной');
 | 
			
		||||
        } else if ($name === 'password' || $name === 'pswd' || $name === 'pass') {
 | 
			
		||||
            throw new Exception('Запрещено деинициализировать пароль');
 | 
			
		||||
        } else if ($name === 'key') {
 | 
			
		||||
            unset($this->key);
 | 
			
		||||
        } else if ($name === 'browser') {
 | 
			
		||||
            unset($this->browser);
 | 
			
		||||
        } else if ($name === 'path') {
 | 
			
		||||
            unset($this->path);
 | 
			
		||||
        } else if ($name === 'ssl') {
 | 
			
		||||
            unset($this->ssl);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										161
									
								
								mirzaev/accounts/system/account.1.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								mirzaev/accounts/system/account.1.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace hood\accounts;
 | 
			
		||||
 | 
			
		||||
use GuzzleHttp\Client as guzzle;
 | 
			
		||||
use GuzzleHttp\Cookie\FileCookieJar;
 | 
			
		||||
 | 
			
		||||
use Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Аккаунт
 | 
			
		||||
 *
 | 
			
		||||
 * @package hood\accounts
 | 
			
		||||
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 | 
			
		||||
 */
 | 
			
		||||
abstract class account
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var guzzle $browser Браузер
 | 
			
		||||
     */
 | 
			
		||||
    protected guzzle $browser;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var bool $ssl SSL-протокол
 | 
			
		||||
     */
 | 
			
		||||
    protected bool $ssl = true;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Конструктор
 | 
			
		||||
     *
 | 
			
		||||
     * @var int $id Идентификатор
 | 
			
		||||
     * @var string $path Корневой каталог аккаунтов
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected int $id,
 | 
			
		||||
        protected string $path = __DIR__ . DIRECTORY_SEPARATOR . 'accounts'
 | 
			
		||||
    ) {
 | 
			
		||||
        // Инициализация
 | 
			
		||||
        $this->path($path . DIRECTORY_SEPARATOR . $id);
 | 
			
		||||
        $this->browser();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Деструктор
 | 
			
		||||
     *
 | 
			
		||||
     * @todo Разработать
 | 
			
		||||
     */
 | 
			
		||||
    public function __destruct()
 | 
			
		||||
    {
 | 
			
		||||
        // Деаутентификация
 | 
			
		||||
        // $this->deauth();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Инициализация браузера
 | 
			
		||||
     */
 | 
			
		||||
    protected function browser(): guzzle
 | 
			
		||||
    {
 | 
			
		||||
        return isset($this->path, $this->ssl) ? $this->browser = new guzzle([
 | 
			
		||||
            'verify' => $this->ssl,
 | 
			
		||||
            'cookies' => (new FileCookieJar($this->path . DIRECTORY_SEPARATOR . 'cookie.txt'))
 | 
			
		||||
        ]) : throw new Exception('Не удалось записать браузер');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Инициализация директории пользователя
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $path Путь к директории
 | 
			
		||||
     */
 | 
			
		||||
    protected function path(string $path): string
 | 
			
		||||
    {
 | 
			
		||||
        // Инициализация директории
 | 
			
		||||
        if (file_exists($this->path = $path) || mkdir($this->path, 0775, true)) {
 | 
			
		||||
            return $this->path;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        throw new Exception('Не удалось записать путь к директории');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Запись свойства
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $name Название
 | 
			
		||||
     * @param mixed $value Значение
 | 
			
		||||
     */
 | 
			
		||||
    public function __set(string $name, mixed $value): void
 | 
			
		||||
    {
 | 
			
		||||
        match ($name) {
 | 
			
		||||
            'id' => match (false) {
 | 
			
		||||
                isset($this->id) => $this->id = $value,
 | 
			
		||||
                default => throw new Exception('Запрещено перезаписывать идентификатор')
 | 
			
		||||
            },
 | 
			
		||||
            'browser' => match (false) {
 | 
			
		||||
                isset($this->browser) => $this->browser = $value,
 | 
			
		||||
                default => throw new Exception('Запрещено перезаписывать браузер')
 | 
			
		||||
            },
 | 
			
		||||
            'path' => match (false) {
 | 
			
		||||
                isset($this->path) => $this->path($value),
 | 
			
		||||
                default => throw new Exception('Запрещено перезаписывать путь к директории')
 | 
			
		||||
            },
 | 
			
		||||
            'ssl' => $this->ssl = $value,
 | 
			
		||||
            default => throw new Exception('Не найдено: ' . $name, 404)
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Чтение свойства
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $name Название
 | 
			
		||||
     */
 | 
			
		||||
    public function __get(string $name): mixed
 | 
			
		||||
    {
 | 
			
		||||
        return match ($name) {
 | 
			
		||||
            'id' => $this->id,
 | 
			
		||||
            'browser' => $this->browser,
 | 
			
		||||
            'path' => $this->path,
 | 
			
		||||
            'ssl' => $this->ssl,
 | 
			
		||||
            default => throw new Exception('Не найдено: ' . $name, 404)
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Проверка инициализации
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $name Название
 | 
			
		||||
     */
 | 
			
		||||
    public function __isset(string $name): bool
 | 
			
		||||
    {
 | 
			
		||||
        return match ($name) {
 | 
			
		||||
            'id' => isset($this->id),
 | 
			
		||||
            'browser' => isset($this->browser),
 | 
			
		||||
            'path' => isset($this->path),
 | 
			
		||||
            'ssl' => isset($this->ssl),
 | 
			
		||||
            default => false
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Удаление свойства
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $name Название
 | 
			
		||||
     */
 | 
			
		||||
    public function __unset(string $name): void
 | 
			
		||||
    {
 | 
			
		||||
        match ($name) {
 | 
			
		||||
            'id' => throw new Exception('Запрещено деинициализировать идентификатор'),
 | 
			
		||||
            'browser' =>  function () {
 | 
			
		||||
                unset($this->browser);
 | 
			
		||||
            },
 | 
			
		||||
            'path' =>  function () {
 | 
			
		||||
                unset($this->path);
 | 
			
		||||
            },
 | 
			
		||||
            'ssl' =>  function () {
 | 
			
		||||
                unset($this->ssl);
 | 
			
		||||
            },
 | 
			
		||||
            default => null
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -2,15 +2,16 @@
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace hood\accounts;
 | 
			
		||||
namespace mirzaev\accounts;
 | 
			
		||||
 | 
			
		||||
// Браузер
 | 
			
		||||
use GuzzleHttp\Client as browser;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Аккаунт
 | 
			
		||||
 *
 | 
			
		||||
 * @package hood\accounts
 | 
			
		||||
 * @author Arsen Mirzaev Tatyano-Muradovich <red@hood.su>
 | 
			
		||||
 * @package mirzaev\accounts
 | 
			
		||||
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 | 
			
		||||
 */
 | 
			
		||||
class account
 | 
			
		||||
{
 | 
			
		||||
@@ -29,7 +30,6 @@ class account
 | 
			
		||||
     */
 | 
			
		||||
    protected string $path;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Конструктор
 | 
			
		||||
     *
 | 
			
		||||
@@ -2,21 +2,10 @@
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace hood\accounts\auth;
 | 
			
		||||
namespace mirzaev\accounts\auth;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Базовая авторизация
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * 
 | 
			
		||||
 * Базовая аутентификация
 | 
			
		||||
 */
 | 
			
		||||
interface basic
 | 
			
		||||
{
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace hood\accounts\tests;
 | 
			
		||||
namespace mirzaev\accounts\tests;
 | 
			
		||||
 | 
			
		||||
trait settings
 | 
			
		||||
{
 | 
			
		||||
@@ -2,11 +2,11 @@
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace hood\accounts\tests;
 | 
			
		||||
namespace mirzaev\accounts\tests;
 | 
			
		||||
 | 
			
		||||
use PHPUnit\Framework\TestCase;
 | 
			
		||||
 | 
			
		||||
use hood\accounts\vk as account;
 | 
			
		||||
use mirzaev\accounts\vk as account;
 | 
			
		||||
 | 
			
		||||
use GuzzleHttp\Client as browser;
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user