Skip to content

Commit e6b8424

Browse files
committed
feat: Database and replay thread
1 parent 4f1ef66 commit e6b8424

File tree

7 files changed

+356
-89
lines changed

7 files changed

+356
-89
lines changed

pasirclogbot.example.config

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
[IRC]
2-
Host="localhost"
2+
Host="irc.libera.chat"
33
Port=6667
44
NickName="[PasLogBot]"
55
UserName="paslogbot"
66
RealName="IRC channel #pascal log bot"
7-
Channel="#pascal"
7+
Channel="#PasLogBot"
8+
[DB]
9+
File="paslogbot.db"

paslogbot.db

20 KB
Binary file not shown.

src/bot/irclogbot.bot.pas

Lines changed: 146 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,37 @@ interface
99
, SysUtils
1010
, IdContext
1111
, IdIRC
12+
, IRCLogBot.Config
13+
, IRCLogBot.Database
1214
;
1315

1416
type
1517
{ TIRCLogBot }
1618
TIRCLogBot = class(TObject)
1719
private
1820
FIRC: TIdIRC;
19-
FNickName: String;
20-
FUserName: String;
21-
FRealName: String;
22-
FHost: String;
23-
FPort: Word;
24-
FChannel: String;
25-
2621
FJoinedChannel: Boolean;
2722

23+
FConfig: TBotConfig;
24+
25+
FDB: TDatabase;
26+
2827
procedure OnConnected(Sender: TObject);
2928
procedure OnDisconnected(Sender: TObject);
3029
procedure OnNotice(ASender: TIdContext; const ANickname, AHost,
3130
ATarget, ANotice: String);
31+
procedure OnServerQuit(ASender: TIdContext; const ANickname, AHost,
32+
AServer, AReason: String);
3233
procedure OnJoin(ASender: TIdContext; const ANickname, AHost,
3334
AChannel: String);
3435
procedure OnPrivateMessage(ASender: TIdContext; const ANickname, AHost,
3536
ATarget, AMessage: String);
3637

3738
procedure Help(const ATarget: String);
38-
procedure Replay(const ATarget: String; Count: Integer);
39+
procedure Replay(const ATarget: String; ACount: Integer);
3940
protected
4041
public
41-
constructor Create(AHost: String; APort: Word;
42-
ANickName, AUserName, ARealName, AChannel: String);
42+
constructor Create(const AConfig: TBotConfig);
4343
destructor Destroy; override;
4444

4545
procedure Run;
@@ -53,6 +53,70 @@ implementation
5353
IRCLogBot.Common
5454
;
5555

56+
type
57+
{ TReplayThread }
58+
TReplayThread = class(TTHread)
59+
private
60+
FIRC: TIdIRC;
61+
FTarget: String;
62+
FLines: TStringList;
63+
protected
64+
procedure Execute; override;
65+
public
66+
constructor Create(const AIRC: TIdIRC; const ATarget: String;
67+
const ALines: TStringList);
68+
published
69+
end;
70+
71+
{ TReplayThread }
72+
73+
procedure TReplayThread.Execute;
74+
var
75+
line: String;
76+
index: Integer = 0;
77+
begin
78+
if not FIRC.Connected then;
79+
begin
80+
debug('Exiting replay thread due not being connected.');
81+
exit;
82+
end;
83+
try
84+
FIRC.Say(FTarget, '!! --> To avoid triggering flooding, for each 5 lines, I will pause for 5 seconds <-- !!');
85+
FIRC.Say(FTarget, Format('*** Here are the last %d lines ***', [FLines.Count]));
86+
for line in FLines do
87+
begin
88+
if (Terminated) or (not FIRC.Connected) then
89+
begin
90+
debug('Exiting replay thread due to termination or not being connected.');
91+
exit;
92+
end;
93+
debug('Sending #%d: "%s"', [index, line]);
94+
Inc(index);
95+
FIRC.Say(FTarget, line);
96+
if (index mod 5) = 0 then
97+
begin
98+
debug('Pausing');
99+
Sleep(5000);
100+
end;
101+
end;
102+
FIRC.Say(FTarget, Format('*** End of the last %d lines ***', [FLines.Count]));
103+
finally
104+
FLines.Free;
105+
end;
106+
end;
107+
108+
constructor TReplayThread.Create(const AIRC: TIdIRC; const ATarget: String;
109+
const ALines: TStringList);
110+
begin
111+
inherited Create(True);
112+
FIRC:= AIRC;
113+
FTarget:= ATarget;
114+
FLines:= TStringList.Create;
115+
FLines.Text := ALines.Text;
116+
FreeOnTerminate:= True;
117+
Start;
118+
end;
119+
56120
{ TIRCLogBot }
57121

