1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2025-11-25 22:12:29 +02:00
Files
OpenIntegrations/XML/CommonModules/OPI_Twitter/Ext/Module.bsl
Vitaly the Alpaca (bot) cdef2d02ab Main build (Jenkins)
2025-10-21 21:43:05 +03:00

662 lines
36 KiB
Plaintext

// OneScript: ./OInt/core/Modules/OPI_Twitter.os
// Lib: Twitter
// CLI: twitter
// Keywords: twitter, x
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// Если в не знаете с чего начать, то стоит найти метод ПолучитьСтандартныеПараметры()
// и почитать комментарии
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check method-too-many-params
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область ДанныеИНастройка
// Получить ссылку для авторизации
// Формирует ссылку для авторизации через браузер
//
// Параметры:
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Строка - URL для перехода в браузере
Функция ПолучитьСсылкуАвторизации(Параметры = "") Экспорт
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
ПараметрыURL = Новый Структура;
ПараметрыURL.Вставить("response_type" , "code");
ПараметрыURL.Вставить("client_id" , Параметры_["client_id"]);
ПараметрыURL.Вставить("redirect_uri" , Параметры_["redirect_uri"]);
ПараметрыURL.Вставить("scope" , Параметры_["scope"]);
ПараметрыURL.Вставить("state" , "state");
ПараметрыURL.Вставить("code_challenge" , "challenge");
ПараметрыURL.Вставить("code_challenge_method", "plain");
ПараметрыURL = OPI_Инструменты.ПараметрыЗапросаВСтроку(ПараметрыURL);
Линк = "https://twitter.com/i/oauth2/authorize" + ПараметрыURL;
Возврат Линк;
КонецФункции
// Получить токен
// Получает токен по коду, полученному при авторизации по ссылке из ПолучитьСсылкуАвторизации
//
// Параметры:
// Код - Строка - Код, полученный из авторизации См.ПолучитьСсылкуАвторизации - code
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция ПолучитьТокен(Знач Код, Знач Параметры = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Код);
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить("code" , Код);
ПараметрыЗапроса.Вставить("grant_type" , "authorization_code");
ПараметрыЗапроса.Вставить("client_id" , Параметры_["client_id"]);
ПараметрыЗапроса.Вставить("redirect_uri" , Параметры_["redirect_uri"]);
ПараметрыЗапроса.Вставить("code_verifier", "challenge");
Ответ = OPI_ЗапросыHTTP.PostСТелом("https://api.twitter.com/2/oauth2/token"
, ПараметрыЗапроса
,
, Ложь);
Возврат Ответ;
КонецФункции
// Обновить токен
// Обновляет v2 токен при помощи refresh_token
//
// Параметры:
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция ОбновитьТокен(Знач Параметры = "") Экспорт
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
Refresh = "refresh_token";
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить(Refresh , Параметры_[Refresh]);
ПараметрыЗапроса.Вставить("grant_type" , Refresh);
ПараметрыЗапроса.Вставить("client_id" , Параметры_["client_id"]);
Ответ = OPI_ЗапросыHTTP.PostСТелом("https://api.twitter.com/2/oauth2/token"
, ПараметрыЗапроса
,
, Ложь);
Возврат Ответ;
КонецФункции
// Обработка входящего запроса после авторизации !NOCLI
// Метод для вставки в http-сервис, адрес которого указывается в redirect_uri
//
// Примечание:
// Вызывает метод получения токена, так как для получения токена из кода, приходящего^^
// на redirect_uri после авторизации через браузер есть всего 30 секунд
//
// Параметры:
// Запрос - HTTPСервисЗапрос - Запрос, приходящий на http-сервис
//
// Возвращаемое значение:
// HTTPОтвет, Произвольный, ДвоичныеДанные - Результат чтения JSON ответа сервера
Функция ОбработкаВходящегоЗапросаПослеАвторизации(Запрос) Экспорт
Код = Запрос.ПараметрыЗапроса["code"];
ОтветТокен = ПолучитьТокен(Код);
// BSLLS:CommentedCode-off
// Предпочтительное хранение токенов
// Константы.TwitterRefresh.Установить(ОтветТокен["refresh_token"]);
// Константы.TwitterToken.Установить(ОтветТокен["access_token"]);
// BSLLS:CommentedCode-on
Возврат ОтветТокен;
КонецФункции
#КонецОбласти
#Область Твиты
// Создать произвольный твит
// Создает твит с произвольным содержимым
//
// Параметры:
// Текст - Строка - Текст твита - text
// МассивМедиа - Массив из Строка,ДвоичныеДанные - Массив двоичных данных или путей к файлам - media
// МассивВариантовОпроса - Массив из Строка - Массив вариантов опроса, если необходимо - options
// ДлительностьОпроса - Строка,Число - Длительность опроса, если необходимо (опрос без длительности не создается) - dur
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьПроизвольныйТвит(Знач Текст = ""
, Знач МассивМедиа = ""
, Знач МассивВариантовОпроса = ""
, Знач ДлительностьОпроса = ""
, Знач Параметры = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Текст);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ДлительностьОпроса);
Если ЗначениеЗаполнено(МассивМедиа) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивМедиа);
КонецЕсли;
Если ЗначениеЗаполнено(МассивВариантовОпроса) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивВариантовОпроса);
КонецЕсли;
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
URL = "https://api.twitter.com/2/tweets";
Массив = "Массив";
Поля = Новый Соответствие;
Если ЗначениеЗаполнено(Текст) Тогда
Поля.Вставить("text", Текст);
КонецЕсли;
Если ТипЗнч(МассивВариантовОпроса) = Тип(Массив) И ЗначениеЗаполнено(ДлительностьОпроса) Тогда
ДлительностьОпроса = Число(ДлительностьОпроса);
Если МассивВариантовОпроса.Количество() > 0 Тогда
СтруктураВарианта = Новый Структура("options,duration_minutes", МассивВариантовОпроса, ДлительностьОпроса);
Поля.Вставить("poll", СтруктураВарианта);
КонецЕсли;
КонецЕсли;
Если ТипЗнч(МассивМедиа) = Тип(Массив) Тогда
Если МассивМедиа.Количество() > 0 Тогда
Поля.Вставить("media", Новый Структура("media_ids", МассивМедиа));
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(Поля["media"]) Тогда
ЭтоV2 = Ложь;
Иначе
ЭтоV2 = Истина;
КонецЕсли;
Ответ = Post(URL, Поля, Параметры_, Истина, ЭтоV2);
Возврат Ответ;
КонецФункции
// Создать текстовый твит
// Создает твит без вложений
//
// Параметры:
// Текст - Строка - Текст твита - text
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТекстовыйТвит(Знач Текст, Знач Параметры = "") Экспорт
Возврат СоздатьПроизвольныйТвит(Текст, , , , Параметры);
КонецФункции
// Создать твит картинки
// Создает твит с картинкой вложением
//
// Параметры:
// Текст - Строка - Текст твита - text
// МассивКартинок - Массив из Строка,ДвоичныеДанные - Массив файлов картинок - pictures
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитКартинки(Знач Текст, Знач МассивКартинок, Знач Параметры = "") Экспорт
МассивМедиа = ЗагрузитьМассивВложений(МассивКартинок, "tweet_image", Параметры);
Если ТипЗнч(МассивМедиа) = Тип("Массив") Тогда
Результат = СоздатьПроизвольныйТвит(Текст, МассивМедиа, , , Параметры);
Иначе
Результат = МассивМедиа;
КонецЕсли;
Возврат Результат;
КонецФункции
// Создать твит гифки
// Создает твит с вложением-гифкой
//
// Параметры:
// Текст - Строка - Текст твита - text
// МассивГифок - Массив из Строка,ДвоичныеДанные - Массив файлов гифок - gifs
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитГифки(Знач Текст, Знач МассивГифок, Знач Параметры = "") Экспорт
МассивМедиа = ЗагрузитьМассивВложений(МассивГифок, "tweet_gif", Параметры);
Если ТипЗнч(МассивМедиа) = Тип("Массив") Тогда
Результат = СоздатьПроизвольныйТвит(Текст, МассивМедиа, , , Параметры);
Иначе
Результат = МассивМедиа;
КонецЕсли;
Возврат Результат;
КонецФункции
// Создать твит видео
// Создает твит с видеовложением
//
// Параметры:
// Текст - Строка - Текст твита - text
// МассивВидео - Массив из Строка,ДвоичныеДанные - Массив файлов видео - videos
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитВидео(Знач Текст, Знач МассивВидео, Знач Параметры = "") Экспорт
МассивМедиа = ЗагрузитьМассивВложений(МассивВидео, "tweet_video", Параметры);
Если ТипЗнч(МассивМедиа) = Тип("Массив") Тогда
Результат = СоздатьПроизвольныйТвит(Текст, МассивМедиа, , , Параметры);
Иначе
Результат = МассивМедиа;
КонецЕсли;
Возврат Результат;
КонецФункции
// Создать твит опрос
// Создает твит с опросом
//
// Параметры:
// Текст - Строка - Текст твита - text
// МассивВариантов - Массив из Строка - Массив вариантов опроса - options
// Длительность - Строка,Число - Длительность опроса - duration
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитОпрос(Знач Текст, Знач МассивВариантов, Знач Длительность, Знач Параметры = "") Экспорт
Возврат СоздатьПроизвольныйТвит(Текст, , МассивВариантов, Длительность, Параметры);
КонецФункции
// Загрузить массив вложений
// Загружает файлы на сервер и возвращает их ID
//
// Параметры:
// МассивФайлов - Массив из Строка, ДвоичныеДанные - Массив файлов для загрузки - files
// ТипВложений - Строка - Тип вложений: tweet_video, tweet_image, tweet_gif - type
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Массив Из Строка - Массив ID медиа
Функция ЗагрузитьМассивВложений(Знач МассивФайлов, Знач ТипВложений, Знач Параметры = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТипВложений);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивФайлов);
МассивМедиа = Новый Массив;
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
MIS = "media_id_string";
Если ЗначениеЗаполнено(МассивФайлов) Тогда
Для Каждого ФайлОтправки Из МассивФайлов Цикл
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(ФайлОтправки);
Ответ = ЗагрузитьМедиафайл(ФайлОтправки, ТипВложений, Параметры_);
IDМедиа = Ответ[MIS];
Если Не ЗначениеЗаполнено(IDМедиа) Тогда
Возврат Ответ;
КонецЕсли;
МассивМедиа.Добавить(IDМедиа);
КонецЦикла;
КонецЕсли;
Возврат МассивМедиа;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ЗагрузитьМедиафайл(Знач Файл, Знач Тип, Знач Параметры)
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
ВидЗапроса = "POST";
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
URL = "https://upload.twitter.com/1.1/media/upload.json";
Ответ = ЗагрузитьМедиаЧастями(Файл, Тип, ВидЗапроса, URL, Параметры_);
Возврат Ответ;
КонецФункции
Функция ЗагрузитьМедиаЧастями(Знач Файл, Знач Тип, Знач ВидЗапроса, Знач URL, Параметры)
Единица = 1024;
Количество = 4;
MID = "media_id";
MIS = "media_id_string";
Command = "command";
Размер = Файл.Размер();
РазмерЧасти = Количество * Единица * Единица;
МассивЧтения = РазделитьДвоичныеДанные(Файл, РазмерЧасти);
Поля = Новый Структура;
Поля.Вставить(Command , "INIT");
Поля.Вставить("total_bytes" , OPI_Инструменты.ЧислоВСтроку(Размер));
Поля.Вставить("media_category", Тип);
ОтветИнициализации = Post(URL, Поля, Параметры);
IDИнициализации = ОтветИнициализации[MID];
IDSИнициализации = ОтветИнициализации[MIS];
Если Не ЗначениеЗаполнено(IDSИнициализации) Или Не ЗначениеЗаполнено(IDИнициализации) Тогда
Возврат ОтветИнициализации;
КонецЕсли;
Счетчик = 0;
Для Каждого Часть Из МассивЧтения Цикл
Поля = Новый Структура;
Поля.Вставить(Command , "APPEND");
Поля.Вставить(MID , IDSИнициализации);
Поля.Вставить("segment_index", OPI_Инструменты.ЧислоВСтроку(Счетчик));
Поля.Вставить("media" , Часть);
Ответ = PostMultipart(URL, Поля, Параметры);
Счетчик = Счетчик + 1;
КонецЦикла;
Поля = Новый Структура;
Поля.Вставить(Command, "FINALIZE");
Поля.Вставить(MID , IDSИнициализации);
СтатусОбработки = ПолучитьСтатусОбработки(Параметры, Поля, URL);
Если Не ТипЗнч(СтатусОбработки) = Тип("Строка") Тогда
Возврат СтатусОбработки;
КонецЕсли;
Ответ = ОжидатьЗавершенияОбработки(СтатусОбработки, IDSИнициализации, URL, Параметры);
Возврат Ответ;
КонецФункции
Функция ОжидатьЗавершенияОбработки(Знач СтатусОбработки, Знач IDИнициализации, Знач URL, Знач Параметры)
ProcessingInfo = "processing_info";
Command = "command";
Поля = Новый Структура;
Поля.Вставить(Command , "STATUS");
Поля.Вставить("media_id", IDИнициализации);
Пока Строка(СтатусОбработки) = "pending" Или Строка(СтатусОбработки) = "in_progress" Цикл
Ответ = Get(URL, Поля, Параметры);
Информация = Ответ[ProcessingInfo];
Если Не ЗначениеЗаполнено(Информация) Тогда
Возврат Ответ;
КонецЕсли;
СтатусОбработки = Информация["state"];
Если Не ЗначениеЗаполнено(СтатусОбработки) Тогда
Возврат Ответ;
КонецЕсли;
КонецЦикла;
Если СтатусОбработки = "failed" Тогда
ВызватьИсключение "Твиттер не смог обработать загруженное вами видео";
КонецЕсли;
Возврат Ответ;
КонецФункции
Функция ПолучитьСтандартныеПараметры(Знач Параметры = "")
// Здесь собрано определение данных, необходимых для работы.
// Для Twitter это довольно значительный набор, что обсуловлено наличием сразу 2-х API,
// которые, при этом, созданы не для разныз задач, но просто являются версиями друг друга.
// Актуальной версией API является v2 и она требует получения временных токенов. Несмотря на то,
// что Twitter настаивает на использовании этой актуальной версии, они как-то умудрились не перенести
// механизм загрузки файлов и некоторые другие из старой версии - v1.1. Поэтому что-то нужно делать
// на версии 1.1, а что-то на 2: вплоть до того что они убрали возможность постить твиты из v1.1,
// но только через нее в твит можно добавить картинку. При этом способы авторизации и токены у них разные
// Мировая гигокорпорация Илона Маска, кстати, напоминаю ;)
// P.S Далее часто упоминается "страница настроек Twitter Developer" - это
// https://developer.twitter.com/en/portal/dashboard и выбор конкретного проекта из списка (значек c ключем)
Параметры_ = Новый Соответствие;
Разрешения = "tweet.read tweet.write tweet.moderate.write users.read "
+ "follows.read follows.write offline.access space.read mute.read "
+ "mute.write like.read like.write list.read list.write block.read "
+ "block.write bookmark.read bookmark.write";
// Данные для API v2
// redirect_uri - URL вашего http-сервиса (или другого обработчика запросов) для авторизации
// scope - набор разрешений для получаемого ключа. Может быть любой, но offline.access обязателен
// client_id - Из OAuth 2.0 Client ID and Client Secret страницы настроек Twitter Developer
// client_secret - Из OAuth 2.0 Client ID and Client Secret страницы настроек Twitter Developer
// access_token - ПолучитьСсылкуАвторизации() -> Браузер -> code придет на redirect_uri -> ПолучитьТокен(code)
// refresh_token - Приходит вместе с access_token и используется для его обновления (время жизни access_token - 2 ч)
// Обновление происходит методом ОбновитьТокен с новыми access_token и refresh_token.
// При следующем обновлении нужно использовать уже новый refresh_token, так что захардкодить
// не получится (access_token тоже не получится)
// |--> ОбновитьТокен() ->|access_token --> Используется в т-нии 2-х часов для запросов
// | |refresh_token --|
// |--------[через 2 ч.]-------------------|
// Данные для API v1.1
// oauth_token - Из Authentication Tokens -> Access Token and Secret страницы настроек Twitter Developer
// oauth_token_secret - Из Authentication Tokens -> Access Token and Secret страницы настроек Twitter Developer
// oauth_consumer_key - Из Consumer Keys -> Access Token and Secret страницы настроек Twitter Developer
// oauth_consumer_secret - Из Consumer Keys -> Access Token and Secret страницы настроек Twitter Developer
// Эти токены обновлять не надо
Параметры_.Вставить("redirect_uri" , "");
Параметры_.Вставить("scope" , Разрешения);
Параметры_.Вставить("client_id" , "");
Параметры_.Вставить("client_secret" , "");
Параметры_.Вставить("access_token" , ""); // Должно быть нечто вроде Константы.TwitterToken.Получить()
Параметры_.Вставить("refresh_token" , ""); // Должно быть нечто вроде Константы.TwitterRefresh.Получить()
Параметры_.Вставить("oauth_token" , "");
Параметры_.Вставить("oauth_token_secret" , "");
Параметры_.Вставить("oauth_consumer_key" , "");
Параметры_.Вставить("oauth_consumer_secret", "");
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Параметры);
Если ТипЗнч(Параметры) = Тип("Структура") Или ТипЗнч(Параметры) = Тип("Соответствие") Тогда
Для Каждого ПереданныйПараметр Из Параметры Цикл
Параметры_.Вставить(ПереданныйПараметр.Ключ, OPI_Инструменты.ЧислоВСтроку(ПереданныйПараметр.Значение));
КонецЦикла;
КонецЕсли;
Возврат Параметры_;
КонецФункции
Функция ПолучитьСтатусОбработки(Знач Параметры, Знач Поля, Знач URL)
ProcessingInfo = "processing_info";
Ответ = Post(URL, Поля, Параметры);
Информация = Ответ[ProcessingInfo];
Если Не ЗначениеЗаполнено(Информация) Тогда
Возврат Ответ;
КонецЕсли;
СтатусОбработки = Информация["state"];
Если Не ЗначениеЗаполнено(СтатусОбработки) Тогда
Возврат Ответ;
Иначе
Возврат СтатусОбработки;
КонецЕсли;
КонецФункции
Функция Get(Знач URL, Знач Поля, Знач УчетныеДанные)
Токен = УчетныеДанные["oauth_token"];
Секрет = УчетныеДанные["oauth_token_secret"];
КлючПользователя = УчетныеДанные["oauth_consumer_key"];
СекретПользователя = УчетныеДанные["oauth_consumer_secret"];
Версия = "1.0";
Результат = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.УстановитьПараметрыURL(Поля)
.ДобавитьOauthV1Авторизацию(Токен, Секрет, КлючПользователя, СекретПользователя, Версия)
.УстановитьАлгоритмOAuthV1("HMAC", "SHA1")
.ОбработатьЗапрос("GET")
.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Возврат Результат;
КонецФункции
Функция Post(Знач URL, Знач Поля, Знач УчетныеДанные, Знач JSON = Ложь, Знач ЭтоV2 = Ложь)
Токен = УчетныеДанные["oauth_token"];
Секрет = УчетныеДанные["oauth_token_secret"];
КлючПользователя = УчетныеДанные["oauth_consumer_key"];
СекретПользователя = УчетныеДанные["oauth_consumer_secret"];
Версия = "1.0";
HttpКлиент = OPI_ЗапросыHTTP.НовыйЗапрос().Инициализировать(URL);
Если ЭтоV2 Тогда
HttpКлиент.ДобавитьЗаголовок("Authorization", "Bearer " + УчетныеДанные["access_token"]);
Иначе
ДействиеСВложениями = OPI_Инструменты.ПолеКоллекцииСуществует(Поля, "media");
HttpКлиент.ДобавитьOauthV1Авторизацию(Токен, Секрет, КлючПользователя, СекретПользователя, Версия)
.УстановитьАлгоритмOAuthV1("HMAC", "SHA1")
.ИспользоватьПоляТелаВOAuth(Не ДействиеСВложениями);
КонецЕсли;
Если JSON Тогда
HttpКлиент.УстановитьJsonТело(Поля);
Иначе
HttpКлиент.УстановитьFormТело(Поля);
КонецЕсли;
Возврат HttpКлиент.ОбработатьЗапрос("POST").ВернутьОтветКакJSONКоллекцию(Истина, Истина);
КонецФункции
Функция PostMultipart(Знач URL, Знач Поля, Знач УчетныеДанные)
Токен = УчетныеДанные["oauth_token"];
Секрет = УчетныеДанные["oauth_token_secret"];
КлючПользователя = УчетныеДанные["oauth_consumer_key"];
СекретПользователя = УчетныеДанные["oauth_consumer_secret"];
Версия = "1.0";
HttpКлиент = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.НачатьЗаписьТелаMultipart()
.ДобавитьOauthV1Авторизацию(Токен, Секрет, КлючПользователя, СекретПользователя, Версия)
.УстановитьАлгоритмOAuthV1("HMAC", "SHA1")
.ИспользоватьПоляТелаВOAuth(Ложь);
Для Каждого Параметр Из Поля Цикл
HttpКлиент.ДобавитьПолеMultipartFormData(Параметр.Ключ, Параметр.Значение);
КонецЦикла;
Результат = HttpКлиент.ОбработатьЗапрос("POST").ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Возврат Результат;
КонецФункции
#КонецОбласти