با سلام و احترام خدمت دوستان و اساتید بزرگوار
می خوام در این تاپیک طریقه کار با API ربات های تلگرام در دلفی رو خدمت دوستان آموزش بدم . شاید بتونه گره از کار برخی دوستان باز کنه.
طریقه کار به این صورت هست که ابتدا باید در تلگرام ربات خود را بسازید که طریقه ساختش راحت هست و من وارد این مقوله نمیشم.
بعد از ساخت ربات ،تلگرام یه توکن منحصر به فرد برای رباتتون در اختیار شما میذاره که شبیه این هست
123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
حالا شما باید با آدرس اصلی تلگرام و با استفاده از این توکن با تلگرام در ارتباط باشید. طریقه ارتباط هم Http Post &Get هست. که در کدی که من استفاده کردم برای این کار در دلفی 7 از Indy و کامپوننت TidHttp هست.
درخواست ها رو به ربات تلگرام به صورت زیر ارسال می کنیم.
https://api.telegram.org/bot<token>/METHOD_NAME
پاسخ هایی که ربات تلگرام براتون میفرسته بصورت متنی و در قالب JSON هست.
نمونه یک پاسخ:
{ "ok":true,
"result":
[
{
"update_id":658807363,
"message":
{
"message_id":41,
"from":
{
"id":79060780,
"first_name":"mehdi",
"last_name":"Jafari",
"username":"ShahvarIMS"
},
"chat":
{
"id":79060780,
"first_name":"mehdi",
"last_name":"Jafari",
"username":"ShahvarIMS",
"type":"private"
},
"date":1468481903,
"text":"\/features",
"entities":
[{
"type":"bot_command",
"offset":0,
"length":9
}]
}
}
]
}
برای کار با این فرمت JSON در دلفی 7 نیاز به کامپوننت و یا کلاس های از پیش طراحی شده دارید و مثل اینکه در دلفی های بالاتر این مشکل رفع شده و دلفی های جدید JSON رو ساپورت میکنن. چون من دیگه سراغشون نرفتم اطلاعات دقیقی ندارم متاسفانه. من در این کد از یک Unit به نام LkJSON v1.07 که در دلفی 7 هم کامپایل میشه استفاده کردم که خدا به این دوست عزیز جناب آقای Leonid Koninin خیرش رو بده انشاالله.
خوب نگران کامپوننت و این unit و کار با JSON نباشید من آخر کد رو میذارم.
دوتا Dll هم کنار برنامه استفاده میشه :
libeay32.dll
ssleay32.dll
دقت کنید اینا ورژن های مختلفی داره که باید با ورژن Indy شما بخونه.
خوب حالا بریم سراغ کد برنامه
ابتدا می بایست یه سری unit ها به بخش use اصلی اضافه کنید که همش رو میذارم
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdHTTP,IdSSLOpenSSL, Buttons;
البته با انداختن کامپوننت TidHttp روی فرم یه سریش اتومات اضافه میشه.
آردس ارسال درخواست به ربات:
BaseUrl = 'https://api.telegram.org/bot';
گرفتن اطلاعات ربات:
ما می خواین این آدرس رو post کنیم
https://api.telegram.org/bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11/getMe
Var Src : string;
LHandler: TIdSSLIOHandlerSocket;
begin
API := edtAPI.Text;
try
LHandler := TIdSSLIOHandlerSocket.Create(nil);
try
IdHTTP1.ReadTimeout := 30000;
IdHTTP1.IOHandler:=LHandler;
LHandler.SSLOptions.Method := sslvTLSv1;
LHandler.SSLOptions.Mode := sslmUnassigned;
Src:= IdHTTP1.Get(BaseUrl + API + '/getme');
memoResponse.lines.clear;
memoresponse.lines.add(src);
memoRequest.Text := IdHTTP1.Response.RawHeaders.Text;
finally
LHandler.Free;
end;
except on E: Exception do
Showmessage(E.Message);
end;
خوب اگر یخورده تحقیق کرده باشید بات تلگرام شماره تلفن رو نمیشناسه و فقط با Chat_ID کار میکنه. یعنی به هر شخصی که بخواین پیام بفرستید ابتدا باید Chat_id اون شخص رو در بیارید و سپس به اون پیام مناسب رو ارسال کنید. شخص هنگامی که رباط شما رو ادد میکنه و یه درخواست یا Bot Command رو که با فرمت /CommandName هست رو برای Bot میفرسته با بررسی همین پیام دریافتی میشه Chat_ID فرد رو به دست آورد، تو کد JSON بالا ID حاوی Chat_id فرد هست که نمونه یک پیام ارسالی به Bot هست.
پس با بررسی پیام ارسالی هم میشه Chat_id اون بابا رو بدست آورد و هم اینکه تو Text که متن پیام هست درخواستش رو بررسی کرد و پبام مناسبی براش ارسال کرد.
با استفاده از این بات می تونید chat_id خودتون رو دربیارید و تو تست برنامه ازش استفاده کنید :
@get_id_bot
ارسال پیام متنی:
Var IDUser : String;
Text : WideString;
msg : WideString;
Src : string;
LHandler: TIdSSLIOHandlerSocket;
begin
API := edtAPI.Text;
IDUser := Edit1.Text;
Text := edtMessage.Text;
try
msg := UTF8Encode('chat_id='+IDUser+'&'+'text='+ Text);
LHandler := TIdSSLIOHandlerSocket.Create(nil);
IdHTTP1.ReadTimeout := 30000;
IdHTTP1.IOHandler:=LHandler;
LHandler.SSLOptions.Method := sslvTLSv1;
LHandler.SSLOptions.Mode := sslmUnassigned;
IdHTTP1.HandleRedirects := true;
memoRequest.Text := BaseUrl + API + '/sendmessage?' + msg;
Src := IdHTTP1.Get(BotUrl + API +'/sendmessage?' + msg);
memoResponse.lines.clear;
memoresponse.lines.add(src);
except
on E: EIdHTTPProtocolException do
begin
memoRequest.Text := IdHTTP1.Response.RawHeaders.Text;
if not ((E.ReplyErrorCode = 301) or (E.ReplyErrorCode = 302)) then raise;
Src := E.ErrorMessage;
ShowMessage(Src);
end
end;
در این کد چون ارتباط ما رو رو تلگرام بصورت اتوماتیک قطع می کنه Indy یک خطا صادر میکنه با متن زیر که الان که تاریخ 26 تیر 95 هست دارم روش کار میکنم ببینم می تونم خفتش کنم یا نه. البته برنامه بدون هیچ مشکلی کار میکنه.
Connection Closed Gracefully
دوستان و اساتید اگه بابت رفع این خطا بتونن راهنمایی کنم ممنون میشم .
خوب حالا کد زیر پیام هایی رو که از طرف افراد مختلف برای Bot ارسال شده رو در قالب JSON برای شما میاره البته JSON رو من در این کد به اصطلاح Deserialize می کنم.
var Offset:integer;
msg : WideString;
Src : string;
LHandler: TIdSSLIOHandlerSocket;
begin
API := edtAPI.Text;
try
Offset := 0;
msg := UTF8Encode('/getUpdates');
//msg := UTF8Encode('/Update?update_id=1');
LHandler := TIdSSLIOHandlerSocket.Create(nil);
IdHTTP1.ReadTimeout := 30000;
IdHTTP1.IOHandler:=LHandler;
LHandler.SSLOptions.Method := sslvTLSv1;
LHandler.SSLOptions.Mode := sslmUnassigned;
IdHTTP1.HandleRedirects := true;
memoRequest.Text := BaseUrl + API + msg;
Src := IdHTTP1.Get(BotUrl + API + msg);
memUpdates.lines.clear;
DeserializeJSON(src);
//memUpdates.lines.add(src);
except
on E: EIdHTTPProtocolException do
begin
//memoRequest.Text := IdHTTP1.Response.RawHeaders.Text;
if not ((E.ReplyErrorCode = 301) or (E.ReplyErrorCode = 302)) then raise;
Src := E.ErrorMessage;
ShowMessage(Src);
end
end;
اینم کد Deserialize کردن JSON
procedure TForm1.DeserializeJSON(returnval: string);var
systems : TStrings;
returnval2: string;
json , item , ResultNode , OKNode , msgNode ,fromNode :TlkJSONbase;
i,j: integer;
list: TlkJSONObject;
okVal : boolean;
nodename : String;
begin
json:= TlkJSON.ParseText(returnval);
OKNode := TlkJSONboolean(json).Field['ok'];
okVal := OKNode.Value;
ResultNode := TlkJSONlist(json).Field['result'];
for i := 0 to pred(ResultNode.Count) do
begin
item := TlkJSONlist(ResultNode).child[i];
msgNode := TlkJSONObject(item).Field['message'];
memUpdates.Lines.Add('Update_id: ' + VarToStr(item.Field['update_id'].Value));
if msgNode.Field['from'].Field['id'] <> nil then
memUpdates.Lines.Add('Chat_id: ' + VarToStr(msgNode.Field['from'].Field['id'].Value));
if msgNode.Field['from'].Field['first_name'] <> nil then
memUpdates.Lines.Add('first_name: ' + VarToStr(msgNode.Field['from'].Field['first_name'].Value));
if msgNode.Field['from'].Field['last_name'] <> nil then
memUpdates.Lines.Add('last_name: ' + VarToStr(msgNode.Field['from'].Field['last_name'].Value));
if msgNode.Field['from'].Field['username'] <> nil then
memUpdates.Lines.Add('username: ' + VarToStr(msgNode.Field['from'].Field['username'].Value));
if msgNode.Field['text'] <> nil then
memUpdates.Lines.Add('Message Text: ' + VarToStr(msgNode.Field['text'].Value));
memUpdates.Lines.Add('-----------------------------');
end;
end;
متد GetUpdates ربات تلگرام پارامترهای مختلفی داره که می تونید اونا رو از آدرس زیر بررسی بفرمایید که می تونن تعداد خاصی پیام رو خفت کنه و برای شما بیاره. حالا پیام های دریافتی رو می تونید بررسی بفرمایید و اولا Chat_id رو بردارید و تو بانک اطلاعاتی خودتون ذخیره کنید و همچنین پاسخ مناسب به افرادی که کامند خاصی رو درخواست کردن ، بدهید. قاعدتا این بخش خود باید بصور مثال هر چند لحظه هی اجرا بشه تا درخواست ها رو بگیره از BOT. این کار باعث میشه که بات شما کاملا Interactive بشه. متد های تلگرام رو بررسی بفرمایید متد Update هم داره.
درپایان هم عاجزانه تقاضا دارم از دوستانی که این کد رو توسعه می دن . هر کسی به نتیجه های خوبی رسید مثلا ارسال عکس و استیکر و فایل و اینا رو بهش اضافه کردید برای من و بقیه دوستان دیگه هم بذارید.
کوچیک همه شما.
مهدی جعفری
توجه: در چند پست پایین تر آخرین نسخه ویرایش شده رو گذاشتم اون رو دانلود بفرمایید