Роботы, плагины и скрипты к чату MyChat. Разработка альтернативных клиентов и различных утилит. Технические вопросы по программированию, замечания и предложения по развитию API
Аватара пользователя
shibanovan
Всем доброго дня. Появилось желание реализовать простенького бота, который бы проверял e-mail ящик и кидал бы новые сообщения в главный чат. Возможно, кто-нибудь что-то делал с api mychat из питона ? Пример бы здорово сэкономил время
Аватара пользователя
Алексей Пикуров
Добрый день. Я так и не начал учить питон, хотя желание было, да времени нет :)

Питон прекрасно умеет работать с сокетами, сделать рабочий пример не составит какого-то большого труда, заодно и людям поможете.

Или вы хотите использовать dll-библиотеку? Что вам ближе?
Аватара пользователя
shibanovan
Алексей, а можете тыкнуть носом в документацию, где описывается работа с mychat через сокеты ?
Аватара пользователя
Алексей Пикуров
Давайте тут расскажу, поскольку внятной доки нет, только для внутреннего пользования пока, всё в процессе :)

Пример, надо отправить приватное сообщение человеку. На псевдокоде.

Константы:
CRLF - #13#10 (ASCII) 2 bytes
MCIAPI_CS_SendPrivateMessage = '0002'; (HEX)
MagicPacket - #23#6 (2 bytes)
cs_integration_api = '0077'; (4 bytes)
iFlag = 0 or 48 = '30' (2 bytes string)

Данные по сети отправляются в ASCII.

JSON объект для отправки приватного сообщения:

Код: Выделить всё
SendPrivateMessage JSON
{
  "UserTo"   : 15427,
  "UserFrom" : 0,
  "Msg"      : "Hello",
  "APIStype" : "joomla3x",
  "ServerKey" : "iddqd"
}

Как отправить команду и получить ответ о том, что случилось?

Код: Выделить всё
try
  1. Connect to IP/port
  2. writeln "mc5.18"
  3. readln (sc_hello)
  4. writeln MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_SendPrivateMessage + JSON
  5. readln (JSON, server reply)
except
  Ahtung!!! Network Error (SOCKET) number and description
end;
Аватара пользователя
Алексей Пикуров
Вместо "APIStype" подставляете что-то своё, например "emailcheck".
Аватара пользователя
shibanovan
cs_integration_api - это токен api, который в админке задаётся ?
Аватара пользователя
Алексей Пикуров
Нет, токен - это "ServerKey". cs_integration_api - это константа одной из множества команд протокола MyChat для соединения с сервером по упрощённой схеме. Соединился, отправил команду, получил ответ, отвалился.
Аватара пользователя
shibanovan
Что ж, выглядит просто, спасибо! ) попробую
Аватара пользователя
Алексей Пикуров
Пожалуйста, пишите сюда, если что. Ждём пример на Python, если толково выйдет — включим его в дистрибутив с указанием вашего авторства, если вы не против.
Аватара пользователя
Алексей Пикуров
Сохраните себе в закладки линк, справка постоянно дополняется.

