- Регистрация
- 22.03.2019
- Сообщения
- 2 014
- Благодарностей
- 1 435
- Баллы
- 113
Поделюсь с общественностью методом хранения профилей в базе данных, которым пользуюсь сам уже как год. Разницы особой с методом хранения с zpprofile не замечено, т. е. субъективно нет разницы, всё в конечном итоге едино.
Итак, приступим.
Введение
Долго пользуясь Зеннопостером, столкнулся с проблемой, когда создаваемые профили на одном сервере нужно перенести на другой, потому что там есть нужные условия для их обработки: свободные ресурсы, версия зенки, программа и т. д., затем их нужно перенести в третье место, потом еще куда-то. А если у кого-то хард помер и потерялись твои аки за год работы... Даже думать не хочется об этом.
В конечном итоге я пришел к методу хранения профилей в базе данных.
Перечислим очевидные плюсы хранения профилей в базе данных перед хранением в zpprofile:
Ну и конечно минусы:
Практическая часть.
После того, как мы решили, что плюсы перевешивают минусы и предстоящие трудности нас не пугают, приступим к развертыванию.
1. Установка веб сервера и MySQL базы данных.
Для этого будем использовать простую и удобную для быстрого старта программу Laragon, там есть все что нам нужно
После установки и запуска попадаем в саму программу
По умолчанию веб серер и сервер баз данных отключены, включаем их.
Нажимаем кнопку "База данных", открывается очень удобный клиент баз HeidiSQL, в ней нажимаем кнопку "Открыть" и попадаем в нашу базу, которой и будем управлять.
По умолчанию у пользователя root нет пароля, поэтому его нужно установить или создадим нового пользователя для управления нашей будущей базой..
Для начала создадим базу данных profile и пользователя для ее управлением user с паролем ZennoUser1 с возможностью подключаться к базе данных извне, что бы работать с единой базой с нескольких компов/серверов
Вставляем в поле "Запрос" и нажимаем синюю стрелочку.
Если команды выполнены успешно, разрываем соедиение с базой и подключаемся снова, заменив root и пустой пароль на наши данные.
После успешного подключения мы видем базу 'profile' и можем ей управлять
2. Следующим шагом нужно создать структуру базы для хранения наших профилей.
Если в процессе вылезло предупреждение - ничего страшного, отключаемся от базы и подключаемся снова. После чего нам видна наша база с ее структурой.
Ну а теперь приступим к тому, для чего все это и предназначено
3. Интеграция Zennoposter и базы данных.
Я не буду рассказывать как создавать подключение к базе, я все делаю кодом, так и проще и не нужно городить огород с кучей кубиков, зависимостями и внешними библиотеками. Задал переменные, выполнил запрос - готово.
Создаем подключение к базе данных в переменную:
[INSERT]
Добавим данные из профиля в базу данных кодом:
Выполнив шаблон 10 раз получаем 10 записей в базе данных.
[SELECT]
Теперь код для чтения случайной строки
Если в зеновском кубике работы с базой данных данные можно сразу сплитовать в перменные, то после чтения кодом нам нужно данные сплитовать самостоятельно. Я просто добавил свой код, т.к. зеновский кубик сплитует только по одному символу из перечисленных.
[КОД В ШАБЛОНЕ]
[UPDATE]
Обновление нужных полей
После того, как мы получили аккаунт из базы и у нас есть все его поля, но нас интересует больше всего ID, он уникальный по нему можно идентифицировать строку и "не промахнуться".
Смоделируем ситуацию
Получили аккаунт со статусом "Valid", но в процессе проверки выяснилось, что там есть капча и нужно поменять его статус. Выполняем код с командой, которая заменяет значение в ячейке `account_status` на "Captcha", не изменяя остальные:
Смотрим в базу. В строке загруженного акккаунта статус должен поменяться на "Captcha"
Если же аккаунт не поменял статус, а нагулялся и получил новые куки, то нужно их так же обновить в базе, не меняя остальные данные.
[DELETE]
Ну а если аккаунт оказался полностью заблокирован и он нам в базе больше не нужен, то удаляем его:
Это базовые запросы, которые закроют ваши 95% всего необходимого для управления аккаунтами.
Так же структура базы не является окончательной, вы в нее можете поместить те данные которые вам необходимо там хранить: разрешения, плагины, да в принципе любые данные профиля которые можно изменить в зенке, но тут базовый минимум, и я вам его дал.
Если пойти еще дальше, то можно в базе данных хранить содержимое всех файлов, которые в себе содержит профиль.
В этом случае нужно полностью переделать структуру базы и логику работы, а профиль после чтения из базы сохранять как zpprofile в файловую систему и его уже загружать. Т.е. zpprofile тут выступает как промежуточное звено и не хранится на локальном компе, а выступает как Temp папка, после обновления в базе - удаляется. Но я считаю данную реализацию избыточной, и это тема отдельной работы.
Так же, за кадром остались вопросы:
Резервного копирования
Я используя S3 хранилище и по Cron (да у меня база на Linux, так надежнее) создаю архив с базой, аналитикой и конфигурационными скриптами выгружаю его.
Оптимизации
Когда количество строк переваливает за 100к, а количество одновременных запросов к базе нагружает сервер, то тут нужно заняться оптимизацией самого Mysql сервера, запросов и индексов. Можно без увеличения железа снизить нагрузку кратно.
Безопасности
На проде юзернейм и пароль подключения к базе должны быть сложными, порт изменить на не очевидный, конфиги с паролями хранится вне веб директории, все файлы и директории защищены от чтения.
Бонус
Смастерил PHP страницу аналитики. Страница простенькая, но основные показатели есть. Положите индекс вместо того, что лежит в папке, если нажать на кнопку "Корневая папка"
Надеюсь данное решение для вас будет полезным.
Ставьте спасибо и голос за работу
Итак, приступим.
Введение
Долго пользуясь Зеннопостером, столкнулся с проблемой, когда создаваемые профили на одном сервере нужно перенести на другой, потому что там есть нужные условия для их обработки: свободные ресурсы, версия зенки, программа и т. д., затем их нужно перенести в третье место, потом еще куда-то. А если у кого-то хард помер и потерялись твои аки за год работы... Даже думать не хочется об этом.
В конечном итоге я пришел к методу хранения профилей в базе данных.
Перечислим очевидные плюсы хранения профилей в базе данных перед хранением в zpprofile:
- Единая точка хранения
- Возможность работать на нескольких серверах с единой базой профилей
- Можно сохранять конкретные данные, не пересохраняя весь профиль
- Удобная выборка по параметрам
- Удобная репликация и резервное копирование
- Можно создать лог изменений по каждой строке
- Можно создать свою страницу аналитики и аудита
Ну и конечно минусы:
- Единая точка отказа
- Разная эмуляция железа (тут вопрос дискуссионный)
- Нельзя хранить суперкуки и другие данные из профиля
- Дополнительные расходы на хранение базы и бакупов
Практическая часть.
После того, как мы решили, что плюсы перевешивают минусы и предстоящие трудности нас не пугают, приступим к развертыванию.
1. Установка веб сервера и MySQL базы данных.
Для этого будем использовать простую и удобную для быстрого старта программу Laragon, там есть все что нам нужно
После установки и запуска попадаем в саму программу
По умолчанию веб серер и сервер баз данных отключены, включаем их.
Нажимаем кнопку "База данных", открывается очень удобный клиент баз HeidiSQL, в ней нажимаем кнопку "Открыть" и попадаем в нашу базу, которой и будем управлять.
По умолчанию у пользователя root нет пароля, поэтому его нужно установить или создадим нового пользователя для управления нашей будущей базой..
Для начала создадим базу данных profile и пользователя для ее управлением user с паролем ZennoUser1 с возможностью подключаться к базе данных извне, что бы работать с единой базой с нескольких компов/серверов
SQL:
CREATE DATABASE profile;
CREATE USER 'user'@'%' IDENTIFIED BY 'ZennoUser1';
GRANT ALL PRIVILEGES ON profile.* TO 'user'@'%';
FLUSH PRIVILEGES;
Если команды выполнены успешно, разрываем соедиение с базой и подключаемся снова, заменив root и пустой пароль на наши данные.
После успешного подключения мы видем базу 'profile' и можем ей управлять
2. Следующим шагом нужно создать структуру базы для хранения наших профилей.
SQL:
CREATE TABLE IF NOT EXISTS `profile` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`human_login` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`human_password` char(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`human_email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`human_email_password` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
`imap` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`human_secret_answer1` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`human_secret_answer2` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`human_birthday` date NOT NULL,
`language` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'en' COMMENT 'ISO 639-1 code',
`human_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`human_surname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`human_sex` tinyint(1) NOT NULL,
`account_status` enum('Create','Valid','Captcha','Logout','Consent','Unknown') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'Create',
`user_agent` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`cookies` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
`proxy` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`lock_assigned_at` datetime DEFAULT NULL COMMENT 'Дата и время назначения лока',
`label` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_login` (`human_login`),
KEY `idx_status_date` (`account_status`,`created_at`),
KEY `idx_updated_at` (`updated_at`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Ну а теперь приступим к тому, для чего все это и предназначено
3. Интеграция Zennoposter и базы данных.
Я не буду рассказывать как создавать подключение к базе, я все делаю кодом, так и проще и не нужно городить огород с кучей кубиков, зависимостями и внешними библиотеками. Задал переменные, выполнил запрос - готово.
Создаем подключение к базе данных в переменную:
C#:
string[] connectionParams = {
"server=127.0.0.1",
"port=3306",
"user id=user",
"password=ZennoUser1",
"database=profile",
"allowuservariables=True"
};
project.Variables["sql_server_connect"].Value = string.Join(";", connectionParams);
[INSERT]
Добавим данные из профиля в базу данных кодом:
C#:
// Скрипт вставляет данные текущего профиля в таблицу profile
string connectionString = project.Variables["sql_server_connect"].Value;
string birthday = project.Profile.BornYear + "-" + project.Profile.BornMonth + "-" + project.Profile.BornDay;
string sexValue = ((int)project.Profile.Sex).ToString();
string insertQuery =
"INSERT INTO profile (" +
"human_login, human_password, human_email, human_email_password, imap, human_birthday, language, human_name, human_surname, human_sex, user_agent, cookies" +
") VALUES (" +
"'" + project.Profile.Login + "', " +
"'" + project.Profile.Password + "', " +
"'" + project.Profile.Email + "', " +
"'" + project.Profile.EmailPassword + "', " +
"'" + project.Variables["sql_imap"].Value + "', " +
"'" + birthday + "', " +
"'" + project.Profile.Language + "', " +
"'" + project.Profile.Name + "', " +
"'" + project.Profile.Surname + "', " +
sexValue + ", " +
"'" + project.Profile.UserAgent + "', " +
"'" + project.Variables["cookies"].Value + "'" +
");";
string insertResult = ZennoPoster.Db.ExecuteQuery(
insertQuery,
null,
ZennoLab.InterfacesLibrary.Enums.Db.DbProvider.MySqlClient,
connectionString,
" | ");
project.Variables["sql_insert_result"].Value = insertResult ?? string.Empty;
Важно сохранить порядок полей, иначе, данные попадут не в ту колонку и будет каша.[SELECT]
Теперь код для чтения случайной строки
C#:
string connectionString = project.Variables["sql_server_connect"].Value;
string query =
"SELECT human_login, human_password, human_email, human_email_password, imap, human_birthday, language, human_name, human_surname, human_sex, user_agent, cookies " +
"FROM profile ORDER BY RAND() LIMIT 1;";
string result = ZennoPoster.Db.ExecuteQuery(
query,
null,
ZennoLab.InterfacesLibrary.Enums.Db.DbProvider.MySqlClient,
connectionString,
"-|-");
project.Variables["sql_profile"].Value = result ?? string.Empty;
[КОД В ШАБЛОНЕ]
[UPDATE]
Обновление нужных полей
После того, как мы получили аккаунт из базы и у нас есть все его поля, но нас интересует больше всего ID, он уникальный по нему можно идентифицировать строку и "не промахнуться".
Смоделируем ситуацию
Получили аккаунт со статусом "Valid", но в процессе проверки выяснилось, что там есть капча и нужно поменять его статус. Выполняем код с командой, которая заменяет значение в ячейке `account_status` на "Captcha", не изменяя остальные:
C#:
var status = "Captcha";
var id = project.Variables["sql_id"].Value;
string connectionString = project.Variables["sql_server_connect"].Value;
string query = $"UPDATE `profile` SET `account_status` = '{status}' WHERE `id` = {id};";
var result = ZennoPoster.Db.ExecuteQuery(
query,
null,
ZennoLab.InterfacesLibrary.Enums.Db.DbProvider.MySqlClient,
connectionString,
" | ");
project.Variables["sql_log"].Value = result;
Если же аккаунт не поменял статус, а нагулялся и получил новые куки, то нужно их так же обновить в базе, не меняя остальные данные.
C#:
var cookies = project.Variables["sql_cookies"].Value;
var id = project.Variables["sql_id"].Value;
string connectionString = project.Variables["sql_server_connect"].Value;
string query = $"UPDATE `profile` SET `cookies` = '{cookies}' WHERE `id` = {id};";
var result = ZennoPoster.Db.ExecuteQuery(
query,
null,
ZennoLab.InterfacesLibrary.Enums.Db.DbProvider.MySqlClient,
connectionString,
" | ");
project.Variables["sql_log"].Value = result;
[DELETE]
Ну а если аккаунт оказался полностью заблокирован и он нам в базе больше не нужен, то удаляем его:
C#:
var sql_id = project.Variables["sql_id"].Value;
string connectionString = project.Variables["sql_server_connect"].Value;
string query = $"DELETE FROM profile WHERE id = {sql_id };";
var result = ZennoPoster.Db.ExecuteQuery(
query,
null,
ZennoLab.InterfacesLibrary.Enums.Db.DbProvider.MySqlClient,
connectionString,
" | ");
project.Variables["sql_log"].Value = result;
Так же структура базы не является окончательной, вы в нее можете поместить те данные которые вам необходимо там хранить: разрешения, плагины, да в принципе любые данные профиля которые можно изменить в зенке, но тут базовый минимум, и я вам его дал.
Если пойти еще дальше, то можно в базе данных хранить содержимое всех файлов, которые в себе содержит профиль.
Если кто не знал, то zpprofile - это обычный zip архив с уникальным расширениемВ этом случае нужно полностью переделать структуру базы и логику работы, а профиль после чтения из базы сохранять как zpprofile в файловую систему и его уже загружать. Т.е. zpprofile тут выступает как промежуточное звено и не хранится на локальном компе, а выступает как Temp папка, после обновления в базе - удаляется. Но я считаю данную реализацию избыточной, и это тема отдельной работы.
Так же, за кадром остались вопросы:
Резервного копирования
Я используя S3 хранилище и по Cron (да у меня база на Linux, так надежнее) создаю архив с базой, аналитикой и конфигурационными скриптами выгружаю его.
Оптимизации
Когда количество строк переваливает за 100к, а количество одновременных запросов к базе нагружает сервер, то тут нужно заняться оптимизацией самого Mysql сервера, запросов и индексов. Можно без увеличения железа снизить нагрузку кратно.
Безопасности
На проде юзернейм и пароль подключения к базе должны быть сложными, порт изменить на не очевидный, конфиги с паролями хранится вне веб директории, все файлы и директории защищены от чтения.
БонусСмастерил PHP страницу аналитики. Страница простенькая, но основные показатели есть. Положите индекс вместо того, что лежит в папке, если нажать на кнопку "Корневая папка"
Надеюсь данное решение для вас будет полезным.
Ставьте спасибо и голос за работу
Вложения
-
7,1 КБ Просмотры: 15
-
15,2 КБ Просмотры: 21
Последнее редактирование:

