Описание системы плагинов

К клиенту greylink возможно подключение внешних плагинов. Плагин должен быть оформлен в виде DLL c именем ChatBot.dll и экспортировать функцию bot_init со следующей спецификацией:

    extern "C" __declspec(dllexport) bool __stdcall bot_init(BotInit* _init)

где структура BotInit описывается так:

    struct BotInit
    {
            typedef bool (__stdcall * tInit)(struct BotInit *);

            typedef bool (__stdcall * tSendMessage)(int msgid, const WCHAR* objid, const void* param, unsigned paramsize);
            typedef bool (__stdcall * tRecvMessage)(int msgid, const WCHAR* objid, const void* param, unsigned paramsize);

            typedef void*(__stdcall * tQueryInfo)(int queryid, const WCHAR* objid, const void *param, unsigned paramsize);
            typedef void (__stdcall * tFreeInfo)(void *info);

            DWORD apiVersion;
            WCHAR* appName;
            WCHAR* appVersion;
            tSendMessage SendMessage;
            tQueryInfo QueryInfo;
            tFreeInfo FreeInfo;

            DWORD botApiVersion;
            WCHAR* botId;
            WCHAR* botVersion;
            WCHAR* botCopyright;
            tRecvMessage RecvMessage;
            DWORD eventMask; // v3

            enum SEND_CODES {
                    SEND_PM         = 0,
                    SEND_SIM_PM     = 1,
                    SEND_CM         = 2,
                    SEND_SIM_CM     = 3,
                    SEND_CLOSE      = 4,
                    SEND_PRIVMODE   = 5,
                    SEND_BAN        = 6,
                    SEND_SLOT       = 7,
                    SEND_DL_MAGNET  = 8,
                    SEND_SEARCH     = 9,  // v3
                    SEND_SYSLOG_MSG = 10, // v3
                    SEND_DL_FILELIST= 11, // v4
                    SEND_DL_PING    = 12, // v4
                    SET_RECV_EVENTS = 20  // v3
            };

            enum RECV_CODES {
                    RECV_COMMAND        = 40,
                    RECV_PM             = 41,
                    RECV_CM             = 42,
                    RECV_USER_UPDATE    = 43,
                    RECV_USER_PART      = 44,
                    RECV_HUB_CONNECT    = 45,
                    RECV_HUB_DISCONNECT = 46,
                    RECV_PM_DROPPED     = 47,
                    RECV_SEARCH_QUERY   = 48, // v3
                    RECV_SEARCH_RESULT  = 49, // v3
                    RECV_DL_FINISHED    = 50, // v4
            };

            enum QUERY_CODES {
                    QUERY_USER_BY_UID       = 80,
                    QUERY_HUB_BY_URL        = 81,
                    QUERY_CONNECTED_HUBS    = 82,
                    QUERY_HUB_USERS         = 83,
                    QUERY_RUNNING_UPLOADS   = 84,
                    QUERY_QUEUED_UPLOADS    = 85,
                    QUERY_DOWNLOADS         = 86,
                    QUERY_SELF              = 87
            };

            enum PrivateAccessMode {
                    PM_NORMAL       = 0,
                    PM_SKIPPASSWORD = 1,
                    PM_IGNORE       = 2,
                    PM_HARDIGNORE   = 3
            };

            // for SEND_SEARCH:
            struct SearchParams {
                    int searchContent; // enum SearchTypeModes
                    int sizeMode; // enum SearchSizeModes
                    unsigned __int64 size;
            };
            enum SearchTypeModes {
                    TYPE_ANY = 0,
                    TYPE_AUDIO,
                    TYPE_COMPRESSED,
                    TYPE_DOCUMENT,
                    TYPE_EXECUTABLE,
                    TYPE_PICTURE,
                    TYPE_VIDEO,
                    TYPE_DIRECTORY,
                    TYPE_TTH
                    ,TYPE_CD_IMAGE
            };
            enum SearchSizeModes {
                    SIZE_DONTCARE = 0x00,
                    SIZE_ATLEAST = 0x01,
                    SIZE_ATMOST = 0x02,
                    SIZE_EXACT = 0x03
            };

            // for SET_RECV_EVENTS
            enum EventFlags {
                    F_RECV_COMMAND        = 1 << 0,
                    F_RECV_PM             = 1 << 1,
                    F_RECV_CM             = 1 << 2,
                    F_RECV_USER_UPDATE    = 1 << 3,
                    F_RECV_USER_PART      = 1 << 4,
                    F_RECV_HUB_CONNECT    = 1 << 5,
                    F_RECV_HUB_DISCONNECT = 1 << 6,
                    F_RECV_PM_DROPPED     = 1 << 7,
                    F_RECV_SEARCH_QUERY   = 1 << 8,
                    F_RECV_SEARCH_RESULT  = 1 << 9,
                    F_RECV_DL_FINISHED    = 1 << 10
            };

            // for SEND_DL_FILELIST, v5
            struct DlFileListParams {
                    int flags; // enum DlFileListFlags
            };

            enum DlFileListFlags { // v5
                    F_DL_FILELIST_OPEN    = 1,
                    F_DL_FILELIST_MATCH   = 2,
                    F_DL_FILELIST_CHECK   = 4

            };
    };

Функция плагина bot_init анализирует поля apiVersion, appName, appVersion. Если плагин умеет работать с данным клиентом и данной версией API, плагин заполняет поля botApiVersion, botId, botVersion, botCopyright, RecvMessage и возвращает true. Иначе greylink выгружает DLL.

В поле botApiVersion плагин указывает предпочтительную версию API (если клиент поддерживает несколько версий API, он может переключится на версию, запрошенную плагином). Текущая версия API: 5

Для версии API 3 и выше, плагин должен заполнить поле eventMask, если хочет получать сообщения о событиях (в любой момент список событий можно изменить вызовом SendMessage с msgid=SET_RECV_EVENTS)
Функция SendMessage

Используется плагином для управления клиентом.

Параметры функции | Описание
msgid = SEND_PM objid = UID param = message | Отослать личное сообщение с содержимым message пользователю с кодом UID
msgid = SEND_SIM_PM objid = UID param = message | Имитировать приём личного сообщения с содержимым message от пользователя с кодом UID
msgid = SEND_СM objid = UID param = huburl | Отослать сообщение с содержимым message в общий чат хаба huburl
msgid = SEND_SIM_CM objid = huburl param = message | Имитировать приём сообщения с содержимым message в чат хаба huburl. Сообщение должно иметь вид <НИК> сообщение...
msgid = SEND_CLOSE objid = UID param = message | Закрыть окно приватного чата с юзером UID
msgid = SEND_PRIVMODE objid = UID param = &mode paramsize = 1 | Установить уровень доступа в личку для юзера с кодом UID. Код уровня доступа описан в перечислении PrivateAccessMode
msgid = SEND_BAN objid = UID param = &isBanned paramsize = 1 | Включить или выключить бан юзера с кодом UID
msgid = SEND_SLOT objid = UID param = &time paramsize = 4 | Дать пользователю экстра-слот на time секунд. При time=0 резервирование слота немедленно снимается (соединение не прерывается, для кика используйте бан+разбан)
msgid = SEND_DL_MAGNET objid = magnet link param = target | Поставить магнет-ссылку на закачку. Если paramsize=0, закачиваем в download-каталог по умолчанию, иначе из (WCHAR*)param берём полный путь+имя файла
msgid = SEND_SEARCH objid = search string param = struct SearchParams | Поставить поисковый запрос в очередь. При param == NULL, objid - строка: слова для поиска, разделенные пробелами. Если SearchParams::searchContent == SearchTypeModes::TYPE_TTH, то objid - TTH в строковом виде без лишних префиксов.
msgid = SET_RECV_EVENTS param = &mask paramsize = 4 | Определяет, какие события передаются в RecvMessage. В зависимости от значения поля botApiVersion, указанного плагином в bot_init, настраивается начальное значение маски (для v1,v2 - все сообщения, поддерживаемые этими версиями API, для v3 и выше начальное значение маски 0, плагин должен установить список событий, на которые приходят оповещения. Флаги для mask нужно брать из enum EventFlags)
msgid = SEND_SYSLOG_MSG objid = message | Посылает строку в системный лог (также отображается в строке статуса главного окна программы)
msgid = SEND_DL_FILELIST objid = UID param = DlFileListParams paramsize = 4 (если paramsize=0, для совместимости с API v4 используется флаг F_DL_FILELIST_OPEN) | Начинает скачку файл-листа пользователя. Флаги в DlFileListParams определяют действия после загрузки файл-листа: F_DL_FILELIST_OPEN: открыть файл-лист для просмотра, F_DL_FILELIST_MATCH: добавить юзера в источники, если в файл-листе есть файлы из очереди закачки, F_DL_FILELIST_CHECK: проверить содержимое через правила ADL-поиска
msgid = SEND_DL_PING objid = UID | Соединяется с пользователем, но ничего не скачивает (Определение IP-адреса, через некоторое время адрес можно получить функцией QUERY_USER_BY_UID)

Функция SendMessage может быть вызвана плагином из любого потока в любое время после возврата из bot_init и до выгрузки DLL плагина
Функции QueryInfo и FreeInfo

Используются плагином для запроса информации. Результат QueryInfo - UTF-16 строка, завершаемая кодом 0; или NULL, если запрос составлен ошибочно или нет данных. Память освобождается функцией FreeInfo.

Если запрос должен вернуть несколько значений, результируюшая строка имеет вид:

    Параметр1=Значение1|Параметр2=Значение2|Параметр3=Значение3|

В строках символы | и \ кодируются соответственно сочетаниями \| и \\

В случаях, когда функция возвращает несколько блоков параметров (QUERY_DOWNLOADS и т.п.), блоки разделяются дополнительным символом |

* Если param и paramsize не описаны, они должны быть NULL и 0 соответственно

Параметры функции | Описание
queryid = QUERY_USER_BY_UID objid = UID | Запросить данные пользователя по его UID. Значения выходных параметров описаны ниже
queryid = QUERY_HUB_BY_URL objid = huburl | Запросить данные хаба по его url. Выходные параметры: URL,NAME,DESC,IP,PORT,ME
queryid = QUERY_CONNECTED_HUBS | Возвращает список URL подключенных хабов
queryid = QUERY_HUB_USERS objid = huburl | В данной версии API не реализовано, плагин может самостоятельно отслеживать актуальный список юзеров, используя сообщения RECV_USER_UPDATE и RECV_USER_PART
queryid = QUERY_RUNNING_UPLOADS objid = UID | Текущие отдачи. Поля: UID,FILENAME,FILESIZE,POS, REASON (значок-причина получения слота)
queryid = QUERY_QUEUED_UPLOADS objid = UID | Получить очередь ждущих юзеров (если objid=NULL), либо список файлов, который ожидает юзер UID
queryid = QUERY_DOWNLOADS objid = UID | Получить данные из очереди закачки. Если objid!=NULL, выдаются только файлы, в источниках для которых есть указанный юзер
queryid = QUERY_SELF | Не документировано. (Новые возможности, где эта информация была бы полезна, не дописаны)

Функция RecvMessage

Адрес своей функции RecvMessage плагин записывает в структуру BotInit, greylink через эту функцию оповещает плагин о различных событиях. Параметры RecvMessage не должны модифицироваться. Если событие обработано плагином, RecvMessage возвращает true, иначе - false

Параметры функции | Описание
queryid = RECV_COMMAND objid = NULL param = command | Пользователь набрал команду
    /bot command
queryid = RECV_PM objid = UID param = message | Пришло ЛС от юзера UID. Если плагин вернул true, сообщение не показывается пользователю. Изменённое сообщение плагин может передать через SEND_SIM_PM. Сообщения, посланные плагином через SEND_SIM_PM, не приходят в RECV_PM
queryid = RECV_CM objid = huburl param = message | Пришло сообщение в чат хаба huburl. Ник юзера может быть получен из текста сообщения по шаблонам: <НИК> Сообщение * НИК Сообщение Если плагин вернул true, сообщение не показывается пользователю. Изменённое сообщение плагин может передать через SEND_SIM_CM. Сообщения, посланные плагином через SEND_SIM_CM, приходят в RECV_CM, но не должны обрабатываться, так как в новых версиях API они могут не передаваться в RECV_CM
queryid = RECV_USER_UPDATE objid = UID | Юзер зашёл на хаб или обновил свои данные (размер шары, кол-во слотов, примечание и т.п.)
queryid = RECV_USER_PART objid = UID | Юзер ушёл с хаба
queryid = RECV_HUB_CONNECT objid = huburl | Подключен хаб huburl
queryid = RECV_HUB_DISCONNECT objid = huburl | Отключен хаб huburl
queryid = RECV_PM_DROPPED objid = UID param = message | Проигнорировано сообщение пользователя (на пользователе игнор или включена защита паролем). Если плагин считает, что сообщение важное, он может повторить его через SEND_SIM_PM
queryid = RECV_SEARCH_QUERY objid = search string param = доп. параметры | От юзера поступил запрос на поиск. В objid указана строка запроса, либо, при поиске по TTH, строка "TTH:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX". В параметрах есть поля USER (ip или Ник при пассивном поиске), HIT (найден в шаре: 0 = нет, 2 = да, 1 = я частичный источник)
queryid = RECV_SEARCH_RESULT objid = TTH param = доп. параметры | От юзера пришёл ответ на поиск. В дополнительных параметрах указывается: FILE (имя файла с путём в шаре), SIZE (размер файла), UID, CID, IP, HUBURL (юзера), SLOTS, FREE (слоты юзера: всего/свободно), TYPE (тип результата: файл/каталог/неполный источник).
queryid = RECV_DL_FINISHED objid = UID param = полный путь к файлу | Завершено скачивание файла / файл-листа. Если мультискачка, то objid = UID юзера, с которого скачался последний сегмент

История версий API

API v2: В запрос QUERY_HUB_BY_URL добавлен выходной параметр ME - UID себя на выбранном хабе

API v3: Команды управления поиском: SEND_SEARCH, RECV_SEARCH_QUERY, RECV_SEARCH_RESULT.
Добавлены системные команды SEND_SYSLOG_MSG, SET_RECV_EVENTS

API v4: Команды скачивания файл-листа и оповещения о завершении закачки: SEND_DL_FILELIST, SEND_DL_PING, RECV_DL_FINISHED.

API v5: Возможно указать параметры для SEND_DL_FILELIST (структура DlFileListParams)