https://nsoft-s.com/mcserverhelp/index. ... ockets.htm
Аватара пользователя
shibanovan
Я правильно понимаю, что при отправке в сокет:
writeln MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_SendPrivateMessage + JSON
Я разделяю константы с помощью CLRF ? Т.е. MagicPacket<CRLF> cs_integration_api и т.д. ?
Аватара пользователя
shibanovan
Алексей, а покажите, пожалуйста, как Вы в делфи отправите MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_SendPrivateMessage + JSON в сокет
Аватара пользователя
Алексей Пикуров
Нет, вы не разделяете ничем константы, просто склеиваете их в одну строку, в самом конце строки будет CRLF, 2 байта (#13#10).

Пример на Indy, Delphi XE3. Без обработки ошибок и какой-либо логики, просто шаблон.

Код: Выделить всё
const
  cs_integration_api = '0077';
  MagicPacket = #23#6;
  mcsignature = 'mc5.3';
  MCIAPI_CS_SendPrivateMessage = '0002';
var
  CSock: TidTCPClient;
  sIn: string;
begin
  CSock := TIdTCPClient.Create;
  CSock.Host := sIP;
  CSock.Port := iPort;
  CSock.Connect;

  CSock.Socket.WriteLnRFC(mcsignature); // функция WriteLnRFC сама добавляет в конец отправляемой строки два байта CRLF
  sIn := CSock.Socket.ReadLn; // читаем входящую строку. Конец строки - CRLF, аналогично
  CSock.Socket.WriteLnRFC(MagicPacket + cs_integration_api + IntToHex(iFlag, 2) + MCIAPI_CS_SendPrivateMessage + JSONobj.AsJSon);
  sIn := CSock.Socket.ReadLn;
  FreeAndNil(CSock);
end;
Аватара пользователя
shibanovan
А сервер, если не может разобрать данные, которые ему прислали - просто молчит ?
Вот по идее всё правлиьно сделал - отправляется в сокет и тишина
Код: Выделить всё
import socket
import json
import struct

HOST = "se-ad01"
PORT = 2004

dict_obj = {
    "UserTo":   4,
    "UserFrom": 1,
    "Msg":      "Hello",
    "hash":     "",
    "APIStype": "emailcheck",
    "ServerKey": "1111"
}
n = json.dumps(dict_obj)

CRLF = r"\r\n"; # #13#10
CRLF = struct.pack("BB", 13, 10) # #13#10

MCIAPI_CS_SendPrivateMessage  = struct.pack("l", 2) # l - signed long type. 4 bytes
MCIAPI_CS_IsUINOnline         = struct.pack("l", 3)
MCIAPI_CS_SendChannelMessage  = struct.pack("l", 4)
MCIAPI_CS_GetUINByNick        = struct.pack("l", 5)
MCIAPI_CS_GetUINByEmail       = struct.pack("l", 6)
MCIAPI_CS_IsUINExists         = struct.pack("l", 7)
MCIAPI_CS_AddBBSMessage       = struct.pack("l", 8)
MCIAPI_SC_SetChannelTopic     = struct.pack("l", 9)
MCIAPI_CS_GetChannelNameByUID = struct.pack("l", 10)
MCIAPI_CS_IsChannelExists     = struct.pack("l", 11)
MCIAPI_CS_GetUINByADLogin     = struct.pack("l", 12)
MCIAPI_CS_GetInfoByUIN        = struct.pack("l", 13)
MCIAPI_CS_GetServerInfo       = struct.pack("l", 14)

MagicPacket = struct.pack("BB", 23, 6) # B - unsigned char. 1 byte
cs_integration_api = struct.pack("l", 77)
iFlag = struct.pack("h", 30) # h - signed short. 2 bytes

try:

    try:
        skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    except socket.error as e:
        print ("Error creating socket: %s" % e)

    try:
        skt.connect((HOST, PORT))
    except socket.gaierror as e:
        print("Address-related error connecting to server: %s" % e)
    except socket.error as e:
        print("Error connecting to socket: %s" % e)

    try:
        #skt.send(b'mc5.18')
        #data = skt.recv(1024)
        #print( bytes.decode(data))
       
        skt.send(MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_SendPrivateMessage + json.dumps(dict_obj))
       
        data = skt.recv(1024)
        print bytes.decode(data)
       
    except socket.error as e:
        print("Error connecting to socket: %s" % e)

finally:
    skt.close()
Аватара пользователя
Алексей Пикуров
#skt.send(b'mc5.18') доклеивает CRLF в конец строки?
Аватара пользователя
Алексей Пикуров
И насколько я понимаю, вы закомментировали строки:
Код: Выделить всё
#skt.send(b'mc5.18')
#data = skt.recv(1024)
#print( bytes.decode(data))

Они должны быть раскомментированы, хотя бы первые две :)
Аватара пользователя
shibanovan
В логах сервера ошибка#102 - попытка подключения неизвестного приложения
Аватара пользователя
Алексей Пикуров
Раскомментируйте строки, которые я показал, иначе вас сервер не впустит.
Аватара пользователя
shibanovan
Внес изменения. Теперь код выглядит вот так:
Код: Выделить всё
import socket
import json
import struct

