Skip to content

Commit f80a02e

Browse files
committed
Implement Discord webhooks for event log
1 parent 96db479 commit f80a02e

11 files changed

+683
-0
lines changed

etc/config.sample.json

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
"vultr": ""
77
},
88
"discord": {
9+
"forward_event_log": {
10+
"enabled": false,
11+
"webhook": null
12+
},
913
"invite_code": "u87WVeu",
1014
"server_id": 405789880749260820
1115
},

src/libraries/Discord/Embed.php

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<?php
2+
3+
namespace BNETDocs\Libraries\Discord;
4+
5+
use \BNETDocs\Libraries\Discord\EmbedAuthor;
6+
use \BNETDocs\Libraries\Discord\EmbedField;
7+
use \BNETDocs\Libraries\Discord\EmbedFooter;
8+
use \BNETDocs\Libraries\Discord\EmbedImage;
9+
use \BNETDocs\Libraries\Discord\EmbedProvider;
10+
use \BNETDocs\Libraries\Discord\EmbedThumbnail;
11+
use \BNETDocs\Libraries\Discord\EmbedVideo;
12+
13+
use \DateTime;
14+
use \JsonSerializable;
15+
use \LengthException;
16+
use \OverflowException;
17+
use \SplObjectStorage;
18+
19+
// <https://discordapp.com/developers/docs/resources/channel#embed-object>
20+
21+
class Embed implements JsonSerializable {
22+
23+
const MAX_DESCRIPTION = 2048;
24+
const MAX_FIELDS = 25;
25+
const MAX_TITLE = 256;
26+
27+
protected $author;
28+
protected $color;
29+
protected $description;
30+
protected $fields;
31+
protected $footer;
32+
protected $image;
33+
protected $provider;
34+
protected $thumbnail;
35+
protected $timestamp;
36+
protected $title;
37+
protected $type;
38+
protected $url;
39+
protected $video;
40+
41+
public function __construct() {
42+
$this->author = null;
43+
$this->color = -1;
44+
$this->description = '';
45+
$this->fields = new SplObjectStorage();
46+
$this->footer = null;
47+
$this->image = null;
48+
$this->provider = null;
49+
$this->thumbnail = null;
50+
$this->timestamp = null;
51+
$this->title = '';
52+
$this->type = 'rich';
53+
$this->url = '';
54+
$this->video = null;
55+
}
56+
57+
public function addField(EmbedField &$field_object) {
58+
if ($this->fields->count() >= self::MAX_FIELDS) {
59+
throw new OverflowException(sprintf(
60+
'Discord forbids adding more than %d fields',
61+
self::MAX_FIELDS
62+
));
63+
}
64+
65+
$this->fields->attach($field_object);
66+
}
67+
68+
public function fieldCount() {
69+
return $this->fields->count();
70+
}
71+
72+
public function hasField(EmbedField &$field_object) {
73+
return $this->fields->contains($field_object);
74+
}
75+
76+
public function jsonSerialize() {
77+
// part of JsonSerializable interface
78+
$r = array();
79+
80+
if (!empty($this->description)) $r['description'] = $this->description;
81+
if (!empty($this->title)) $r['title'] = $this->title;
82+
if (!empty($this->type)) $r['type'] = $this->type;
83+
if (!empty($this->url)) $r['url'] = $this->url;
84+
if ($this->author) $r['author'] = $this->author;
85+
if ($this->color > -1) $r['color'] = $this->color;
86+
if ($this->fields->count() > 0) $r['fields'] = array();
87+
if ($this->footer) $r['footer'] = $this->footer;
88+
if ($this->image) $r['image'] = $this->image;
89+
if ($this->provider) $r['provider'] = $this->provider;
90+
if ($this->thumbnail) $r['thumbnail'] = $this->thumbnail;
91+
if ($this->video) $r['video'] = $this->video;
92+
93+
if ($this->timestamp) $r['timestamp'] = $this->timestamp->format(
94+
DateTime::ISO8601
95+
);
96+
97+
foreach ($this->fields as $field_object) {
98+
$r['fields'][] = $field_object;
99+
}
100+
101+
return $r;
102+
}
103+
104+
public function removeAllFields() {
105+
$this->fields = new SplObjectStorage();
106+
}
107+
108+
public function removeField(EmbedField &$field_object) {
109+
$this->fields->detach($field_object);
110+
}
111+
112+
public function setAuthor(EmbedAuthor &$author_object) {
113+
$this->author = $author_object;
114+
}
115+
116+
public function setColor(int $color) {
117+
$this->color = $color;
118+
}
119+
120+
public function setDescription(string $description) {
121+
if (strlen($description) > self::MAX_DESCRIPTION) {
122+
throw new LengthException(sprintf(
123+
'Discord forbids description longer than %d characters',
124+
self::MAX_DESCRIPTION
125+
));
126+
}
127+
128+
$this->title = $title;
129+
}
130+
131+
public function setFooter(EmbedFooter &$footer_object) {
132+
$this->footer = $footer_object;
133+
}
134+
135+
public function setImage(EmbedImage &$image_object) {
136+
$this->image = $image_object;
137+
}
138+
139+
public function setProvider(EmbedProvider &$provider_object) {
140+
$this->provider = $provider_object;
141+
}
142+
143+
public function setThumbnail(EmbedThumbnail &$thumbnail_object) {
144+
$this->thumbnail = $thumbnail_object;
145+
}
146+
147+
public function setTimestamp(DateTime $timestamp) {
148+
$this->timestamp = $timestamp;
149+
}
150+
151+
public function setTitle(string $title) {
152+
if (strlen($title) > self::MAX_TITLE) {
153+
throw new LengthException(sprintf(
154+
'Discord forbids title longer than %d characters',
155+
self::MAX_TITLE
156+
));
157+
}
158+
159+
$this->title = $title;
160+
}
161+
162+
public function setType(string $type) {
163+
$this->type = $type;
164+
}
165+
166+
public function setUrl(string $url) {
167+
$this->url = $url;
168+
}
169+
170+
public function setVideo(EmbedVideo &$video_object) {
171+
$this->video = $video_object;
172+
}
173+
174+
}

