5 место Асинхронный Websocket для вас и ваших близких

WLDN

Client
Регистрация
09.07.2015
Сообщения
117
Благодарностей
160
Баллы
43
Здарова, братцы. :-)

Я так вдохновился вашими положительными отзывами на предыдущую статью, что решил поделиться ещё одной. :ay:

Предисловие.
В ноябре прошлого года у меня была одна удалённая работёнка, в которой мне потребовался ZennoPoster. Задача состояла в продвижении криптопроекта на ресурсах, где может находиться целевая аудитория. Одним из таких ресурсов был Discord, автоматизацию которого я стал реализовывать на стандартных кубиках. По сути с этого момента и началось моё изучение ZP.

Прошло несколько месяцев и от работы не осталось и следа, зато остался ZennoPoster с уже написанным Discord. Нужен был новый источник дохода, и после нескольких профитных тестов я решил реализовать регистратор и рассыльщик на запросах, дабы запустить больше потоков на паре моих ПК оставшихся после майнинга. Спустя некоторое время задача была реализована и трафик полился, а с ним и профит, но затем Discord стал запрашивать авторизацию, тут и началось моё изучение Websocket.

WebSocket — протокол связи поверх TCP-соединения, предназначенный для обмена сообщениями между браузером и веб-сервером в режиме реального времени. (c)Википедия

WS в основном используется на ресурсах, где необходим активный обмен данными. Это могут быть мессенджеры, онлайн-игры, форексы и различные приложения, где важно обмениваться большим объёмом данных в режиме реального времени.
Клиент (браузер или приложение) с помощью WS подключается к серверу только один раз и внутри этого подключения обменивается данными.
За счет этого уменьшается объём передаваемого трафика, и тем самым WS имеет огромное преимущество перед обычными POST/GET запросами, где нужно постоянно устанавливать новые подключения и передавать заголовки.

По сути WS похож на обычный POST запрос, но чтобы его выполнить на ZP нам понадобится библиотека. В моём случае это была websocket-sharp.
О том как ей пользоваться я и опишу в этой статье. :df:


Sniffаем.
Проанализировать трафик WS можно разными способами, но самый простой и доступный это использование браузера на базе Chromium. В моём случае это SWIron.
  1. Заходим на discordapp.com
  2. Открываем DevTools нажатием на F12
  3. Переходим на вкладку Network -> WS -> Frames
  4. Регистрируем новый аккаунт и заходим
Должна отобразиться следующая картина:
45838


Разберёмся что здесь к чему.
В колонке Name при наведении отобразится ссылка для запроса, её можно скопировать к себе нажав на пр. кн. мыши и соответствующее меню: wss://gateway.discord.gg/?encoding=json&v=6&compress=zlib-stream
В колонке Data можно увидеть исходящие и поступающие запросы. Копируем себе первый исходящий запрос (это запрос, который мы должны отправить серверу для авторизации):
{"op":2,"d":{"token":"NjMwMTU2ODYzNDcxNjE2MDMw.Xe9SFw.GLgMR8R7vQPnHOmaD5KmHqU4vmk","properties":{"os":"Windows","browser":"Chrome","device":"","browser_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3650.0 Iron Safari/537.36","browser_version":"","os_version":"10","referrer":"","referring_domain":"","referrer_current":"","referring_domain_current":"","release_channel":"stable","client_build_number":50980,"client_event_source":null},"presence":{"status":"online","since":0,"activities":[],"afk":false},"compress":false}}

Теперь мы можем проверить будет ли работать наш WS на отдельном клиенте. Для этого можно использовать расширение Simple WebSocket Client.
  • Прописываем URL
  • Открываем Websocket нажатием на Open (в логах должно появиться первое сообщение с heartbeat_interval)
  • Вставляем тело исходящего запроса в поле Request и нажимаем Send. В логах мы получим ответ, что всё прошло успешно.
45856


Супер! :ay: Всё работает как надо, дело осталось за малым - реализовать тоже самое на ZennoPoster.:du:

Realизуем.
Для начала нам нужен сам websocket-sharp.dll. Качаем и вытаскиваем его с помощью WinRAR. Закидываем библиотеку в папку ExternalAssemblies. Добавляем его в наш проект с помощью блока "Ссылки из GAC" и прописываем using:
Директивы using и общий код:
using WebSocketSharp;
using WebSocketSharp.Server;
using WebSocketSharp.Net;
Сразу закинем тело запроса в переменную wss_data.
45971


Кстати, в тестовом шаблоне я использовал тело запроса от десктопной версии, поэтому просто можете закинуть свой токен в переменную для теста. (build number - версия клиента)
Если взглянуть на трафик в браузере, то можно заметить, что сокет не закрывается и принимает/отправляет периодично новые запросы, поэтому в коде мы должны будем использовать асинхронный метод, чтобы сам шаблон выполнялся, а сокет работал в фоновом режиме и не закрывался, пока мы его об этом не попросим.