HOST = "se-ad01"
PORT = 2004

dict_obj = {
    "UserTo":   4,
    "UserFrom": 0,
    "Msg":      "Hello",
    "hash":     "",
    "APIStype": "emailcheck",
    "ServerKey": "1111"
}
n = json.dumps(dict_obj)

CRLF = r"\r\n"; # #13#10
CRLF = struct.pack("BB", 13, 10) # #13#10

MCIAPI_CS_SendPrivateMessage  = struct.pack("l", 2) # l - signed long type. 4 bytes
MCIAPI_CS_IsUINOnline         = struct.pack("l", 3)
MCIAPI_CS_SendChannelMessage  = struct.pack("l", 4)
MCIAPI_CS_GetUINByNick        = struct.pack("l", 5)
MCIAPI_CS_GetUINByEmail       = struct.pack("l", 6)
MCIAPI_CS_IsUINExists         = struct.pack("l", 7)
MCIAPI_CS_AddBBSMessage       = struct.pack("l", 8)
MCIAPI_SC_SetChannelTopic     = struct.pack("l", 9)
MCIAPI_CS_GetChannelNameByUID = struct.pack("l", 10)
MCIAPI_CS_IsChannelExists     = struct.pack("l", 11)
MCIAPI_CS_GetUINByADLogin     = struct.pack("l", 12)
MCIAPI_CS_GetInfoByUIN        = struct.pack("l", 13)
MCIAPI_CS_GetServerInfo       = struct.pack("l", 14)

MagicPacket = struct.pack("BB", 23, 6) # B - unsigned char. 1 byte
cs_integration_api = struct.pack("l", 77)
iFlag = struct.pack("h", 30) # h - signed short. 2 bytes

try:

    try:
        skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    except socket.error as e:
        print ("Error creating socket: %s" % e)

    try:
        skt.connect((HOST, PORT))
    except socket.gaierror as e:
        print("Address-related error connecting to server: %s" % e)
    except socket.error as e:
        print("Error connecting to socket: %s" % e)

    try:
        skt.send(b'mc5.18')
        data = skt.recv(1024)
        print( bytes.decode(data))
       
        skt.send(MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_SendPrivateMessage + json.dumps(dict_obj)+CRLF)
       
        data = skt.recv(1024)
        print bytes.decode(data)
       
    except socket.error as e:
        print("Error connecting to socket: %s" % e)

finally:
    skt.close()



На что в ответ в сокет приходит
Код: Выделить всё
800000{"ServPass":false,"ServName":"","UpdatePacketVer":"","UTC":6,"RelDate":"23.03.2016","ProtocolVer":"2.17","PortNode":80,"PortFTP":20000,"ServerVer":"5.18.0","HTTPS":false,"Registered":"-","HelloMsg":"","UpdatePacketSize":44769884,"YourIP":"192.168.3.2","HWID":"340981260_4497_6-10-5-600000000","Free":true,"UpdateCRC32":4072895046,"ForceUpdate":true,"CurrentDT":"26.04.2016.20.15.38.021"}


А в логах сервера (см. вложение)
Вложения
err1.png
err1.png (16.28 КБ) Просмотров: 9110
Аватара пользователя
Андрей Раков
Вы получаете ответ от сервера — sc_hello (приветствие с описанием параметров сервера).

Пожалуйста залогируйте и покажите текстовую строку, которую вы отправляете после получения sc_hello.
Аватара пользователя
Андрей Раков
Команда json.dumps(dict_obj) выполняет преобразование объекта в текстовую строку?
Аватара пользователя
shibanovan
+ skt.send не заканчивает CLRF - в обоих местах приклеил его - изменений в ошибках нет
Аватара пользователя
shibanovan
Команда json.dumps(dict_obj) напротив, преобразует строку в json
Аватара пользователя
Андрей Раков
Поэтому я и говорю, чтобы вы залогировали, что вы передаете на сервер и здесь покажите.
Аватара пользователя
shibanovan
Вот что отправляется в сокет
Код: Выделить всё
'\x17\x06M\x00\x00\x00\x1e\x00\x02\x00\x00\x00{"APIStype": "emailcheck", "hash": "", "ServerKey": "1111", "Msg": "Hello", "UserTo": 4, "UserFrom": 0}\r\n'
Аватара пользователя
shibanovan
Вот в итоге рабочий пример, как из питона (2.7 на 3 не проверял) отправить сообщения через сокеты
Код: Выделить всё
import socket
import json
import struct

