본문 바로가기
C++, MFC

[MFC] 텔레그램 봇 만들고 메세지 보내기 예제

by dev_drive 2025. 8. 23.
반응형

 
 
 
간혹 자동으로 돌아가는 데몬같은 프로그램에서 알림 메세지를 전송 받아야 하는 경우가 있는데
텔레그램 봇을 생성하고 메세지를 전송하는 방법에 대해 알아보겠습니다.
 

텔레그램에서 @Botfather를 검색해서 대화를 시작합니다.
 
 

대화를 시작하고 /newbot를 입력하거나 선택합니다.
 
 

봇의 이름을 지정합니다.
 

봇 이름 끝에는 반드시 bot이 들어가야된다고 합니다.
 
 

이미 만들어진 이름은 사용할 수 없습니다.
 
 

봇 이름이 정해지면 HTTP API 엑세스 토큰이 발급됩니다.
 
 
 

봇이 만들어졌으면 먼저 그룹을 만듭니다. 
 
 

그 다음 만든 봇 이름을 검색해서 채팅을 시작하고 그룹에 추가 버튼으로 이전에 만든 그룹에 초대하고
아무 채팅이나 입력해서 대화방을 활성화 합니다.
 
 
그 다음 브라우저에 아래와 같이 입력하여 chat id를 확인합니다.
https://api.telegram.org/bot79804.../getUpdates
(bot 뒷부분에는 토큰을 입력합니다)
 
응답 중 "chat":{"id":440.., 이 부분이 chat id입니다.
 
 
 
그럼 이제 아래와 같이 입력하면 봇이 메세지를 전송합니다.
https://api.telegram.org/bot<토큰>/sendMessage?chat_id=<채팅ID>&text=Hello

 
 
 
이제 MFC프로젝트에서 위의 기능을 API로 전송하는 방법을 알아보겠습니다.

 

1. WinHttp방식

#include <windows.h>
#include <winhttp.h>
#pragma comment(lib, "winhttp.lib")

void CtelebotDlg::SendTelegramMessage(CString token, CString chatId, CString message)
{
	CString host = _T("api.telegram.org");
	CString path;
	path.Format(_T("/bot%s/sendMessage?chat_id=%s&text=%s"),
		token, chatId, message);

	HINTERNET hSession = WinHttpOpen(L"MFC Telegram Bot/1.0",
		WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
		WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);

	if (!hSession) return;

	HINTERNET hConnect = WinHttpConnect(hSession, host, INTERNET_DEFAULT_HTTPS_PORT, 0);
	if (!hConnect) { WinHttpCloseHandle(hSession); return; }

	HINTERNET hRequest = WinHttpOpenRequest(
		hConnect,
		L"GET",
		path,
		NULL,
		WINHTTP_NO_REFERER,
		WINHTTP_DEFAULT_ACCEPT_TYPES,
		WINHTTP_FLAG_SECURE);

	if (hRequest)
	{
		BOOL bResult = WinHttpSendRequest(hRequest,
			WINHTTP_NO_ADDITIONAL_HEADERS,
			0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);

		if (bResult) {
			bResult = WinHttpReceiveResponse(hRequest, NULL);
		}

		WinHttpCloseHandle(hRequest);
	}

	WinHttpCloseHandle(hConnect);
	WinHttpCloseHandle(hSession);
}

 

 

 

2. CHttpFile 방식

#include <memory>
#include <afxinet.h>

void CtelebotDlg::SendTelegramMessage(CString token, CString chatId, CString message)
{
	try
	{
		CInternetSession session(_T("MFC Telegram Bot"), 1, INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr, INTERNET_FLAG_SECURE);

		CString urlPath = _T("/bot") + token + _T("/sendMessage");
		CString server = _T("api.telegram.org");

		std::string utf8ChatId = CStringToUTF8(chatId);
		std::string utf8Message = CStringToUTF8(message);
		std::string encodedChatId = UrlEncode(utf8ChatId);
		std::string encodedMessage = UrlEncode(utf8Message);

		CStringA postData;
		postData.Format("chat_id=%s&text=%s", encodedChatId.c_str(), encodedMessage.c_str());

		std::unique_ptr<CHttpConnection> pConnection(
			session.GetHttpConnection(server, INTERNET_DEFAULT_HTTPS_PORT, _T(""), _T(""))
		);
		std::unique_ptr<CHttpFile> pFile(
			pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST, urlPath, nullptr, 1, nullptr, nullptr, INTERNET_FLAG_SECURE)
		);

		CString headers = _T("Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n");

		pFile->AddRequestHeaders(headers);
		pFile->SendRequest(nullptr, 0, (LPVOID)(LPCSTR)postData, postData.GetLength());

		CString response;
		CHAR buffer[1024];
		UINT bytesRead;
		while ((bytesRead = pFile->Read(buffer, sizeof(buffer) - 1)) > 0)
		{
			buffer[bytesRead] = '\0';
			response += buffer;
		}

		pFile->Close();
		pConnection->Close();
	}
	catch (CInternetException* pEx)
	{
		TCHAR error[1024];
		pEx->GetErrorMessage(error, 1024);
		AfxMessageBox(_T("Error: ") + CString(error));
		pEx->Delete();
	}

}

std::string CtelebotDlg::CStringToUTF8(const CString& str)
{
	int len = WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr);
	std::string utf8Str(len, 0);
	WideCharToMultiByte(CP_UTF8, 0, str, -1, &utf8Str[0], len, nullptr, nullptr);
	return utf8Str;
}

std::string CtelebotDlg::UrlEncode(const std::string& str)
{
	std::string encoded;
	for (unsigned char c : str)
	{
		if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
			encoded += c;
		else
		{
			char buf[4];
			sprintf_s(buf, "%%%02X", c);
			encoded += buf;
		}
	}
	return encoded;
}

 

 

 
 
WinHttp와 CHttpFile을 사용한 소스입니다. 
응답이 빠른편은 아니고 전송이 안되는 환경에서는 먹통이되니

가급적 스레드로 구현하는 것이 좋아보입니다.
 

반응형

댓글