2941 lines
112 KiB
Plaintext
2941 lines
112 KiB
Plaintext
|
{
|
||
|
$Project$
|
||
|
$Workfile$
|
||
|
$Revision$
|
||
|
$DateUTC$
|
||
|
$Id$
|
||
|
|
||
|
This file is part of the Indy (Internet Direct) project, and is offered
|
||
|
under the dual-licensing agreement described on the Indy website.
|
||
|
(http://www.indyproject.org/)
|
||
|
|
||
|
Copyright:
|
||
|
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
|
||
|
}
|
||
|
{
|
||
|
$Log$
|
||
|
}
|
||
|
{
|
||
|
2003-11-Jul:
|
||
|
Original author: Sergio Perry
|
||
|
Matthew Elzer - bug fixes & modifications
|
||
|
}
|
||
|
|
||
|
unit IdIRC;
|
||
|
|
||
|
{
|
||
|
Based on TIRCClient component by Steve Williams (stevewilliams@kromestudios.com)
|
||
|
ported to Indy by Daaron Dwyer (ddwyer@ncic.com)
|
||
|
}
|
||
|
|
||
|
{ Based on RFC 2812 }
|
||
|
|
||
|
interface
|
||
|
|
||
|
{$i IdCompilerDefines.inc}
|
||
|
|
||
|
uses
|
||
|
Classes,
|
||
|
IdAssignedNumbers, IdContext, IdCmdTCPClient, IdCommandHandlers,
|
||
|
IdIOHandler, IdGlobal, IdException;
|
||
|
|
||
|
type
|
||
|
TIdIRC = class;
|
||
|
|
||
|
TIdIRCUserMode = (amAway, amInvisible, amWallops, amRestricted, amOperator, amLocalOperator, amReceiveServerNotices);
|
||
|
TIdIRCUserModes = set of TIdIRCUserMode;
|
||
|
|
||
|
TIdIRCStat = (stServerConnectionsList, stCommandUsageCount, stOperatorList, stUpTime);
|
||
|
|
||
|
{ -WELCOME- }
|
||
|
TIdIRCServerMsgEvent = procedure(ASender: TIdContext; const AMsg: String) of object;
|
||
|
TIdIRCMyInfoEvent = procedure(ASender: TIdContext; const AServer, AVersion, AUserModes, AChanModes, AExtra: String) of object;
|
||
|
TIdIRCBounceEvent = procedure(ASender: TIdContext; const AHost: String; APort: Integer; const AInfo: String) of object;
|
||
|
TIdIRCISupportEvent = procedure(ASender: TIdContext; AParameters: TStrings) of object;
|
||
|
{ -PING- }
|
||
|
TIdIRCPingPongEvent = procedure(ASender: TIdContext) of object;
|
||
|
{ -MESSAGE- }
|
||
|
TIdIRCPrivMessageEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATarget, AMessage: String) of object;
|
||
|
{ -NOTICE- }
|
||
|
TIdIRCNoticeEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATarget, ANotice: String) of object;
|
||
|
{ -REHASH- }
|
||
|
TIdIRCRehashEvent = procedure(ASender: TIdContext; const ANickname, AHost: String) of object;
|
||
|
{ -SUMMON- }
|
||
|
TIdIRCSummonEvent = procedure(ASender: TIdContext; const ANickname, AHost: String) of object;
|
||
|
{ -WALLOPS- }
|
||
|
TIdIRCWallopsEvent = procedure(ASender: TIdContext; const ANickname, AHost, AMessage: String) of object;
|
||
|
{ -ISON- }
|
||
|
TIdIRCIsOnIRCEvent = procedure(ASender: TIdContext; const ANickname, AHost: String) of object;
|
||
|
{ -AWAY- }
|
||
|
TIdIRCAwayEvent = procedure(ASender: TIdContext; const ANickname, AHost, AAwayMessage: String; UserAway: Boolean) of object;
|
||
|
{ -JOIN- }
|
||
|
TIdIRCJoinEvent = procedure(ASender: TIdContext; const ANickname, AHost, AChannel: String) of object;
|
||
|
{ -PART- }
|
||
|
TIdIRCPartEvent = procedure(ASender: TIdContext; const ANickname, AHost, AChannel, APartMessage: String) of object;
|
||
|
{ -TOPIC- }
|
||
|
TIdIRCTopicEvent = procedure(ASender: TIdContext; const ANickname, AHost, AChannel, ATopic: String) of object;
|
||
|
{ -KICK- }
|
||
|
TIdIRCKickEvent = procedure(ASender: TIdContext; const ANickname, AHost, AChannel, ATarget, AReason: String) of object;
|
||
|
{ -MOTD- }
|
||
|
TIdIRCMOTDEvent = procedure(ASender: TIdContext; AMOTD: TStrings) of object;
|
||
|
{ -TRACE- }
|
||
|
TIdIRCServerTraceEvent = procedure(ASender: TIdContext; ATraceInfo: TStrings) of object;
|
||
|
{ -OPER- }
|
||
|
TIdIRCOpEvent = procedure(ASender: TIdContext; const ANickname, AChannel, AHost: String) of object;
|
||
|
{ -INV- }
|
||
|
TIdIRCInvitingEvent = procedure(ASender: TIdContext; const ANickname, AHost: String) of object;
|
||
|
TIdIRCInviteEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATarget, AChannel: String) of object;
|
||
|
{ -LIST- }
|
||
|
TIdIRCChanBANListEvent = procedure(ASender: TIdContext; const AChannel: String; ABanList: TStrings) of object;
|
||
|
TIdIRCChanEXCListEvent = procedure(ASender: TIdContext; const AChannel: String; AExceptList: TStrings) of object;
|
||
|
TIdIRCChanINVListEvent = procedure(ASender: TIdContext; const AChannel: String; AInviteList: TStrings) of object;
|
||
|
TIdIRCServerListEvent = procedure(ASender: TIdContext; AServerList: TStrings) of object;
|
||
|
TIdIRCNickListEvent = procedure(ASender: TIdContext; const AChannel: String; ANicknameList: TStrings) of object;
|
||
|
{ -STATS- }
|
||
|
TIdIRCServerUsersEvent = procedure(ASender: TIdContext; AUsers: TStrings) of object;
|
||
|
TIdIRCServerStatsEvent = procedure(ASender: TIdContext; AStatus: TStrings) of object;
|
||
|
TIdIRCKnownServerNamesEvent = procedure(ASender: TIdContext; AKnownServers: TStrings) of object;
|
||
|
{ -INFO- }
|
||
|
TIdIRCAdminInfoRecvEvent = procedure(ASender: TIdContext; AAdminInfo: TStrings) of object;
|
||
|
TIdIRCUserInfoRecvEvent = procedure(ASender: TIdContext; const AUserInfo: String) of object;
|
||
|
{ -WHO- }
|
||
|
TIdIRCWhoEvent = procedure(ASender: TIdContext; AWhoResults: TStrings) of object;
|
||
|
TIdIRCWhoIsEvent = procedure(ASender: TIdContext; AWhoIsResults: TStrings) of object;
|
||
|
TIdIRCWhoWasEvent = procedure(ASender: TIdContext; AWhoWasResults: TStrings) of object;
|
||
|
{ Mode }
|
||
|
TIdIRCChanModeEvent = procedure(ASender: TIdContext; const ANickname, AHost, AChannel, AMode, AParams: String) of object;
|
||
|
TIdIRCUserModeEvent = procedure(ASender: TIdContext; const ANickname, AHost, AMode: String) of object;
|
||
|
{ -CTCP- }
|
||
|
TIdIRCCTCPQueryEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATarget, ACommand, AParams: String) of object;
|
||
|
TIdIRCCTCPReplyEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATarget, ACommand, AParams: String) of object;
|
||
|
{ -DCC- }
|
||
|
TIdIRCDCCChatEvent = procedure(ASender: TIdContext; const ANickname, AHost: String; APort: Integer) of object;
|
||
|
TIdIRCDCCSendEvent = procedure(ASender: TIdContext; const ANickname, AHost, AFilename: String; APort: TIdPort; AFileSize: Int64) of object;
|
||
|
TIdIRCDCCResumeEvent = procedure(ASender: TIdContext; const ANickname, AHost, AFilename: String; APort: TIdPort; AFilePos: Int64) of object;
|
||
|
TIdIRCDCCAcceptEvent = procedure(ASender: TIdContext; const ANickname, AHost, AFilename: String; APort: TIdPort; AFilePos: Int64) of object;
|
||
|
{ -Errors- }
|
||
|
TIdIRCServerErrorEvent = procedure(ASender: TIdContext; AErrorCode: Integer; const AErrorMessage: String) of object;
|
||
|
TIdIRCNickErrorEvent = procedure(ASender: TIdContext; AError: Integer) of object;
|
||
|
TIdIRCKillErrorEvent = procedure(ASender: TIdContext) of object;
|
||
|
{ Other }
|
||
|
TIdIRCNicknameChangedEvent = procedure(ASender: TIdContext; const AOldNickname, AHost, ANewNickname: String) of object;
|
||
|
TIdIRCKillEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATargetNickname, AReason: String) of object;
|
||
|
TIdIRCQuitEvent = procedure(ASender: TIdContext; const ANickname, AHost, AReason: String) of object;
|
||
|
TIdIRCSvrQuitEvent = procedure(ASender: TIdContext; const ANickname, AHost, AServer, AReason: String) of object;
|
||
|
TIdIRCSvrTimeEvent = procedure(ASender: TIdContext; const AHost, ATime: String) of object;
|
||
|
TIdIRCServiceEvent = procedure(ASender: TIdContext) of object;
|
||
|
TIdIRCSvrVersionEvent = procedure(ASender: TIdContext; const AVersion, AHost, AComments: String) of object;
|
||
|
TIdIRCRawEvent = procedure(ASender: TIdContext; AIn: Boolean; const AMessage: String) of object;
|
||
|
|
||
|
EIdIRCError = class(EIdException);
|
||
|
|
||
|
TIdIRCReplies = class(TPersistent)
|
||
|
protected
|
||
|
FFinger: String;
|
||
|
FVersion: String;
|
||
|
FUserInfo: String;
|
||
|
FClientInfo: String;
|
||
|
public
|
||
|
constructor Create;
|
||
|
procedure Assign(Source: TPersistent); override;
|
||
|
published
|
||
|
property Finger: String read FFinger write FFinger;
|
||
|
property Version: String read FVersion write FVersion;
|
||
|
property UserInfo: String read FUserInfo write FUserInfo;
|
||
|
property ClientInfo: String read FClientInfo write FClientInfo;
|
||
|
end;
|
||
|
|
||
|
TIdIRC = class(TIdCmdTCPClient)
|
||
|
protected
|
||
|
FNickname: String;
|
||
|
FAltNickname: String;
|
||
|
FAltNickUsed: Boolean;
|
||
|
//
|
||
|
FUsername: String;
|
||
|
FRealName: String;
|
||
|
FPassword: String;
|
||
|
FUserMode: TIdIRCUserModes;
|
||
|
FUserAway: Boolean;
|
||
|
FReplies: TIdIRCReplies;
|
||
|
//
|
||
|
FSenderNick: String;
|
||
|
FSenderHost: String;
|
||
|
//
|
||
|
FBans: TStrings;
|
||
|
FExcepts: TStrings;
|
||
|
FInvites: TStrings;
|
||
|
FLinks: TStrings;
|
||
|
FMotd: TStrings;
|
||
|
FNames: TStrings;
|
||
|
FWho: TStrings;
|
||
|
FWhoIs: TStrings;
|
||
|
FWhoWas: TStrings;
|
||
|
FSvrList: TStrings;
|
||
|
FUsers: TStrings;
|
||
|
//
|
||
|
FOnSWelcome: TIdIRCServerMsgEvent;
|
||
|
FOnYourHost: TIdIRCServerMsgEvent;
|
||
|
FOnSCreated: TIdIRCServerMsgEvent;
|
||
|
FOnMyInfo: TIdIRCMyInfoEvent;
|
||
|
FOnBounce: TIdIRCBounceEvent;
|
||
|
FOnISupport: TIdIRCISupportEvent;
|
||
|
FOnSError: TIdIRCServerMsgEvent;
|
||
|
FOnPingPong: TIdIRCPingPongEvent;
|
||
|
FOnPrivMessage: TIdIRCPrivMessageEvent;
|
||
|
FOnNotice: TIdIRCNoticeEvent;
|
||
|
FOnRehash: TIdIRCRehashEvent;
|
||
|
FOnSummon: TIdIRCSummonEvent;
|
||
|
FOnWallops: TIdIRCWallopsEvent;
|
||
|
FOnIsOnIRC: TIdIRCIsOnIRCEvent;
|
||
|
FOnAway: TIdIRCAwayEvent;
|
||
|
FOnJoin: TIdIRCJoinEvent;
|
||
|
FOnPart: TIdIRCPartEvent;
|
||
|
FOnTopic: TIdIRCTopicEvent;
|
||
|
FOnKick: TIdIRCKickEvent;
|
||
|
FOnMOTD: TIdIRCMOTDEvent;
|
||
|
FOnTrace: TIdIRCServerTraceEvent;
|
||
|
FOnOp: TIdIRCOpEvent;
|
||
|
FOnInviting: TIdIRCInvitingEvent;
|
||
|
FOnInvite: TIdIRCInviteEvent;
|
||
|
FOnBANList: TIdIRCChanBANListEvent;
|
||
|
FOnEXCList: TIdIRCChanEXCListEvent;
|
||
|
FOnINVList: TIdIRCChanINVListEvent;
|
||
|
FOnSvrList: TIdIRCServerListEvent;
|
||
|
FOnNickList: TIdIRCNickListEvent;
|
||
|
FOnSvrUsers: TIdIRCServerUsersEvent;
|
||
|
FOnSvrStats: TIdIRCServerStatsEvent;
|
||
|
FOnKnownSvrs: TIdIRCKnownServerNamesEvent;
|
||
|
FOnAdminInfo: TIdIRCAdminInfoRecvEvent;
|
||
|
FOnUserInfo: TIdIRCUserInfoRecvEvent;
|
||
|
FOnWho: TIdIRCWhoEvent;
|
||
|
FOnWhoIs: TIdIRCWhoIsEvent;
|
||
|
FOnWhoWas: TIdIRCWhoWasEvent;
|
||
|
FOnChanMode: TIdIRCChanModeEvent;
|
||
|
FOnUserMode: TIdIRCUserModeEvent;
|
||
|
FOnCTCPQry: TIdIRCCTCPQueryEvent;
|
||
|
FOnCTCPRep: TIdIRCCTCPReplyEvent;
|
||
|
FOnDCCChat: TIdIRCDCCChatEvent;
|
||
|
FOnDCCSend: TIdIRCDCCSendEvent;
|
||
|
FOnDCCResume: TIdIRCDCCResumeEvent;
|
||
|
FOnDCCAccept: TIdIRCDCCAcceptEvent;
|
||
|
FOnServerError: TIdIRCServerErrorEvent;
|
||
|
FOnNickError: TIdIRCNickErrorEvent;
|
||
|
FOnKillError: TIdIRCKillErrorEvent;
|
||
|
FOnNickChange: TIdIRCNicknameChangedEvent;
|
||
|
FOnKill: TIdIRCKillEvent;
|
||
|
FOnQuit: TIdIRCQuitEvent;
|
||
|
FOnSvrQuit: TIdIRCSvrQuitEvent;
|
||
|
FOnSvrTime: TIdIRCSvrTimeEvent;
|
||
|
FOnService: TIdIRCServiceEvent;
|
||
|
FOnSvrVersion: TIdIRCSvrVersionEvent;
|
||
|
FOnRaw: TIdIRCRawEvent;
|
||
|
//
|
||
|
function GetUsedNickname: String;
|
||
|
procedure SetNickname(const AValue: String);
|
||
|
procedure SetUsername(const AValue: String);
|
||
|
procedure SetIdIRCUserMode(AValue: TIdIRCUserModes);
|
||
|
procedure SetIdIRCReplies(AValue: TIdIRCReplies);
|
||
|
function GetUserMode: String;
|
||
|
procedure ParseDCC(AContext: TIdContext; const ADCC: String);
|
||
|
//Command handlers
|
||
|
procedure DoBeforeCmd(ASender: TIdCommandHandlers; var AData: string; AContext: TIdContext);
|
||
|
procedure DoReplyUnknownCommand(AContext: TIdContext; ALine: string); override;
|
||
|
procedure DoBounce(ASender: TIdCommand; ALegacy: Boolean);
|
||
|
procedure CommandPRIVMSG(ASender: TIdCommand);
|
||
|
procedure CommandNOTICE(ASender: TIdCommand);
|
||
|
procedure CommandJOIN(ASender: TIdCommand);
|
||
|
procedure CommandPART(ASender: TIdCommand);
|
||
|
procedure CommandKICK(ASender: TIdCommand);
|
||
|
procedure CommandMODE(ASender: TIdCommand);
|
||
|
procedure CommandNICK(ASender: TIdCommand);
|
||
|
procedure CommandQUIT(ASender: TIdCommand);
|
||
|
procedure CommandSQUIT(ASender: TIdCommand);
|
||
|
procedure CommandINVITE(ASender: TIdCommand);
|
||
|
procedure CommandKILL(ASender: TIdCommand);
|
||
|
procedure CommandPING(ASender: TIdCommand);
|
||
|
procedure CommandERROR(ASender: TIdCommand);
|
||
|
procedure CommandWALLOPS(ASender: TIdCommand);
|
||
|
procedure CommandTOPIC(ASender: TIdCommand);
|
||
|
procedure CommandWELCOME(ASender: TIdCommand);
|
||
|
procedure CommandYOURHOST(ASender: TIdCommand);
|
||
|
procedure CommandCREATED(ASender: TIdCommand);
|
||
|
procedure CommandMYINFO(ASender: TIdCommand);
|
||
|
procedure CommandISUPPORT(ASender: TIdCommand);
|
||
|
procedure CommandBOUNCE(ASender: TIdCommand);
|
||
|
procedure CommandUSERHOST(ASender: TIdCommand);
|
||
|
procedure CommandISON(ASender: TIdCommand);
|
||
|
procedure CommandWHOIS(ASender: TIdCommand);
|
||
|
procedure CommandENDOFWHOIS(ASender: TIdCommand);
|
||
|
procedure CommandWHOWAS(ASender: TIdCommand);
|
||
|
procedure CommandENDOFWHOWAS(ASender: TIdCommand);
|
||
|
procedure CommandLISTSTART(ASender: TIdCommand);
|
||
|
procedure CommandLIST(ASender: TIdCommand);
|
||
|
procedure CommandLISTEND(ASender: TIdCommand);
|
||
|
procedure CommandAWAY(ASender: TIdCommand);
|
||
|
procedure CommandINVITING(ASender: TIdCommand);
|
||
|
procedure CommandSUMMONING(ASender: TIdCommand);
|
||
|
procedure CommandINVITELIST(ASender: TIdCommand);
|
||
|
procedure CommandENDOFINVITELIST(ASender: TIdCommand);
|
||
|
procedure CommandEXCEPTLIST(ASender: TIdCommand);
|
||
|
procedure CommandENDOFEXCEPTLIST(ASender: TIdCommand);
|
||
|
procedure CommandWHOREPLY(ASender: TIdCommand);
|
||
|
procedure CommandENDOFWHO(ASender: TIdCommand);
|
||
|
procedure CommandNAMEREPLY(ASender: TIdCommand);
|
||
|
procedure CommandENDOFNAMES(ASender: TIdCommand);
|
||
|
procedure CommandLINKS(ASender: TIdCommand);
|
||
|
procedure CommandENDOFLINKS(ASender: TIdCommand);
|
||
|
procedure CommandBANLIST(ASender: TIdCommand);
|
||
|
procedure CommandENDOFBANLIST(ASender: TIdCommand);
|
||
|
procedure CommandINFO(ASender: TIdCommand);
|
||
|
procedure CommandENDOFINFO(ASender: TIdCommand);
|
||
|
procedure CommandMOTD(ASender: TIdCommand);
|
||
|
procedure CommandENDOFMOTD(ASender: TIdCommand);
|
||
|
procedure CommandREHASHING(ASender: TIdCommand);
|
||
|
procedure CommandUSERSSTART(ASender: TIdCommand);
|
||
|
procedure CommandUSERS(ASender: TIdCommand);
|
||
|
procedure CommandENDOFUSERS(ASender: TIdCommand);
|
||
|
procedure CommandENDOFSTATS(ASender: TIdCommand);
|
||
|
procedure CommandSERVLIST(ASender: TIdCommand);
|
||
|
procedure CommandSERVLISTEND(ASender: TIdCommand);
|
||
|
procedure CommandTIME(ASender: TIdCommand);
|
||
|
procedure CommandSERVICE(ASender: TIdCommand);
|
||
|
procedure CommandVERSION(ASender: TIdCommand);
|
||
|
procedure CommandCHANMODE(ASender: TIdCommand);
|
||
|
procedure CommandOPER(ASender: TIdCommand);
|
||
|
procedure CommandNICKINUSE(ASender: TIdCommand);
|
||
|
//
|
||
|
procedure AssignIRCClientCommands;
|
||
|
function GetCmdHandlerClass: TIdCommandHandlerClass; override;
|
||
|
procedure SetIOHandler(AValue: TIdIOHandler); override;
|
||
|
procedure InitComponent; override;
|
||
|
public
|
||
|
destructor Destroy; override;
|
||
|
//
|
||
|
procedure Connect; override;
|
||
|
procedure Disconnect(const AReason: String = ''); reintroduce;
|
||
|
//
|
||
|
function IsChannel(const AChannel: String): Boolean;
|
||
|
function IsOp(const ANickname: String): Boolean;
|
||
|
function IsVoice(const ANickname: String): Boolean;
|
||
|
procedure Raw(const ALine: String);
|
||
|
procedure Say(const ATarget, AMsg: String);
|
||
|
procedure Notice(const ATarget, AMsg: String);
|
||
|
procedure Action(const ATarget, AMsg: String);
|
||
|
procedure CTCPQuery(const ATarget, ACommand, AParameters: String);
|
||
|
procedure CTCPReply(const ATarget, ACTCP, AReply: String);
|
||
|
procedure Join(const AChannel: String; const AKey: String ='');
|
||
|
procedure Part(const AChannel: String; const AReason: String = '');
|
||
|
procedure Kick(const AChannel, ANickname: String; const AReason: String = '');
|
||
|
procedure SetChannelMode(const AChannel, AMode: String; const AParams: String = '');
|
||
|
procedure SetUserMode(const ANickname, AMode: String);
|
||
|
procedure GetChannelTopic(const AChannel: String);
|
||
|
procedure SetChannelTopic(const AChannel, ATopic: String);
|
||
|
procedure SetAway(const AMsg: String);
|
||
|
procedure Op(const AChannel, ANickname: String);
|
||
|
procedure Deop(const AChannel, ANickname: String);
|
||
|
procedure Voice(const AChannel, ANickname: String);
|
||
|
procedure Devoice(const AChannel, ANickname: String);
|
||
|
procedure Ban(const AChannel, AHostmask: String);
|
||
|
procedure Unban(const AChannel, AHostmask: String);
|
||
|
procedure RegisterService(const ANickname, ADistribution, AInfo: String; AType: Integer);
|
||
|
procedure ListChannelNicknames(const AChannel: String; const ATarget: String = '');
|
||
|
procedure ListChannel(const AChannel: String; const ATarget: String = '');
|
||
|
procedure Invite(const ANickname, AChannel: String);
|
||
|
procedure GetMessageOfTheDay(const ATarget: String = '');
|
||
|
procedure GetNetworkStatus(const AHostMask: String = ''; const ATarget: String = '');
|
||
|
procedure GetServerVersion(const ATarget: String = '');
|
||
|
procedure GetServerStatus(AQuery: TIdIRCStat; const ATarget: String = '');
|
||
|
procedure ListKnownServerNames(const ARemoteHost: String = ''; const AHostMask: String = '');
|
||
|
procedure QueryServerTime(const ATarget: String = '');
|
||
|
procedure RequestServerConnect(const ATargetHost: String; APort: Integer; const ARemoteHost: String = '');
|
||
|
procedure TraceServer(const ATarget: String = '');
|
||
|
procedure GetAdminInfo(const ATarget: String = '');
|
||
|
procedure GetServerInfo(const ATarget: String = '');
|
||
|
procedure ListNetworkServices(const AHostMask: String = ''; const AType: String = '');
|
||
|
procedure QueryService(const AServiceName, AMessage: String);
|
||
|
procedure Who(const AMask: String; AOnlyAdmins: Boolean);
|
||
|
procedure WhoIs(const AMask: String; const ATarget: String = '');
|
||
|
procedure WhoWas(const ANickname: String; ACount: Integer = -1; const ATarget: String = '');
|
||
|
procedure Kill(const ANickname, AComment: String);
|
||
|
procedure Ping(const AServer1: String; const AServer2: String = '');
|
||
|
procedure Pong(const AServer1: String; const AServer2: String = '');
|
||
|
procedure Error(const AMessage: String);
|
||
|
procedure ReHash;
|
||
|
procedure Die;
|
||
|
procedure Restart;
|
||
|
procedure Summon(const ANickname: String; const ATarget: String = ''; const AChannel: String = '');
|
||
|
procedure ListServerUsers(const ATarget: String = '');
|
||
|
procedure SayWALLOPS(const AMessage: String);
|
||
|
procedure GetUserInfo(const ANickname: String);
|
||
|
procedure GetUsersInfo(const ANicknames: array of String);
|
||
|
procedure IsOnIRC(const ANickname: String); overload;
|
||
|
procedure IsOnIRC(const ANicknames: array of String); overload;
|
||
|
procedure BecomeOp(const ANickname, APassword: String);
|
||
|
procedure SQuit(const AHost, AComment: String);
|
||
|
procedure SetChannelLimit(const AChannel: String; ALimit: Integer);
|
||
|
procedure SetChannelKey(const AChannel, AKey: String);
|
||
|
//
|
||
|
property Away: Boolean read FUserAway;
|
||
|
published
|
||
|
property Nickname: String read FNickname write SetNickname;
|
||
|
property AltNickname: String read FAltNickname write FAltNickname;
|
||
|
property UsedNickname: String read GetUsedNickname; // returns Nickname or AltNickname
|
||
|
property Username: String read FUsername write SetUsername;
|
||
|
property RealName: String read FRealName write FRealName;
|
||
|
property Password: String read FPassword write FPassword;
|
||
|
property Port default IdPORT_IRC;
|
||
|
property Replies: TIdIRCReplies read FReplies write SetIdIRCReplies;
|
||
|
property UserMode: TIdIRCUserModes read FUserMode write SetIdIRCUserMode;
|
||
|
{ Events }
|
||
|
property OnServerWelcome: TIdIRCServerMsgEvent read FOnSWelcome write FOnSWelcome;
|
||
|
property OnYourHost: TIdIRCServerMsgEvent read FOnYourHost write FOnYourHost;
|
||
|
property OnServerCreated: TIdIRCServerMsgEvent read FOnSCreated write FOnSCreated;
|
||
|
property OnMyInfo: TIdIRCMyInfoEvent read FOnMyInfo write FOnMyInfo;
|
||
|
property OnBounce: TIdIRCBounceEvent read FOnBounce write FOnBounce;
|
||
|
property OnISupport: TIdIRCISupportEvent read FOnISupport write FOnISupport;
|
||
|
property OnPingPong: TIdIRCPingPongEvent read FOnPingPong write FOnPingPong;
|
||
|
property OnPrivateMessage: TIdIRCPrivMessageEvent read FOnPrivMessage write FOnPrivMessage;
|
||
|
property OnNotice: TIdIRCNoticeEvent read FOnNotice write FOnNotice;
|
||
|
property OnRehash: TIdIRCRehashEvent read FOnRehash write FOnRehash;
|
||
|
property OnSummon: TIdIRCSummonEvent read FOnSummon write FOnSummon;
|
||
|
property OnWallops: TIdIRCWallopsEvent read FOnWallops write FOnWallops;
|
||
|
property OnIsOnIRC: TIdIRCIsOnIRCEvent read FOnIsOnIRC write FOnIsOnIRC;
|
||
|
property OnAway: TIdIRCAwayEvent read FOnAway write FOnAway;
|
||
|
property OnJoin: TIdIRCJoinEvent read FOnJoin write FOnJoin;
|
||
|
property OnPart: TIdIRCPartEvent read FOnPart write FOnPart;
|
||
|
property OnTopic: TIdIRCTopicEvent read FOnTopic write FOnTopic;
|
||
|
property OnKick: TIdIRCKickEvent read FOnKick write FOnKick;
|
||
|
property OnMOTD: TIdIRCMOTDEvent read FOnMOTD write FOnMOTD;
|
||
|
property OnTrace: TIdIRCServerTraceEvent read FOnTrace write FOnTrace;
|
||
|
property OnOp: TIdIRCOpEvent read FOnOp write FOnOp;
|
||
|
property OnInviting: TIdIRCInvitingEvent read FOnInviting write FOnInviting;
|
||
|
property OnInvite: TIdIRCInviteEvent read FOnInvite write FOnInvite;
|
||
|
property OnBanListReceived: TIdIRCChanBANListEvent read FOnBANList write FOnBANList;
|
||
|
property OnExceptionListReceived: TIdIRCChanEXCListEvent read FOnEXCList write FOnEXCList;
|
||
|
property OnInvitationListReceived: TIdIRCChanINVListEvent read FOnINVList write FOnINVList;
|
||
|
property OnServerListReceived: TIdIRCServerListEvent read FOnSvrList write FOnSvrList;
|
||
|
property OnNicknamesListReceived: TIdIRCNickListEvent read FOnNickList write FOnNickList;
|
||
|
property OnServerUsersListReceived: TIdIRCServerUsersEvent read FOnSvrUsers write FOnSvrUsers;
|
||
|
property OnServerStatsReceived: TIdIRCServerStatsEvent read FOnSvrStats write FOnSvrStats;
|
||
|
property OnKnownServersListReceived: TIdIRCKnownServerNamesEvent read FOnKnownSvrs write FOnKnownSvrs;
|
||
|
property OnAdminInfoReceived: TIdIRCAdminInfoRecvEvent read FOnAdminInfo write FOnAdminInfo;
|
||
|
property OnUserInfoReceived: TIdIRCUserInfoRecvEvent read FOnUserInfo write FOnUserInfo;
|
||
|
property OnWho: TIdIRCWhoEvent read FOnWho write FOnWho;
|
||
|
property OnWhoIs: TIdIRCWhoIsEvent read FOnWhoIs write FOnWhoIs;
|
||
|
property OnWhoWas: TIdIRCWhoWasEvent read FOnWhoWas write FOnWhoWas;
|
||
|
property OnChannelMode: TIdIRCChanModeEvent read FOnChanMode write FOnChanMode;
|
||
|
property OnUserMode: TIdIRCUserModeEvent read FOnUserMode write FOnUserMode;
|
||
|
property OnCTCPQuery: TIdIRCCTCPQueryEvent read FOnCTCPQry write FOnCTCPQry;
|
||
|
property OnCTCPReply: TIdIRCCTCPReplyEvent read FOnCTCPRep write FOnCTCPRep;
|
||
|
property OnDCCChat: TIdIRCDCCChatEvent read FOnDCCChat write FOnDCCChat;
|
||
|
property OnDCCSend: TIdIRCDCCSendEvent read FOnDCCSend write FOnDCCSend;
|
||
|
property OnDCCResume: TIdIRCDCCResumeEvent read FOnDCCResume write FOnDCCResume;
|
||
|
property OnDCCAccept: TIdIRCDCCAcceptEvent read FOnDCCAccept write FOnDCCAccept;
|
||
|
property OnServerError: TIdIRCServerErrorEvent read FOnServerError write FOnServerError;
|
||
|
property OnNicknameError: TIdIRCNickErrorEvent read FOnNickError write FOnNickError;
|
||
|
property OnKillError: TIdIRCKillErrorEvent read FOnKillError write FOnKillError;
|
||
|
property OnNicknameChange: TIdIRCNicknameChangedEvent read FOnNickChange write FOnNickChange;
|
||
|
property OnKill: TIdIRCKillEvent read FOnKill write FOnKill;
|
||
|
property OnQuit: TIdIRCQuitEvent read FOnQuit write FOnQuit;
|
||
|
property OnServerQuit: TIdIRCSvrQuitEvent read FOnSvrQuit write FOnSvrQuit;
|
||
|
property OnServerTime: TIdIRCSvrTimeEvent read FOnSvrTime write FOnSvrTime;
|
||
|
property OnService: TIdIRCServiceEvent read FOnService write FOnService;
|
||
|
property OnServerVersion: TIdIRCSvrVersionEvent read FOnSvrVersion write FOnSvrVersion;
|
||
|
property OnRaw: TIdIRCRawEvent read FOnRaw write FOnRaw;
|
||
|
end;
|
||
|
|
||
|
implementation
|
||
|
|
||
|
uses
|
||
|
IdGlobalProtocols, IdResourceStringsProtocols, IdSSL,
|
||
|
IdStack, IdBaseComponent, SysUtils;
|
||
|
|
||
|
const
|
||
|
IdIRCCTCP: array[0..11] of String = ('ACTION', 'SOUND', 'PING', 'FINGER', {do not localize}
|
||
|
'USERINFO', 'VERSION', 'CLIENTINFO', 'TIME', 'ERROR', 'DCC', 'SED', 'ERRMSG'); {do not localize}
|
||
|
|
||
|
MQuote = #16;
|
||
|
XDelim = #1;
|
||
|
XQuote = #92;
|
||
|
|
||
|
{ TIdIRCReplies }
|
||
|
|
||
|
constructor TIdIRCReplies.Create;
|
||
|
begin
|
||
|
inherited Create;
|
||
|
//
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRCReplies.Assign(Source: TPersistent);
|
||
|
var
|
||
|
LSource: TIdIRCReplies;
|
||
|
begin
|
||
|
if Source is TIdIRCReplies then
|
||
|
begin
|
||
|
LSource := TIdIRCReplies(Source);
|
||
|
FFinger := LSource.Finger;
|
||
|
FFinger := LSource.Finger;
|
||
|
FVersion := LSource.Version;
|
||
|
FUserInfo := LSource.UserInfo;
|
||
|
FClientInfo := LSource.ClientInfo;
|
||
|
end else begin
|
||
|
inherited Assign(Source);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{ TIdIRC }
|
||
|
|
||
|
// RLebeau 1/7/2010: SysUtils.TrimLeft() removes all characters < #32, but
|
||
|
// CTC requires character #1, so don't remove that character when parsing
|
||
|
// IRC parameters in FetchIRCParam()...
|
||
|
//
|
||
|
function IRCTrimLeft(const S: string): string;
|
||
|
var
|
||
|
I, L: Integer;
|
||
|
begin
|
||
|
L := Length(S);
|
||
|
I := 1;
|
||
|
while (I <= L) and (S[I] <= ' ') and (S[I] <> XDelim) do begin
|
||
|
Inc(I);
|
||
|
end;
|
||
|
Result := Copy(S, I, Maxint);
|
||
|
end;
|
||
|
|
||
|
function FetchIRCParam(var S: String): String;
|
||
|
var
|
||
|
LTmp: String;
|
||
|
begin
|
||
|
LTmp := IRCTrimLeft(S);
|
||
|
if TextStartsWith(LTmp, ':') then
|
||
|
begin
|
||
|
Result := Copy(LTmp, 2, MaxInt);
|
||
|
S := '';
|
||
|
end else
|
||
|
begin
|
||
|
Result := Fetch(LTmp, ' ');
|
||
|
S := IRCTrimLeft(LTmp);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function IRCQuote(const S: String): String;
|
||
|
begin
|
||
|
// IMPORTANT! MQuote needs to be the first character in the replacement
|
||
|
// list, otherwise it will end up being double-escaped if the other
|
||
|
// character get replaced, which will produce the wrong output!!
|
||
|
Result := StringsReplace(S, [MQuote, #0, LF, CR], [MQuote+MQuote, MQuote+'0', MQuote+'n', MQuote+'r']);
|
||
|
end;
|
||
|
|
||
|
{$IFDEF STRING_IS_IMMUTABLE}
|
||
|
function FindCharInSB(const ASB: TIdStringBuilder; AChar: Char; AStart: Integer): Integer;
|
||
|
begin
|
||
|
for Result := AStart to ASB.Length-1 do begin
|
||
|
if ASB[Result] = AChar then begin
|
||
|
Exit;
|
||
|
end;
|
||
|
end;
|
||
|
Result := -1;
|
||
|
end;
|
||
|
{$ENDIF}
|
||
|
|
||
|
function IRCUnquote(const S: String): String;
|
||
|
var
|
||
|
I, L: Integer;
|
||
|
{$IFDEF STRING_IS_IMMUTABLE}
|
||
|
LSB: TIdStringBuilder;
|
||
|
{$ENDIF}
|
||
|
|
||
|
begin
|
||
|
{$IFDEF STRING_IS_IMMUTABLE}
|
||
|
LSB := TIdStringBuilder.Create(S);
|
||
|
L := LSB.Length;
|
||
|
I := 0;
|
||
|
while I < L do begin
|
||
|
I := FindCharInSB(LSB, MQuote, I);
|
||
|
if I = -1 then begin
|
||
|
Break;
|
||
|
end;
|
||
|
LSB.Remove(I, 1);
|
||
|
Dec(L);
|
||
|
if I >= L then begin
|
||
|
Break;
|
||
|
end;
|
||
|
case LSB[I] of
|
||
|
'0': LSB[I] := #0;
|
||
|
'n': LSB[I] := LF;
|
||
|
'r': LSB[I] := CR;
|
||
|
end;
|
||
|
Inc(I);
|
||
|
end;
|
||
|
Result := LSB.ToString;
|
||
|
{$ELSE}
|
||
|
Result := S;
|
||
|
L := Length(Result);
|
||
|
I := 1;
|
||
|
while I <= L do begin
|
||
|
I := PosIdx(MQuote, Result, I);
|
||
|
if I = 0 then begin
|
||
|
Break;
|
||
|
end;
|
||
|
IdDelete(Result, I, 1);
|
||
|
Dec(L);
|
||
|
if I > L then begin
|
||
|
Break;
|
||
|
end;
|
||
|
case Result[I] of
|
||
|
'0': Result[I] := #0;
|
||
|
'n': Result[I] := LF;
|
||
|
'r': Result[I] := CR;
|
||
|
end;
|
||
|
Inc(I);
|
||
|
end;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
function CTCPQuote(const S: String): String;
|
||
|
begin
|
||
|
Result := StringsReplace(S, [XDelim, XQuote], [XQuote+'a', XQuote+XQuote]);
|
||
|
end;
|
||
|
|
||
|
function CTCPUnquote(const S: String): String;
|
||
|
var
|
||
|
I, L: Integer;
|
||
|
{$IFDEF STRING_IS_IMMUTABLE}
|
||
|
LSB: TIdStringBuilder;
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
{$IFDEF STRING_IS_IMMUTABLE}
|
||
|
LSB := TIdStringBuilder.Create(S);
|
||
|
L := LSB.Length;
|
||
|
I := 0;
|
||
|
while I < L do begin
|
||
|
I := FindCharInSB(LSB, XQuote, I);
|
||
|
if I = -1 then begin
|
||
|
Break;
|
||
|
end;
|
||
|
LSB.Remove(I, 1);
|
||
|
Dec(L);
|
||
|
if I >= L then begin
|
||
|
Break;
|
||
|
end;
|
||
|
if LSB[I] = 'a' then begin
|
||
|
LSB[I] := XDelim;
|
||
|
end;
|
||
|
Inc(I);
|
||
|
end;
|
||
|
Result := LSB.ToString;
|
||
|
{$ELSE}
|
||
|
Result := S;
|
||
|
L := Length(Result);
|
||
|
I := 1;
|
||
|
while I <= L do begin
|
||
|
I := PosIdx(XQuote, Result, I);
|
||
|
if I = 0 then begin
|
||
|
Break;
|
||
|
end;
|
||
|
IdDelete(Result, I, 1);
|
||
|
Dec(L);
|
||
|
if I > L then begin
|
||
|
Break;
|
||
|
end;
|
||
|
if Result[I] = 'a' then begin
|
||
|
Result[I] := XDelim;
|
||
|
end;
|
||
|
Inc(I);
|
||
|
end;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
|
||
|
procedure ExtractCTCPs(var AText: String; CTCPs: TStrings);
|
||
|
var
|
||
|
LTmp: String;
|
||
|
I, J, K: Integer;
|
||
|
begin
|
||
|
I := 1;
|
||
|
repeat
|
||
|
J := PosIdx(XDelim, AText, I);
|
||
|
if J = 0 then begin
|
||
|
Break;
|
||
|
end;
|
||
|
K := PosIdx(XDelim, AText, J+1);
|
||
|
if K = 0 then begin
|
||
|
Break;
|
||
|
end;
|
||
|
LTmp := Copy(AText, J+1, K-J-1);
|
||
|
LTmp := CTCPUnquote(LTmp);
|
||
|
CTCPs.Add(LTmp);
|
||
|
IdDelete(AText, J, (K-J)+1);
|
||
|
I := J;
|
||
|
until False;
|
||
|
end;
|
||
|
|
||
|
type
|
||
|
TIdIRCCommandHandler = class(TIdCommandHandler)
|
||
|
public
|
||
|
procedure DoParseParams(AUnparsedParams: string; AParams: TStrings); override;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRCCommandHandler.DoParseParams(AUnparsedParams: string; AParams: TStrings);
|
||
|
begin
|
||
|
AParams.Clear;
|
||
|
while AUnparsedParams <> '' do begin
|
||
|
AParams.Add(FetchIRCParam(AUnparsedParams));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdIRC.GetCmdHandlerClass: TIdCommandHandlerClass;
|
||
|
begin
|
||
|
Result := TIdIRCCommandHandler;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.InitComponent;
|
||
|
begin
|
||
|
inherited InitComponent;
|
||
|
//
|
||
|
FReplies := TIdIRCReplies.Create;
|
||
|
Port := IdPORT_IRC;
|
||
|
FUserMode := [];
|
||
|
|
||
|
// RLebeau 2/21/08: for the IRC protocol, RFC 2812 section 2.4 says that
|
||
|
// clients are not allowed to issue numeric replies for server-issued
|
||
|
// commands. Added the PerformReplies property so TIdIRC can specify
|
||
|
// that behavior.
|
||
|
CommandHandlers.PerformReplies := False;
|
||
|
|
||
|
// RLebeau 3/11/08: most of the command handlers should parse parameters by default
|
||
|
CommandHandlers.ParseParamsDefault := True;
|
||
|
|
||
|
if not IsDesignTime then begin
|
||
|
AssignIRCClientCommands;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
destructor TIdIRC.Destroy;
|
||
|
begin
|
||
|
FreeAndNil(FReplies);
|
||
|
FreeAndNil(FBans);
|
||
|
FreeAndNil(FExcepts);
|
||
|
FreeAndNil(FInvites);
|
||
|
FreeAndNil(FLinks);
|
||
|
FreeAndNil(FMotd);
|
||
|
FreeAndNil(FNames);
|
||
|
FreeAndNil(FWho);
|
||
|
FreeAndNil(FWhoIs);
|
||
|
FreeAndNil(FWhoWas);
|
||
|
FreeAndNil(FSvrList);
|
||
|
FreeAndNil(FUsers);
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
function TIdIRC.GetUserMode: String;
|
||
|
const
|
||
|
IdIRCUserModeChars: array[TIdIRCUserMode] of Char = ('a', 'i', 'w', 'r', 'o', 'O', 's'); {do not localize}
|
||
|
var
|
||
|
i: TIdIRCUserMode;
|
||
|
begin
|
||
|
if FUserMode <> [] then
|
||
|
begin
|
||
|
Result := '+';
|
||
|
for i := amAway to amReceiveServerNotices do begin
|
||
|
if i in FUserMode then begin
|
||
|
Result := Result + IdIRCUserModeChars[i];
|
||
|
end;
|
||
|
end;
|
||
|
end else begin
|
||
|
Result := '0';
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Connect;
|
||
|
begin
|
||
|
// I doubt that there is explicit SSL support in the IRC protocol
|
||
|
if (IOHandler is TIdSSLIOHandlerSocketBase) then begin
|
||
|
(IOHandler as TIdSSLIOHandlerSocketBase).PassThrough := False;
|
||
|
end;
|
||
|
inherited Connect;
|
||
|
//
|
||
|
try
|
||
|
FAltNickUsed := False;
|
||
|
if FPassword <> '' then begin
|
||
|
Raw(IndyFormat('PASS %s', [FPassword])); {do not localize}
|
||
|
end;
|
||
|
SetNickname(FNickname);
|
||
|
SetUsername(FUsername);
|
||
|
except
|
||
|
on E: EIdSocketError do begin
|
||
|
inherited Disconnect;
|
||
|
IndyRaiseOuterException(EIdIRCError.Create(RSIRCCannotConnect));
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Disconnect(const AReason: String = '');
|
||
|
begin
|
||
|
try
|
||
|
Raw(IndyFormat('QUIT :%s', [AReason])); {do not localize}
|
||
|
finally
|
||
|
inherited Disconnect;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Raw(const ALine: String);
|
||
|
begin
|
||
|
if Connected then begin
|
||
|
if Assigned(FOnRaw) then begin
|
||
|
FOnRaw(nil, False, ALine);
|
||
|
end;
|
||
|
IOHandler.WriteLn(IRCQuote(ALine));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.AssignIRCClientCommands;
|
||
|
var
|
||
|
LCommandHandler: TIdCommandHandler;
|
||
|
begin
|
||
|
{ Text commands }
|
||
|
//PRIVMSG Nickname/#channel :message
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'PRIVMSG'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandPRIVMSG;
|
||
|
LCommandHandler.ParseParams := False;
|
||
|
|
||
|
//NOTICE Nickname/#channel :message
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'NOTICE'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandNOTICE;
|
||
|
LCommandHandler.ParseParams := False;
|
||
|
|
||
|
//JOIN #channel
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'JOIN'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandJOIN;
|
||
|
|
||
|
//PART #channel
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'PART'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandPART;
|
||
|
|
||
|
//KICK #channel target :reason
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'KICK'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandKICK;
|
||
|
|
||
|
//MODE Nickname/#channel +/-modes parameters...
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'MODE'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandMODE;
|
||
|
LCommandHandler.ParseParams := False;
|
||
|
|
||
|
//NICK newNickname
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'NICK'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandNICK;
|
||
|
|
||
|
//QUIT :reason
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'QUIT'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandQUIT;
|
||
|
|
||
|
//SQUIT server :reason
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'SQUIT'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandSQUIT;
|
||
|
|
||
|
//INVITE Nickname :#channel
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'INVITE'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandINVITE;
|
||
|
|
||
|
//KILL Nickname :reason
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'KILL'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandKILL;
|
||
|
|
||
|
//PING server
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'PING'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandPING;
|
||
|
|
||
|
//WALLOPS :message
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'WALLOPS'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandWALLOPS;
|
||
|
LCommandHandler.ParseParams := False;
|
||
|
|
||
|
//TOPIC
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'TOPIC'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandTOPIC;
|
||
|
|
||
|
//ERROR message
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := 'ERROR'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandERROR;
|
||
|
LCommandHandler.ParseParams := False;
|
||
|
|
||
|
{ Numeric commands, refer to http://www.alien.net.au/irc/irc2numerics.html }
|
||
|
//RPL_WELCOME
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '001'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandWELCOME;
|
||
|
LCommandHandler.ParseParams := False;
|
||
|
|
||
|
//RPL_YOURHOST
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '002'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandYOURHOST;
|
||
|
|
||
|
//RPL_CREATED
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '003'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandCREATED;
|
||
|
|
||
|
//RPL_MYINFO
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '004'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandMYINFO;
|
||
|
LCommandHandler.ParseParams := False;
|
||
|
|
||
|
//RPL_BOUNCE (deprecated), RPL_ISUPPORT (new)
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '005'; {do not localize}
|
||
|
//LCommandHandler.OnCommand := CommandBOUNCE; // deprecated
|
||
|
LCommandHandler.OnCommand := CommandISUPPORT;
|
||
|
|
||
|
{ TODO:
|
||
|
008 RPL_SNOMASK ircu Server notice mask (hex)
|
||
|
009 RPL_STATMEMTOT ircu
|
||
|
014 RPL_YOURCOOKIE Hybrid?
|
||
|
042 RPL_YOURID IRCnet
|
||
|
043 RPL_SAVENICK IRCnet :<info> Sent to the client when their nickname was forced to change due to a collision
|
||
|
050 RPL_ATTEMPTINGJUNC aircd
|
||
|
051 RPL_ATTEMPTINGREROUTE aircd
|
||
|
200 RPL_TRACELINK RFC1459 Link <version>[.<debug_level>] <destination> <next_server> [V<protocol_version> <link_uptime_in_seconds> <backstream_sendq> <upstream_sendq>] See RFC
|
||
|
201 RPL_TRACECONNECTING RFC1459 Try. <class> <server> See RFC
|
||
|
202 RPL_TRACEHANDSHAKE RFC1459 H.S. <class> <server> See RFC
|
||
|
203 RPL_TRACEUNKNOWN RFC1459 ???? <class> [<connection_address>] See RFC
|
||
|
204 RPL_TRACEOPERATOR RFC1459 Oper <class> <nick> See RFC
|
||
|
205 RPL_TRACEUSER RFC1459 User <class> <nick> See RFC
|
||
|
206 RPL_TRACESERVER RFC1459 Serv <class> <int>S <int>C <server> <nick!user|*!*>@<host|server> [V<protocol_version>] See RFC
|
||
|
207 RPL_TRACESERVICE RFC2812 Service <class> <name> <type> <active_type> See RFC
|
||
|
208 RPL_TRACENEWTYPE RFC1459 <newtype> 0 <client_name> See RFC
|
||
|
209 RPL_TRACECLASS RFC2812 Class <class> <count> See RFC
|
||
|
210 RPL_TRACERECONNECT RFC2812
|
||
|
210 RPL_STATS aircd Used instead of having multiple stats numerics
|
||
|
211 RPL_STATSLINKINFO RFC1459 <linkname> <sendq> <sent_msgs> <sent_bytes> <recvd_msgs> <rcvd_bytes> <time_open> Reply to STATS (See RFC)
|
||
|
212 RPL_STATSCOMMANDS RFC1459 <command> <count> [<byte_count> <remote_count>] Reply to STATS (See RFC)
|
||
|
213 RPL_STATSCLINE RFC1459 C <host> * <name> <port> <class> Reply to STATS (See RFC)
|
||
|
214 RPL_STATSNLINE RFC1459 N <host> * <name> <port> <class> Reply to STATS (See RFC), Also known as RPL_STATSOLDNLINE (ircu, Unreal)
|
||
|
215 RPL_STATSILINE RFC1459 I <host> * <host> <port> <class> Reply to STATS (See RFC)
|
||
|
216 RPL_STATSKLINE RFC1459 K <host> * <username> <port> <class> Reply to STATS (See RFC)
|
||
|
217 RPL_STATSQLINE RFC1459
|
||
|
217 RPL_STATSPLINE ircu
|
||
|
218 RPL_STATSYLINE
|
||
|
}
|
||
|
// RPL_BOUNCE (new)
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '010'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandBOUNCE;
|
||
|
|
||
|
//RPL_ENDOFSTATS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '219'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFSTATS;
|
||
|
|
||
|
{TODO:
|
||
|
221 RPL_UMODEIS RFC1459 <user_modes> [<user_mode_params>] Information about a user's own modes. Some daemons have extended the mode command and certain modes take parameters (like channel modes).
|
||
|
}
|
||
|
//RPL_SERVLIST
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '234'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandSERVLIST;
|
||
|
|
||
|
//RPL_SERVLISTEND
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '235'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandSERVLISTEND;
|
||
|
|
||
|
{TODO:
|
||
|
236 RPL_STATSVERBOSE ircu Verbose server list?
|
||
|
237 RPL_STATSENGINE ircu Engine name?
|
||
|
239 RPL_STATSIAUTH IRCnet
|
||
|
241 RPL_STATSLLINE RFC1459 L <hostmask> * <servername> <maxdepth> Reply to STATS (See RFC)
|
||
|
242 RPL_STATSUPTIME RFC1459 :Server Up <days> days <hours>:<minutes>:<seconds> Reply to STATS (See RFC)
|
||
|
243 RPL_STATSOLINE RFC1459 O <hostmask> * <nick> [:<info>] Reply to STATS (See RFC); The info field is an extension found in some IRC daemons, which returns info such as an e-mail address or the name/job of an operator
|
||
|
244 RPL_STATSHLINE RFC1459 H <hostmask> * <servername> Reply to STATS (See RFC)
|
||
|
245 RPL_STATSSLINE Bahamut, IRCnet, Hybrid
|
||
|
250 RPL_STATSCONN ircu, Unreal
|
||
|
251 RPL_LUSERCLIENT RFC1459 :There are <int> users and <int> invisible on <int> servers Reply to LUSERS command, other versions exist (eg. RFC2812); Text may vary.
|
||
|
252 RPL_LUSEROP RFC1459 <int> :<info> Reply to LUSERS command - Number of IRC operators online
|
||
|
253 RPL_LUSERUNKNOWN RFC1459 <int> :<info> Reply to LUSERS command - Number of unknown/unregistered connections
|
||
|
254 RPL_LUSERCHANNELS RFC1459 <int> :<info> Reply to LUSERS command - Number of channels formed
|
||
|
255 RPL_LUSERME RFC1459 :I have <int> clients and <int> servers Reply to LUSERS command - Information about local connections; Text may vary.
|
||
|
256 RPL_ADMINME RFC1459 <server> :<info> Start of an RPL_ADMIN* reply. In practise, the server parameter is often never given, and instead the info field contains the text 'Administrative info about <server>'. Newer daemons seem to follow the RFC and output the server's hostname in the 'server' parameter, but also output the server name in the text as per traditional daemons.
|
||
|
257 RPL_ADMINLOC1 RFC1459 :<admin_location> Reply to ADMIN command (Location, first line)
|
||
|
258 RPL_ADMINLOC2 RFC1459 :<admin_location> Reply to ADMIN command (Location, second line)
|
||
|
259 RPL_ADMINEMAIL RFC1459 :<email_address> Reply to ADMIN command (E-mail address of administrator)
|
||
|
261 RPL_TRACELOG RFC1459 File <logfile> <debug_level> See RFC
|
||
|
263 RPL_TRYAGAIN RFC2812 <command> :<info> When a server drops a command without processing it, it MUST use this reply. Also known as RPL_LOAD_THROTTLED and RPL_LOAD2HI, I'm presuming they do the same thing.
|
||
|
265 RPL_LOCALUSERS aircd, Hybrid, Hybrid, Bahamut Also known as RPL_CURRENT_LOCAL
|
||
|
266 RPL_GLOBALUSERS aircd, Hybrid, Hybrid, Bahamut Also known as RPL_CURRENT_GLOBAL
|
||
|
267 RPL_START_NETSTAT aircd
|
||
|
268 RPL_NETSTAT aircd
|
||
|
269 RPL_END_NETSTAT aircd
|
||
|
270 RPL_PRIVS ircu
|
||
|
271 RPL_SILELIST ircu
|
||
|
272 RPL_ENDOFSILELIST ircu
|
||
|
273 RPL_NOTIFY aircd
|
||
|
276 RPL_VCHANEXIST
|
||
|
277 RPL_VCHANLIST
|
||
|
278 RPL_VCHANHELP
|
||
|
280 RPL_GLIST ircu
|
||
|
296 RPL_CHANINFO_KICKS aircd
|
||
|
299 RPL_END_CHANINFO aircd
|
||
|
300 RPL_NONE RFC1459 Dummy reply, supposedly only used for debugging/testing new features, however has appeared in production daemons.
|
||
|
}
|
||
|
//RPL_AWAY
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '301'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandAWAY;
|
||
|
|
||
|
//RPL_USERHOST
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '302'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandUSERHOST;
|
||
|
LCommandHandler.ParseParams := False;
|
||
|
|
||
|
//RPL_ISON
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '303'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandISON;
|
||
|
|
||
|
//RPL_UNAWAY
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '305'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandAWAY;
|
||
|
|
||
|
//RPL_NOWAWAY
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '306'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandAWAY;
|
||
|
|
||
|
//RPL_WHOISUSER
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '311'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandWHOIS;
|
||
|
|
||
|
//RPL_WHOISSERVER
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '312'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandWHOIS;
|
||
|
|
||
|
//RPL_WHOISOPERATOR
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '313'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandWHOIS;
|
||
|
|
||
|
//RPL_WHOWASUSER
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '314';
|
||
|
LCommandHandler.OnCommand := CommandWHOWAS;
|
||
|
|
||
|
//RPL_ENDOFWHO
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '315'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFWHO;
|
||
|
|
||
|
//RPL_WHOISIDLE
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '317'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandWHOIS;
|
||
|
|
||
|
//RPL_ENDOFWHOIS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '318'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFWHOIS;
|
||
|
|
||
|
//RPL_WHOISCHANNELS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '319'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandWHOIS;
|
||
|
|
||
|
{TODO:
|
||
|
320 RPL_WHOISVIRT AustHex
|
||
|
320 RPL_WHOIS_HIDDEN Anothernet
|
||
|
320 RPL_WHOISSPECIAL Unreal
|
||
|
}
|
||
|
//RPL_LISTSTART
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '321'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandLISTSTART;
|
||
|
|
||
|
//RPL_LIST
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '322'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandLIST;
|
||
|
|
||
|
//RPL_LISTEND
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '323'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandLISTEND;
|
||
|
|
||
|
//RPL_CHANMODEIS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '324'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandCHANMODE;
|
||
|
|
||
|
//RPL_UNIQOPIS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '325'; {do not localize}
|
||
|
//LCommandHandler.OnCommand := CommandUNIQOP;
|
||
|
|
||
|
{TODO:
|
||
|
326 RPL_NOCHANPASS
|
||
|
327 RPL_CHPASSUNKNOWN
|
||
|
328 RPL_CHANNEL_URL Bahamut, AustHex
|
||
|
329 RPL_CREATIONTIME Bahamut
|
||
|
}
|
||
|
//RPL_NOTOPIC
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '331'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandTOPIC;
|
||
|
|
||
|
//RPL_TOPIC
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '332';
|
||
|
LCommandHandler.OnCommand := CommandTOPIC;
|
||
|
|
||
|
{TODO:
|
||
|
333 RPL_TOPICWHOTIME ircu
|
||
|
339 RPL_BADCHANPASS
|
||
|
340 RPL_USERIP ircu
|
||
|
}
|
||
|
//RPL_INVITING
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '341'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandINVITING;
|
||
|
|
||
|
//RPL_SUMMONING
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '342'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandSUMMONING;
|
||
|
|
||
|
{TODO:
|
||
|
345 RPL_INVITED GameSurge <channel> <user being invited> <user issuing invite> :<user being invited> has been invited by <user issuing invite> Sent to users on a channel when an INVITE command has been issued
|
||
|
}
|
||
|
//RPL_INVITELIST
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '346'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandINVITELIST;
|
||
|
|
||
|
//RPL_ENDOFINVITELIST
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '347'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFINVITELIST;
|
||
|
|
||
|
//RPL_EXCEPTLIST
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '348'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandEXCEPTLIST;
|
||
|
|
||
|
//RPL_ENDOFEXCEPTLIST
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '349'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFEXCEPTLIST;
|
||
|
|
||
|
//RPL_VERSION
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '351'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandVERSION;
|
||
|
|
||
|
//RPL_WHOREPLY
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '352'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandWHOREPLY;
|
||
|
|
||
|
//RPL_NAMEREPLY
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '353'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandNAMEREPLY;
|
||
|
|
||
|
{ TODO:
|
||
|
354 RPL_WHOSPCRPL ircu Reply to WHO, however it is a 'special' reply because it is returned using a non-standard (non-RFC1459) format. The format is dictated by the command given by the user, and can vary widely. When this is used, the WHO command was invoked in its 'extended' form, as announced by the 'WHOX' ISUPPORT tag.
|
||
|
355 RPL_NAMREPLY_ QuakeNet ( '=' / '*' / '@' ) <channel> ' ' : [ '@' / '+' ] <nick> *( ' ' [ '@' / '+' ] <nick> ) Reply to the "NAMES -d" command - used to show invisible users (when the channel is set +D, QuakeNet relative). The proper define name for this numeric is unknown at this time Also see #353.
|
||
|
}
|
||
|
//RPL_LINKS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '364'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandLINKS;
|
||
|
|
||
|
//RPL_ENDOFLINKS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '365'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFLINKS;
|
||
|
|
||
|
//RPL_ENDOFNAMES
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '366'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFNAMES;
|
||
|
|
||
|
// RPL_BANLIST
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '367'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandBANLIST;
|
||
|
|
||
|
//RPL_ENDOFBANLIST
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '368'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFBANLIST;
|
||
|
|
||
|
//RPL_ENDOFWHOWAS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '369'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFWHOWAS;
|
||
|
|
||
|
//RPL_INFO
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '371'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandINFO;
|
||
|
|
||
|
//RPL_MOTD
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '372'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandMOTD;
|
||
|
|
||
|
//RPL_ENDOFINFO
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '374'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFINFO;
|
||
|
LCommandHandler.ParseParams := False;
|
||
|
|
||
|
//RPL_MOTDSTART
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '375'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandMOTD;
|
||
|
|
||
|
//RPL_ENDOFMOTD
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '376'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFMOTD;
|
||
|
|
||
|
//RPL_YOUREOPER
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '381'; {do not localize}
|
||
|
//LCommandHandler.OnCommand := CommandYOUAREOPER;
|
||
|
|
||
|
//RPL_REHASHING
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '382'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandREHASHING;
|
||
|
|
||
|
//RPL_YOUARESERVICE
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '383'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandSERVICE;
|
||
|
|
||
|
{TODO:
|
||
|
385 RPL_NOTOPERANYMORE AustHex, Hybrid, Unreal
|
||
|
388 RPL_ALIST Unreal
|
||
|
389 RPL_ENDOFALIST Unreal
|
||
|
}
|
||
|
//RPL_TIME
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '391'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandTIME;
|
||
|
|
||
|
//RPL_USERSSTART
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '392'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandUSERSSTART;
|
||
|
|
||
|
//RPL_USERS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '393'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandUSERS;
|
||
|
|
||
|
//RPL_ENDOFUSERS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '394'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandENDOFUSERS;
|
||
|
|
||
|
//RPL_NOUSERS
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
LCommandHandler.Command := '395'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandUSERS;
|
||
|
|
||
|
//ERR_NICKNAMEINUSE
|
||
|
LCommandHandler := CommandHandlers.Add;
|
||
|
// 433 ERR_NICKNAMEINUSE RFC1459 <nick> :<reason>
|
||
|
// Returned by the NICK command when the given nickname is already in use
|
||
|
LCommandHandler.Command := '433'; {do not localize}
|
||
|
LCommandHandler.OnCommand := CommandNICKINUSE;
|
||
|
|
||
|
{TODO:
|
||
|
396 RPL_HOSTHIDDEN Undernet Reply to a user when user mode +x (host masking) was set successfully
|
||
|
400 ERR_UNKNOWNERROR <command> [<?>] :<info> Sent when an error occured executing a command, but it is not specifically known why the command could not be executed.
|
||
|
401 ERR_NOSUCHNICK RFC1459 <nick> :<reason> Used to indicate the nickname parameter supplied to a command is currently unused
|
||
|
402 ERR_NOSUCHSERVER RFC1459 <server> :<reason> Used to indicate the server name given currently doesn't exist
|
||
|
403 ERR_NOSUCHCHANNEL RFC1459 <channel> :<reason> Used to indicate the given channel name is invalid, or does not exist
|
||
|
404 ERR_CANNOTSENDTOCHAN RFC1459 <channel> :<reason> Sent to a user who does not have the rights to send a message to a channel
|
||
|
405 ERR_TOOMANYCHANNELS RFC1459 <channel> :<reason> Sent to a user when they have joined the maximum number of allowed channels and they tried to join another channel
|
||
|
406 ERR_WASNOSUCHNICK RFC1459 <nick> :<reason> Returned by WHOWAS to indicate there was no history information for a given nickname
|
||
|
407 ERR_TOOMANYTARGETS RFC1459 <target> :<reason> The given target(s) for a command are ambiguous in that they relate to too many targets
|
||
|
408 ERR_NOSUCHSERVICE RFC2812 <service_name> :<reason> Returned to a client which is attempting to send an SQUERY (or other message) to a service which does not exist
|
||
|
409 ERR_NOORIGIN RFC1459 :<reason> PING or PONG message missing the originator parameter which is required since these commands must work without valid prefixes
|
||
|
411 ERR_NORECIPIENT RFC1459 :<reason> Returned when no recipient is given with a command
|
||
|
412 ERR_NOTEXTTOSEND RFC1459 :<reason> Returned when NOTICE/PRIVMSG is used with no message given
|
||
|
413 ERR_NOTOPLEVEL RFC1459 <mask> :<reason> Used when a message is being sent to a mask without being limited to a top-level domain (i.e. * instead of *.au)
|
||
|
414 ERR_WILDTOPLEVEL RFC1459 <mask> :<reason> Used when a message is being sent to a mask with a wild-card for a top level domain (i.e. *.*)
|
||
|
415 ERR_BADMASK RFC2812 <mask> :<reason> Used when a message is being sent to a mask with an invalid syntax
|
||
|
416 ERR_TOOMANYMATCHES IRCnet <command> [<mask>] :<info> Returned when too many matches have been found for a command and the output has been truncated. An example would be the WHO command, where by the mask '*' would match everyone on the network! Ouch!
|
||
|
416 ERR_QUERYTOOLONG ircu Same as ERR_TOOMANYMATCHES
|
||
|
419 ERR_LENGTHTRUNCATED aircd
|
||
|
421 ERR_UNKNOWNCOMMAND RFC1459 <command> :<reason> Returned when the given command is unknown to the server (or hidden because of lack of access rights)
|
||
|
422 ERR_NOMOTD RFC1459 :<reason> Sent when there is no MOTD to send the client
|
||
|
423 ERR_NOADMININFO RFC1459 <server> :<reason> Returned by a server in response to an ADMIN request when no information is available. RFC1459 mentions this in the list of numerics. While it's not listed as a valid reply in section 4.3.7 ('Admin command'), it's confirmed to exist in the real world.
|
||
|
424 ERR_FILEERROR RFC1459 :<reason> Generic error message used to report a failed file operation during the processing of a command
|
||
|
425 ERR_NOOPERMOTD Unreal
|
||
|
429 ERR_TOOMANYAWAY Bahamut
|
||
|
430 ERR_EVENTNICKCHANGE AustHex Returned by NICK when the user is not allowed to change their nickname due to a channel event (channel mode +E)
|
||
|
431 ERR_NONICKNAMEGIVEN RFC1459 :<reason> Returned when a nickname parameter expected for a command isn't found
|
||
|
432 ERR_ERRONEUSNICKNAME RFC1459 <nick> :<reason> Returned after receiving a NICK message which contains a nickname which is considered invalid, such as it's reserved ('anonymous') or contains characters considered invalid for nicknames. This numeric is misspelt, but remains with this name for historical reasons :)
|
||
|
436 ERR_NICKCOLLISION RFC1459 <nick> :<reason> Returned by a server to a client when it detects a nickname collision
|
||
|
439 ERR_TARGETTOOFAST ircu Also known as many other things, RPL_INVTOOFAST, RPL_MSGTOOFAST etc
|
||
|
440 ERR_SERVICESDOWN Bahamut, Unreal
|
||
|
441 ERR_USERNOTINCHANNEL RFC1459 <nick> <channel> :<reason> Returned by the server to indicate that the target user of the command is not on the given channel
|
||
|
442 ERR_NOTONCHANNEL RFC1459 <channel> :<reason> Returned by the server whenever a client tries to perform a channel effecting command for which the client is not a member
|
||
|
443 ERR_USERONCHANNEL RFC1459 <nick> <channel> [:<reason>] Returned when a client tries to invite a user to a channel they're already on
|
||
|
444 ERR_NOLOGIN RFC1459 <user> :<reason> Returned by the SUMMON command if a given user was not logged in and could not be summoned
|
||
|
445 ERR_SUMMONDISABLED RFC1459 :<reason> Returned by SUMMON when it has been disabled or not implemented
|
||
|
446 ERR_USERSDISABLED RFC1459 :<reason> Returned by USERS when it has been disabled or not implemented
|
||
|
447 ERR_NONICKCHANGE Unreal
|
||
|
449 ERR_NOTIMPLEMENTED Undernet Unspecified Returned when a requested feature is not implemented (and cannot be completed)
|
||
|
451 ERR_NOTREGISTERED RFC1459 :<reason> Returned by the server to indicate that the client must be registered before the server will allow it to be parsed in detail
|
||
|
452 ERR_IDCOLLISION
|
||
|
453 ERR_NICKLOST
|
||
|
455 ERR_HOSTILENAME Unreal
|
||
|
456 ERR_ACCEPTFULL
|
||
|
457 ERR_ACCEPTEXIST
|
||
|
458 ERR_ACCEPTNOT
|
||
|
459 ERR_NOHIDING Unreal Not allowed to become an invisible operator?
|
||
|
460 ERR_NOTFORHALFOPS Unreal
|
||
|
461 ERR_NEEDMOREPARAMS RFC1459 <command> :<reason> Returned by the server by any command which requires more parameters than the number of parameters given
|
||
|
462 ERR_ALREADYREGISTERED RFC1459 :<reason> Returned by the server to any link which attempts to register again
|
||
|
463 ERR_NOPERMFORHOST RFC1459 :<reason> Returned to a client which attempts to register with a server which has been configured to refuse connections from the client's host
|
||
|
464 ERR_PASSWDMISMATCH RFC1459 :<reason> Returned by the PASS command to indicate the given password was required and was either not given or was incorrect
|
||
|
465 ERR_YOUREBANNEDCREEP RFC1459 :<reason> Returned to a client after an attempt to register on a server configured to ban connections from that client
|
||
|
466 ERR_YOUWILLBEBANNED RFC1459 Sent by a server to a user to inform that access to the server will soon be denied
|
||
|
467 ERR_KEYSET RFC1459 <channel> :<reason> Returned when the channel key for a channel has already been set
|
||
|
468 ERR_INVALIDUSERNAME ircu
|
||
|
468 ERR_ONLYSERVERSCANCHANGE Bahamut, Unreal
|
||
|
469 ERR_LINKSET Unreal
|
||
|
470 ERR_LINKCHANNEL Unreal
|
||
|
470 ERR_KICKEDFROMCHAN aircd
|
||
|
471 ERR_CHANNELISFULL RFC1459 <channel> :<reason> Returned when attempting to join a channel which is set +l and is already full
|
||
|
472 ERR_UNKNOWNMODE RFC1459 <char> :<reason> Returned when a given mode is unknown
|
||
|
473 ERR_INVITEONLYCHAN RFC1459 <channel> :<reason> Returned when attempting to join a channel which is invite only without an invitation
|
||
|
474 ERR_BANNEDFROMCHAN RFC1459 <channel> :<reason> Returned when attempting to join a channel a user is banned from
|
||
|
475 ERR_BADCHANNELKEY RFC1459 <channel> :<reason> Returned when attempting to join a key-locked channel either without a key or with the wrong key
|
||
|
476 ERR_BADCHANMASK RFC2812 <channel> :<reason> The given channel mask was invalid
|
||
|
478 ERR_BANLISTFULL RFC2812 <channel> <char> :<reason> Returned when a channel access list (i.e. ban list etc) is full and cannot be added to
|
||
|
479 ERR_BADCHANNAME Hybrid
|
||
|
479 ERR_LINKFAIL Unreal
|
||
|
481 ERR_NOPRIVILEGES RFC1459 :<reason> Returned by any command requiring special privileges (eg. IRC operator) to indicate the operation was unsuccessful
|
||
|
482 ERR_CHANOPRIVSNEEDED RFC1459 <channel> :<reason> Returned by any command requiring special channel privileges (eg. channel operator) to indicate the operation was unsuccessful
|
||
|
483 ERR_CANTKILLSERVER RFC1459 :<reason> Returned by KILL to anyone who tries to kill a server
|
||
|
485 ERR_UNIQOPRIVSNEEDED RFC2812 :<reason> Any mode requiring 'channel creator' privileges returns this error if the client is attempting to use it while not a channel creator on the given channel
|
||
|
488 ERR_TSLESSCHAN IRCnet
|
||
|
491 ERR_NOOPERHOST RFC1459 :<reason> Returned by OPER to a client who cannot become an IRC operator because the server has been configured to disallow the client's host
|
||
|
493 ERR_NOFEATURE ircu
|
||
|
494 ERR_BADFEATURE ircu
|
||
|
495 ERR_BADLOGTYPE ircu
|
||
|
496 ERR_BADLOGSYS ircu
|
||
|
497 ERR_BADLOGVALUE ircu
|
||
|
498 ERR_ISOPERLCHAN ircu
|
||
|
499 ERR_CHANOWNPRIVNEEDED Unreal Works just like ERR_CHANOPRIVSNEEDED except it indicates that owner status (+q) is needed. Also see #482.
|
||
|
501 ERR_UMODEUNKNOWNFLAG RFC1459 :<reason> Returned by the server to indicate that a MODE message was sent with a nickname parameter and that the mode flag sent was not recognised
|
||
|
502 ERR_USERSDONTMATCH RFC1459 :<reason> Error sent to any user trying to view or change the user mode for a user other than themselves
|
||
|
503 ERR_GHOSTEDCLIENT Hybrid
|
||
|
504 ERR_USERNOTONSERV
|
||
|
511 ERR_SILELISTFULL ircu
|
||
|
512 ERR_TOOMANYWATCH Bahamut Also known as ERR_NOTIFYFULL (aircd), I presume they are the same
|
||
|
513 ERR_BADPING ircu Also known as ERR_NEEDPONG (Unreal/Ultimate) for use during registration, however it's not used in Unreal (and might not be used in Ultimate either).
|
||
|
515 ERR_BADEXPIRE ircu
|
||
|
516 ERR_DONTCHEAT ircu
|
||
|
517 ERR_DISABLED ircu <command> :<info/reason>
|
||
|
522 ERR_WHOSYNTAX Bahamut
|
||
|
523 ERR_WHOLIMEXCEED Bahamut
|
||
|
525 ERR_REMOTEPFX CAPAB USERCMDPFX <nickname> :<reason> Proposed.
|
||
|
526 ERR_PFXUNROUTABLE CAPAB USERCMDPFX <nickname> :<reason> Proposed.
|
||
|
550 ERR_BADHOSTMASK QuakeNet
|
||
|
551 ERR_HOSTUNAVAIL QuakeNet
|
||
|
552 ERR_USINGSLINE QuakeNet
|
||
|
600 RPL_LOGON Bahamut, Unreal
|
||
|
601 RPL_LOGOFF Bahamut, Unreal
|
||
|
602 RPL_WATCHOFF Bahamut, Unreal
|
||
|
603 RPL_WATCHSTAT Bahamut, Unreal
|
||
|
604 RPL_NOWON Bahamut, Unreal
|
||
|
605 RPL_NOWOFF Bahamut, Unreal
|
||
|
606 RPL_WATCHLIST Bahamut, Unreal
|
||
|
607 RPL_ENDOFWATCHLIST Bahamut, Unreal
|
||
|
608 RPL_WATCHCLEAR Ultimate
|
||
|
611 RPL_ISLOCOP Ultimate
|
||
|
612 RPL_ISNOTOPER Ultimate
|
||
|
613 RPL_ENDOFISOPER Ultimate
|
||
|
618 RPL_DCCLIST
|
||
|
624 RPL_OMOTDSTART Ultimate
|
||
|
625 RPL_OMOTD Ultimate
|
||
|
626 RPL_ENDOFO Ultimate
|
||
|
630 RPL_SETTINGS Ultimate
|
||
|
631 RPL_ENDOFSETTINGS Ultimate
|
||
|
660 RPL_TRACEROUTE_HOP KineIRCd <target> <hop#> [<address> [<hostname> | '*'] <usec_ping>] Returned from the TRACEROUTE IRC-Op command when tracerouting a host
|
||
|
661 RPL_TRACEROUTE_START KineIRCd <target> <target_FQDN> <target_address> <max_hops> Start of an RPL_TRACEROUTE_HOP list
|
||
|
662 RPL_MODECHANGEWARN KineIRCd ['+' | '-']<mode_char> :<warning> Plain text warning to the user about turning on or off a user mode. If no '+' or '-' prefix is used for the mode char, '+' is presumed.
|
||
|
663 RPL_CHANREDIR KineIRCd <old_chan> <new_chan> :<info> Used to notify the client upon JOIN that they are joining a different channel than expected because the IRC Daemon has been set up to map the channel they attempted to join to the channel they eventually will join.
|
||
|
664 RPL_SERVMODEIS KineIRCd <server> <modes> <parameters>.. Reply to MODE <servername>. KineIRCd supports server modes to simplify configuration of servers; Similar to RPL_CHANNELMODEIS
|
||
|
665 RPL_OTHERUMODEIS KineIRCd <nickname> <modes> Reply to MODE <nickname> to return the user-modes of another user to help troubleshoot connections, etc. Similar to RPL_UMODEIS, however including the target
|
||
|
666 RPL_ENDOF_GENERIC KineIRCd <command> [<parameter> ...] :<info> Generic response for new lists to save numerics.
|
||
|
670 RPL_WHOWASDETAILS KineIRCd <nick> <type> :<information> Returned by WHOWAS to return extended information (if available). The type field is a number indication what kind of information.
|
||
|
671 RPL_WHOISSECURE KineIRCd <nick> <type> [:<info>] Reply to WHOIS command - Returned if the target is connected securely, eg. type may be TLSv1, or SSLv2 etc. If the type is unknown, a '*' may be used.
|
||
|
672 RPL_UNKNOWNMODES Ithildin <modes> :<info> Returns a full list of modes that are unknown when a client issues a MODE command (rather than one numeric per mode)
|
||
|
673 RPL_CANNOTSETMODES Ithildin <modes> :<info> Returns a full list of modes that cannot be set when a client issues a MODE command
|
||
|
678 RPL_LUSERSTAFF KineIRCd <staff_online_count> :<info> Reply to LUSERS command - Number of network staff (or 'helpers') online (differs from Local/Global operators). Similar format to RPL_LUSEROP
|
||
|
679 RPL_TIMEONSERVERIS KineIRCd <seconds> [<nanoseconds> | '0'] <timezone> <flags> :<info> Optionally sent upon connection, and/or sent as a reply to the TIME command. This returns the time on the server in a uniform manner. The seconds (and optionally nanoseconds) is the time since the UNIX Epoch, and is used since many existing timestamps in the IRC-2 protocol are done this way (i.e. ban lists). The timezone is hours and minutes each of Greenwich ('[+/-]HHMM'). Since all timestamps sent from the server are in a similar format, this numeric is designed to give clients the ability to provide accurate timestamps to their users.
|
||
|
682 RPL_NETWORKS KineIRCd <name> <through_name> <hops> :<info> A reply to the NETWORKS command when requesting a list of known networks (within the IIRC domain).
|
||
|
687 RPL_YOURLANGUAGEIS KineIRCd <code(s)> :<info> Reply to the LANGUAGE command, informing the client of the language(s) it has set
|
||
|
688 RPL_LANGUAGE KineIRCd <code> <revision> <maintainer> <flags> * :<info> A language reply to LANGUAGE when requesting a list of known languages
|
||
|
689 RPL_WHOISSTAFF KineIRCd :<info> The user is a staff member. The information may explain the user's job role, or simply state that they are a part of the network staff. Staff members are not IRC operators, but rather people who have special access in association with network services. KineIRCd uses this numeric instead of the existing numerics due to the overwhelming number of conflicts.
|
||
|
690 RPL_WHOISLANGUAGE KineIRCd <nick> <language codes> Reply to WHOIS command - A list of languages someone can speak. The language codes are comma delimitered.
|
||
|
702 RPL_MODLIST RatBox <?> 0x<?> <?> <?> Output from the MODLIST command
|
||
|
703 RPL_ENDOFMODLIST RatBox :<text> Terminates MODLIST output
|
||
|
704 RPL_HELPSTART RatBox <command> :<text> Start of HELP command output
|
||
|
705 RPL_HELPTXT RatBox <command> :<text> Output from HELP command
|
||
|
706 RPL_ENDOFHELP RatBox <command> :<text> End of HELP command output
|
||
|
708 RPL_ETRACEFULL RatBox <?> <?> <?> <?> <?> <?> <?> :<?> Output from 'extended' trace
|
||
|
709 RPL_ETRACE RatBox <?> <?> <?> <?> <?> <?> :<?> Output from 'extended' trace
|
||
|
710 RPL_KNOCK RatBox <channel> <nick>!<user>@<host> :<text> Message delivered using KNOCK command
|
||
|
711 RPL_KNOCKDLVR RatBox <channel> :<text> Message returned from using KNOCK command
|
||
|
712 ERR_TOOMANYKNOCK RatBox <channel> :<text> Message returned when too many KNOCKs for a channel have been sent by a user
|
||
|
713 ERR_CHANOPEN RatBox <channel> :<text> Message returned from KNOCK when the channel can be freely joined by the user
|
||
|
714 ERR_KNOCKONCHAN RatBox <channel> :<text> Message returned from KNOCK when the user has used KNOCK on a channel they have already joined
|
||
|
715 ERR_KNOCKDISABLED RatBox :<text> Returned from KNOCK when the command has been disabled
|
||
|
716 RPL_TARGUMODEG RatBox <nick> :<info> Sent to indicate the given target is set +g (server-side ignore)
|
||
|
717 RPL_TARGNOTIFY RatBox <nick> :<info> Sent following a PRIVMSG/NOTICE to indicate the target has been notified of an attempt to talk to them while they are set +g
|
||
|
718 RPL_UMODEGMSG RatBox <nick> <user>@<host> :<info> Sent to a user who is +g to inform them that someone has attempted to talk to them (via PRIVMSG/NOTICE), and that they will need to be accepted (via the ACCEPT command) before being able to talk to them
|
||
|
720 RPL_OMOTDSTART RatBox :<text> IRC Operator MOTD header, sent upon OPER command
|
||
|
721 RPL_OMOTD RatBox :<text> IRC Operator MOTD text (repeated, usually)
|
||
|
722 RPL_ENDOFOMOTD RatBox :<text> IRC operator MOTD footer
|
||
|
723 ERR_NOPRIVS RatBox <command> :<text> Returned from an oper command when the IRC operator does not have the relevant operator privileges.
|
||
|
724 RPL_TESTMARK RatBox <nick>!<user>@<host> <?> <?> :<text> Reply from an oper command reporting how many users match a given user@host mask
|
||
|
725 RPL_TESTLINE RatBox <?> <?> <?> :<?> Reply from an oper command reporting relevant I/K lines that will match a given user@host
|
||
|
726 RPL_NOTESTLINE RatBox <?> :<text> Reply from oper command reporting no I/K lines match the given user@host
|
||
|
771 RPL_XINFO Ithildin Used to send 'eXtended info' to the client, a replacement for the STATS command to send a large variety of data and minimise numeric pollution.
|
||
|
773 RPL_XINFOSTART Ithildin Start of an RPL_XINFO list
|
||
|
774 RPL_XINFOEND Ithildin Termination of an RPL_XINFO list
|
||
|
972 ERR_CANNOTDOCOMMAND Unreal Works similarly to all of KineIRCd's CANNOT* numerics. This one indicates that a command could not be performed for an arbitrary reason. For example, a halfop trying to kick an op.
|
||
|
973 ERR_CANNOTCHANGEUMODE KineIRCd <mode_char> :<reason> Reply to MODE when a user cannot change a user mode
|
||
|
974 ERR_CANNOTCHANGECHANMODE KineIRCd <mode_char> :<reason> Reply to MODE when a user cannot change a channel mode
|
||
|
975 ERR_CANNOTCHANGESERVERMODE KineIRCd <mode_char> :<reason> Reply to MODE when a user cannot change a server mode
|
||
|
976 ERR_CANNOTSENDTONICK KineIRCd <nick> :<reason> Returned from NOTICE, PRIVMSG or other commands to notify the user that they cannot send a message to a particular client. Similar to ERR_CANNOTSENDTOCHAN. KineIRCd uses this in conjunction with user-mode +R to allow users to block people who are not identified to services (spam avoidance)
|
||
|
977 ERR_UNKNOWNSERVERMODE KineIRCd <modechar> :<info> Returned by MODE to inform the client they used an unknown server mode character.
|
||
|
979 ERR_SERVERMODELOCK KineIRCd <target> :<info> Returned by MODE to inform the client the server has been set mode +L by an administrator to stop server modes being changed
|
||
|
980 ERR_BADCHARENCODING KineIRCd <command> <charset> :<info> Returned by any command which may have had the given data modified because one or more glyphs were incorrectly encoded in the current charset (given). Such a use would be where an invalid UTF-8 sequence was given which may be considered insecure, or defines a character which is invalid within that context. For safety reasons, the invalid character is not returned to the client.
|
||
|
981 ERR_TOOMANYLANGUAGES KineIRCd <max_langs> :<info> Returned by the LANGUAGE command to tell the client they cannot set as many languages as they have requested. To assist the client, the maximum languages which can be set at one time is given, and the language settings are not changed.
|
||
|
982 ERR_NOLANGUAGE KineIRCd <language_code> :<info> Returned by the LANGUAGE command to tell the client it has specified an unknown language code.
|
||
|
983 ERR_TEXTTOOSHORT KineIRCd <command> :<info> Returned by any command requiring text (such as a message or a reason), which was not long enough to be considered valid. This was created initially to combat '/wallops foo' abuse, but is also used by DIE and RESTART commands to attempt to encourage meaningful reasons.
|
||
|
999 ERR_NUMERIC_ERR Bahamut
|
||
|
}
|
||
|
|
||
|
FCommandHandlers.OnBeforeCommandHandler := DoBeforeCmd;
|
||
|
end;
|
||
|
|
||
|
{ Command handlers }
|
||
|
|
||
|
procedure TIdIRC.DoBeforeCmd(ASender: TIdCommandHandlers; var AData: string; AContext: TIdContext);
|
||
|
var
|
||
|
LTmp: String;
|
||
|
begin
|
||
|
AData := IRCUnquote(AData);
|
||
|
// ":nickname!user@host"
|
||
|
if TextStartsWith(AData, ':') then begin
|
||
|
LTmp := Fetch(AData, ' ');
|
||
|
Delete(LTmp, 1, 1); // remove ':'
|
||
|
FSenderNick := Fetch(LTmp, '!');
|
||
|
FSenderHost := LTmp;
|
||
|
end else begin
|
||
|
FSenderNick := '';
|
||
|
FSenderHost := '';
|
||
|
end;
|
||
|
if Assigned(FOnRaw) then begin
|
||
|
FOnRaw(AContext, True, AData);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.DoReplyUnknownCommand(AContext: TIdContext; ALine: string);
|
||
|
var
|
||
|
ACmdCode: Integer;
|
||
|
begin
|
||
|
ACmdCode := IndyStrToInt(Fetch(ALine, ' '), -1);
|
||
|
//
|
||
|
case ACmdCode of
|
||
|
6,
|
||
|
7:
|
||
|
begin
|
||
|
//MAP
|
||
|
end;
|
||
|
5,
|
||
|
400..424,
|
||
|
437..502:
|
||
|
begin
|
||
|
if Assigned(FOnServerError) then begin
|
||
|
OnServerError(AContext, ACmdCode, ALine);
|
||
|
end;
|
||
|
end;
|
||
|
431..432,
|
||
|
436:
|
||
|
begin
|
||
|
if Assigned(FOnNickError) then begin
|
||
|
OnNicknameError(AContext, ACmdCode);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandPRIVMSG(ASender: TIdCommand);
|
||
|
var
|
||
|
LTmp, LTarget, LData, LCTCP: String;
|
||
|
I: Integer;
|
||
|
CTCPList: TStringList;
|
||
|
begin
|
||
|
LTmp := ASender.UnparsedParams;
|
||
|
LTarget := FetchIRCParam(LTmp);
|
||
|
LData := FetchIRCParam(LTmp);
|
||
|
|
||
|
CTCPList := TStringList.Create;
|
||
|
try
|
||
|
ExtractCTCPs(LData, CTCPList);
|
||
|
if CTCPList.Count = 0 then begin
|
||
|
if Assigned(FOnPrivMessage) then begin
|
||
|
OnPrivateMessage(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
|
||
|
end;
|
||
|
end else
|
||
|
begin
|
||
|
if (LData <> '') and Assigned(FOnPrivMessage) then begin
|
||
|
OnPrivateMessage(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
|
||
|
end;
|
||
|
for I := 0 to CTCPList.Count - 1 do begin
|
||
|
LData := CTCPList[I];
|
||
|
LCTCP := Fetch(LData, ' ');
|
||
|
case PosInStrArray(LCTCP, IdIRCCTCP) of
|
||
|
0: { ACTION }
|
||
|
begin
|
||
|
{
|
||
|
if Assigned(FOnAction) then begin
|
||
|
FOnAction(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
|
||
|
end;
|
||
|
}
|
||
|
if Assigned(FOnCTCPQry) then begin
|
||
|
FOnCTCPQry(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
|
||
|
end;
|
||
|
// RLebeau: CTCP ACTION does not send a reply back
|
||
|
//CTCPReply(FSenderNick, 'ERRMSG', LCTCP +' ' + LData + ' unknown query'); {do not localize}
|
||
|
end;
|
||
|
1: { SOUND }
|
||
|
begin
|
||
|
{
|
||
|
if Assigned(FOnSound) then begin
|
||
|
FOnSound(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
|
||
|
end;
|
||
|
}
|
||
|
if Assigned(FOnCTCPQry) then begin
|
||
|
FOnCTCPQry(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
|
||
|
end;
|
||
|
CTCPReply(FSenderNick, 'ERRMSG', LCTCP +' ' + LData + ' unknown query'); {do not localize}
|
||
|
end;
|
||
|
2: { PING }
|
||
|
begin
|
||
|
{
|
||
|
LTmp := '';
|
||
|
if Assigned(FOnPing) then begin
|
||
|
FOnPing(ASender.Context, LTmp);
|
||
|
end;
|
||
|
if LTmp = '' then begin
|
||
|
LTmp := DateTimeToStr(Now);
|
||
|
end;
|
||
|
CTCPReply(FSenderNick, LCTCP, ':' + LTmp);
|
||
|
}
|
||
|
if Assigned(FOnCTCPQry) then begin
|
||
|
FOnCTCPQry(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
|
||
|
end;
|
||
|
// AWinkelsdorf 3/10/2010 ToDo: CTCP Ping might need a CTIME result but
|
||
|
// many clients do not send the required CTIME with the Ping Query...
|
||
|
CTCPReply(FSenderNick, LCTCP, DateTimeToStr(Now)); {do not localize}
|
||
|
end;
|
||
|
3: { FINGER }
|
||
|
begin
|
||
|
CTCPReply(FSenderNick, LCTCP, Replies.Finger); {do not localize}
|
||
|
end;
|
||
|
4: { USERINFO }
|
||
|
begin
|
||
|
CTCPReply(FSenderNick, LCTCP, Replies.UserInfo); {do not localize}
|
||
|
end;
|
||
|
5: { VERSION }
|
||
|
begin
|
||
|
CTCPReply(FSenderNick, LCTCP, Replies.Version); {do not localize}
|
||
|
end;
|
||
|
6: { CLIENTINFO }
|
||
|
begin
|
||
|
// TODO: add OnClientInfoQuery event to handle per-command queries
|
||
|
CTCPReply(FSenderNick, LCTCP, Replies.ClientInfo); {do not localize}
|
||
|
end;
|
||
|
7: { TIME }
|
||
|
begin
|
||
|
CTCPReply(FSenderNick, LCTCP, DateTimeToStr(Now));
|
||
|
end;
|
||
|
8: { ERROR }
|
||
|
begin
|
||
|
CTCPReply(FSenderNick, LCTCP, LData + ' No Error'); {do not localize}
|
||
|
end;
|
||
|
9: { DCC }
|
||
|
begin
|
||
|
ParseDCC(ASender.Context, LData);
|
||
|
end;
|
||
|
10: { SED }
|
||
|
begin
|
||
|
//ParseSED(AContext, LData);
|
||
|
if Assigned(FOnCTCPQry) then begin
|
||
|
FOnCTCPQry(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
|
||
|
end;
|
||
|
CTCPReply(FSenderNick, LCTCP, LData + ' unknown query'); {do not localize}
|
||
|
end;
|
||
|
11: { ERRMSG }
|
||
|
begin
|
||
|
CTCPReply(FSenderNick, LCTCP, LData + ' No Error'); {do not localize}
|
||
|
end;
|
||
|
else
|
||
|
begin
|
||
|
if Assigned(FOnCTCPQry) then begin
|
||
|
FOnCTCPQry(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
|
||
|
end;
|
||
|
CTCPReply(FSenderNick, LCTCP, LData + ' unknown query'); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
finally
|
||
|
CTCPList.Free;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandNOTICE(ASender: TIdCommand);
|
||
|
var
|
||
|
LTmp, LTarget, LData, LCTCP: String;
|
||
|
I: Integer;
|
||
|
CTCPList: TStringList;
|
||
|
begin
|
||
|
LTmp := ASender.UnparsedParams;
|
||
|
LTarget := FetchIRCParam(LTmp);
|
||
|
LData := FetchIRCParam(LTmp);
|
||
|
|
||
|
CTCPList := TStringList.Create;
|
||
|
try
|
||
|
ExtractCTCPs(LData, CTCPList);
|
||
|
if CTCPList.Count = 0 then begin
|
||
|
if Assigned(FOnNotice) then begin
|
||
|
OnNotice(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
|
||
|
end;
|
||
|
end else
|
||
|
begin
|
||
|
if (LData <> '') and Assigned(FOnNotice) then begin
|
||
|
OnNotice(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
|
||
|
end;
|
||
|
for I := 0 to CTCPList.Count - 1 do begin
|
||
|
LData := CTCPList[I];
|
||
|
LCTCP := Fetch(LData, ' ');
|
||
|
case PosInStrArray(LCTCP, IdIRCCTCP) of
|
||
|
0: { ACTION }
|
||
|
begin
|
||
|
{
|
||
|
if Assigned(FOnAction) then begin
|
||
|
FOnAction(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
|
||
|
end;
|
||
|
}
|
||
|
if Assigned(FOnCTCPRep) then begin
|
||
|
FOnCTCPRep(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
|
||
|
end;
|
||
|
end;
|
||
|
9: { DCC }
|
||
|
begin
|
||
|
ParseDCC(ASender.Context, LData);
|
||
|
end;
|
||
|
10: { SED }
|
||
|
begin
|
||
|
//ParseSED(AContext, LData);
|
||
|
if Assigned(FOnCTCPRep) then begin
|
||
|
FOnCTCPRep(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
|
||
|
end;
|
||
|
end;
|
||
|
else
|
||
|
if Assigned(FOnCTCPRep) then begin
|
||
|
FOnCTCPRep(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
finally
|
||
|
CTCPList.Free;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandJOIN(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnJoin) then begin
|
||
|
OnJoin(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0]);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandPART(ASender: TIdCommand);
|
||
|
var
|
||
|
LChannel, LMsg: string;
|
||
|
begin
|
||
|
if Assigned(FOnPart) then begin
|
||
|
if ASender.Params.Count > 0 then begin
|
||
|
LChannel := ASender.Params[0];
|
||
|
end;
|
||
|
if ASender.Params.Count > 1 then begin
|
||
|
LMsg := ASender.Params[1];
|
||
|
end;
|
||
|
OnPart(ASender.Context, FSenderNick, FSenderHost, LChannel, LMsg);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandKICK(ASender: TIdCommand);
|
||
|
var
|
||
|
LChannel, LTarget, LReason: string;
|
||
|
begin
|
||
|
if Assigned(FOnKick) then begin
|
||
|
if ASender.Params.Count > 0 then begin
|
||
|
LChannel := ASender.Params[0];
|
||
|
end;
|
||
|
if ASender.Params.Count > 1 then begin
|
||
|
LTarget := ASender.Params[1];
|
||
|
end;
|
||
|
if ASender.Params.Count > 2 then begin
|
||
|
LReason := ASender.Params[2];
|
||
|
end;
|
||
|
OnKick(ASender.Context, FSenderNick, FSenderHost, LChannel, LTarget, LReason);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandMODE(ASender: TIdCommand);
|
||
|
var
|
||
|
LTmp, LParam: String;
|
||
|
begin
|
||
|
LTmp := ASender.UnparsedParams;
|
||
|
LParam := FetchIRCParam(LTmp);
|
||
|
if IsChannel(LParam) then begin
|
||
|
if Assigned(FOnChanMode) then begin
|
||
|
OnChannelMode(ASender.Context, FSenderNick, FSenderHost, LParam, LTmp, '');
|
||
|
end;
|
||
|
end
|
||
|
else if Assigned(FOnUserMode) then begin
|
||
|
OnUserMode(ASender.Context, FSenderNick, FSenderHost, LTmp);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandNICK(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnNickChange) then begin
|
||
|
OnNicknameChange(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0]);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandQUIT(ASender: TIdCommand);
|
||
|
var
|
||
|
LReason: string;
|
||
|
begin
|
||
|
if Assigned(FOnQuit) then begin
|
||
|
if ASender.Params.Count > 0 then begin
|
||
|
LReason := ASender.Params[0];
|
||
|
end;
|
||
|
OnQuit(ASender.Context, FSenderNick, FSenderHost, LReason);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandSQUIT(ASender: TIdCommand);
|
||
|
var
|
||
|
LServer, LComment: string;
|
||
|
begin
|
||
|
if Assigned(FOnSvrQuit) then begin
|
||
|
if ASender.Params.Count > 0 then begin
|
||
|
LServer := ASender.Params[0];
|
||
|
end;
|
||
|
if ASender.Params.Count > 1 then begin
|
||
|
LComment := ASender.Params[1];
|
||
|
end;
|
||
|
OnServerQuit(ASender.Context, FSenderNick, FSenderHost, LServer, LComment);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandINVITE(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnInvite) then begin
|
||
|
OnInvite(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0], ASender.Params[1]);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandKILL(ASender: TIdCommand);
|
||
|
var
|
||
|
LTarget, LReason: string;
|
||
|
begin
|
||
|
if Assigned(FOnKill) then begin
|
||
|
if ASender.Params.Count > 0 then begin
|
||
|
LTarget := ASender.Params[0];
|
||
|
end;
|
||
|
if ASender.Params.Count > 1 then begin
|
||
|
LReason := ASender.Params[1];
|
||
|
end;
|
||
|
OnKill(ASender.Context, FSenderNick, FSenderHost, LTarget, LReason);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandPING(ASender: TIdCommand);
|
||
|
var
|
||
|
LServer1: String;
|
||
|
begin
|
||
|
if ASender.Params.Count > 0 then begin
|
||
|
LServer1 := ASender.Params[0];
|
||
|
end;
|
||
|
Pong(LServer1);
|
||
|
if Assigned(FOnPingPong) then begin
|
||
|
OnPingPong(ASender.Context);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandWALLOPS(ASender: TIdCommand);
|
||
|
var
|
||
|
LTmp: string;
|
||
|
begin
|
||
|
if Assigned(FOnWallops) then begin
|
||
|
LTmp := ASender.UnparsedParams;
|
||
|
OnWallops(ASender.Context, FSenderNick, FSenderHost, FetchIRCParam(LTmp));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandTOPIC(ASender: TIdCommand);
|
||
|
var
|
||
|
LChannel, LTopic: String;
|
||
|
begin
|
||
|
if Assigned(FOnTopic) then
|
||
|
begin
|
||
|
if ASender.Params.Count > 0 then begin
|
||
|
LChannel := ASender.Params[0];
|
||
|
end;
|
||
|
if (ASender.CommandHandler.Command <> '331') and (ASender.Params.Count > 1) then begin {do not localize}
|
||
|
LTopic := ASender.Params[1];
|
||
|
end else begin
|
||
|
LTopic := '';
|
||
|
end;
|
||
|
OnTopic(ASender.Context, FSenderNick, FSenderHost, LChannel, LTopic);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandWELCOME(ASender: TIdCommand);
|
||
|
var
|
||
|
LTmp: string;
|
||
|
begin
|
||
|
if Assigned(FOnSWelcome) then begin
|
||
|
LTmp := ASender.UnparsedParams;
|
||
|
OnServerWelcome(ASender.Context, FetchIRCParam(LTmp));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandERROR(ASender: TIdCommand);
|
||
|
var
|
||
|
LTmp: String;
|
||
|
begin
|
||
|
if Assigned(FOnServerError) then begin
|
||
|
LTmp := ASender.UnparsedParams;
|
||
|
OnServerError(ASender.Context, 0, FetchIRCParam(LTmp));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandYOURHOST(ASender: TIdCommand);
|
||
|
var
|
||
|
LTmp: String;
|
||
|
begin
|
||
|
if Assigned(FOnYourHost) then begin
|
||
|
LTmp := ASender.UnparsedParams;
|
||
|
OnYourHost(ASender.Context, FetchIRCParam(LTmp));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandCREATED(ASender: TIdCommand);
|
||
|
var
|
||
|
LTmp: string;
|
||
|
begin
|
||
|
if Assigned(FOnSCreated) then begin
|
||
|
LTmp := ASender.UnparsedParams;
|
||
|
OnServerCreated(ASender.Context, FetchIRCParam(LTmp));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandMYINFO(ASender: TIdCommand);
|
||
|
var
|
||
|
LTmp, LServer, LVersion, LUserModes, LChanModes: String;
|
||
|
begin
|
||
|
if Assigned(FOnMyInfo) then begin
|
||
|
LTmp := ASender.UnparsedParams;
|
||
|
LServer := FetchIRCParam(LTmp);
|
||
|
LVersion := FetchIRCParam(LTmp);
|
||
|
LUserModes := FetchIRCParam(LTmp);
|
||
|
LChanModes := FetchIRCParam(LTmp);
|
||
|
// TODO: <channel_modes_with_params> <user_modes_with_params> <server_modes> <server_modes_with_params>
|
||
|
OnMyInfo(ASender.Context, LServer, LVersion, LUserModes, LChanModes, LTmp);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.DoBounce(ASender: TIdCommand; ALegacy: Boolean);
|
||
|
var
|
||
|
LHost, LPort, LInfo: string;
|
||
|
begin
|
||
|
if Assigned(FOnBounce) then begin
|
||
|
if ALegacy then begin
|
||
|
LInfo := ASender.Params[0];
|
||
|
LHost := FetchIRCParam(LInfo);
|
||
|
LPort := FetchIRCParam(LInfo);
|
||
|
end else
|
||
|
begin
|
||
|
LHost := ASender.Params[0];
|
||
|
LPort := ASender.Params[1];
|
||
|
if ASender.Params.Count > 2 then begin
|
||
|
LInfo := ASender.Params[2];
|
||
|
end;
|
||
|
end;
|
||
|
// TODO: reconnect automatically
|
||
|
OnBounce(ASender.Context, LHost, IndyStrToInt(LPort, 0), LInfo);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandISUPPORT(ASender: TIdCommand);
|
||
|
var
|
||
|
LParams: TStringList;
|
||
|
I: Integer;
|
||
|
begin
|
||
|
if ASender.Params.Count = 1 then begin
|
||
|
DoBounce(ASender, True); // legacy, deprecated
|
||
|
Exit;
|
||
|
end;
|
||
|
if Assigned(FOnISupport) then
|
||
|
begin
|
||
|
LParams := TStringList.Create;
|
||
|
try
|
||
|
for I := 1 to ASender.Params.Count-1 do // skip nickname
|
||
|
begin
|
||
|
LParams.Add(ASender.Params[I]);
|
||
|
end;
|
||
|
OnISupport(ASender.Context, LParams);
|
||
|
finally
|
||
|
LParams.Free;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandBOUNCE(ASender: TIdCommand);
|
||
|
begin
|
||
|
DoBounce(ASender, False);
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandAWAY(ASender: TIdCommand);
|
||
|
var
|
||
|
LCmd: Integer;
|
||
|
begin
|
||
|
LCmd := IndyStrToInt(ASender.CommandHandler.Command, 0);
|
||
|
case LCmd of
|
||
|
301:
|
||
|
begin
|
||
|
if Assigned(FOnAway) then begin
|
||
|
OnAway(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0], True);
|
||
|
end;
|
||
|
end;
|
||
|
305, 306:
|
||
|
begin
|
||
|
FUserAway := (LCmd = 306);
|
||
|
if Assigned(FOnAway) then begin
|
||
|
OnAway(ASender.Context, GetUsedNickname, '', ASender.Params[0], FUserAway);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandUSERHOST(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnUserInfo) then begin
|
||
|
OnUserInfoReceived(ASender.Context, ASender.UnparsedParams);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandISON(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnIsOnIRC) then begin
|
||
|
OnIsOnIRC(ASender.Context, FSenderNick, FSenderHost);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandWHOIS(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FWhoIs) then begin
|
||
|
FWhoIs := TStringList.Create;
|
||
|
end;
|
||
|
FWhoIs.Add(ASender.Params[0]);
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFWHOIS(ASender: TIdCommand);
|
||
|
begin
|
||
|
CommandWHOIS(ASender);
|
||
|
if Assigned(FOnWhoIs) then begin
|
||
|
OnWhoIs(ASender.Context, FWhoIs);
|
||
|
end;
|
||
|
FWhoIs.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandWHOWAS(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FWhoWas) then begin
|
||
|
FWhoWas := TStringList.Create;
|
||
|
end;
|
||
|
FWhoWas.Add(ASender.Params[0]);
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFWHOWAS(ASender: TIdCommand);
|
||
|
begin
|
||
|
CommandWHOWAS(ASender);
|
||
|
if Assigned(FOnWhoWas) then begin
|
||
|
OnWhoWas(ASender.Context, FWhoWas);
|
||
|
end;
|
||
|
FWhoWas.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandLISTSTART(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FSvrList) then begin
|
||
|
FSvrList := TStringList.Create;
|
||
|
end else begin
|
||
|
FSvrList.Clear;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandLIST(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FSvrList) then begin
|
||
|
FSvrList := TStringList.Create;
|
||
|
end;
|
||
|
FSvrList.Add(ASender.Params[0] + ' ' + ASender.Params[1] + ' ' + ASender.Params[2]); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandLISTEND(ASender: TIdCommand);
|
||
|
begin
|
||
|
CommandLIST(ASender);
|
||
|
if Assigned(FOnSvrList) then begin
|
||
|
OnServerListReceived(ASender.Context, FSvrList);
|
||
|
end;
|
||
|
FSvrList.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandINVITING(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnInviting) then begin
|
||
|
OnInviting(ASender.Context, FSenderNick, FSenderHost);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandSUMMONING(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnSummon) then begin
|
||
|
OnSummon(ASender.Context, FSenderNick, FSenderHost);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandINVITELIST(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FInvites) then begin
|
||
|
FInvites := TStringList.Create;
|
||
|
end;
|
||
|
// TODO: use a collection instead
|
||
|
FInvites.Add(ASender.Params[0] + ' ' + ASender.Params[1]); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFINVITELIST(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FInvites) then begin
|
||
|
FInvites := TStringList.Create;
|
||
|
end;
|
||
|
FInvites.Add(ASender.Params[0]);
|
||
|
if Assigned(FOnINVList) then begin
|
||
|
OnInvitationListReceived(ASender.Context, FSenderNick, FInvites);
|
||
|
end;
|
||
|
FInvites.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandEXCEPTLIST(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FExcepts) then begin
|
||
|
FExcepts := TStringList.Create;
|
||
|
end;
|
||
|
// TODO: use a collection instead
|
||
|
FExcepts.Add(ASender.Params[0] + ' ' + ASender.Params[1]); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFEXCEPTLIST(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FExcepts) then begin
|
||
|
FExcepts := TStringList.Create;
|
||
|
end;
|
||
|
FExcepts.Add(ASender.Params[0]);
|
||
|
if Assigned(FOnEXCList) then begin
|
||
|
OnExceptionListReceived(ASender.Context, FSenderNick, FExcepts);
|
||
|
end;
|
||
|
FExcepts.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandWHOREPLY(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FWho) then begin
|
||
|
FWho := TStringList.Create;
|
||
|
end;
|
||
|
FWho.Add(''); // TODO
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFWHO(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FWho) then begin
|
||
|
FWho := TStringList.Create;
|
||
|
end;
|
||
|
FWho.Add(ASender.Params[0]);
|
||
|
if Assigned(FOnWho) then begin
|
||
|
OnWho(ASender.Context, FWho);
|
||
|
end;
|
||
|
FWho.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandNAMEREPLY(ASender: TIdCommand);
|
||
|
var
|
||
|
i: Integer;
|
||
|
LNames: string;
|
||
|
LNameList: TStringList;
|
||
|
begin
|
||
|
if not Assigned(FNames) then begin
|
||
|
FNames := TStringList.Create;
|
||
|
end;
|
||
|
// AWinkelsdorf 3/10/2010 Rewrote logic to split Names into single Lines of FNames
|
||
|
if ASender.Params.Count >= 4 then begin // Names are in [3]
|
||
|
LNames := StringsReplace(ASender.Params[3], [' '], [',']); {do not localize}
|
||
|
LNameList := TStringList.Create;
|
||
|
try
|
||
|
LNameList.CommaText := LNames;
|
||
|
for i := 0 to LNameList.Count - 1 do
|
||
|
begin
|
||
|
if LNameList[i] <> '' then
|
||
|
FNames.Add(LNameList[i]);
|
||
|
end;
|
||
|
finally
|
||
|
LNameList.Free;
|
||
|
end;
|
||
|
end else begin
|
||
|
FNames.Add(ASender.Params[0]);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFNAMES(ASender: TIdCommand);
|
||
|
var
|
||
|
LChannel: string;
|
||
|
begin
|
||
|
if not Assigned(FNames) then begin
|
||
|
FNames := TStringList.Create;
|
||
|
end;
|
||
|
LChannel := '';
|
||
|
if ASender.Params.Count > 0 then begin
|
||
|
LChannel := ASender.Params[1];
|
||
|
end;
|
||
|
if Assigned(FOnNickList) then begin
|
||
|
OnNicknamesListReceived(ASender.Context, LChannel, FNames);
|
||
|
end;
|
||
|
FNames.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandLINKS(ASender: TIdCommand);
|
||
|
var
|
||
|
LHopCnt, LInfo: String;
|
||
|
begin
|
||
|
if not Assigned(FLinks) then begin
|
||
|
FLinks := TStringList.Create;
|
||
|
end;
|
||
|
LInfo := ASender.Params[2];
|
||
|
LHopCnt := Fetch(LInfo);
|
||
|
// TODO: use a collection instead
|
||
|
FLinks.Add(ASender.Params[0] + ' ' + ASender.Params[1] + ' ' + LHopCnt + ' ' + LInfo); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFLINKS(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FLinks) then begin
|
||
|
FLinks := TStringList.Create;
|
||
|
end;
|
||
|
FLinks.Add(ASender.Params[0]);
|
||
|
if Assigned(FOnKnownSvrs) then begin
|
||
|
OnKnownServersListReceived(ASender.Context, FLinks);
|
||
|
end;
|
||
|
FLinks.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandBANLIST(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FBans) then begin
|
||
|
FBans := TStringList.Create;
|
||
|
end;
|
||
|
// TODO: use a collection instead
|
||
|
FBans.Add(ASender.Params[0] + ' ' + ASender.Params[1]); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFBANLIST(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FBans) then begin
|
||
|
FBans := TStringList.Create;
|
||
|
end;
|
||
|
FBans.Add(ASender.Params[0]);
|
||
|
if Assigned(FOnBanList) then begin
|
||
|
OnBanListReceived(ASender.Context, FSenderNick, FBans);
|
||
|
end;
|
||
|
FBans.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandINFO(ASender: TIdCommand);
|
||
|
begin
|
||
|
// TODO
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFINFO(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnUserInfo) then begin
|
||
|
OnUserInfoReceived(ASender.Context, ASender.UnparsedParams);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandMOTD(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FMotd) then begin
|
||
|
FMotd := TStringList.Create;
|
||
|
end;
|
||
|
FMotd.Add(ASender.Params[0]);
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFMOTD(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FMotd) then begin
|
||
|
FMotd := TStringList.Create;
|
||
|
end;
|
||
|
if Assigned(FOnMOTD) then begin
|
||
|
OnMOTD(ASender.Context, FMotd);
|
||
|
end;
|
||
|
FMotd.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandREHASHING(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnRehash) then begin
|
||
|
OnRehash(ASender.Context, FSenderNick, FSenderHost);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandUSERSSTART(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FUsers) then begin
|
||
|
FUsers := TStringList.Create;
|
||
|
end else begin
|
||
|
FUsers.Clear;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandUSERS(ASender: TIdCommand);
|
||
|
begin
|
||
|
if ASender.CommandHandler.Command = '393' then {do not localize}
|
||
|
begin
|
||
|
if not Assigned(FUsers) then begin
|
||
|
FUsers := TStringList.Create;
|
||
|
end;
|
||
|
// TODO: use a collection instead
|
||
|
FUsers.Add(ASender.Params[0] + ' ' + ASender.Params[1] + ' ' + ASender.Params[2]); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFUSERS(ASender: TIdCommand);
|
||
|
begin
|
||
|
if not Assigned(FUsers) then begin
|
||
|
FUsers := TStringList.Create;
|
||
|
end;
|
||
|
if Assigned(FOnSvrUsers) then begin
|
||
|
OnServerUsersListReceived(ASender.Context, FUsers);
|
||
|
end;
|
||
|
FUsers.Clear;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandENDOFSTATS(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnSvrStats) then begin
|
||
|
OnServerStatsReceived(ASender.Context, nil); // TODO
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandSERVLIST(ASender: TIdCommand);
|
||
|
begin
|
||
|
// <name> <server> <mask> <type> <hopcount> <info>
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandSERVLISTEND(ASender: TIdCommand);
|
||
|
begin
|
||
|
// <mask> <type> :<info>
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandTIME(ASender: TIdCommand);
|
||
|
var
|
||
|
LServer, LTimeString: String;
|
||
|
begin
|
||
|
if Assigned(FOnSvrTime) then begin
|
||
|
LServer := ASender.Params[0];
|
||
|
case ASender.Params.Count of
|
||
|
2: begin // "<server> :<time string>"
|
||
|
LTimeString := ASender.Params[1];
|
||
|
end;
|
||
|
4: begin // "<server> <timestamp> <offset> :<time string>" or "<server> <timezone name> <microseconds> :<time string>"
|
||
|
LTimeString := IndyFormat('%s %s %s', [ASender.Params[1], ASender.Params[2], ASender.Params[3]]); {do not localize}
|
||
|
end;
|
||
|
7: begin // "<server> <year> <month> <day> <hour> <minute> <second>"
|
||
|
LTimeString := IndyFormat('%s %s %s %s %s %s', {do not localize}
|
||
|
[ASender.Params[1], ASender.Params[2], ASender.Params[3],
|
||
|
ASender.Params[4], ASender.Params[5], ASender.Params[6]]);
|
||
|
end;
|
||
|
end;
|
||
|
OnServerTime(ASender.Context, LServer, LTimeString);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandSERVICE(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnService) then begin
|
||
|
OnService(ASender.Context);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandVERSION(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnSvrVersion) then begin
|
||
|
OnServerVersion(ASender.Context, ASender.Params[0], ASender.Params[1], ASender.Params[2]);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandCHANMODE(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnChanMode) then begin
|
||
|
OnChannelMode(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0], ASender.Params[1], ASender.Params[2]);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandOPER(ASender: TIdCommand);
|
||
|
begin
|
||
|
if Assigned(FOnOp) then begin
|
||
|
OnOp(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0]);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CommandNICKINUSE(ASender: TIdCommand);
|
||
|
begin
|
||
|
if ASender.CommandHandler.Command = '433' then {do not localize}
|
||
|
begin
|
||
|
if (Connected) and (FAltNickname <> '') then
|
||
|
begin
|
||
|
if not FAltNickUsed then begin
|
||
|
// try only once using AltNickname (FAltNickUsed is cleared in .Connect)
|
||
|
SetNickname(FAltNickname);
|
||
|
FAltNickUsed := True;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
// already tried to use AltNickName...
|
||
|
if Assigned(FOnNickError) then begin
|
||
|
OnNicknameError(ASender.Context, IndyStrToInt(ASender.CommandHandler.Command));
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.ParseDCC(AContext: TIdContext; const ADCC: String);
|
||
|
const
|
||
|
IdIRCDCC: array[0..3] of String = ('SEND', 'CHAT', 'RESUME', 'ACCEPT'); {do not localize}
|
||
|
var
|
||
|
LTmp, LType, LArg, LAddr, LPort, LSize: String;
|
||
|
begin
|
||
|
LTmp := ADCC;
|
||
|
LType := FetchIRCParam(LTmp);
|
||
|
LArg := FetchIRCParam(LTmp);
|
||
|
LAddr := FetchIRCParam(LTmp);
|
||
|
LPort := FetchIRCParam(LTmp);
|
||
|
LSize := FetchIRCParam(LTmp);
|
||
|
//
|
||
|
case PosInStrArray(LType, IdIRCDCC) of
|
||
|
0: {SEND}
|
||
|
begin
|
||
|
if Assigned(FOnDCCSend) then begin
|
||
|
FOnDCCSend(AContext, FSenderNick, LAddr, ExtractFileName(LArg), IndyStrToInt(LPort), IndyStrToInt64(LSize));
|
||
|
end;
|
||
|
end;
|
||
|
1: {CHAT}
|
||
|
begin
|
||
|
if Assigned(FOnDCCChat) then begin
|
||
|
FOnDCCChat(AContext, FSenderNick, LAddr, IndyStrToInt(LPort));
|
||
|
end;
|
||
|
end;
|
||
|
2: {RESUME}
|
||
|
begin
|
||
|
if Assigned(FOnDCCResume) then begin
|
||
|
FOnDCCResume(AContext, FSenderNick, LAddr, LArg, IndyStrToInt(LPort), IndyStrToInt64(LSize));
|
||
|
end;
|
||
|
end;
|
||
|
3: {ACCEPT}
|
||
|
begin
|
||
|
if Assigned(FOnDCCAccept) then begin
|
||
|
FOnDCCAccept(AContext, FSenderNick, LAddr, LArg, IndyStrToInt(LPort), IndyStrToInt64(LSize));
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdIRC.GetUsedNickname: String;
|
||
|
begin
|
||
|
if FAltNickUsed then
|
||
|
Result := FAltNickname
|
||
|
else
|
||
|
Result := FNickname;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetNickname(const AValue: String);
|
||
|
begin
|
||
|
if not Connected then begin
|
||
|
FNickname := AValue;
|
||
|
end else begin
|
||
|
Raw(IndyFormat('NICK %s', [AValue])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetUsername(const AValue: String);
|
||
|
begin
|
||
|
if not Connected then begin
|
||
|
FUsername := AValue;
|
||
|
end else begin
|
||
|
Raw(IndyFormat('USER %s %s %s :%s', [AValue, GetUserMode, '*', FRealName])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetIdIRCUserMode(AValue: TIdIRCUserModes);
|
||
|
begin
|
||
|
FUserMode := AValue;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetIdIRCReplies(AValue: TIdIRCReplies);
|
||
|
begin
|
||
|
FReplies.Assign(AValue);
|
||
|
end;
|
||
|
|
||
|
function TIdIRC.IsChannel(const AChannel: String): Boolean;
|
||
|
begin
|
||
|
//Result := (Length(AChannel) > 0) and CharIsInSet(AChannel, 1, ['&','#','+','!']); {do not localize}
|
||
|
Result := CharIsInSet(AChannel, 1, '&#+!'); {do not localize}
|
||
|
end;
|
||
|
|
||
|
function TIdIRC.IsOp(const ANickname: String): Boolean;
|
||
|
begin
|
||
|
Result := TextStartsWith(ANickname, '@');
|
||
|
end;
|
||
|
|
||
|
function TIdIRC.IsVoice(const ANickname: String): Boolean;
|
||
|
begin
|
||
|
Result := TextEndsWith(ANickname, '+');
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Say(const ATarget, AMsg: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('PRIVMSG %s :%s', [ATarget, AMsg])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Notice(const ATarget, AMsg: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('NOTICE %s :%s', [ATarget, AMsg])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Action(const ATarget, AMsg: String);
|
||
|
begin
|
||
|
CTCPQuery(ATarget, 'ACTION', AMsg); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CTCPQuery(const ATarget, ACommand, AParameters: String);
|
||
|
var
|
||
|
LTmp: String;
|
||
|
begin
|
||
|
LTmp := UpperCase(ACommand);
|
||
|
if AParameters <> '' then begin
|
||
|
LTmp := LTmp + ' ' + AParameters;
|
||
|
end;
|
||
|
Say(ATarget, XDelim+CTCPQuote(LTmp)+XDelim); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.CTCPReply(const ATarget, ACTCP, AReply: String);
|
||
|
var
|
||
|
LTmp: String;
|
||
|
begin
|
||
|
LTmp := ACTCP;
|
||
|
if AReply <> '' then begin
|
||
|
LTmp := LTmp + ' ' + AReply;
|
||
|
end;
|
||
|
Notice(ATarget, XDelim+CTCPQuote(LTmp)+XDelim); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Join(const AChannel: String; const AKey: String = '');
|
||
|
begin
|
||
|
if IsChannel(AChannel) then begin
|
||
|
if AKey <> '' then begin
|
||
|
Raw(IndyFormat('JOIN %s %s', [AChannel, AKey])) {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('JOIN %s', [AChannel])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Part(const AChannel: String; const AReason: String = '');
|
||
|
begin
|
||
|
if IsChannel(AChannel) then begin
|
||
|
if AReason <> '' then begin
|
||
|
Raw(IndyFormat('PART %s :%s', [AChannel, AReason])) {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('PART %s', [AChannel])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Kick(const AChannel, ANickname: String; const AReason: String = '');
|
||
|
begin
|
||
|
if IsChannel(AChannel) then begin
|
||
|
if AReason <> '' then begin
|
||
|
Raw(IndyFormat('KICK %s %s :%s', [AChannel, ANickname, AReason])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('KICK %s %s', [AChannel, ANickname])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetChannelMode(const AChannel, AMode: String; const AParams: String = '');
|
||
|
begin
|
||
|
if IsChannel(AChannel) then begin
|
||
|
if AParams = '' then begin
|
||
|
Raw(IndyFormat('MODE %s %s', [AChannel, AMode])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('MODE %s %s %s', [AChannel, AMode, AParams])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetUserMode(const ANickname, AMode: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('MODE %s %s', [ANickname, AMode])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.GetChannelTopic(const AChannel: String);
|
||
|
begin
|
||
|
if IsChannel(AChannel) then begin
|
||
|
Raw(IndyFormat('TOPIC %s', [AChannel])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetChannelTopic(const AChannel, ATopic: String);
|
||
|
begin
|
||
|
if IsChannel(AChannel) then begin
|
||
|
Raw(IndyFormat('TOPIC %s :%s', [AChannel, ATopic])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetAway(const AMsg: String);
|
||
|
begin
|
||
|
if AMsg <> '' then begin
|
||
|
Raw(IndyFormat('AWAY :%s', [AMsg])); {do not localize}
|
||
|
end else begin
|
||
|
Raw('AWAY'); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Op(const AChannel, ANickname: String);
|
||
|
begin
|
||
|
SetChannelMode(AChannel, '+o', ANickname); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Deop(const AChannel, ANickname: String);
|
||
|
begin
|
||
|
SetChannelMode(AChannel, '-o', ANickname); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Voice(const AChannel, ANickname: String);
|
||
|
begin
|
||
|
SetChannelMode(AChannel, '+v', ANickname); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Devoice(const AChannel, ANickname: String);
|
||
|
begin
|
||
|
SetChannelMode(AChannel, '-v', ANickname); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Ban(const AChannel, AHostmask: String);
|
||
|
begin
|
||
|
SetChannelMode(AChannel, '+b', AHostmask); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Unban(const AChannel, AHostmask: String);
|
||
|
begin
|
||
|
SetChannelMode(AChannel, '-b', AHostmask); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.RegisterService(const ANickname, ADistribution, AInfo: String; AType: Integer);
|
||
|
begin
|
||
|
Raw(IndyFormat('SERVICE %s * %s %s 0 :%s', {do not localize}
|
||
|
[ANickname, ADistribution, AType, AInfo]));
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.ListChannelNicknames(const AChannel: String; const ATarget: String = '');
|
||
|
begin
|
||
|
if IsChannel(AChannel) then begin
|
||
|
if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('NAMES %s %s', [AChannel, ATarget])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('NAMES %s', [AChannel])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.ListChannel(const AChannel: String; const ATarget: String = '');
|
||
|
begin
|
||
|
if IsChannel(AChannel) then begin
|
||
|
if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('LIST %s %s', [AChannel, ATarget])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('LIST %s', [AChannel])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Invite(const ANickname, AChannel: String);
|
||
|
begin
|
||
|
if IsChannel(AChannel) then begin
|
||
|
Raw(IndyFormat('INVITE %s %s', [ANickname, AChannel])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.GetMessageOfTheDay(const ATarget: String = '');
|
||
|
begin
|
||
|
if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('MOTD %s', [ATarget])); {do not localize}
|
||
|
end else begin
|
||
|
Raw('MOTD'); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.GetNetworkStatus(const AHostMask: String = ''; const ATarget: String = '');
|
||
|
begin
|
||
|
if (AHostMask = '') and (ATarget = '') then begin
|
||
|
Raw('LUSERS'); {do not localize}
|
||
|
end
|
||
|
else if AHostMask = '' then begin
|
||
|
Raw(IndyFormat('LUSERS %s', [ATarget])); {do not localize}
|
||
|
end
|
||
|
else if ATarget = '' then begin
|
||
|
Raw(IndyFormat('LUSERS %s', [AHostMask])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('LUSERS %s %s', [AHostMask, ATarget])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.GetServerVersion(const ATarget: String = '');
|
||
|
begin
|
||
|
if ATarget = '' then begin
|
||
|
Raw('VERSION'); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('VERSION %s', [ATarget])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.GetServerStatus(AQuery: TIdIRCStat; const ATarget: String = '');
|
||
|
const
|
||
|
IdIRCStatChars: array[TIdIRCStat] of Char = ('l', 'm', 'o', 'u'); {do not localize}
|
||
|
begin
|
||
|
if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('STATS %s %s', [IdIRCStatChars[AQuery], ATarget])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('STATS %s', [IdIRCStatChars[AQuery]])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.ListKnownServerNames(const ARemoteHost: String = ''; const AHostMask: String = '');
|
||
|
begin
|
||
|
if (ARemoteHost = '') and (AHostMask = '') then begin
|
||
|
Raw('LINKS'); {do not localize}
|
||
|
end
|
||
|
else if ARemoteHost = '' then begin
|
||
|
Raw(IndyFormat('LINKS %s', [AHostMask])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('LINKS %s %s', [ARemoteHost, AHostMask])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.QueryServerTime(const ATarget: String = '');
|
||
|
begin
|
||
|
if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('TIME %s', [ATarget])); {do not localize}
|
||
|
end else begin
|
||
|
Raw('TIME'); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.RequestServerConnect(const ATargetHost: String; APort: Integer;
|
||
|
const ARemoteHost: String = '');
|
||
|
begin
|
||
|
if ARemoteHost <> '' then begin
|
||
|
Raw(IndyFormat('CONNECT %s %d %s', [ATargetHost, APort, ARemoteHost])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('CONNECT %s %d', [ATargetHost, APort])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.TraceServer(const ATarget: String = '');
|
||
|
begin
|
||
|
if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('TRACE %s', [ATarget])); {do not localize}
|
||
|
end else begin
|
||
|
Raw('TRACE'); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.GetAdminInfo(const ATarget: String = '');
|
||
|
begin
|
||
|
if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('ADMIN %s', [ATarget])); {do not localize}
|
||
|
end else begin
|
||
|
Raw('ADMIN'); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.GetServerInfo(const ATarget: String = '');
|
||
|
begin
|
||
|
if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('INFO %s', [ATarget])); {do not localize}
|
||
|
end else begin
|
||
|
Raw('INFO'); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.ListNetworkServices(const AHostMask: String = ''; const AType: String = '');
|
||
|
begin
|
||
|
if (AHostMask = '') and (AType = '') then begin
|
||
|
Raw('SERVLIST'); {do not localize}
|
||
|
end
|
||
|
else if AType <> '' then begin
|
||
|
Raw(IndyFormat('SERVLIST %s %s', [AHostMask, AType])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('SERVLIST %s', [AHostMask])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.QueryService(const AServiceName, AMessage: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('SQUERY %s :%s', [AServiceName, AMessage])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Who(const AMask: String; AOnlyAdmins: Boolean);
|
||
|
begin
|
||
|
if (AMask = '') and (not AOnlyAdmins) then begin
|
||
|
Raw('WHO'); {do not localize}
|
||
|
end
|
||
|
else if AOnlyAdmins then begin
|
||
|
Raw(IndyFormat('WHO %s o', [AMask])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('WHO %s', [AMask])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.WhoIs(const AMask: String; const ATarget: String = '');
|
||
|
begin
|
||
|
if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('WHOIS %s %s', [ATarget, AMask])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('WHOIS %s', [AMask])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.WhoWas(const ANickname: String; ACount: Integer = -1; const ATarget: String = '');
|
||
|
begin
|
||
|
if (ATarget = '') and (ACount < 0) then begin
|
||
|
Raw(IndyFormat('WHOWAS %s', [ANickname])); {do not localize}
|
||
|
end
|
||
|
else if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('WHOWAS %s %d %s', [ANickname, ACount, ATarget])); {do not localize}
|
||
|
end
|
||
|
else begin
|
||
|
Raw(IndyFormat('WHOWAS %s %d', [ANickname, ACount])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Kill(const ANickname, AComment: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('KILL %s :%s', [ANickname, AComment])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Ping(const AServer1: String; const AServer2: String = '');
|
||
|
begin
|
||
|
if AServer2 <> '' then begin
|
||
|
Raw(IndyFormat('PING %s %s', [AServer1, AServer2])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('PING %s', [AServer1])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Pong(const AServer1: String; const AServer2: String = '');
|
||
|
begin
|
||
|
if AServer2 <> '' then begin
|
||
|
Raw(IndyFormat('PONG %s %s', [AServer1, AServer2])); {do not localize}
|
||
|
end else begin
|
||
|
Raw(IndyFormat('PONG %s', [AServer1])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Error(const AMessage: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('ERROR :%s', [AMessage])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.ReHash;
|
||
|
begin
|
||
|
Raw('REHASH'); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Die;
|
||
|
begin
|
||
|
Raw('DIE'); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Restart;
|
||
|
begin
|
||
|
Raw('RESTART'); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.Summon(const ANickname: String; const ATarget: String = '';
|
||
|
const AChannel: String = '');
|
||
|
begin
|
||
|
if (ATarget = '') and (AChannel = '') then begin
|
||
|
Raw(IndyFormat('SUMMON %s', [ANickname])); {do not localize}
|
||
|
end
|
||
|
else if AChannel <> '' then
|
||
|
begin
|
||
|
if IsChannel(AChannel) then begin
|
||
|
Raw(IndyFormat('SUMMON %s %s %s', [ANickname, ATarget, AChannel])); {do not localize}
|
||
|
end;
|
||
|
end else begin
|
||
|
Raw(IndyFormat('SUMMON %s %s', [ANickname, ATarget])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.ListServerUsers(const ATarget: String = '');
|
||
|
begin
|
||
|
if ATarget <> '' then begin
|
||
|
Raw(IndyFormat('USERS %s', [ATarget])); {do not localize}
|
||
|
end else begin
|
||
|
Raw('USERS'); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SayWALLOPS(const AMessage: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('WALLOPS :%s', [AMessage])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.GetUserInfo(const ANickname: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('USERHOST %s', [ANickname])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.GetUsersInfo(const ANicknames: array of string);
|
||
|
var
|
||
|
I: Integer;
|
||
|
S: string;
|
||
|
begin
|
||
|
if Length(ANicknames) > 0 then
|
||
|
begin
|
||
|
for I := Low(ANicknames) to High(ANicknames) do begin
|
||
|
S := S + ' ' + ANicknames[I]; {do not localize}
|
||
|
end;
|
||
|
Raw(IndyFormat('USERHOST%s', [S])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.IsOnIRC(const ANickname: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('ISON %s', [ANickname])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.IsOnIRC(const ANicknames: array of String);
|
||
|
var
|
||
|
I: Integer;
|
||
|
S: string;
|
||
|
begin
|
||
|
if Length(ANicknames) > 0 then
|
||
|
begin
|
||
|
for I := Low(ANicknames) to High(ANicknames) do begin
|
||
|
S := S + ' ' + ANicknames[I]; {do not localize}
|
||
|
end;
|
||
|
Raw(IndyFormat('ISON%s', [S])); {do not localize}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.BecomeOp(const ANickname, APassword: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('OPER %s %s', [ANickname, APassword])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SQuit(const AHost, AComment: String);
|
||
|
begin
|
||
|
Raw(IndyFormat('SQUIT %s :%s', [AHost, AComment])); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetChannelLimit(const AChannel: String; ALimit: Integer);
|
||
|
begin
|
||
|
SetChannelMode(AChannel, '+l', IntToStr(ALimit)); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetChannelKey(const AChannel, AKey: String);
|
||
|
begin
|
||
|
SetChannelMode(AChannel, '+k', AKey); {do not localize}
|
||
|
end;
|
||
|
|
||
|
procedure TIdIRC.SetIOHandler(AValue: TIdIOHandler);
|
||
|
begin
|
||
|
inherited SetIOHandler(AValue);
|
||
|
//we do it this way so that if a user is using a custom value <> default, the port
|
||
|
//is not set when the IOHandler is changed.
|
||
|
if (IOHandler is TIdSSLIOHandlerSocketBase) then begin
|
||
|
if Port = IdPORT_IRC then begin
|
||
|
Port := IdPORT_IRCS;
|
||
|
end;
|
||
|
end else begin
|
||
|
if Port = IdPORT_IRCS then begin
|
||
|
Port := IdPORT_IRC;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
end.
|
||
|
|
||
|
|