HOST = "se-ad01"
PORT = 2004

dict_obj = {
    "UserTo":   4,
    "UserFrom": 0,
    "Msg":      "Hello",
    "hash":     "",
    "APIStype": "customapi",
    "ServerKey": "1111"
}

CRLF = r"\r\n"; # #13#10
CRLF = struct.pack("BB", 13, 10) # #13#10

# MCIAPI_CS_SendPrivateMessage  = struct.pack("l", 2) # l - signed long type. 4 bytes
# MCIAPI_CS_IsUINOnline         = struct.pack("l", 3)
# MCIAPI_CS_SendChannelMessage  = struct.pack("l", 4)
# MCIAPI_CS_GetUINByNick        = struct.pack("l", 5)
# MCIAPI_CS_GetUINByEmail       = struct.pack("l", 6)
# MCIAPI_CS_IsUINExists         = struct.pack("l", 7)
# MCIAPI_CS_AddBBSMessage       = struct.pack("l", 8)
# MCIAPI_SC_SetChannelTopic     = struct.pack("l", 9)
# MCIAPI_CS_GetChannelNameByUID = struct.pack("l", 10)
# MCIAPI_CS_IsChannelExists     = struct.pack("l", 11)
# MCIAPI_CS_GetUINByADLogin     = struct.pack("l", 12)
# MCIAPI_CS_GetInfoByUIN        = struct.pack("l", 13)
# MCIAPI_CS_GetServerInfo       = struct.pack("l", 14)

MCIAPI_CS_SendPrivateMessage  = "0002"
MCIAPI_CS_IsUINOnline         = "0003"
MCIAPI_CS_SendChannelMessage  = "0004"
MCIAPI_CS_GetUINByNick        = "0005"
MCIAPI_CS_GetUINByEmail       = "0006"
MCIAPI_CS_IsUINExists         = "0007"
MCIAPI_CS_AddBBSMessage       = "0008"
MCIAPI_SC_SetChannelTopic     = "0009"
MCIAPI_CS_GetChannelNameByUID = "0010"
MCIAPI_CS_IsChannelExists     = "0011"
MCIAPI_CS_GetUINByADLogin     = "0012"
MCIAPI_CS_GetInfoByUIN        = "0013"
MCIAPI_CS_GetServerInfo       = "0014"

MagicPacket = struct.pack("BB", 23, 6) # B - unsigned char. 1 byte
cs_integration_api = "0077"
# iFlag = struct.pack("h", 30) # h - signed short. 2 bytes
iFlag = "30"

try:

    try:
        skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    except socket.error as e:
        print ("Error creating socket: %s" % e)

    try:
        skt.connect((HOST, PORT))
    except socket.gaierror as e:
        print("Address-related error connecting to server: %s" % e)
    except socket.error as e:
        print("Error connecting to socket: %s" % e)

    try:
        skt.send(b'mc5.18\r\n')
        data = skt.recv(1024)
        print( bytes.decode(data))
       
        skt.send(MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_SendPrivateMessage + json.dumps(dict_obj)+CRLF)
       
        data = skt.recv(1024)
        print bytes.decode(data)
       
    except socket.error as e:
        print("Error connecting to socket: %s" % e)

finally:
    skt.close()
