Compare commits
No commits in common. "stable" and "0.0.0" have entirely different histories.
|
@ -1,2 +1,2 @@
|
||||||
/vendor
|
cookie.txt
|
||||||
!.gitignore
|
/vendor
|
|
@ -0,0 +1,22 @@
|
||||||
|
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,7 +1,21 @@
|
||||||
# Менеджер аккаунтов
|
# Менеджер аккаунтов
|
||||||
Инициализирует аккаунты для использования в фреймворках
|
Инициализирует аккаунты для их использования в колпачных фреймворках и библеотеках
|
||||||
|
|
||||||
### Установка:
|
### Установка:
|
||||||
```sh
|
```sh
|
||||||
$ composer install mirzaev/accounts
|
$ 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;
|
||||||
|
```
|
|
@ -1,37 +1,32 @@
|
||||||
{
|
{
|
||||||
"name": "mirzaev/accounts",
|
"name": "hood/accounts",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"description": "Simple accounts manager",
|
"description": "Менеджер аккаунтов",
|
||||||
"readme": "README.md",
|
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"accounts"
|
"hood",
|
||||||
|
"accounts",
|
||||||
|
"vk"
|
||||||
],
|
],
|
||||||
"homepage": "https://git.mirzaev.sexy/mirzaev/accounts",
|
"homepage": "https://git.hood.su/hood/accounts",
|
||||||
"license": "WTFPL",
|
"license": "AGPL-3.0-or-later",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Arsen Mirzaev Tatyano-Muradovich",
|
"name": "Arsen Mirzaev",
|
||||||
"email": "arsen@mirzaev.sexy",
|
"email": "red@hood.su",
|
||||||
"homepage": "https://mirzaev.sexy",
|
"homepage": "https://hood.su/sex",
|
||||||
"role": "Programmer"
|
"role": "Developer"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"email": "arsen@mirzaev.sexy",
|
"docs": "https://git.hood.su/hood/accounts/manual",
|
||||||
"wiki": "https://git.mirzaev.sexy/mirzaev/accounts/wiki",
|
"issues": "https://git.hood.su/hood/accounts/issues",
|
||||||
"issues": "https://git.mirzaev.sexy/mirzaev/accounts/issues"
|
"chat": "https://vk.me/darkweb228"
|
||||||
},
|
},
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "funding",
|
|
||||||
"url": "https://fund.mirzaev.sexy"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
"require": {
|
||||||
"php": "~8.2",
|
"php": ">=7.4.0",
|
||||||
"ext-dom": "*",
|
"ext-dom": "20031129",
|
||||||
"ext-libxml": "*",
|
"ext-libxml": "^7.4",
|
||||||
"guzzlehttp/guzzle": "^7.5"
|
"guzzlehttp/guzzle": "^7.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpdocumentor/phpdocumentor": ">=2.9",
|
"phpdocumentor/phpdocumentor": ">=2.9",
|
||||||
|
@ -39,17 +34,18 @@
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"mirzaev\\accounts\\": "mirzaev/accounts/system"
|
"hood\\accounts\\": "hood/accounts/system"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"mirzaev\\accounts\\tests\\": "mirzaev/accounts/tests"
|
"hood\\accounts\\tests\\": "hood/accounts/tests"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"config": {
|
"funding": [
|
||||||
"allow-plugins": {
|
{
|
||||||
"symfony/flex": true
|
"type": "Hood",
|
||||||
|
"url": "https://git.hood.su/hood/accounts/thanks"
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,16 +2,15 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\accounts;
|
namespace hood\accounts;
|
||||||
|
|
||||||
// Браузер
|
|
||||||
use GuzzleHttp\Client as browser;
|
use GuzzleHttp\Client as browser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Аккаунт
|
* Аккаунт
|
||||||
*
|
*
|
||||||
* @package mirzaev\accounts
|
* @package hood\accounts
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <red@hood.su>
|
||||||
*/
|
*/
|
||||||
class account
|
class account
|
||||||
{
|
{
|
||||||
|
@ -19,7 +18,7 @@ class account
|
||||||
* @var browser $browser Браузер
|
* @var browser $browser Браузер
|
||||||
*/
|
*/
|
||||||
protected browser $browser;
|
protected browser $browser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool $ssl SSL-протокол
|
* @var bool $ssl SSL-протокол
|
||||||
*/
|
*/
|
||||||
|
@ -30,12 +29,13 @@ class account
|
||||||
*/
|
*/
|
||||||
protected string $path;
|
protected string $path;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Конструктор
|
* Конструктор
|
||||||
*
|
*
|
||||||
* @param int $id Идентификатор
|
* @param int $id Идентификатор
|
||||||
* @param float|null $version Версия API
|
* @param float|null $version Версия API
|
||||||
*
|
*
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function __construct(int $id, float $version = null)
|
public function __construct(int $id, float $version = null)
|
||||||
|
@ -58,10 +58,10 @@ class account
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Установка свойства
|
* Установка свойства
|
||||||
*
|
*
|
||||||
* @param mixed $name Название
|
* @param mixed $name Название
|
||||||
* @param mixed $value Значение
|
* @param mixed $value Значение
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __set($name, $value): void
|
public function __set($name, $value): void
|
||||||
|
@ -84,9 +84,9 @@ class account
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Чтение свойства
|
* Чтение свойства
|
||||||
*
|
*
|
||||||
* @param mixed $name Название
|
* @param mixed $name Название
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function __get($name)
|
public function __get($name)
|
||||||
|
@ -95,15 +95,15 @@ class account
|
||||||
return $this->id;
|
return $this->id;
|
||||||
} else if ($name === 'browser') {
|
} else if ($name === 'browser') {
|
||||||
return $this->browser;
|
return $this->browser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Проверка инициализированности свойства
|
* Проверка инициализированности свойства
|
||||||
*
|
*
|
||||||
* @param mixed $name Название
|
* @param mixed $name Название
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function __isset($name)
|
public function __isset($name)
|
|
@ -2,10 +2,21 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\accounts\auth;
|
namespace hood\accounts\auth;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Базовая аутентификация
|
* Базовая авторизация
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
interface basic
|
interface basic
|
||||||
{
|
{
|
|
@ -0,0 +1,396 @@
|
||||||
|
<?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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\accounts\tests;
|
namespace hood\accounts\tests;
|
||||||
|
|
||||||
trait settings
|
trait settings
|
||||||
{
|
{
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\accounts\tests;
|
namespace hood\accounts\tests;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
use mirzaev\accounts\vk as account;
|
use hood\accounts\vk as account;
|
||||||
|
|
||||||
use GuzzleHttp\Client as browser;
|
use GuzzleHttp\Client as browser;
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ final class vkTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @testdox Аутентификация (базовая) в мобильном режиме с неправильным логином
|
* @testdox Аутентификация (базовая) в мобильном режиме с неправильным логином
|
||||||
*
|
*
|
||||||
* Тест может завериться неудачей, если ВКонтакте выдаст блокировку (надо повторить тест позже)
|
* Тест может завериться неудачей, если ВКонтакте выдаст блокировку (надо повторить тест позже)
|
||||||
*/
|
*/
|
||||||
public function testVkAuthBasicModeMobileWhenLoginIncorrect(): void
|
public function testVkAuthBasicModeMobileWhenLoginIncorrect(): void
|
|
@ -1,161 +0,0 @@
|
||||||
<?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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue