Встала задача написания телеграм-бота для передачи в телеграм данных из БД Firebird; при этом программа должна работать на линуксовом сервере без графики. По понятным причинам я выбрал Lazarus, который хорошо дружит с Firebird через компоненты IBX (использую модификацию от Rik). Оптимальный вариант - это написание демона, но это я пока не осилил, поэтому хочу для начала сделать консольное приложение.
Однако добавление TDataModule в консольное приложение - это не так просто, как в LCL. Где бы почитать, как это делать правильно? Я перепробовал разные варианты, в том числе ручное создание компонентов, и всегда получаю при попытке соединения с БД непонятную ошибку: Failed to create win32 control, error: 1407 : Не удается найти класс окна. Как это получается - не пойму.
Добавлено спустя 7 минут 54 секунды:
Забыл написать, что пока пишу под виндой, чтобы отработать процесс. Потом буду открывать в линуксовом Лазаре.
Добавлено спустя 25 минут 46 секунд:
Немного деталей, как пытаюсь делать сейчас.
Основной код
- Код: Выделить всё
- program docbotapp;
 {$mode objfpc}{$H+}
 uses
 {$IFDEF UNIX}{$IFDEF UseCThreads}
 cthreads,
 {$ENDIF}{$ENDIF}
 Classes, Interfaces, SysUtils, ibexpress, CustApp, dbunit
 { you can add units after this };
 type
 { DocBot }
 DocBot = class(TCustomApplication)
 protected
 procedure DoRun; override;
 public
 constructor Create(TheOwner: TComponent); override;
 destructor Destroy; override;
 end;
 { DocBot }
 procedure DocBot.DoRun;
 begin
 if DM.Start then
 { add your program here }
 while not Terminated do DM.Loop;
 // stop program loop
 Terminate;
 end;
 constructor DocBot.Create(TheOwner: TComponent);
 begin
 inherited Create(TheOwner);
 DM:=TDM.Create(TheOwner);
 end;
 destructor DocBot.Destroy;
 begin
 DM.Free;
 inherited Destroy;
 end;
 var
 Application: DocBot;
 begin
 Application:=DocBot.Create(nil);
 Application.Title:='Bot Application';
 Application.Run;
 Application.Free;
 end.
Модуль данных:
- Код: Выделить всё
- unit dbunit;
 {$mode objfpc}{$H+}
 interface
 uses
 Classes, SysUtils, IBDatabase, IBSQL, tgsendertypes, tgtypes,
 tgfclhttpclientbroker;
 type
 { TDM }
 TDM = class(TDataModule)
 DB: TIBDatabase;
 Qry: TIBSQL;
 ReadTransaction: TIBTransaction;
 procedure DataModuleCreate(Sender: TObject);
 procedure DataModuleDestroy(Sender: TObject);
 procedure BotReceiveMessage(ASender: TObject; AMessage: TTelegramMessageObj);
 private
 FBot: TTelegramSender;
 public
 function Start: Boolean;
 procedure Loop;
 end;
 const
 BOTTOKEN = 'MyToken';
 ERRORMESSAGE = 'Ошибка: неверный запрос или нет соединения с базой данных.';
 var
 DM: TDM;
 implementation
 {$R *.lfm}
 { TDM }
 procedure TDM.DataModuleCreate(Sender: TObject);
 begin
 DB:=TIBDatabase.Create(Self);
 with DB
 do begin
 Connected:=False;
 AllowStreamedConnected:=False;
 DatabaseName:='localhost:E:\DB\MyDB.fdb';
 {$IFDEF WINDOWS}
 DB.LibraryName:='fbclient.dll';
 {$ELSE}
 DB.LibraryName:='libfbclient.so.2.5.9';
 {$ENDIF}
 Params.Text:='user_name=SYSDBA'+sLineBreak
 +'password=masterke'+sLineBreak
 //+'role='+DBConfig.role+sLineBreak
 +'lc_ctype=UTF8'+sLineBreak;
 DefaultTransaction:=Nil;
 DefaultUpdTransaction:=Nil;
 IdleTimer:=0;
 TraceFlags:=[];
 //Left:=49;
 //Top:=30;
 end;
 ReadTransaction:=TIBTransaction.Create(Self);
 with ReadTransaction
 do begin
 Active:=False;
 DefaultDatabase:=DB;
 Params.Text:='read'+sLineBreak+'read_committed'+sLineBreak
 +'rec_version';
 //Left:=136;
 //Top:=30;
 end;
 DB.DefaultTransaction:=ReadTransaction;
 DB.DefaultUpdTransaction:=ReadTransaction;
 Qry:=TIBSQL.Create(Self);
 with Qry
 do begin
 Database:=DB;
 ParamCheck:=True;
 Transaction:=ReadTransaction;
 SelectOnBlock:=False;
 //Left:=216;
 //Top:=32;
 end;
 FBot:=TTelegramSender.Create (BOTTOKEN);
 FBot.OnReceiveMessage:=@BotReceiveMessage;
 end;
 function TDM.Start: Boolean;
 begin
 Result:=True;
 try
 DB.Connected:=True; //на этой строке вылетает приведенная ошибка
 ReadTransaction.StartTransaction;
 except
 on E: Exception
 do begin
 with TStringList.Create
 do try
 Add (E.Message);
 SaveToFile ('error.log');
 finally
 Free;
 end;
 writeln (E.Message);
 Result:=False;
 Exit;
 end;
 end;
 if not FBot.getMe then Result:=False;
 end;
 procedure TDM.Loop;
 begin
 FBot.getUpdatesEx(0, 10);
 end;
 procedure TDM.BotReceiveMessage(ASender: TObject; AMessage: TTelegramMessageObj);
 var
 AChatID: Int64;
 SendingMessage, RcvMessage: String;
 label SendStr;
 begin
 RcvMessage:=AMessage.Text;
 AChatID:=AMessage.Chat.ID;
 if (Length(RcvMessage)>50) or (Length(RcvMessage)=0)
 then begin
 SendingMessage:=ERRORMESSAGE;
 goto SendStr;
 end;
 //...
 SendingMessage:='Ответ: '+RcvMessage;
 SendStr:
 FBot.sendMessage(AChatID, SendingMessage);
 end;
 procedure TDM.DataModuleDestroy(Sender: TObject);
 begin
 DB.Connected:=False;
 FBot.Free;
 end;
 end.