Аватара пользователя
shibanovan
И уточните в документации:
MCIAPI_CS_SendPrivateMessage и iFlag - это у вас всё же строки...
Аватара пользователя
shibanovan
Алексей, подскажите, что движок принимает за перевод строки в чате ?
Другими словами: как в JSON сделать перевод строки, что бы клиент отработал это ?
Аватара пользователя
Алексей Пикуров
Сейчас это работает некорректно, в 5.19 уже будет работать, достаточно передать обычный текст с CRLF внутри (\r\n). Мы как раз сейчас интеграцию с phpbb доделываем :)
Аватара пользователя
shibanovan
Мой скрипт по задаче почти готов, осталось отловить баги. А есть у сервера mychat механизм, которым можно было бы дергать внешнюю программу (просто запускать) скажем, каждую минуту ?
Аватара пользователя
Алексей Пикуров
Да, есть, в скриптовом движке есть функция для запуска приложения. Запускать на событие (Every...).

Код: Выделить всё
function ExecuteEx(FileName,Parameters,WorkFolder:string;RunType:integer):integer


RunType:
SW_HIDE Hides the window and activates another window.
SW_MAXIMIZE Maximizes the specified window.
SW_MINIMIZE Minimizes the specified window and activates the next top-level window in the Z order.
SW_RESTORE Activates and displays the window. If the window is minimized or maximized, Windows restores it to its original size and position. An application should specify this flag when restoring a minimized window.
SW_SHOW Activates the window and displays it in its current size and position.
SW_SHOWDEFAULT Sets the show state based on the SW_ flag specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application.
SW_SHOWMAXIMIZED Activates the window and displays it as a maximized window.
SW_SHOWMINIMIZED Activates the window and displays it as a minimized window.
SW_SHOWMINNOACTIVE Displays the window as a minimized window. The active window remains active.
SW_SHOWNA Displays the window in its current state. The active window remains active.
SW_SHOWNOACTIVATE Displays a window in its most recent size and position. The active window remains active.
SW_SHOWNORMAL Activates and displays a window. If the window is minimized or maximized, Windows restores it to its original size and position. An application should specify this flag when displaying the window for the first time.

Использовать осторожно, запуск приложения из-под сервера — не очень хорошая идея, это должно быть легковесное приложение, которое быстро отработает.
Аватара пользователя
shibanovan
Да...что-то около 6000 мсек стоит тайм аут ) Для меня в некоторых сценариях мало. Ок, есть еще сервисы windows )
Аватара пользователя
shibanovan
Алексей (или Андрей), расскажите, пожалуйста, как должен выглядеть json в случае отправки сообщения в канал
Аватара пользователя
Алексей Пикуров
Для периодичного запуска программ в Windows кроме планировщика хорош cron. Я им часто пользовался несколько лет назад, работает отлично. Насчёт отправки сообщения в конференцию напишу позже сегодня, когда буду в офисе.
Аватара пользователя
Алексей Пикуров
Команда MyChat Integration API для отправки сообщения в текстовую конференцию.

Чтобы задать максимальное время выполнения скрипта, если он не укладывается в 5 секунд, воспользуйтесь функцией SetScriptTimeOut.
Аватара пользователя
vansql
Здравствуйте, а какого вида будет JSON для MCIAPI_CS_AddBBSMessage ?? Может есть у кого пример подключения из .NET ??
Аватара пользователя
Алексей Пикуров
Добрый день. Примера на дотнете нет, мы на нём пока ещё ничего не делаем, ссылку на справку дам сегодня по формату команды.

Вам пример на C# нужен?
Аватара пользователя
vansql
Да, очень нужен пример на С#.
Аватара пользователя
Алексей Пикуров
Добрый вечер, vansql.

Справка: https://nsoft-s.com/mcserverhelp/index. ... essage.htm
Обновить сервер: https://www.nsoft-s.com/files/mcserv.zip (установить поверху последней версии).

Пример на шарпе попробуем сделать на днях.
Аватара пользователя
vansql
Большое спасибо. Добавлю рабочий код на c#.
Код: Выделить всё
using System; 
using System.Net.Sockets;
using System.Net;
using System.IO;
using Newtonsoft.Json;

namespace Client
{
    class PrivateMessage
    {
        public string UserTo { get; set; }
        public string UserFrom { get; set; }
        public string Msg { get; set; }
        public string hash { get; set; }
        public string APIStype { get; set; }
        public string ServerKey { get; set; }
    }
    class AddBBSMessage
    {
        public string ServerKey { get; set; }
        public string APIStyle { get; set; }
        public string UserFrom { get; set; }
        public string Expired { get; set; }
        public string Sticky { get; set; }
        public string Msg { get; set; }

    }
    class Program
    {
        static void Main(string[] args)
        {
            PrivateMessage PM = new PrivateMessage();
            PM.UserTo = "2";
            PM.UserFrom = "0";
            PM.Msg = "lalala";
            PM.hash = "";
            PM.APIStype = "customapi";
            PM.ServerKey = "U65aRYZfZM0zgrw6_MTi";
            string json_send_message = JsonConvert.SerializeObject(PM);

            AddBBSMessage add_bbs = new AddBBSMessage();
            add_bbs.ServerKey = "U65aRYZfZM0zgrw6_MTi";
            add_bbs.APIStyle = "customapi";
            add_bbs.UserFrom = "1";
            add_bbs.Expired = "10.09.2016.17.34.15";
            add_bbs.Sticky = "true";
            add_bbs.Msg = "html?";
            string json_add_bbs = JsonConvert.SerializeObject(add_bbs);


           
            string CRLF = "\u000D\u000A";
            string MagicPacket = "\u0017\u0006";           
            string cs_integration_api = "0077";
            string iFlag = "30";
            string MCIAPI_CS_SendPrivateMessage = "0002";
            string MCIAPI_CS_AddBBSMessage = "0008";
           

            TcpClient client = new TcpClient();
            client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2004));

            StreamWriter sw = new StreamWriter(client.GetStream());
            sw.AutoFlush = true;
            string message = "mc5.18" + CRLF;
            Console.WriteLine("Client : " + message);
            sw.WriteLine(message);

            StreamReader sr = new StreamReader(client.GetStream());
            Console.WriteLine("Server : " + sr.ReadLine());

            //message = aaa;
            Console.WriteLine("Client : " + MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_SendPrivateMessage + json_send_message + CRLF);
            sw.WriteLine(MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_AddBBSMessage + json_add_bbs + CRLF);
            Console.WriteLine("Server : " + sr.ReadLine());
            client.Close();

            Console.ReadKey();
        }
    }
}
   
