Telegtam API Отправить текст Кириллицу через с++ curl
Создал простенькую функцию отправки сообщения в телеграм группу, но английский тест отправляет, а русский нет, при этом в тестовый скрипт отправляет и возвращает отлично, подскажите в чём ошибка. Это все на виндовс, тестовый скрип в том числе. Прошу обратить внимание что тестовый скрипт HTTP А телеграм HTTPS. Чистый g++ CodeClocks
Токит и ид конечно же скрыты
#include <iostream>
#include <curl\curl.h>
#include <string>
#include<fstream>
#include <chrono>
#include<ctime>
#include<vector>
#include <sstream>
#include <windows.h>
//Функцыя обработки возвратных данных скорее всего
size_t curlWriteFunc(char *data, size_t size, size_t nmemb, std::string *buffer)
{
size_t result = 0;
if (buffer != NULL)
{
buffer->append(data, size * nmemb);
result = size * nmemb;
}
return result;
}
std::string SendPost(std::string url,std::string post,std::string &source)
{
// буфер для сохранения текстовых ошибок
char curlErrorBuffer[CURL_ERROR_SIZE];
std::string curlBuffer;
CURL *curl = curl_easy_init();
if (curl) {
//Ошыбки писать в curlErrorBuffer
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curlErrorBuffer);
// задаем URL...
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
// переходить по "Location:" указаному в HTTP заголовке учет пнренаправлений
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
// не проверять сертификат удаленного сервера они оыбочни часто почему то
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); //O
// использовать метод POST для отправки данных
curl_easy_setopt(curl, CURLOPT_POST, 1);
// параметры POST
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post.c_str());
// функция, вызываемая cURL для записи полученых данных.
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &curlBuffer);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteFunc);
//Кодировка
// curl_easy_setopt(curl,CURLOPT_HTTPHEADER, "Accept-Charset: WINDOWS-1251");
// выполнить запрос
CURLcode curlResult = curl_easy_perform(curl);
// завершение сеанса
curl_easy_cleanup(curl);
//Удача всё ок
if (curlResult == CURLE_OK)
{
//std::cout<<curlBuffer;
// ret+=curlBuffer;
source = curlBuffer;
return "";
} else { //Ошыбочка
//std::cout << "error(" << curlResult << "): " << curlErrorBuffer << std::endl;
std::stringstream convert;
convert << "error(" << curlResult << "): " << curlErrorBuffer << std::endl;
return convert.str();
}
}
else
//std::cout<<"curl nooo init\n";
return "curl nooo init\n";
}
int main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
std::string source = "";
std::string post = "z=текст для отправки&all=еще что то";
std::string url = "http://test.zp";
if(SendPost(url,post,source) == "")
{
std::cout<<source<<std::endl;
}
std::string toket = "2*********8:A****6-2**********************M"; //Токит который выдають после создания бота так сказать пароль
std::string chatID = "-6********3"; //ИД групы телеграм в которой бот куда и писать будет
url = std::string("https://api.telegram.org/bot") + toket + std::string("/sendMessage"); // -d
post = "chat_id=" + chatID + "&text=";
post+="Привет телеграм";
if(SendPost(url,post,source) == "")
{
std::cout<<"zp1:"<<source<<std::endl;
}
url = std::string("https://api.telegram.org/bot") + toket + std::string("/sendMessage"); // -d
post = "chat_id=" + chatID + "&text=";
post+="Hello telegram";
if(SendPost(url,post,source) == "")
{
std::cout<<"zp2:"<<source<<std::endl;
}
}
php Тестовый локальный
<?
if(isset($_POST['z']))
{
echo "Post: " . $_POST['z'];
file_put_contents("POST.txt","Get: " . $_GET['z']);
}
if(isset($_GET['z']))
{
echo "Get: " . $_GET['z'];
file_put_contents("GET.txt","Get: " . $_GET['z']);
}
?>
Что вижу в консоли
Post: текст для отправки
zp1:{"ok":false,"error_code":400,"description":"Bad Request: strings must be encoded in UTF-8"}
zp2:{"ok":true,"result":{"message_id":69,"from":{"id":2**********,"is_bot":true,"first_name":"M********t_bot","username":"Yong************Bot"},"chat":{"id":-6*******,"title":"\ud83e\ude93******** club\u26cf\ufe0f","type":"group","all_members_are_administrators":true},"date":1636892306,"text":"Hello telegram"}}
Ответы (1 шт):
Как отметил KoVadim Нужно конвертировать строку в utf-8 что видно из ответа от телеграм. Обычно в Виндовс проектах кодировка cp1251.
Есть 2 пути
Путь 1 конвертировать cp1251 в utf-8 каждый раз перед отправкой. Теоретически можно с файла считывать текст сразу в нужной кодировке.
Путь 2 пере сохранить исходный файл каким либо редактором в кодировку utf-8 и настроить ide чтобы и дальше сохраняла в utf-8 но
тогда в при выводе в консоль нужно будит конвертировать с utf-8 cp1251
**Как настроить CodeBlocks**
Menu **Settings->Editor...->General Settings.** Далее выбираете закладку "**Encoding settings**".
Выбираете из выпадающего списка любимую кодировку (UTF-8). И чуть ниже ставите ее как "As default"
https://ru.stackoverflow.com/questions/874904/codeblocks-как-заставить-ide-сохранять-файлы-в-utf-8
**Конвертировать cp1251 в utf-8 и обратно utf-8 cp1251**
https://ru.stackoverflow.com/questions/783946/Конвертировать-в-кодировку-utf8
Код дублирую так как сам не переношу когда отправляют на силку
cp1251_to_utf8
string cp1251_to_utf8(const char *str){
string res;
int result_u, result_c;
result_u = MultiByteToWideChar(1251, 0, str, -1, 0, 0);
if(!result_u ){return 0;}
wchar_t *ures = new wchar_t[result_u];
if(!MultiByteToWideChar(1251, 0, str, -1, ures, result_u)){
delete[] ures;
return 0;
}
result_c = WideCharToMultiByte(65001, 0, ures, -1, 0, 0, 0, 0);
if(!result_c){
delete [] ures;
return 0;
}
char *cres = new char[result_c];
if(!WideCharToMultiByte(65001, 0, ures, -1, cres, result_c, 0, 0)){
delete[] cres;
return 0;
}
delete[] ures;
res.append(cres);
delete[] cres;
return res;
}
Utf8_to_cp1251
std::string Utf8_to_cp1251(const char *str)
{
std::string res;
int result_u, result_c;
result_u = MultiByteToWideChar(CP_UTF8,
0,
str,
-1,
0,
0);
if (!result_u)
return 0;
wchar_t *ures = new wchar_t[result_u];
if(!MultiByteToWideChar(CP_UTF8,
0,
str,
-1,
ures,
result_u))
{
delete[] ures;
return 0;
}
result_c = WideCharToMultiByte(
1251,
0,
ures,
-1,
0,
0,
0, 0);
if(!result_c)
{
delete [] ures;
return 0;
}
char *cres = new char[result_c];
if(!WideCharToMultiByte(
1251,
0,
ures,
-1,
cres,
result_c,
0, 0))
{
delete[] cres;
return 0;
}
delete[] ures;
res.append(cres);
delete[] cres;
return res;
}
Проверка на UTF8:
bool is_valid_utf8(const char * string){
if(!string){return true;}
const unsigned char * bytes = (const unsigned char *)string;
unsigned int cp;
int num;
while(*bytes != 0x00){
if((*bytes & 0x80) == 0x00){
// U+0000 to U+007F
cp = (*bytes & 0x7F);
num = 1;
}
else if((*bytes & 0xE0) == 0xC0){
// U+0080 to U+07FF
cp = (*bytes & 0x1F);
num = 2;
}
else if((*bytes & 0xF0) == 0xE0){
// U+0800 to U+FFFF
cp = (*bytes & 0x0F);
num = 3;
}
else if((*bytes & 0xF8) == 0xF0){
// U+10000 to U+10FFFF
cp = (*bytes & 0x07);
num = 4;
}
else{return false;}
bytes += 1;
for(int i = 1; i < num; ++i){
if((*bytes & 0xC0) != 0x80){return false;}
cp = (cp << 6) | (*bytes & 0x3F);
bytes += 1;
}
if( (cp > 0x10FFFF) ||
((cp <= 0x007F) && (num != 1)) ||
((cp >= 0xD800) && (cp <= 0xDFFF)) ||
((cp >= 0x0080) && (cp <= 0x07FF) && (num != 2)) ||
((cp >= 0x0800) && (cp <= 0xFFFF) && (num != 3)) ||
((cp >= 0x10000)&& (cp <= 0x1FFFFF)&& (num != 4)) ){return false;}
}
return true;
}
string в wstring:
wstring string_to_wstring(string str){
wstring convertedString;
int requiredSize = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, 0, 0);
if( requiredSize > 0){
vector<wchar_t> buffer(requiredSize);
MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &buffer[0], requiredSize);
convertedString.assign(buffer.begin(), buffer.end() - 1);
}
return convertedString;
}