src/libraries/Discord/EmbedAuthor.php

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
namespace BNETDocs\Libraries\Discord;
4+
5+
use \JsonSerializable;
6+
use \LengthException;
7+
8+
// <https://discordapp.com/developers/docs/resources/channel#embed-object-embed-author-structure>
9+
10+
class EmbedAuthor implements JsonSerializable {
11+
12+
const MAX_NAME = 256;
13+
14+
protected $icon_url;
15+
protected $name;
16+
protected $proxy_icon_url;
17+
protected $url;
18+
19+
public function __construct(string $name, string $url = '', string $icon_url = '') {
20+
$this->setIconUrl($icon_url);
21+
$this->setName($name);
22+
$this->setProxyIconUrl('');
23+
$this->setUrl($url);
24+
}
25+
26+
public function jsonSerialize() {
27+
// part of JsonSerializable interface
28+
$r = array();
29+
30+
if (!empty($this->icon_url)) $r['icon_url'] = $this->icon_url;
31+
if (!empty($this->name)) $r['name'] = $this->name;
32+
if (!empty($this->proxy_icon_url)) $r['proxy_icon_url'] = $this->proxy_icon_url;
33+
if (!empty($this->url)) $r['url'] = $this->url;
34+
35+
return $r;
36+
}
37+
38+
public function setIconUrl(string $icon_url) {
39+
$this->icon_url = $icon_url;
40+
}
41+
42+
public function setName(string $name) {
43+
if (empty($name)) {
44+
throw new LengthException('The name cannot be empty');
45+
}
46+
47+
if (strlen($name) > self::MAX_NAME) {
48+
throw new LengthException(sprintf(
49+
'Discord forbids name longer than %d characters', self::MAX_NAME
50+
));
51+
}
52+
53+
$this->name = $name;
54+
}
55+
56+
public function setProxyIconUrl(string $proxy_icon_url) {
57+
$this->proxy_icon_url = $proxy_icon_url;
58+
}
59+
60+
public function setUrl(string $url) {
61+
$this->url = $url;
62+
}
63+
64+
}

