如何将我的 Delphi TS3 Serverquery IdTelnet 作为控制台应用程序获取到 运行?
How can I get my Delphi TS3 Serverquery IdTelnet to run as a console application?
我需要 运行 我的 Delphi 应用程序处于控制台模式,这样我就可以 运行 它在我的 VPS 上作为我的 [=34] 上的 Wine 模拟应用程序=] 服务器,以便它作为 serverquery 通过 telnet 与我的 Teamspeak 服务器通信。它需要始终保持连接并将玩家从一个频道转移到另一个频道,因此被动使用 PHP 不是一种选择。我知道 TS3 机器人已经存在,但是 none 是在 Delphi 中为 Teamspeak 3 编程的。该程序在 Windows 应用程序中运行完美,但只是挂在控制台版本中。
我在数据模块中设置了 indy IdTelnet1.ThreadedEvent := true ,这似乎有点帮助。我猜我需要以某种方式与该线程交谈,但不确定如何。
我试过这样做,但是程序挂了:
program TS3bot;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Unit1 in 'Unit1.pas' {DataModule1: TDataModule};
begin
try
DataModule1 := TDataModule1.Create(nil);
try
{ TODO -oUser -cConsole Main : Insert code here }
DataModule1.IdTelnet1.Connect;
DataModule1.IdTelnet1.TelnetThread.Start;
repeat
//
until (DataModule1.IdTelnet1.Connected = false);
DataModule1.IdTelnet1.TelnetThread.Stop;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
finally
writeln('Program ended.');
DataModule1.Free;
end;
end.
UNIT1
unit Unit1;
interface
uses
System.SysUtils, System.Classes, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdTelnet, IdGlobal;
type
TDataModule1 = class(TDataModule)
IdTelnet1: TIdTelnet;
procedure IdTelnet1Connected(Sender: TObject);
procedure IdTelnet1DataAvailable(Sender: TIdTelnet; const Buffer: TIdBytes);
procedure IdTelnet1Disconnected(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
private
{ Private declarations }
procedure processCommand(Command : string);
procedure processCommands;
procedure InterpetBuffer(Buffer: string);
public
{ Public declarations }
end;
Const
Elements = (3); //(Elements - 1)
ListOfOnConnectCommands : array [0..Elements] of string =
('login serverquery password',
'use 1',
'clientupdate client_nickname=NickNameServer',
'servernotifyregister event=server');
var
DataModule1: TDataModule1;
BufferNumber: integer = 0;
CommandSent : boolean = false;
CommandOK : boolean = false;
CommandNumber : integer = 0;
implementation
{%CLASSGROUP 'System.Classes.TPersistent'}
{$R *.dfm}
procedure pSplitIT(BreakString, BaseString: string; StringList: TStrings);
var
EndOfCurrentString: byte;
begin
StringList.Clear;
repeat
EndOfCurrentString := Pos(BreakString, BaseString);
if EndOfCurrentString = 0 then
StringList.add(BaseString)
else
StringList.add(Copy(BaseString, 1, EndOfCurrentString - 1));
BaseString := Copy(BaseString, EndOfCurrentString + length(BreakString), length(BaseString) - EndOfCurrentString);
until EndOfCurrentString = 0;
end;
procedure TDataModule1.processCommand(Command : string);
begin
writeln('processCommand: ' + Command);
IdTelnet1.SendString(Command);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
end;
procedure TDataModule1.processCommands;
var
MyString: string;
begin
if CommandNumber <= Elements then
begin
MyString := ListOfOnConnectCommands[CommandNumber];
writeln('processCommands: ' + MyString);
IdTelnet1.SendString(MyString);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
inc(CommandNumber);
//exit;
end;
end;
procedure TDataModule1.InterpetBuffer(Buffer: string);
var
MyTstringlist: Tstringlist;
MyBuffer: string;
I: integer;
clid: integer;
member, legionnaire, enteredGuestChannel: boolean;
begin
enteredGuestChannel := false;
member := false;
legionnaire := false;
inc(BufferNumber);
writeln('---------------------------------------------------------');
writeln('IdTelnet1DataAvailable BufferNumber: ' + BufferNumber.ToString);
writeln('---------------------------------------------------------');
if Pos('notifycliententerview',Buffer)>0 then
begin
writeln('----------------------');
writeln('EXIT notifycliententerview:');
writeln(Buffer);
MyTstringlist := Tstringlist.Create;
MyBuffer := Buffer;
pSplitIT(' ',MyBuffer,MyTstringlist);
writeln('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
writeln(MyTstringlist.Strings[I]);
if MyTstringlist.Strings[I] = 'ctid=45' then
begin
// client entered GUESTS CHANNEL, see if we can move them.
enteredGuestChannel := true;
end;
if Pos('client_servergroups=',MyTstringlist.Strings[I]) > 0 then
begin
if Pos('18',MyTstringlist.Strings[I]) > 0 then
begin
member := true;
end;
if Pos('19',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
if Pos('28',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
end;
//clid
if Pos('clid=',MyTstringlist.Strings[I]) > 0 then
begin
clid := StrToInt(copy(MyTstringlist.Strings[I],6,high(MyTstringlist.Strings[I])));
end;
end;
writeln('----------------------');
MyTstringlist.Free;
if ( (enteredGuestChannel = true)
and (member = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end
else if ( (enteredGuestChannel = true)
and (legionnaire = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end;
exit;
end;
// Create Returns in terminal
if Pos(#10#13,Buffer)>0 then
begin
MyTstringlist := Tstringlist.Create;
pSplitIT(#10#13,Buffer,MyTstringlist);
writeln('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
writeln(MyTstringlist.Strings[I]);
end;
MyTstringlist.Free;
end
else
begin
writeln(Buffer);
end;
if Pos('error id=0 msg=ok',Buffer)>0 then
begin
processCommands;
end;
writeln('');
end;
procedure TDataModule1.DataModuleDestroy(Sender: TObject);
begin
processCommand('logout');
processCommand('quit');
IdTelnet1.Disconnect(true);
end;
procedure TDataModule1.IdTelnet1Connected(Sender: TObject);
begin
writeln('IdTelnet1Connected');
// sleep(5000);
//writeln('processCommands:');
// processCommands;
end;
procedure TDataModule1.IdTelnet1DataAvailable(Sender: TIdTelnet;
const Buffer: TIdBytes);
begin
InterpetBuffer(bytestostring(Buffer));
end;
procedure TDataModule1.IdTelnet1Disconnected(Sender: TObject);
begin
writeln('IdTelnet1Disconnected');
end;
end.
这是我来自 TForm 的原始代码:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, IdBaseComponent,
IdComponent, IdTCPConnection, IdTCPClient, IdTelnet, IdGlobal, Vcl.ExtCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Edit1: TEdit;
IdTelnet1: TIdTelnet;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Memo2: TMemo;
Timer1: TTimer;
Button4: TButton;
IdSchedulerOfThreadDefault1: TIdSchedulerOfThreadDefault;
procedure Button1Click(Sender: TObject);
procedure IdTelnet1Disconnected(Sender: TObject);
procedure IdTelnet1DataAvailable(Sender: TIdTelnet; const Buffer: TIdBytes);
procedure Button3Click(Sender: TObject);
procedure IdTelnet1Status(ASender: TObject; const AStatus: TIdStatus;
const AStatusText: string);
procedure IdTelnet1Connected(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure InterpetBuffer(buffer: string);
procedure processCommands;
procedure processCommand(Command : string);
public
{ Public declarations }
end;
Const
Elements = (3); //(Elements - 1)
ListOfOnConnectCommands : array [0..Elements] of string =
('login severquery password',
'use 1',
'clientupdate client_nickname=NickNameServer',
'servernotifyregister event=server');
var
Form1: TForm1;
BufferNumber: integer = 0;
CommandSent : boolean = false;
CommandOK : boolean = false;
CommandNumber : integer = 0;
implementation
{$R *.dfm}
procedure pSplitIT(BreakString, BaseString: string; StringList: TStrings);
var
EndOfCurrentString: byte;
begin
StringList.Clear;
repeat
EndOfCurrentString := Pos(BreakString, BaseString);
if EndOfCurrentString = 0 then
StringList.add(BaseString)
else
StringList.add(Copy(BaseString, 1, EndOfCurrentString - 1));
BaseString := Copy(BaseString, EndOfCurrentString + length(BreakString), length(BaseString) - EndOfCurrentString);
until EndOfCurrentString = 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
BufferNumber := 0;
IdTelnet1.Connect;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
MyString: string;
I: integer;
begin
MyString := edit1.Text;
for I := Low(MyString) to High(MyString) do
begin
IdTelnet1.SendCh(MyString[I]);
end;
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
edit1.Text := '';
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
processCommand('logout');
processCommand('quit');
IdTelnet1.Disconnect(true);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
processCommands;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
processCommand('logout');
processCommand('quit');
IdTelnet1.Disconnect(true);
end;
procedure TForm1.IdTelnet1Connected(Sender: TObject);
begin
memo1.Lines.Add('IdTelnet1Connected');
// Wait 1 second after connected to send commands.
Timer1.Enabled := true;
end;
procedure TForm1.InterpetBuffer(Buffer: string);
var
MyTstringlist: Tstringlist;
MyBuffer: string;
I: integer;
//ctid: integer;
clid: integer;
member, legionnaire, enteredGuestChannel: boolean;
begin
inc(BufferNumber);
memo1.Lines.Add('---------------------------------------------------------');
memo1.Lines.Add('IdTelnet1DataAvailable BufferNumber: ' + BufferNumber.ToString);
memo1.Lines.Add('---------------------------------------------------------');
OutputDebugString(PChar('IdTelnet1DataAvailable BufferNumber: ' + BufferNumber.ToString));
if Pos('notifycliententerview',Buffer)>0 then
begin
memo1.Lines.Add('----------------------');
memo1.Lines.Add('EXIT notifycliententerview:');
memo1.Lines.Add(Buffer);
MyTstringlist := Tstringlist.Create;
MyBuffer := Buffer;
pSplitIT(' ',MyBuffer,MyTstringlist);
memo1.Lines.Add('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
memo1.Lines.Add(MyTstringlist.Strings[I]);
if MyTstringlist.Strings[I] = 'ctid=45' then
begin
// client entered GUESTS CHANNEL, see if we can move them.
enteredGuestChannel := true;
end;
if Pos('client_servergroups=',MyTstringlist.Strings[I]) > 0 then
begin
if Pos('18',MyTstringlist.Strings[I]) > 0 then
begin
member := true;
end;
if Pos('19',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
if Pos('28',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
end;
//clid
if Pos('clid=',MyTstringlist.Strings[I]) > 0 then
begin
clid := StrToInt(copy(MyTstringlist.Strings[I],6,high(MyTstringlist.Strings[I])));
end;
end;
memo1.Lines.Add('----------------------');
MyTstringlist.Free;
if ( (enteredGuestChannel = true)
and (member = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end
else if ( (enteredGuestChannel = true)
and (legionnaire = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end;
exit;
end;
// Create Returns in terminal
if Pos(#10#13,Buffer)>0 then
begin
MyTstringlist := Tstringlist.Create;
pSplitIT(#10#13,Buffer,MyTstringlist);
memo1.Lines.Add('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
memo1.Lines.Add(MyTstringlist.Strings[I]);
end;
MyTstringlist.Free;
end
else
begin
memo1.Lines.Add(Buffer);
end;
if Pos('error id=0 msg=ok',Buffer)>0 then
begin
processCommands;
end;
memo1.Lines.Add('');
end;
procedure TForm1.processCommand(Command : string);
begin
memo2.Lines.Add('processCommand: ' + Command);
IdTelnet1.SendString(Command);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
end;
procedure TForm1.processCommands;
var
MyString: string;
begin
if CommandNumber <= Elements then
begin
MyString := ListOfOnConnectCommands[CommandNumber];
memo2.Lines.Add('processCommands: ' + MyString);
IdTelnet1.SendString(MyString);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
inc(CommandNumber);
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if IdTelnet1.Connected = false then
begin
memo2.Lines.Add('NOT CONNECTED YET...WAITING TO SEND COMMANDS.');
exit;
end;
processCommands;
Timer1.Enabled := false;
end;
procedure TForm1.IdTelnet1DataAvailable(Sender: TIdTelnet;
const Buffer: TIdBytes);
begin
InterpetBuffer(bytestostring(Buffer));
end;
procedure TForm1.IdTelnet1Disconnected(Sender: TObject);
begin
memo1.Lines.Add('IdTelnet1Disconnected');
end;
procedure TForm1.IdTelnet1Status(ASender: TObject; const AStatus: TIdStatus;
const AStatusText: string);
begin
memo1.Lines.Add('AStatusText: ' + AStatusText);
end;
end.
我希望程序在控制台中 运行 就像 GUI windows 版本本身一样,但我不确定如何使用 indy idTelnet 来解决这个问题。我主要根据我的知识和我在互联网上可以找到的内容(不多)将其转换。我需要以某种方式找出导致它挂起的原因,而不是处理 telnet 消息?
好的,我做了很多研究并找到了一些代码来帮助我使用控制台应用程序。
我知道 Remy Lebeau 说 Teamspeak 不使用 telnet 协议,但我使用它并且工作得很好。
感谢 Tony Caduto 在此网页上的功劳:http://www.44342.com/delphi-f1279-t5081-p1.htm 按照 link 并转到页面底部。搜索 Tony Caduto 的最后回复。
此代码现在有效!
现在我可以通过 WINE 在我的 VPS 运行ning linux 上 运行 这个了!我只是没钱买更贵的 Delphi 版本 运行 它会在 linux 上。我将等到他们为像我这样的小型开发人员发布一个版本,允许我们在 linux 上 运行 delphi 应用程序。在那之前,WINE 才是出路。
编辑:确保你输入 IdTelnet1.TelnetThread.Loop := true;在 IdTelnet1.Connect 之后;或者你得到一个错误。
代码如下:
program TS3bot;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Unit1 in 'Unit1.pas' {DataModule1: TDataModule};
begin
try
DataModule1 := TDataModule1.Create(nil);
with DataModule1 do
try
{ TODO -oUser -cConsole Main : Insert code here }
IdTelnet1.ThreadedEvent := true;
IdTelnet1.Connect;
IdTelnet1.TelnetThread.Loop := true;
while (IdTelnet1.Connected = true) do
begin
Sleep(60);
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
finally
writeln('Program ended.');
freeandnil(DataModule1);
end;
end.
这是另一部分,以防万一它发生了变化:
unit Unit1;
interface
uses
System.SysUtils, System.Classes, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdTelnet, IdGlobal;
type
TDataModule1 = class(TDataModule)
IdTelnet1: TIdTelnet;
procedure IdTelnet1Connected(Sender: TObject);
procedure IdTelnet1DataAvailable(Sender: TIdTelnet; const Buffer: TIdBytes);
procedure IdTelnet1Disconnected(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
private
{ Private declarations }
procedure processCommand(Command : string);
procedure processCommands;
procedure InterpetBuffer(Buffer: string);
public
{ Public declarations }
end;
Const
Elements = (3); //(Elements - 1)
ListOfOnConnectCommands : array [0..Elements] of string =
('login serverquery mypassword',
'use 1',
'clientupdate client_nickname=ServerNickName',
'servernotifyregister event=server');
var
DataModule1: TDataModule1;
BufferNumber: integer = 0;
CommandSent : boolean = false;
CommandOK : boolean = false;
CommandNumber : integer = 0;
implementation
{%CLASSGROUP 'System.Classes.TPersistent'}
{$R *.dfm}
procedure pSplitIT(BreakString, BaseString: string; StringList: TStrings);
var
EndOfCurrentString: byte;
begin
StringList.Clear;
repeat
EndOfCurrentString := Pos(BreakString, BaseString);
if EndOfCurrentString = 0 then
StringList.add(BaseString)
else
StringList.add(Copy(BaseString, 1, EndOfCurrentString - 1));
BaseString := Copy(BaseString, EndOfCurrentString + length(BreakString), length(BaseString) - EndOfCurrentString);
until EndOfCurrentString = 0;
end;
procedure TDataModule1.processCommand(Command : string);
begin
writeln('processCommand: ' + Command);
IdTelnet1.SendString(Command);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
end;
procedure TDataModule1.processCommands;
var
MyString: string;
begin
if CommandNumber <= Elements then
begin
MyString := ListOfOnConnectCommands[CommandNumber];
writeln('processCommands: ' + MyString);
IdTelnet1.SendString(MyString);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
inc(CommandNumber);
//exit;
end;
end;
procedure TDataModule1.InterpetBuffer(Buffer: string);
var
MyTstringlist: Tstringlist;
MyBuffer: string;
I: integer;
clid: integer;
member, legionnaire, enteredGuestChannel: boolean;
begin
enteredGuestChannel := false;
member := false;
legionnaire := false;
inc(BufferNumber);
writeln('---------------------------------------------------------');
writeln('IdTelnet1DataAvailable BufferNumber: ' + BufferNumber.ToString);
writeln('---------------------------------------------------------');
if Pos('notifycliententerview',Buffer)>0 then
begin
writeln('----------------------');
writeln('EXIT notifycliententerview:');
writeln(Buffer);
MyTstringlist := Tstringlist.Create;
MyBuffer := Buffer;
pSplitIT(' ',MyBuffer,MyTstringlist);
writeln('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
writeln(MyTstringlist.Strings[I]);
if MyTstringlist.Strings[I] = 'ctid=45' then
begin
// client entered GUESTS CHANNEL, see if we can move them.
enteredGuestChannel := true;
end;
if Pos('client_servergroups=',MyTstringlist.Strings[I]) > 0 then
begin
if Pos('18',MyTstringlist.Strings[I]) > 0 then
begin
member := true;
end;
if Pos('19',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
if Pos('28',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
end;
//clid
if Pos('clid=',MyTstringlist.Strings[I]) > 0 then
begin
clid := StrToInt(copy(MyTstringlist.Strings[I],6,high(MyTstringlist.Strings[I])));
end;
end;
writeln('----------------------');
MyTstringlist.Free;
if ( (enteredGuestChannel = true)
and (member = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end
else if ( (enteredGuestChannel = true)
and (legionnaire = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end;
exit;
end;
// Create Returns in terminal
if Pos(#10#13,Buffer)>0 then
begin
MyTstringlist := Tstringlist.Create;
pSplitIT(#10#13,Buffer,MyTstringlist);
writeln('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
writeln(MyTstringlist.Strings[I]);
end;
MyTstringlist.Free;
end
else
begin
writeln(Buffer);
end;
if Pos('error id=0 msg=ok',Buffer)>0 then
begin
processCommands;
end;
writeln('');
end;
procedure TDataModule1.DataModuleDestroy(Sender: TObject);
begin
processCommand('logout');
processCommand('quit');
IdTelnet1.Disconnect(true);
end;
procedure TDataModule1.IdTelnet1Connected(Sender: TObject);
begin
writeln('IdTelnet1Connected');
sleep(5000);
writeln('processCommands:');
processCommands;
end;
procedure TDataModule1.IdTelnet1DataAvailable(Sender: TIdTelnet;
const Buffer: TIdBytes);
begin
InterpetBuffer(bytestostring(Buffer));
end;
procedure TDataModule1.IdTelnet1Disconnected(Sender: TObject);
begin
writeln('IdTelnet1Disconnected');
end;
end.
我需要 运行 我的 Delphi 应用程序处于控制台模式,这样我就可以 运行 它在我的 VPS 上作为我的 [=34] 上的 Wine 模拟应用程序=] 服务器,以便它作为 serverquery 通过 telnet 与我的 Teamspeak 服务器通信。它需要始终保持连接并将玩家从一个频道转移到另一个频道,因此被动使用 PHP 不是一种选择。我知道 TS3 机器人已经存在,但是 none 是在 Delphi 中为 Teamspeak 3 编程的。该程序在 Windows 应用程序中运行完美,但只是挂在控制台版本中。
我在数据模块中设置了 indy IdTelnet1.ThreadedEvent := true ,这似乎有点帮助。我猜我需要以某种方式与该线程交谈,但不确定如何。
我试过这样做,但是程序挂了:
program TS3bot;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Unit1 in 'Unit1.pas' {DataModule1: TDataModule};
begin
try
DataModule1 := TDataModule1.Create(nil);
try
{ TODO -oUser -cConsole Main : Insert code here }
DataModule1.IdTelnet1.Connect;
DataModule1.IdTelnet1.TelnetThread.Start;
repeat
//
until (DataModule1.IdTelnet1.Connected = false);
DataModule1.IdTelnet1.TelnetThread.Stop;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
finally
writeln('Program ended.');
DataModule1.Free;
end;
end.
UNIT1
unit Unit1;
interface
uses
System.SysUtils, System.Classes, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdTelnet, IdGlobal;
type
TDataModule1 = class(TDataModule)
IdTelnet1: TIdTelnet;
procedure IdTelnet1Connected(Sender: TObject);
procedure IdTelnet1DataAvailable(Sender: TIdTelnet; const Buffer: TIdBytes);
procedure IdTelnet1Disconnected(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
private
{ Private declarations }
procedure processCommand(Command : string);
procedure processCommands;
procedure InterpetBuffer(Buffer: string);
public
{ Public declarations }
end;
Const
Elements = (3); //(Elements - 1)
ListOfOnConnectCommands : array [0..Elements] of string =
('login serverquery password',
'use 1',
'clientupdate client_nickname=NickNameServer',
'servernotifyregister event=server');
var
DataModule1: TDataModule1;
BufferNumber: integer = 0;
CommandSent : boolean = false;
CommandOK : boolean = false;
CommandNumber : integer = 0;
implementation
{%CLASSGROUP 'System.Classes.TPersistent'}
{$R *.dfm}
procedure pSplitIT(BreakString, BaseString: string; StringList: TStrings);
var
EndOfCurrentString: byte;
begin
StringList.Clear;
repeat
EndOfCurrentString := Pos(BreakString, BaseString);
if EndOfCurrentString = 0 then
StringList.add(BaseString)
else
StringList.add(Copy(BaseString, 1, EndOfCurrentString - 1));
BaseString := Copy(BaseString, EndOfCurrentString + length(BreakString), length(BaseString) - EndOfCurrentString);
until EndOfCurrentString = 0;
end;
procedure TDataModule1.processCommand(Command : string);
begin
writeln('processCommand: ' + Command);
IdTelnet1.SendString(Command);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
end;
procedure TDataModule1.processCommands;
var
MyString: string;
begin
if CommandNumber <= Elements then
begin
MyString := ListOfOnConnectCommands[CommandNumber];
writeln('processCommands: ' + MyString);
IdTelnet1.SendString(MyString);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
inc(CommandNumber);
//exit;
end;
end;
procedure TDataModule1.InterpetBuffer(Buffer: string);
var
MyTstringlist: Tstringlist;
MyBuffer: string;
I: integer;
clid: integer;
member, legionnaire, enteredGuestChannel: boolean;
begin
enteredGuestChannel := false;
member := false;
legionnaire := false;
inc(BufferNumber);
writeln('---------------------------------------------------------');
writeln('IdTelnet1DataAvailable BufferNumber: ' + BufferNumber.ToString);
writeln('---------------------------------------------------------');
if Pos('notifycliententerview',Buffer)>0 then
begin
writeln('----------------------');
writeln('EXIT notifycliententerview:');
writeln(Buffer);
MyTstringlist := Tstringlist.Create;
MyBuffer := Buffer;
pSplitIT(' ',MyBuffer,MyTstringlist);
writeln('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
writeln(MyTstringlist.Strings[I]);
if MyTstringlist.Strings[I] = 'ctid=45' then
begin
// client entered GUESTS CHANNEL, see if we can move them.
enteredGuestChannel := true;
end;
if Pos('client_servergroups=',MyTstringlist.Strings[I]) > 0 then
begin
if Pos('18',MyTstringlist.Strings[I]) > 0 then
begin
member := true;
end;
if Pos('19',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
if Pos('28',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
end;
//clid
if Pos('clid=',MyTstringlist.Strings[I]) > 0 then
begin
clid := StrToInt(copy(MyTstringlist.Strings[I],6,high(MyTstringlist.Strings[I])));
end;
end;
writeln('----------------------');
MyTstringlist.Free;
if ( (enteredGuestChannel = true)
and (member = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end
else if ( (enteredGuestChannel = true)
and (legionnaire = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end;
exit;
end;
// Create Returns in terminal
if Pos(#10#13,Buffer)>0 then
begin
MyTstringlist := Tstringlist.Create;
pSplitIT(#10#13,Buffer,MyTstringlist);
writeln('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
writeln(MyTstringlist.Strings[I]);
end;
MyTstringlist.Free;
end
else
begin
writeln(Buffer);
end;
if Pos('error id=0 msg=ok',Buffer)>0 then
begin
processCommands;
end;
writeln('');
end;
procedure TDataModule1.DataModuleDestroy(Sender: TObject);
begin
processCommand('logout');
processCommand('quit');
IdTelnet1.Disconnect(true);
end;
procedure TDataModule1.IdTelnet1Connected(Sender: TObject);
begin
writeln('IdTelnet1Connected');
// sleep(5000);
//writeln('processCommands:');
// processCommands;
end;
procedure TDataModule1.IdTelnet1DataAvailable(Sender: TIdTelnet;
const Buffer: TIdBytes);
begin
InterpetBuffer(bytestostring(Buffer));
end;
procedure TDataModule1.IdTelnet1Disconnected(Sender: TObject);
begin
writeln('IdTelnet1Disconnected');
end;
end.
这是我来自 TForm 的原始代码:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, IdBaseComponent,
IdComponent, IdTCPConnection, IdTCPClient, IdTelnet, IdGlobal, Vcl.ExtCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Edit1: TEdit;
IdTelnet1: TIdTelnet;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Memo2: TMemo;
Timer1: TTimer;
Button4: TButton;
IdSchedulerOfThreadDefault1: TIdSchedulerOfThreadDefault;
procedure Button1Click(Sender: TObject);
procedure IdTelnet1Disconnected(Sender: TObject);
procedure IdTelnet1DataAvailable(Sender: TIdTelnet; const Buffer: TIdBytes);
procedure Button3Click(Sender: TObject);
procedure IdTelnet1Status(ASender: TObject; const AStatus: TIdStatus;
const AStatusText: string);
procedure IdTelnet1Connected(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure InterpetBuffer(buffer: string);
procedure processCommands;
procedure processCommand(Command : string);
public
{ Public declarations }
end;
Const
Elements = (3); //(Elements - 1)
ListOfOnConnectCommands : array [0..Elements] of string =
('login severquery password',
'use 1',
'clientupdate client_nickname=NickNameServer',
'servernotifyregister event=server');
var
Form1: TForm1;
BufferNumber: integer = 0;
CommandSent : boolean = false;
CommandOK : boolean = false;
CommandNumber : integer = 0;
implementation
{$R *.dfm}
procedure pSplitIT(BreakString, BaseString: string; StringList: TStrings);
var
EndOfCurrentString: byte;
begin
StringList.Clear;
repeat
EndOfCurrentString := Pos(BreakString, BaseString);
if EndOfCurrentString = 0 then
StringList.add(BaseString)
else
StringList.add(Copy(BaseString, 1, EndOfCurrentString - 1));
BaseString := Copy(BaseString, EndOfCurrentString + length(BreakString), length(BaseString) - EndOfCurrentString);
until EndOfCurrentString = 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
BufferNumber := 0;
IdTelnet1.Connect;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
MyString: string;
I: integer;
begin
MyString := edit1.Text;
for I := Low(MyString) to High(MyString) do
begin
IdTelnet1.SendCh(MyString[I]);
end;
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
edit1.Text := '';
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
processCommand('logout');
processCommand('quit');
IdTelnet1.Disconnect(true);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
processCommands;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
processCommand('logout');
processCommand('quit');
IdTelnet1.Disconnect(true);
end;
procedure TForm1.IdTelnet1Connected(Sender: TObject);
begin
memo1.Lines.Add('IdTelnet1Connected');
// Wait 1 second after connected to send commands.
Timer1.Enabled := true;
end;
procedure TForm1.InterpetBuffer(Buffer: string);
var
MyTstringlist: Tstringlist;
MyBuffer: string;
I: integer;
//ctid: integer;
clid: integer;
member, legionnaire, enteredGuestChannel: boolean;
begin
inc(BufferNumber);
memo1.Lines.Add('---------------------------------------------------------');
memo1.Lines.Add('IdTelnet1DataAvailable BufferNumber: ' + BufferNumber.ToString);
memo1.Lines.Add('---------------------------------------------------------');
OutputDebugString(PChar('IdTelnet1DataAvailable BufferNumber: ' + BufferNumber.ToString));
if Pos('notifycliententerview',Buffer)>0 then
begin
memo1.Lines.Add('----------------------');
memo1.Lines.Add('EXIT notifycliententerview:');
memo1.Lines.Add(Buffer);
MyTstringlist := Tstringlist.Create;
MyBuffer := Buffer;
pSplitIT(' ',MyBuffer,MyTstringlist);
memo1.Lines.Add('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
memo1.Lines.Add(MyTstringlist.Strings[I]);
if MyTstringlist.Strings[I] = 'ctid=45' then
begin
// client entered GUESTS CHANNEL, see if we can move them.
enteredGuestChannel := true;
end;
if Pos('client_servergroups=',MyTstringlist.Strings[I]) > 0 then
begin
if Pos('18',MyTstringlist.Strings[I]) > 0 then
begin
member := true;
end;
if Pos('19',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
if Pos('28',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
end;
//clid
if Pos('clid=',MyTstringlist.Strings[I]) > 0 then
begin
clid := StrToInt(copy(MyTstringlist.Strings[I],6,high(MyTstringlist.Strings[I])));
end;
end;
memo1.Lines.Add('----------------------');
MyTstringlist.Free;
if ( (enteredGuestChannel = true)
and (member = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end
else if ( (enteredGuestChannel = true)
and (legionnaire = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end;
exit;
end;
// Create Returns in terminal
if Pos(#10#13,Buffer)>0 then
begin
MyTstringlist := Tstringlist.Create;
pSplitIT(#10#13,Buffer,MyTstringlist);
memo1.Lines.Add('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
memo1.Lines.Add(MyTstringlist.Strings[I]);
end;
MyTstringlist.Free;
end
else
begin
memo1.Lines.Add(Buffer);
end;
if Pos('error id=0 msg=ok',Buffer)>0 then
begin
processCommands;
end;
memo1.Lines.Add('');
end;
procedure TForm1.processCommand(Command : string);
begin
memo2.Lines.Add('processCommand: ' + Command);
IdTelnet1.SendString(Command);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
end;
procedure TForm1.processCommands;
var
MyString: string;
begin
if CommandNumber <= Elements then
begin
MyString := ListOfOnConnectCommands[CommandNumber];
memo2.Lines.Add('processCommands: ' + MyString);
IdTelnet1.SendString(MyString);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
inc(CommandNumber);
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if IdTelnet1.Connected = false then
begin
memo2.Lines.Add('NOT CONNECTED YET...WAITING TO SEND COMMANDS.');
exit;
end;
processCommands;
Timer1.Enabled := false;
end;
procedure TForm1.IdTelnet1DataAvailable(Sender: TIdTelnet;
const Buffer: TIdBytes);
begin
InterpetBuffer(bytestostring(Buffer));
end;
procedure TForm1.IdTelnet1Disconnected(Sender: TObject);
begin
memo1.Lines.Add('IdTelnet1Disconnected');
end;
procedure TForm1.IdTelnet1Status(ASender: TObject; const AStatus: TIdStatus;
const AStatusText: string);
begin
memo1.Lines.Add('AStatusText: ' + AStatusText);
end;
end.
我希望程序在控制台中 运行 就像 GUI windows 版本本身一样,但我不确定如何使用 indy idTelnet 来解决这个问题。我主要根据我的知识和我在互联网上可以找到的内容(不多)将其转换。我需要以某种方式找出导致它挂起的原因,而不是处理 telnet 消息?
好的,我做了很多研究并找到了一些代码来帮助我使用控制台应用程序。
我知道 Remy Lebeau 说 Teamspeak 不使用 telnet 协议,但我使用它并且工作得很好。
感谢 Tony Caduto 在此网页上的功劳:http://www.44342.com/delphi-f1279-t5081-p1.htm 按照 link 并转到页面底部。搜索 Tony Caduto 的最后回复。
此代码现在有效!
现在我可以通过 WINE 在我的 VPS 运行ning linux 上 运行 这个了!我只是没钱买更贵的 Delphi 版本 运行 它会在 linux 上。我将等到他们为像我这样的小型开发人员发布一个版本,允许我们在 linux 上 运行 delphi 应用程序。在那之前,WINE 才是出路。
编辑:确保你输入 IdTelnet1.TelnetThread.Loop := true;在 IdTelnet1.Connect 之后;或者你得到一个错误。
代码如下:
program TS3bot;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Unit1 in 'Unit1.pas' {DataModule1: TDataModule};
begin
try
DataModule1 := TDataModule1.Create(nil);
with DataModule1 do
try
{ TODO -oUser -cConsole Main : Insert code here }
IdTelnet1.ThreadedEvent := true;
IdTelnet1.Connect;
IdTelnet1.TelnetThread.Loop := true;
while (IdTelnet1.Connected = true) do
begin
Sleep(60);
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
finally
writeln('Program ended.');
freeandnil(DataModule1);
end;
end.
这是另一部分,以防万一它发生了变化:
unit Unit1;
interface
uses
System.SysUtils, System.Classes, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdTelnet, IdGlobal;
type
TDataModule1 = class(TDataModule)
IdTelnet1: TIdTelnet;
procedure IdTelnet1Connected(Sender: TObject);
procedure IdTelnet1DataAvailable(Sender: TIdTelnet; const Buffer: TIdBytes);
procedure IdTelnet1Disconnected(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
private
{ Private declarations }
procedure processCommand(Command : string);
procedure processCommands;
procedure InterpetBuffer(Buffer: string);
public
{ Public declarations }
end;
Const
Elements = (3); //(Elements - 1)
ListOfOnConnectCommands : array [0..Elements] of string =
('login serverquery mypassword',
'use 1',
'clientupdate client_nickname=ServerNickName',
'servernotifyregister event=server');
var
DataModule1: TDataModule1;
BufferNumber: integer = 0;
CommandSent : boolean = false;
CommandOK : boolean = false;
CommandNumber : integer = 0;
implementation
{%CLASSGROUP 'System.Classes.TPersistent'}
{$R *.dfm}
procedure pSplitIT(BreakString, BaseString: string; StringList: TStrings);
var
EndOfCurrentString: byte;
begin
StringList.Clear;
repeat
EndOfCurrentString := Pos(BreakString, BaseString);
if EndOfCurrentString = 0 then
StringList.add(BaseString)
else
StringList.add(Copy(BaseString, 1, EndOfCurrentString - 1));
BaseString := Copy(BaseString, EndOfCurrentString + length(BreakString), length(BaseString) - EndOfCurrentString);
until EndOfCurrentString = 0;
end;
procedure TDataModule1.processCommand(Command : string);
begin
writeln('processCommand: ' + Command);
IdTelnet1.SendString(Command);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
end;
procedure TDataModule1.processCommands;
var
MyString: string;
begin
if CommandNumber <= Elements then
begin
MyString := ListOfOnConnectCommands[CommandNumber];
writeln('processCommands: ' + MyString);
IdTelnet1.SendString(MyString);
IdTelnet1.SendCh(#10);
IdTelnet1.SendCh(#13);
inc(CommandNumber);
//exit;
end;
end;
procedure TDataModule1.InterpetBuffer(Buffer: string);
var
MyTstringlist: Tstringlist;
MyBuffer: string;
I: integer;
clid: integer;
member, legionnaire, enteredGuestChannel: boolean;
begin
enteredGuestChannel := false;
member := false;
legionnaire := false;
inc(BufferNumber);
writeln('---------------------------------------------------------');
writeln('IdTelnet1DataAvailable BufferNumber: ' + BufferNumber.ToString);
writeln('---------------------------------------------------------');
if Pos('notifycliententerview',Buffer)>0 then
begin
writeln('----------------------');
writeln('EXIT notifycliententerview:');
writeln(Buffer);
MyTstringlist := Tstringlist.Create;
MyBuffer := Buffer;
pSplitIT(' ',MyBuffer,MyTstringlist);
writeln('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
writeln(MyTstringlist.Strings[I]);
if MyTstringlist.Strings[I] = 'ctid=45' then
begin
// client entered GUESTS CHANNEL, see if we can move them.
enteredGuestChannel := true;
end;
if Pos('client_servergroups=',MyTstringlist.Strings[I]) > 0 then
begin
if Pos('18',MyTstringlist.Strings[I]) > 0 then
begin
member := true;
end;
if Pos('19',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
if Pos('28',MyTstringlist.Strings[I]) > 0 then
begin
legionnaire := true;
end;
end;
//clid
if Pos('clid=',MyTstringlist.Strings[I]) > 0 then
begin
clid := StrToInt(copy(MyTstringlist.Strings[I],6,high(MyTstringlist.Strings[I])));
end;
end;
writeln('----------------------');
MyTstringlist.Free;
if ( (enteredGuestChannel = true)
and (member = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end
else if ( (enteredGuestChannel = true)
and (legionnaire = true) ) then
begin
processCommand('clientmove clid=' + clid.ToString + ' cid=47');
end;
exit;
end;
// Create Returns in terminal
if Pos(#10#13,Buffer)>0 then
begin
MyTstringlist := Tstringlist.Create;
pSplitIT(#10#13,Buffer,MyTstringlist);
writeln('COUNT: ' + MyTstringlist.Count.ToString);
for I := 0 to MyTstringlist.Count - 1 do
begin
writeln(MyTstringlist.Strings[I]);
end;
MyTstringlist.Free;
end
else
begin
writeln(Buffer);
end;
if Pos('error id=0 msg=ok',Buffer)>0 then
begin
processCommands;
end;
writeln('');
end;
procedure TDataModule1.DataModuleDestroy(Sender: TObject);
begin
processCommand('logout');
processCommand('quit');
IdTelnet1.Disconnect(true);
end;
procedure TDataModule1.IdTelnet1Connected(Sender: TObject);
begin
writeln('IdTelnet1Connected');
sleep(5000);
writeln('processCommands:');
processCommands;
end;
procedure TDataModule1.IdTelnet1DataAvailable(Sender: TIdTelnet;
const Buffer: TIdBytes);
begin
InterpetBuffer(bytestostring(Buffer));
end;
procedure TDataModule1.IdTelnet1Disconnected(Sender: TObject);
begin
writeln('IdTelnet1Disconnected');
end;
end.