58122
procedure TIRCLogBot.OnConnected(Sender: TObject);
@@ -68,21 +132,34 @@ procedure TIRCLogBot.OnDisconnected(Sender: TObject);
68132
procedure TIRCLogBot.OnNotice(ASender: TIdContext; const ANickname, AHost,
69133
ATarget, ANotice: String);
70134
begin
71-
debug('>> NOTICE: <%s> "%s"', [
135+
debug('>> NOTICE: <%s:%s> (%s) "%s"', [
72136
ANickname,
137+
AHost,
138+
ATarget,
73139
ANotice
74140
]);
75141
end;
76142

143+
procedure TIRCLogBot.OnServerQuit(ASender: TIdContext; const ANickname, AHost,
144+
AServer, AReason: String);
145+
begin
146+
debug('>> QUIT: <%s:%s> %s "%s"',[
147+
ANickname,
148+
AHost,
149+
AServer,
150+
AReason
151+
]);
152+
end;
153+
77154
procedure TIRCLogBot.OnJoin(ASender: TIdContext; const ANickname, AHost,
78155
AChannel: String);
79156
begin
80-
debug('>> JOIN: <%s@%s> %s', [
157+
debug('>> JOIN: <%s:%s> %s', [
81158
ANickname,
82159
AHost,
83160
AChannel
84161
]);
85-
if (ANickname = FNickName) and (AChannel = FChannel) then
162+
if (ANickname = FConfig.NickName) and (AChannel = FConfig.Channel) then
86163
begin
87164
debug('Successfully joined my channel');
88165
FJoinedChannel:= True;
@@ -96,13 +173,24 @@ procedure TIRCLogBot.OnPrivateMessage(ASender: TIdContext; const ANickname,
96173
strings: TStringArray;
97174
count: Integer;
98175
begin
99-
debug('>> PRIVMSG: <%s@%s>(%s) "%s"', [
176+
debug('>> PRIVMSG: <%s:%s>(%s) "%s"', [
100177
ANickname,
101178
AHost,
102179
ATarget,
103180
AMessage
104181
]);
105-
if ATarget = FNickName then
182+
if ATarget = FConfig.Channel then
183+
begin
184+
debug('Inserting: %s, %s, %s, %s', [
185+
ANickname,
186+
AHost,
187+
ATarget,
188+
AMessage
189+
]);
190+
FDB.Insert(ANickname, ATarget, AMessage);
191+
exit;
192+
end;
193+
if ATarget = FConfig.NickName then
106194
begin
107195
if Pos('.', AMessage) = 1 then
108196
begin
@@ -115,18 +203,23 @@ procedure TIRCLogBot.OnPrivateMessage(ASender: TIdContext; const ANickname,
115203
if Pos('.replay', Trim(AMessage)) = 1 then
116204
begin
117205
strings:= AMessage.Split([' ']);
206+
//debug('Strings: %d', [Length(strings)]);
118207
try
119208
if Length(strings) > 1 then
120209
begin
121210
count:= StrToInt(strings[1]);
122211
end
123212
else
124213
begin
125-
count:= 0;
214+
count:= 10;
126215
end;
216+
//debug('Count: %d', [count]);
127217
Replay(ANickname, count);
128218
except
129-
FIRC.Say(ANickname, 'That <count> is not a number.');
219+
on e:Exception do
220+
begin
221+
FIRC.Say(ANickname, 'Something went wrong: "' + e.Message + '". It''s been logged. Please contact the admin if I stop working.');
222+
end;
130223
end;
131224
exit;
132225
end;
@@ -136,6 +229,7 @@ procedure TIRCLogBot.OnPrivateMessage(ASender: TIdContext; const ANickname,
136229
debug('No command.');
137230
FIRC.Say(ANickname, 'Not a command. Please use ".help" to see a list of commands.');
138231
end;
232+
exit;
139233
end;
140234
end;
141235

@@ -147,10 +241,16 @@ procedure TIRCLogBot.Help(const ATarget: String);
147241
FIRC.Say(ATarget, '.replay [count] - Raplays last <count> lines. Default is last 10 lines.');
148242
end;
149243

150-
procedure TIRCLogBot.Replay(const ATarget: String; Count: Integer);
244+
procedure TIRCLogBot.Replay(const ATarget: String; ACount: Integer);
245+
var
246+
replayThread: TReplayThread;
247+
lines: TStringList;
151248
begin
152-
debug('Replay command.');
153-
FIRC.Say(ATarget, Format('Not fully implemented yet: %d',[Count]));
249+
debug('Replay command(%d).', [ACount]);
250+
lines:= FDB.Get(ACount);
251+
debug('Lines: %d', [lines.Count]);
252+
replayThread:= TReplayThread.Create(FIRC, ATarget, lines);
253+
lines.Free;
154254
end;
155255

156256
procedure TIRCLogBot.Run;
@@ -164,9 +264,9 @@ procedure TIRCLogBot.Run;
164264
debug('Error connecting: %s', [e.Message]);
165265
end;
166266
end;
167-
debug('Joining channel: "%s"...', [FChannel]);
267+
debug('Joining channel: "%s"...', [FConfig.Channel]);
168268
try
169-
FIRC.Join(FChannel);
269+
FIRC.Join(FConfig.Channel);
170270
except
171271
on e:Exception do
172272
begin
@@ -181,7 +281,8 @@ procedure TIRCLogBot.Shutdown;
181281
begin
182282
debug('Disconnecting...');
183283
try
184-
FIRC.Disconnect('Need to go and have a wee nap.');
284+
if FJoinedChannel then FIRC.Say(FConfig.Channel, 'Boss sais I need to have a wee nap. See Y''All later...');
285+
FIRC.Disconnect('ZzZzZzZzZzZzZzZz...');
185286
except
186287
on e:Exception do
187288
begin
@@ -191,33 +292,41 @@ procedure TIRCLogBot.Shutdown;
191292
end;
192293
end;
193294

194-
constructor TIRCLogBot.Create(AHost: String; APort: Word; ANickName, AUserName,
195-
ARealName, AChannel: String);
295+
constructor TIRCLogBot.Create(const AConfig: TBotConfig);
196296
begin
197-
FNickname:= ANickname;
198-
FUsername:= AUserName;
199-
FRealName:= ARealName;
200-
FHost:= AHost;
201-
FPort:= APort;
202-
FChannel:= AChannel;
297+
FJoinedChannel:= False;
298+
299+
// Config
300+
FConfig:= AConfig;
203301

302+
// Setup IRC Client
204303
FIRC:= TIdIRC.Create;
205-
FIRC.Nickname:= FNickName;
206-
FIRC.Username:= FUserName;
207-
FIRC.RealName:= FRealName;
208-
FIRC.Host:= FHost;
209-
FIRC.Port:= FPort;
304+
FIRC.Nickname:= FConfig.NickName;
305+
FIRC.Username:= FConfig.UserName;
306+
FIRC.RealName:= FConfig.RealName;
307+
FIRC.Host:= FConfig.Host;
308+
FIRC.Port:= FConfig.Port;
210309
FIRC.OnConnected:= @OnConnected;
211310
FIRC.OnDisconnected:= @OnDisconnected;
311+
FIRC.OnServerQuit:= @OnServerQuit;
212312
FIRC.OnJoin:= @OnJoin;
213313
FIRC.OnNotice:= @OnNotice;
214314
FIRC.OnPrivateMessage:= @OnPrivateMessage;
215315

216-
FJoinedChannel:= False;
316+
// Setup Database
317+
try
318+
FDB:= TDatabase.Create(FConfig.Database);
319+
except
320+
on e:Exception do
321+
begin
322+
debug('Error creating db: ', [e.Message]);
323+
end;
324+
end;
217325
end;
218326

219327
destructor TIRCLogBot.Destroy;
220328
begin
329+
FDB.Free;
221330
FIRC.Free;
222331
inherited Destroy;
223332
end;

0 commit comments

Comments
 (0)