В общем коде дописываем using:
using System.Threading.Tasks;
В общем коде в классе CommonCode пишем наш код:
Описываем методы для WSS:
public static void Wss(IZennoPosterProjectModel project) //определяем метод Wss
{
Random rnd = new Random(); //инициализация Random
string data = project.Variables["wss_data"].Value; //загружаем тело запроса из переменной
//подключаем прокси, если необходимо
//string ip = project.Variables["proxy_ip"].Value;
//string login = project.Variables["proxy_login"].Value;
//string pass = project.Variables["proxy_pass"].Value;

using (var ws = new WebSocket("wss://gateway.discord.gg/")) //определяем ссылку запроса
{
//ws.SetProxy (ip, login, pass); //устанавливаем прокси, если необходимо
//ws.SetCookie (new Cookie("__cfduid", project.Variables["cookies_value"].Value)); //устанавливаем куки, если необходимо
ws.Origin = "https://discordapp.com";

ws.OnMessage += (sender, e) => //объявляем, что будем получать сообщение
project.SendInfoToLog(e.Data); //пишем инфу в лог для наглядности
ws.Connect(); //подключаемся по wss
ws.Send (data); //отправляем тело запроса
System.Threading.Thread.Sleep(1000); //небольшая пауза
ws.Send ("{\"op\":4,\"d\":{\"guild_id\":null,\"channel_id\":null,\"self_mute\":true,\"self_deaf\":true,\"self_video\":false}}"); //отправляем тело второго запроса

int q = 0;

while (Convert.ToBoolean(project.Variables["wss_lock"].Value)) //пока переменная = true, цикл будет выполняться
    {
        Thread.Sleep(rnd.Next(40000, 43000));
        q = q + rnd.Next(4, 40);
        ws.Send ("{\"op\":1,\"d\":" + q + "}"); //отправляем тело запроса
     };
}
}

public static async Task WssAsync(IZennoPosterProjectModel project) //определяем асинхронный метод
{
        await Task.Run(() => Wss(project)); //запуск метода Wss
}
Если упрощенно, то сначала вы пишете в методе Wss код, который вы хотите выполнить, а потом в WssAsync указываете, что Wss нужно запустить асинхронно.

Вызвать асинхронный Wss можно с помощью C# кубика.
Подключаемся к Websocket:
CommonCode.WssAsync(project); //запускаем Wss асинхронно
После того как мы присвоим переменной wss_lock значение false через кубик "Обработка переменных", код успешно завершится и websocket закроется. А в Discord ваш аккаунт уйдёт в оффлайн. :bf:
Также завершить поток можно другими интересными и, возможно, более "правильными" способами, но я не сильно углублялся в эту тему.

Запускаем шаблон и проверяем лог в ProjectMaker.
46069


Вот и всё, наш Websocket готов!:bp:

Видео


Summary
В конечном итоге всё оказалось не так уж и сложно, но пришлось разбираться и потратить какое-то время. После чего я успешно возобновил трафик, а позже реализовал рассыльщик по чату в Reddit, там также используется wss. Вообще Websocket часто используют в авторизациях и мессенджерах, поэтому, думаю, эти знания вам пригодятся. ;-)

P.S. Асинхронный WSS гарантированно работает в версии 5.28. Если нужно заменить какие-то заголовки, то можно подредактировать некоторые файлы с Github (например User-Agent) и скомпилировать в VS измененный websocket-sharp.dll.
 
Категория
Полезно

Вложения

Последнее редактирование модератором:

Manfred

Client
Регистрация
06.08.2019
Сообщения
36
Благодарностей
17
Баллы
8
За вебсокеты спасибо, большущее!
 
  • Спасибо
Реакции: WLDN

Sanekk

Client
Регистрация
24.06.2016
Сообщения
717
Благодарностей
261
Баллы
63
  • Спасибо
Реакции: WLDN

prmaaq

Client
Регистрация
08.05.2014
Сообщения
22
Благодарностей
5
Баллы
3
Интересно, но пока не фига не понятно. :-)
 
  • Спасибо
Реакции: Amigo и WLDN

WLDN

Client
Регистрация
09.07.2015
Сообщения
117
Благодарностей
160
Баллы
43

prmaaq

Client
Регистрация
08.05.2014
Сообщения
22
Благодарностей
5
Баллы
3
Я новичок, поэтому меня собственно говоря интересовала сама причина возникновения этой ситуации, для чего авторы ресурсов используют этот метод и как его диагностировать, определить, что он используется. На мой взгляд именно этой информации не хватает в статье для полноты решения.
 
Последнее редактирование:
  • Спасибо
Реакции: PlayerT7 и WLDN

WLDN

