accounts/mirzaev/site/account/system/models/vk.php

556 lines
24 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace mirzaev\site\account\models;
// Файлы проекта
use mirzaev\site\account\models\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\account\models
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class vk 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://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;
}
}