-
Notifications
You must be signed in to change notification settings - Fork 6
/
Slackbot.pas
116 lines (96 loc) · 2.67 KB
/
Slackbot.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
unit Slackbot;
interface
uses
System.SysUtils,
SlackbotHTTPClient;
const
SLACKBOT_CHANNEL = 'SLACKBOT_CHANNEL';
SLACKBOT_URL = 'SLACKBOT_URL';
type
THTTPPostFunc = reference to function(const URL, Msg: string): string;
TExceptionEvent = reference to procedure(E: Exception);
TSlackbot = class
private
class var FOnException: TExceptionEvent;
class procedure HandleException;
class function ReadConfigFromEnvironment(const VarName: string): string;
class procedure ValidateURL(const URL: string);
public
class var HTTPPostFunc: THTTPPostFunc;
class procedure Send(const Text: string); overload;
class procedure Send(const Channel, Text: string); overload;
class procedure Send(const URL, Channel, Text: string); overload;
class property OnException: TExceptionEvent read FOnException write FOnException;
end;
ESlackbotError = class(Exception);
implementation
uses
System.NetEncoding;
class procedure TSlackbot.HandleException;
var
E: Exception;
begin
E := AcquireExceptionObject as Exception;
if not Assigned(FOnException) then
raise E;
try
try
FOnException(E);
except
// If the exception handler crashes the show must go on
end;
finally
E.Free;
end;
end;
class procedure TSlackbot.Send(const Channel, Text: string);
var
URL: string;
begin
try
URL := ReadConfigFromEnvironment(SLACKBOT_URL);
Send(URL, Channel, Text);
except
HandleException;
end;
end;
class function TSlackbot.ReadConfigFromEnvironment(const VarName: string): string;
begin
Result := GetEnvironmentVariable(VarName);
if Result.IsEmpty then
raise ESlackbotError.CreateFmt('%s environment variable not set.', [VarName]);
end;
class procedure TSlackbot.Send(const URL, Channel, Text: string);
var
URLWithChannel: string;
begin
try
ValidateURL(URL);
URLWithChannel := Format('%s&channel=%s', [URL, TNetEncoding.URL.Encode(Channel)]);
if not Assigned(HTTPPostFunc) then
HTTPPostFunc := TSlackbotHTTPClient.Post;
HTTPPostFunc(URLWithChannel, Text.Replace(#13, ''));
except
HandleException;
end;
end;
class procedure TSlackbot.Send(const Text: string);
var
URL, Channel: string;
begin
try
URL := ReadConfigFromEnvironment(SLACKBOT_URL);
Channel := ReadConfigFromEnvironment(SLACKBOT_CHANNEL);
Send(URL, Channel, Text);
except
HandleException;
end;
end;
class procedure TSlackbot.ValidateURL(const URL: string);
begin
if not URL.StartsWith('https') then
raise ESlackbotError.CreateFmt('Invalid URL: %s. Protocol must be https.', [URL]);
if not URL.Contains('?token=') then
raise ESlackbotError.CreateFmt('Invalid URL: %s. Token not found.', [URL]);
end;
end.