Client
Регистрация
09.07.2015
Сообщения
117
Благодарностей
160
Баллы
43
Я новичок, поэтому меня собственно говоря интересовала сама причина возникновения этой ситуации, для чего авторы ресурсов используют этот метод и как его диагностировать определить, что он используется. На мой взгляд именно этой информации не хватает в статье для полноты решения.
Спасибо за полезное замечание, действительно думаю будет полезно добавить эту информацию. :-)
 

Oleg1987

Client
Регистрация
11.08.2014
Сообщения
817
Благодарностей
440
Баллы
63
Годнота!!!
 
  • Спасибо
Реакции: WLDN

Dr.Pipetka

Client
Регистрация
12.12.2017
Сообщения
394
Благодарностей
228
Баллы
43
Крутяк. +
 
  • Спасибо
Реакции: WLDN

AZANIR

Client
Регистрация
09.06.2014
Сообщения
329
Благодарностей
139
Баллы
43
Плюс в карму , класс !
 
  • Спасибо
Реакции: WLDN

Supergrok

Client
Регистрация
05.03.2019
Сообщения
60
Благодарностей
68
Баллы
18
Пока еще не понял как я буду это применять у себя, буду разбираться и учиться. Спасибо, однозначно в копилку.
 
  • Спасибо
Реакции: WLDN

Finiti

Новичок
Регистрация
27.08.2017
Сообщения
17
Благодарностей
14
Баллы
3
То что надо, плюсую.
 
  • Спасибо
Реакции: WLDN

BAZAg

Client
Регистрация
08.11.2015
Сообщения
569
Благодарностей
749
Баллы
93
WSS уже давно должны были бы сделать стандартным функционалом Зеннопостера как кубики GET, POST, DELETE, OPTION, а также как работа с базой и FTP.
Спасибо за статью!
 

Babulia

Client
Регистрация
18.11.2018
Сообщения
13
Благодарностей
6
Баллы
3
спасибо!!!!!! теперь с биржами по битку можно работать)))))
 
  • Спасибо
Реакции: Finiti и WLDN

Nike59

Client
Регистрация
05.08.2011
Сообщения
66
Благодарностей
47
Баллы
18
Отдельное спасибо за нестандартное (по крайней мере, для меня) использование SWIron в качестве сниффера.
 
  • Спасибо
Реакции: WLDN

one

Client
Регистрация
22.09.2015
Сообщения
5 322
Благодарностей
895
Баллы
113
  • Спасибо
Реакции: WLDN

64rus1

Client
Регистрация
13.06.2016
Сообщения
40
Благодарностей
6
Баллы
8
Спасибо
 
  • Спасибо
Реакции: WLDN

Metrix

Client
Регистрация
03.01.2014
Сообщения
264
Благодарностей
202
Баллы
43
Полезная техническая статья, очень пригодится для того чтобы решать вопросы автоматизации на сокетах, ведь всё больше и больше ресурсов их используют. :ay:
 
  • Спасибо
Реакции: WLDN

Чешир

Client
Регистрация
27.06.2014
Сообщения
1 259
Благодарностей
618
Баллы
113
Круто!
 
  • Спасибо
Реакции: WLDN

dimanis

Client
Регистрация
16.04.2016
Сообщения
166
Благодарностей
79
Баллы
28
А как бы получить данные не в лог а в переменную? project.SendInfoToLog(e.Data); шлет в лог, а в переменную (e.Data) не кладется, ошибку выдает что нет переменной 'e' итд

Цепь событий пройти: отправить дата на аунтенификацию, получить ответ, если гуд то выпарсить данные и отправить другое тело и так далее. Может есть пример такой работы?
 
Последнее редактирование:

WLDN

Client
Регистрация
09.07.2015
Сообщения
117
Благодарностей
160
Баллы
43
А как бы получить данные не в лог а в переменную? project.SendInfoToLog(e.Data); шлет в лог, а в переменную (e.Data) не кладется, ошибку выдает что нет переменной 'e' итд

Цепь событий пройти: отправить дата на аунтенификацию, получить ответ, если гуд то выпарсить данные и отправить другое тело и так далее. Может есть пример такой работы?
Пришли сюда код, посмотрим.
Вообще если e.Data это тип string, то

project.Variables["peremennaya"].Value = e.Data;

должно работать.
 

WLDN

Client
Регистрация
09.07.2015
Сообщения
117
Благодарностей
160
Баллы
43
код ваш, только вынес для тестов в C#кубик.

Посмотреть вложение 52583Посмотреть вложение 52584

тут https://zennolab.com/discussion/threads/zennoposter-websocket.60366/ человек заморачивался, такая же проблема была
надо убрать строчку для логирования, а на её место строчку с переменной
 

dimanis

Client
Регистрация
16.04.2016
Сообщения
166
Благодарностей
79
Баллы
28
чудеса конечно, но заработало))
 
  • Спасибо
Реакции: WLDN

Кто просматривает тему: (Всего: 2, Пользователи: 0, Гости: 2)