src/libraries/Discord/EmbedField.php

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace BNETDocs\Libraries\Discord;
4+
5+
use \JsonSerializable;
6+
use \LengthException;
7+
8+
// <https://discordapp.com/developers/docs/resources/channel#embed-object-embed-field-structure>
9+
10+
class EmbedField implements JsonSerializable {
11+
12+
const MAX_NAME = 256;
13+
const MAX_VALUE = 1024;
14+
15+
protected $inline;
16+
protected $name;
17+
protected $value;
18+
19+
public function __construct(string $name, string $value, bool $inline) {
20+
$this->setInline($inline);
21+
$this->setName($name);
22+
$this->setValue($value);
23+
}
24+
25+
public function jsonSerialize() {
26+
// part of JsonSerializable interface
27+
$r = array();
28+
29+
if (!empty($this->name)) $r['name'] = $this->name;
30+
if (!empty($this->value)) $r['value'] = $this->value;
31+
32+
$r['inline'] = $this->inline;
33+
34+
return $r;
35+
}
36+
37+
public function setInline(bool $inline) {
38+
$this->inline = $inline;
39+
}
40+
41+
public function setName(string $name) {
42+
if (strlen($name) > self::MAX_NAME) {
43+
throw new LengthException(sprintf(
44+
'Discord forbids name longer than %d characters', self::MAX_NAME
45+
));
46+
}
47+
48+
$this->name = $name;
49+
}
50+
51+
public function setValue(string $value) {
52+
if (strlen($value) > self::MAX_VALUE) {
53+
throw new LengthException(sprintf(
54+
'Discord forbids value longer than %d characters', self::MAX_VALUE
55+
));
56+
}
57+
58+
$this->value = $value;
59+
}
60+
61+
}

src/libraries/Discord/EmbedFooter.php

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace BNETDocs\Libraries\Discord;
4+
5+
use \JsonSerializable;
6+
7+
// <https://discordapp.com/developers/docs/resources/channel#embed-object-embed-footer-structure>
8+
9+
class EmbedFooter implements JsonSerializable {
10+
11+
const MAX_TEXT = 2048;
12+
13+
protected $icon_url;
14+
protected $proxy_icon_url;
15+
protected $text;
16+
17+
public function __construct(string $text, string $icon_url = '', string $proxy_icon_url = '') {
18+
$this->setIconUrl($icon_url);
19+
$this->setProxyIconUrl($proxy_icon_url);
20+
$this->setText($text);
21+
}
22+
23+
public function jsonSerialize() {
24+
// part of JsonSerializable interface
25+
$r = array();
26+
27+
if (!empty($this->icon_url)) $r['icon_url'] = $this->icon_url;
28+
if (!empty($this->proxy_icon_url)) $r['proxy_icon_url'] = $this->proxy_icon_url;
29+
if (!empty($this->text)) $r['text'] = $this->text;
30+
31+
return $r;
32+
}
33+
34+
public function setIconUrl(string $icon_url) {
35+
$this->icon_url = $icon_url;
36+
}
37+
38+
public function setProxyIconUrl(string $proxy_icon_url) {
39+
$this->proxy_icon_url = $proxy_icon_url;
40+
}
41+
42+
public function setText(string $text) {
43+
if (strlen($text) > self::MAX_TEXT) {
44+
throw new LengthException(sprintf(
45+
'Discord forbids text longer than %d characters', self::MAX_TEXT
46+
));
47+
}
48+
49+
$this->text = $text;
50+
}
51+
52+
}

0 commit comments

Comments
 (0)