Аватара пользователя
vansql
Все равно дает ошибку в логах(( Ошибка парсинга UIN -1 команда ID 119 , но сообщение отправляет
Аватара пользователя
Алексей Пикуров
Можно целиком увидеть ответ, полный текст?
Аватара пользователя
vansql
HTML таблицу можно добавить программно в BBS?

Ошибка
Вложения
111.jpg
111.jpg (26.6 КБ) Просмотров: 9013
Последний раз редактировалось vansql Ср июн 15, 2016 11:25 am, всего редактировалось 1 раз.
Аватара пользователя
Алексей Пикуров
Сейчас можно, но я не рекомендую, потому что от HTML на доске объявлений мы откажемся в будущем. Лучше только обычный текст.
Аватара пользователя
vansql
ехх, мне нужно таблицу вставить в ббс ,: товар, текущая цена, новая цена(((

Хорошо, а перенос строки работает?? можно символами таблицу нарисовать.
Аватара пользователя
Алексей Пикуров
Сейчас можете "лупить" html, пока мы не поменяли, в будущем будет markdown разметка, скорее всего.

<br> для переноса строки можно вставить.
Аватара пользователя
Алексей Пикуров
P.S. Символами особо не нарисуете, там не моноширинный шрифт.
Аватара пользователя
Георгий Лысенко
Рекомендуем отправлять на сервер signature с актуальной версией сервера, в вашем коде так:
Код: Выделить всё
string message = "mc5.20" + CRLF;

Ну и для всех, кто хочет воспользоваться примером для отправки сообщения, код должен быть таким:
Код: Выделить всё
Console.WriteLine("Client : " + MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_SendPrivateMessage + json_send_message + CRLF);
            sw.WriteLine(MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_SendPrivateMessage + json_send_message + CRLF);

Просто в вашем примере, вы в консоль выводите информацию про команду отправки приватного сообщения, а отправляете серверу MCIAPI_CS_AddBBSMessage.
Аватара пользователя
Алексей Пикуров
Вы показали лог сервера. Я попросил лог клиента. Сервер вам шлёт ответку, покажите её.
Аватара пользователя
vansql
Код: Выделить всё
using System; 
using System.Net.Sockets;
using System.Net;
using System.IO;
using Newtonsoft.Json;
using System.Text;


namespace Client
{
    class PrivateMessage
    {
        public string UserTo { get; set; }
        public string UserFrom { get; set; }
        public string Msg { get; set; }
        public string hash { get; set; }
        public string APIStype { get; set; }
        public string ServerKey { get; set; }
    }
    class AddBBSMessage
    {
        public string ServerKey { get; set; }
        public string APIStyle { get; set; }
        public string UserFrom { get; set; }
        public string Expired { get; set; }
        public string Sticky { get; set; }
        public string Msg { get; set; }

    }
    class Program
    {
        static void Main(string[] args)
        {
            PrivateMessage PM = new PrivateMessage();
            PM.UserTo = "1";
            PM.UserFrom = "0";
            PM.Msg = "lalala";
            PM.hash = "";
            PM.APIStype = "customapi";
            PM.ServerKey = "tRmbkBc6ZqHzuyk7dkEL";
            string json_send_message = JsonConvert.SerializeObject(PM);

            AddBBSMessage add_bbs = new AddBBSMessage();
            add_bbs.ServerKey = "tRmbkBc6ZqHzuyk7dkEL";
            add_bbs.APIStyle = "customapi";
            add_bbs.UserFrom = "1";
            add_bbs.Expired = "10.09.2016.17.34.15";
            add_bbs.Sticky = "true";
            add_bbs.Msg = @"текст ";
            string json_add_bbs = JsonConvert.SerializeObject(add_bbs);


           
            string CRLF = "\u000D\u000A";
            string MagicPacket = "\u0017\u0006";           
            string cs_integration_api = "0077";
            string iFlag = "30";
            string MCIAPI_CS_SendPrivateMessage = "0002";
            string MCIAPI_CS_AddBBSMessage = "0008";
           

            TcpClient client = new TcpClient();
            client.Connect(new IPEndPoint(IPAddress.Parse("192.168.1.10"), 2004));

            StreamWriter sw = new StreamWriter(client.GetStream(),Encoding.GetEncoding(1251));
            sw.AutoFlush = true;
            string message = "mc5.20" + CRLF;
            Console.WriteLine("Client : " + message);
            sw.WriteLine(message);

            StreamReader sr = new StreamReader(client.GetStream(),Encoding.GetEncoding(1251));
            Console.WriteLine("Server : " + sr.ReadLine());

           
            Console.WriteLine("Client : " + MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_AddBBSMessage + json_add_bbs + CRLF);
            sw.WriteLine(MagicPacket + cs_integration_api + iFlag + MCIAPI_CS_AddBBSMessage + json_add_bbs + CRLF);
            Console.WriteLine("Server : " + sr.ReadLine());
            client.Close();

            Console.ReadKey();
        }
    }
}
   


Спасибо, чуть подправил, добавил кодировку 1251.
Вложения
1212.jpg
1212.jpg (86.92 КБ) Просмотров: 7953
Аватара пользователя
Георгий Лысенко
И к вашему сведению, для отправки каждой новой команды на сервер нужна повторная авторизация посредством отправки signature.
Аватара пользователя
Алексей Пикуров
Иными словами, из-за упрощённой процедуры авторизации IntegrationAPI схема работы такая: подключился, получил информацию о сервере, отправил одну команду, получил ответ, отключился.

Собственно, потому сервер в логе и писал ошибку, когда вы одним махом пытались пару команд отправить. Кодировка win1251 необязательна, кстати, JSON правильно обрабатывает юникодовые строки, делает из них ESC-последовательности.
Аватара пользователя
Алексей Пикуров
Новая тема по работе с MyChat IntegrationAPI на C#: viewtopic.php?p=22945#p22945

Спасибо за прототип :) Включим доработанный вариант в дистрибутив MyChat Server.