├── .gitignore
├── .idea
├── codeStyles
│ └── Project.xml
├── dbnavigator.xml
├── discord.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── widgetbot-docs.iml
├── .vitepress
└── config.mts
├── README.md
├── bot
└── moderation.md
├── embed
├── crate
│ ├── api.md
│ ├── examples.md
│ ├── index.md
│ ├── options.md
│ └── tutorial.md
├── embed-api
│ ├── commands.md
│ ├── events.md
│ └── index.md
├── html-embed
│ ├── api.md
│ ├── attributes.md
│ ├── index.md
│ └── tutorial.md
├── index.md
└── react-embed
│ ├── api.md
│ ├── index.md
│ └── props.md
├── guides
├── automod.md
├── css.md
├── custom-colors.md
├── index.md
└── patreon.md
├── index.md
├── package.json
├── pnpm-lock.yaml
├── public
├── _headers
├── logo-black.svg
└── logo.svg
└── tutorial
├── iframes.md
└── index.md
/.gitignore:
--------------------------------------------------------------------------------
1 | site
2 | .DS_Store
3 | .idea/workspace.xml
4 | /.vuepress/dist/
5 | .vitepress/dist
6 | .vitepress/cache
7 | /node_modules/
8 | debug.log
9 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.idea/dbnavigator.xml:
--------------------------------------------------------------------------------
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 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
--------------------------------------------------------------------------------
/.idea/discord.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/widgetbot-docs.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.vitepress/config.mts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitepress'
2 |
3 | // https://vitepress.dev/reference/site-config
4 | export default defineConfig({
5 | title: 'WidgetBot',
6 | description: 'Embed your Discord server on your website with WidgetBot!',
7 | cleanUrls: true,
8 | head: [
9 | ['link', { rel: 'icon', href: '/logo.svg' }],
10 | [
11 | 'script',
12 | { src: 'https://cdn.jsdelivr.net/npm/@widgetbot/crate@3', async: '', defer: '' },
13 | `new Crate({
14 | server: '299881420891881473',
15 | channel: '368427726358446110',
16 | shard: 'https://emerald.widgetbot.io'
17 | })
18 | `
19 | ]
20 | ],
21 | sitemap: {
22 | hostname: 'https://docs.widgetbot.io'
23 | },
24 | themeConfig: {
25 | // https://vitepress.dev/reference/default-theme-config
26 | logo: { dark: '/logo.svg', light: '/logo-black.svg' },
27 | nav: [
28 | { text: 'Home', link: 'https://widgetbot.io', target: '_self' },
29 | { text: 'Docs', link: '/', activeMatch: '^(\/$|\/[^g])' },
30 | { text: 'Guides', link: '/guides/', activeMatch: '/guides/' },
31 | { text: 'Pricing', link: 'https://widgetbot.io/pricing', target: '_self' },
32 | { text: 'Blog', link: 'https://blog.widgetbot.io', target: '_self'}
33 | ],
34 | sidebar: {
35 | '/guides/': [
36 | {
37 | text: 'Helpful Guides',
38 | link: '/guides/',
39 | items: [
40 | { text: 'Automod', link: '/guides/automod' },
41 | { text: 'Custom Colors', link: '/guides/custom-colors' },
42 | ]
43 | },
44 | ],
45 | '/': [
46 | {
47 | text: 'WidgetBot',
48 | link: '/'
49 | },
50 | {
51 | text: 'Tutorial',
52 | link: '/tutorial/',
53 | items: [
54 | { text: 'Crate', link: '/embed/crate/tutorial' },
55 | { text: 'html-embed', link: '/embed/html-embed/tutorial' },
56 | { text: 'iframes', link: '/tutorial/iframes' }
57 | ]
58 | },
59 | {
60 | text: 'Embed',
61 | link: '/embed/',
62 | items: [
63 | {
64 | text: 'Crate',
65 | link: '/embed/crate/',
66 | items: [
67 | { text: 'Intro', link: '/embed/crate/' },
68 | { text: 'Tutorial', link: 'embed/crate/tutorial' },
69 | { text: 'Options', link: 'embed/crate/options' },
70 | { text: 'API', link: 'embed/crate/api' },
71 | { text: 'Examples', link: 'embed/crate/examples' }
72 | ]
73 | },
74 | {
75 | text: 'html-embed',
76 | link: '/embed/html-embed/',
77 | items: [
78 | { text: 'Intro', link: '/embed/html-embed/' },
79 | { text: 'Tutorial', link: 'embed/html-embed/tutorial' },
80 | { text: 'Attributes', link: 'embed/html-embed/attributes' },
81 | { text: 'API', link: 'embed/html-embed/api' }
82 | ]
83 | },
84 | {
85 | text: 'react-embed',
86 | link: '/embed/react-embed/',
87 | items: [
88 | { text: 'Intro', link: '/embed/react-embed/' },
89 | { text: 'Props', link: 'embed/react-embed/props' },
90 | { text: 'API', link: 'embed/react-embed/api' }
91 | ]
92 | },
93 | {
94 | text: 'embed-api',
95 | link: '/embed/embed-api/',
96 | items: [
97 | { text: 'Intro', link: '/embed/embed-api/' },
98 | { text: 'Commands', link: 'embed/embed-api/commands' },
99 | { text: 'Events', link: 'embed/embed-api/events' }
100 | ]
101 | }
102 | ]
103 | },
104 | {
105 | text: 'Bot',
106 | items: [
107 | { text: 'Moderation', link: '/bot/moderation' },
108 | ]
109 | }
110 | ]
111 | },
112 | socialLinks: [
113 | { icon: 'discord', link: 'https://discord.gg/RVNmwdy' },
114 | { icon: 'github', link: 'https://github.com/widgetbot-io/embed' },
115 | { icon: 'twitter', link: 'https://twitter.com/widgetbot_io' }
116 | ],
117 | search: {
118 | provider: 'local'
119 | },
120 | editLink: {
121 | pattern: 'https://github.com/widgetbot-io/documentation/edit/master/:path',
122 | text: 'Help us improve this page!'
123 | }
124 | }
125 | })
126 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WidgetBot Docs
2 |
3 | https://docs.widgetbot.io
4 |
--------------------------------------------------------------------------------
/bot/moderation.md:
--------------------------------------------------------------------------------
1 | # Moderation
2 |
3 | WidgetBot messages can be seen and deleted in Discord clients and by other bots. However, you cannot see WidgetBot user details or ban them from your server like normal users. Instead, we have set up context menu commands to let you moderate WidgetBot users as easily as moderating regular users. On mobile, you'll need to send a command for now.
4 |
5 | WidgetBot has 3 moderation actions:
6 |
7 | - **Ban**: Prevents the user who sent this message from sending more messages through WidgetBot
8 | - **Unban**: Removes a ban if the user is already banned, allowing them to send messages again
9 | - **User**: Shows some information about the user who sent the message
10 |
11 | The **Ban Members** Discord permission is required to use these.
12 |
13 | ## Context Menus
14 |
15 | You can moderate using the message context menu. In the desktop client, you can open this by right-clicking the message sent through WidgetBot. You can also open it by hovering over the message and clicking the three-dot button at the right. On mobile, hold the message.
16 |
17 | In the context menu, you should see an "Apps" button. Hover over it or tap it on mobile, and the WidgetBot commands should appear, along with commands from other applications you might have in your server. Click an action to do it.
18 |
19 | 
20 |
21 | :::tip Don't see it?
22 | If you have WidgetBot in your server but you do not see the Apps button, or it does not include any WidgetBot commands, you'll have to [give it access](https://discord.com/api/oauth2/authorize?client_id=543225764036870167&scope=applications.commands). In most servers, the commands should show without needing to do this.
23 | :::
24 |
25 | ## Commands
26 |
27 | As an alternative to context menus, you can moderate with slash commands.
28 |
29 | To use the /ban or /user commands, you'll need to first copy the ID of the WidgetBot message. There are 2 ways to do this:
30 | - Enable Developer Mode in User Settings > Appearance, then hold the message to show its context menu on mobile, and tap "Copy ID"
31 | - Hold the message to show its context menu on mobile, tap "Copy Message Link", then copy just the ID at the end of the link
32 |
33 | Discord IDs are long numbers, an example is 543225764036870167.
34 |
35 | You'll need to use a WidgetBot slash command. Type / to show commands, and type the command name to filter it.
36 | - /ban id: 543225764036870167
37 | - /unban id: 543225764036870167
38 | - /user id: 543225764036870167
39 |
40 | 
41 |
42 | The /unban slash command supports autocomplete to see the currently banned users and select one. You can also use the /listbans command to see all the banned users.
43 |
--------------------------------------------------------------------------------
/embed/crate/api.md:
--------------------------------------------------------------------------------
1 | # Crate API
2 |
3 | Once you've initialised a new constructor, you can manipulate it using the following methods
4 |
5 | ## Crate APIs
6 |
7 | ### Toggle
8 |
9 | :::tip Definition
10 |
11 | ```ts
12 | type toggle = (open?: boolean) => void
13 | ```
14 | :::
15 |
16 | Toggles the widget's visibility, with an optional param to set it.
17 |
18 | ::: tip Usage
19 |
20 | ```js
21 | // Toggle
22 | crate.toggle()
23 |
24 | // Toggle open
25 | crate.toggle(true)
26 |
27 | // Toggle closed
28 | crate.toggle(false)
29 | ```
30 | :::
31 | Try it:
32 |
33 |
34 |
35 | ---
36 |
37 | ### Notify
38 |
39 | ::: tip Definition
40 | ```ts
41 | type notify = (
42 | content:
43 | | string
44 | | Notification & {
45 | content: string
46 | timeout?: number
47 | }
48 | ) => { hide: Function; delete: Function }
49 | ```
50 | :::
51 | Displays a notification message to the user. Markdown supported
52 |
53 | ::: tip Usage
54 | ```js
55 | // Hello world
56 | crate.notify(`**hello** world`)
57 |
58 | // Display for 2 seconds + custom avatar
59 | crate.notify({
60 | content: '`2 seconds`',
61 | timeout: 2000,
62 | avatar: 'https://cdn.discordapp.com/avatars/293731150239891456/f7d78d0c7e6522ed296bfa315b3a1969.png'
63 | })
64 |
65 | // Programmatically hide notification
66 | const notification = crate.notify({
67 | content: 'Test',
68 | timeout: false
69 | })
70 | /* business logic */
71 | notification.hide()
72 | ```
73 | :::
74 | Try it:
75 |
76 |
77 | ---
78 |
79 | ### Update options
80 |
81 | ::: tip Definition
82 |
83 | ```ts
84 | type setOptions = (newOptions: Options) => Options
85 | ```
86 | :::
87 | Updates the options for crate in real time. [Available options](options)
88 |
89 | ::: tip Usage
90 |
91 | ```js
92 | // Update an option by mutating it
93 | crate.options.color = '#'+Math.random().toString(16).slice(2, 8) // random color
94 |
95 | // Update options by passing an object
96 | crate.setOptions({
97 | location: [-Math.random() * 200), 'right'], // Random position
98 | })
99 | ```
100 | :::
101 | Try it:
102 |
103 |
104 | ---
105 |
106 | ### Visibility
107 |
108 | ::: tip Definition
109 |
110 | ```ts
111 | type hide = () => void
112 | type show = () => void
113 | ```
114 | :::
115 | Hides / un-hides the crate instance, eg. the button, notifications and widget
116 |
117 | ::: tip Usage
118 |
119 | ```js
120 | // Button will now disappear
121 | crate.hide()
122 |
123 | // Button will now re-appear
124 | crate.show()
125 | ```
126 | :::
127 | Try it:
128 |
129 | ---
130 |
131 | ### Navigation
132 |
133 | ::: tip Definition
134 |
135 | ```ts
136 | type navigate = (channelID: string) => void
137 | ```
138 | :::
139 | Navigates to a different channel and opens the widget if it's closed
140 |
141 | ::: tip Usage
142 |
143 | ```js
144 | // Navigates to #general
145 | crate.navigate('368427726358446110')
146 |
147 | // Navigates to #live-demo
148 | crate.navigate('355719584830980096')
149 | ```
150 | :::
151 | Try it:
152 |
153 | ---
154 |
155 | ## Embed API
156 |
157 |
158 | ### Emit
159 |
160 | ::: tip Definition
161 |
162 | ```ts
163 | type emit = (event: Event, data?: Events[Event]) => void
164 | ```
165 | :::
166 | Emits an event to the `embed-api`
167 |
168 | For details, see [embed-api commands](/embed/embed-api/commands)
169 |
170 | ::: tip Usage
171 |
172 | ```js
173 | // Navigate to a different server/channel
174 | crate.emit('navigate', {
175 | guild: '299881420891881473',
176 | channel: '368427726358446110'
177 | })
178 |
179 | // Request login
180 | crate.emit('login')
181 |
182 | // Log out
183 | crate.emit('logout')
184 | ```
185 | :::
186 | ---
187 |
188 | ### On
189 |
190 | ::: tip Definition
191 |
192 | ```ts
193 | type on = (event: Event, (data?: Events[Event]) => void) => void
194 | ```
195 | :::
196 | Listens for a specific event from the `embed-api`
197 |
198 | For details, see [embed-api events](/embed/embed-api/events)
199 |
200 | ::: tip Usage
201 |
202 | ```js
203 | // Listens for when the user has signed in
204 | crate.on('signIn', (user) => {
205 | console.log(`User signed in as ${user.username}`, user)
206 | })
207 |
208 | // Listen for discord message events
209 | crate.on('message', ({ message, channel }) => {
210 | console.log(`New message in #${channel.name}`, message)
211 | })
212 |
213 | // Listen for discord message delete events
214 | crate.on('messageDelete', ({ channel, id }) => {
215 | console.log(`Message ${id} in #${channel.name} was deleted`)
216 | })
217 | ```
218 | :::
219 |
--------------------------------------------------------------------------------
/embed/crate/examples.md:
--------------------------------------------------------------------------------
1 | # Crate Examples
2 |
3 | ## Async
4 |
5 | ### [Default `window.crate` object](https://codepen.io/advaith1/pen/xmXpeG)
6 |
10 |
11 | ### [Custom glyph](https://codepen.io/advaith1/pen/dyMOOjb)
12 |
16 |
17 | ### [Initialising a custom crate object](https://codepen.io/advaith1/pen/MZErRx)
18 |
22 |
23 | ### [Multiple instances at the same time](https://codepen.io/advaith1/pen/oJGpRz)
24 |
28 |
29 | ### [Updating the state](https://codepen.io/advaith1/pen/jXGYoQ)
30 |
34 |
35 | ### [Dynamically interacting with the button](https://codepen.io/advaith1/pen/oJGEvY)
36 |
40 |
41 | ## Sync
42 | We recommend using the **[async](#async)** version of the API, as it'll make your website *way faster*. The synchronous version should only be used if it's being dynamically inserted into your website after the page's initial load (eg. A custom JS script)
43 |
44 | ### [Initialising a custom crate object](https://codepen.io/advaith1/pen/OrxQLv)
45 |
49 |
--------------------------------------------------------------------------------
/embed/crate/index.md:
--------------------------------------------------------------------------------
1 | # Crate
2 |
3 | 
4 |
5 | ---
6 | ::: tip Crate (recommended)
7 | [`@widgetbot/crate`](/embed/crate/tutorial) provides a little chat button in the corner of your website. It shows message notifications from your server and provides an extensive API.
8 | :::
9 |
10 | ```html
11 |
17 | ```
18 |
--------------------------------------------------------------------------------
/embed/crate/options.md:
--------------------------------------------------------------------------------
1 | # Crate Options
2 |
3 | You can pass custom options to Crate when initializing it, for example:
4 |
5 | ```ts
6 | new Crate({ server: '299881420891881473', location: ['top', 'left'] })
7 | ```
8 |
9 | ## Definitions
10 |
11 | ::: tip TypeScript definitions
12 |
13 | ```ts
14 | type url = string
15 | type size = string
16 |
17 | export type vertical = 'top' | 'bottom' | number
18 | export type horizontal = 'left' | 'right' | number
19 |
20 | interface Options {
21 | // Server + channel IDs
22 | server: string
23 | channel?: string
24 |
25 | // Thread ID
26 | thread?: string
27 |
28 | // Dynamic username
29 | username?: string
30 | // Dynamic avatar
31 | avatar?: string
32 |
33 | // Accessibility settings
34 | accessibility?: string[]
35 | // The settings group to use
36 | settingsGroup?: string
37 |
38 | // JWT login
39 | token?: string
40 |
41 | // Where the button should appear on-screen
42 | location?: [vertical, horizontal]
43 |
44 | // The color of the button
45 | color?: string
46 | // The glyph to display on the button
47 | glyph?: [url, size]
48 | // Custom CSS to be injected into the Shadow root
49 | css?: string
50 |
51 | // Crate message notifications
52 | notifications?: boolean
53 | // Crate unread message indicator
54 | indicator?: boolean
55 | // Crate notification timeout
56 | timeout?: number
57 |
58 | // Enables notifications to be triggered for all channels, in crate and embed
59 | allChannelNotifications?: boolean
60 | // Embed notification timeout
61 | embedNotificationTimeout?: number
62 |
63 | // Only load the widget once the user opens it
64 | defer?: boolean
65 | // Connect to a custom WidgetBot server
66 | shard?: url
67 | }
68 |
69 | export default Options
70 | ```
71 |
--------------------------------------------------------------------------------
/embed/crate/tutorial.md:
--------------------------------------------------------------------------------
1 | # Crate Tutorial
2 |
3 | Welcome to the Crate tutorial!
4 |
5 | ::: warning Important
6 | **This tutorial assumes you have already completed the [Getting Started with WidgetBot](/tutorial/) tutorial.** If you have not, please read it and **invite the bot**.
7 | :::
8 |
9 | ::: tip Need help?
10 | If you need any assistance adding WidgetBot, please ask in [the server](https://discord.gg/NYBEhN7). **However**, please make sure you mention **what the issue is**, **send your code** in a codeblock (` ``` `), include **your server and channel IDs**, and optionally include **a link to your site**.
11 | :::
12 |
13 | ## Getting Started
14 |
15 | **To get started with Crate, use `/crate` in your server.** You should run it in the channel you want to show as default on your website. (Note that users can switch between the public channels in the sidebar). WidgetBot should send code that looks like this:
16 |
17 | ```html
18 |
24 | ```
25 |
26 | The code sent by the bot goes in your site's HTML source at the end of your website's `body`, right before the closing `