· 5 years ago · Jun 05, 2020, 04:56 PM
1[
2 {
3 "title":"Home",
4 "content":"---\r\nhome: true\r\nheroImage: https://javacord.org/img/javacord3_banner.png\r\nheroText: null\r\ntagline: An easy to use multithreaded library for creating Discord bots in Java.\r\nactionText: View Wiki →\r\nactionLink: /wiki/\r\n---\r\n\r\n",
5 "_strippedContent":"\r\n",
6 "path":"/"
7 },
8 {
9 "title":"Imprint",
10 "content":"---\r\nsearch: false\r\n---\r\n\r\n# Imprint\r\n\r\n<iframe src=\"/im.html\" style=\"height: calc(100vh - 250px); width: 100%\"></iframe>",
11 "_strippedContent":"\r\n# Imprint\r\n\r\n<iframe src=\"/im.html\" style=\"height: calc(100vh - 250px); width: 100%\"></iframe>",
12 "path":"/imprint.html"
13 },
14 {
15 "title":"Privacy Policy",
16 "content":"---\r\nsearch: false\r\n---\r\n\r\n# Privacy Policy\r\n\r\n<iframe src=\"/pp.html\" style=\"height: calc(100vh - 250px); width: 100%\"></iframe>",
17 "_strippedContent":"\r\n# Privacy Policy\r\n\r\n<iframe src=\"/pp.html\" style=\"height: calc(100vh - 250px); width: 100%\"></iframe>",
18 "path":"/privacy-policy.html"
19 },
20 {
21 "title":"Bot Lifecycle",
22 "headers":[
23 {
24 "level":2,
25 "title":"? The four states",
26 "slug":"the-four-states"
27 },
28 {
29 "level":3,
30 "title":"Connected",
31 "slug":"connected"
32 },
33 {
34 "level":3,
35 "title":"Disconnected",
36 "slug":"disconnected"
37 },
38 {
39 "level":3,
40 "title":"Resuming",
41 "slug":"resuming"
42 },
43 {
44 "level":3,
45 "title":"Reconnecting",
46 "slug":"reconnecting"
47 },
48 {
49 "level":2,
50 "title":"? How to handle disconnects",
51 "slug":"how-to-handle-disconnects"
52 }
53 ],
54 "content":"# Bot Lifecycle\r\n\r\nIt's important to know the life-cycle of a discord bot to properly handle disconnects. \r\nThe following state diagram shows the 4 states a bot can have:\r\n\r\n\r\n\r\n## :bulb: The four states\r\n\r\n### Connected\r\n\r\nThe bot is connected to the websocket and receives all events.\r\n\r\n### Disconnected\r\n\r\nThe bot is not connected to the websocket and receives no events. It's not uncommon for a bot to occasionally lose connection.\r\nThis can have various reasons, for example:\r\n* Your bot lost its internet connection\r\n* Discord restarted the gateway server you are currently connected to\r\n* A plane crashed into Discord's data center\r\n\r\nThe bot will periodically try ro resume/reconnect to the websocket. It will start with a small frequency and increase it\r\nwith every failed reconnect attempt. You can modify this reconnect delay with the `DiscordApi#setReconnectDelay(...)` method.\r\nThe following example code would increase the delay linearly.\r\nThe 1st attempt would be delayed for `2` seconds, the 2nd attempt for `4` seconds, the 3rd attempts for `6` seconds, ...\r\n```java\r\napi.setReconnectDelay(attempt -> attempt * 2);\r\n```\r\n\r\n> **Important:** Bots can only reconnect 1000 times in a 24-hour period (every ~90 seconds). This limit is global and across all shards.\r\n Upon hitting this limit, all active sessions for the bot will be terminated, the bot's token will be reset, and\r\n you will receive an email notification. This is the reason Javacord increases the reconnect delay with every attempt.\r\n\r\nBy default, the $default\\_delay$ formula below is used to calculate the reconnect delay\r\n\r\n$$\r\ndefault\\_delay(a) = \\lfloor a^{1.5} - \\frac{a^{1.5}}{\\frac{1}{(0.1 \\cdot a)} + 1} \\rceil\r\n$$\r\n\r\nwith $a$ being the attempt.\r\n\r\nThe formula will generate the following recollect delay:\r\n\r\n| Attempt | Delay |\r\n| ------- | ----- |\r\n| 1 | 1 |\r\n| 2 | 2 |\r\n| 3 | 4 |\r\n| 4 | 6 |\r\n| 5 | 7 |\r\n| ... | ... |\r\n| 10 | 16 |\r\n| 15 | 23 |\r\n| 20 | 30 |\r\n| ... | ... |\r\n| 50 | 59 |\r\n| 100 | 91 |\r\n| 150 | 115 |\r\n| ... | ... |\r\n\r\n### Resuming\r\n\r\nResuming is only possible for a short time after being disconnected. If the bot can successfully resume the connection,\r\nyou will not miss any events. Your bot will receive all events you missed while being disconnected. The cache gets updated\r\naccordingly.\r\n\r\n### Reconnecting\r\n\r\nIf your bot reconnects (not resumes!), the whole cache gets wiped and you will not receive any missed events. \r\n\r\n**What does this mean?** \r\n* References to entities (e.g. a `Server`, `User`, `Channel`, ...) will be outdated. This is why you should never store\r\n entities, but the id instead. See [Entity Cache](http://localhost:4000/wiki/advanced-tutorials/entity-cache/#how-long-are-cached-entities-valid).\r\n* You will miss events. There's no way to receive the missed events.\r\n* Listeners attached to entities will **not** be affected, because they are bound to the entity's id, not the object itself.\r\n\r\n## :pill: How to handle disconnects\r\n\r\nFor most bots, there's nothing you have to do. All registered listeners are reconnect-resistant, which means if your bot\r\nis only reacting to events, it will work fine after a restart. For example, the following code will not be affected by a \r\nreconnect (besides maybe some missed `!ping` messages):\r\n```java\r\napi.addMessageCreateListener(event -> {\r\n if (event.getMessage().getContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n});\r\n```\r\n\r\nIn case you want to handle reconnects (e.g. fetch the message history to detect missed messages), there are\r\nspecial connection-related listeners which can be used to track the state of the bot:\r\n* `LostConnectionListener`\r\n* `ReconnectListener`\r\n* `ResumeListener`",
55 "_strippedContent":"# Bot Lifecycle\r\n\r\nIt's important to know the life-cycle of a discord bot to properly handle disconnects. \r\nThe following state diagram shows the 4 states a bot can have:\r\n\r\n\r\n\r\n## :bulb: The four states\r\n\r\n### Connected\r\n\r\nThe bot is connected to the websocket and receives all events.\r\n\r\n### Disconnected\r\n\r\nThe bot is not connected to the websocket and receives no events. It's not uncommon for a bot to occasionally lose connection.\r\nThis can have various reasons, for example:\r\n* Your bot lost its internet connection\r\n* Discord restarted the gateway server you are currently connected to\r\n* A plane crashed into Discord's data center\r\n\r\nThe bot will periodically try ro resume/reconnect to the websocket. It will start with a small frequency and increase it\r\nwith every failed reconnect attempt. You can modify this reconnect delay with the `DiscordApi#setReconnectDelay(...)` method.\r\nThe following example code would increase the delay linearly.\r\nThe 1st attempt would be delayed for `2` seconds, the 2nd attempt for `4` seconds, the 3rd attempts for `6` seconds, ...\r\n```java\r\napi.setReconnectDelay(attempt -> attempt * 2);\r\n```\r\n\r\n> **Important:** Bots can only reconnect 1000 times in a 24-hour period (every ~90 seconds). This limit is global and across all shards.\r\n Upon hitting this limit, all active sessions for the bot will be terminated, the bot's token will be reset, and\r\n you will receive an email notification. This is the reason Javacord increases the reconnect delay with every attempt.\r\n\r\nBy default, the $default\\_delay$ formula below is used to calculate the reconnect delay\r\n\r\n$$\r\ndefault\\_delay(a) = \\lfloor a^{1.5} - \\frac{a^{1.5}}{\\frac{1}{(0.1 \\cdot a)} + 1} \\rceil\r\n$$\r\n\r\nwith $a$ being the attempt.\r\n\r\nThe formula will generate the following recollect delay:\r\n\r\n| Attempt | Delay |\r\n| ------- | ----- |\r\n| 1 | 1 |\r\n| 2 | 2 |\r\n| 3 | 4 |\r\n| 4 | 6 |\r\n| 5 | 7 |\r\n| ... | ... |\r\n| 10 | 16 |\r\n| 15 | 23 |\r\n| 20 | 30 |\r\n| ... | ... |\r\n| 50 | 59 |\r\n| 100 | 91 |\r\n| 150 | 115 |\r\n| ... | ... |\r\n\r\n### Resuming\r\n\r\nResuming is only possible for a short time after being disconnected. If the bot can successfully resume the connection,\r\nyou will not miss any events. Your bot will receive all events you missed while being disconnected. The cache gets updated\r\naccordingly.\r\n\r\n### Reconnecting\r\n\r\nIf your bot reconnects (not resumes!), the whole cache gets wiped and you will not receive any missed events. \r\n\r\n**What does this mean?** \r\n* References to entities (e.g. a `Server`, `User`, `Channel`, ...) will be outdated. This is why you should never store\r\n entities, but the id instead. See [Entity Cache](http://localhost:4000/wiki/advanced-tutorials/entity-cache/#how-long-are-cached-entities-valid).\r\n* You will miss events. There's no way to receive the missed events.\r\n* Listeners attached to entities will **not** be affected, because they are bound to the entity's id, not the object itself.\r\n\r\n## :pill: How to handle disconnects\r\n\r\nFor most bots, there's nothing you have to do. All registered listeners are reconnect-resistant, which means if your bot\r\nis only reacting to events, it will work fine after a restart. For example, the following code will not be affected by a \r\nreconnect (besides maybe some missed `!ping` messages):\r\n```java\r\napi.addMessageCreateListener(event -> {\r\n if (event.getMessage().getContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n});\r\n```\r\n\r\nIn case you want to handle reconnects (e.g. fetch the message history to detect missed messages), there are\r\nspecial connection-related listeners which can be used to track the state of the bot:\r\n* `LostConnectionListener`\r\n* `ReconnectListener`\r\n* `ResumeListener`",
56 "path":"/wiki/advanced-topics/bot-lifecycle.html"
57 },
58 {
59 "title":"Performance Tweaks",
60 "headers":[
61 {
62 "level":2,
63 "title":"✂️ Disabling Startup Wait",
64 "slug":"disabling-startup-wait"
65 },
66 {
67 "level":2,
68 "title":"⚙️ Fine Tuning the Message Cache",
69 "slug":"fine-tuning-the-message-cache"
70 },
71 {
72 "level":2,
73 "title":"? Using the Updater classes",
74 "slug":"using-the-updater-classes"
75 },
76 {
77 "level":3,
78 "title":"Example",
79 "slug":"example"
80 }
81 ],
82 "content":"# Performance Tweaks\r\n\r\n## :scissors: Disabling Startup Wait\r\n\r\nBy default, Javacord waits for all servers and members being loaded on startup. You can disable this behavior in the `DiscordApiBuilder` before logging in:\r\n```java\r\nnew DiscordApiBuilder()\r\n .setToken(\"abc\")\r\n .setWaitForServersOnStartup(false)\r\n .login()\r\n .thenAccept(api -> {\r\n // Do something\r\n }).exceptionally(ExceptionLogger.get());\r\n```\r\nDepending on the size of your bot, this can significantly speed up the login process. This comes with one downside however: The `api.getServers()` collection is empty directly after logging in. You will receive `ServerBecomesAvailableEvent`s for every server which finished loading.\r\n\r\n## :gear: Fine Tuning the Message Cache\r\n\r\nIn order to reduce memory usage, you can completely disable the message cache or reduce the number of cached messages. By default, Javacord caches up to 50 messages per channel and removes messages from cache which are older than 12 hours. You can lower this limit by using `DiscordApi#setMessageCacheSize(Capacity, StorageTimeInSeconds)`\r\n```java\r\n// Cache a maximum of 10 messages per channel for and remove messages older than 1 hour\r\napi.setMessageCacheSize(10, 60*60);\r\n```\r\nYou can even set this limit on a per-channel basis:\r\n```java\r\nTextChannel channel = ...;\r\nchannel.getMessageCache().setCapacity(10);\r\nchannel.getMessageCache().setStorageTimeInSeconds(60*60);\r\n```\r\n\r\n## :gem: Using the Updater classes\r\n\r\nIf you update several settings of an entity (server, channel, ...) at once, you should use the updater for this entity instead of the `updateXyz(...)` methods.\r\n\r\n### Example\r\n\r\n```java\r\n// Sends 1 request to Discord\r\nServerTextChannel channel = ...;\r\nnew ServerTextChannelUpdater(channel)\r\n .setName(\"example-channel\")\r\n .setTopic(\"This is an example channel\")\r\n .setNsfwFlag(true)\r\n .update();\r\n```\r\ninstead of\r\n```java\r\n// Sends 3 requests to Discord\r\nServerTextChannel channel = ...;\r\nchannel.updateName(\"example-channel\");\r\nchannel.updateTopic(\"This is an example channel\");\r\nchannel.updateNsfwFlag(true);\r\n```",
83 "_strippedContent":"# Performance Tweaks\r\n\r\n## :scissors: Disabling Startup Wait\r\n\r\nBy default, Javacord waits for all servers and members being loaded on startup. You can disable this behavior in the `DiscordApiBuilder` before logging in:\r\n```java\r\nnew DiscordApiBuilder()\r\n .setToken(\"abc\")\r\n .setWaitForServersOnStartup(false)\r\n .login()\r\n .thenAccept(api -> {\r\n // Do something\r\n }).exceptionally(ExceptionLogger.get());\r\n```\r\nDepending on the size of your bot, this can significantly speed up the login process. This comes with one downside however: The `api.getServers()` collection is empty directly after logging in. You will receive `ServerBecomesAvailableEvent`s for every server which finished loading.\r\n\r\n## :gear: Fine Tuning the Message Cache\r\n\r\nIn order to reduce memory usage, you can completely disable the message cache or reduce the number of cached messages. By default, Javacord caches up to 50 messages per channel and removes messages from cache which are older than 12 hours. You can lower this limit by using `DiscordApi#setMessageCacheSize(Capacity, StorageTimeInSeconds)`\r\n```java\r\n// Cache a maximum of 10 messages per channel for and remove messages older than 1 hour\r\napi.setMessageCacheSize(10, 60*60);\r\n```\r\nYou can even set this limit on a per-channel basis:\r\n```java\r\nTextChannel channel = ...;\r\nchannel.getMessageCache().setCapacity(10);\r\nchannel.getMessageCache().setStorageTimeInSeconds(60*60);\r\n```\r\n\r\n## :gem: Using the Updater classes\r\n\r\nIf you update several settings of an entity (server, channel, ...) at once, you should use the updater for this entity instead of the `updateXyz(...)` methods.\r\n\r\n### Example\r\n\r\n```java\r\n// Sends 1 request to Discord\r\nServerTextChannel channel = ...;\r\nnew ServerTextChannelUpdater(channel)\r\n .setName(\"example-channel\")\r\n .setTopic(\"This is an example channel\")\r\n .setNsfwFlag(true)\r\n .update();\r\n```\r\ninstead of\r\n```java\r\n// Sends 3 requests to Discord\r\nServerTextChannel channel = ...;\r\nchannel.updateName(\"example-channel\");\r\nchannel.updateTopic(\"This is an example channel\");\r\nchannel.updateNsfwFlag(true);\r\n```",
84 "path":"/wiki/advanced-topics/performance-tweaks.html"
85 },
86 {
87 "title":"Entity Cache",
88 "headers":[
89 {
90 "level":2,
91 "title":"? What is in the cache?",
92 "slug":"what-is-in-the-cache"
93 },
94 {
95 "level":2,
96 "title":"❓ When are cached entities updated?",
97 "slug":"when-are-cached-entities-updated"
98 },
99 {
100 "level":2,
101 "title":"⌚️ How long are cached entities valid?",
102 "slug":"how-long-are-cached-entities-valid"
103 }
104 ],
105 "content":"# Entity Cache\r\n\r\nJavacord keeps an internal cache for entities (e.g. Servers, Channels, Users, ...). It is important to know how the cache behaves to properly use it.\r\n\r\n## :crystal_ball: What is in the cache?\r\n\r\nNearly every entity known by the bot is guaranteed to be in the cache. There are a few exceptions though:\r\n\r\n#### Messages\r\n\r\nNot every single message is in the cache, which means you can encounter messages which exist but are not in the cache. This can happen for most message events, e.g. the [`ReactionAddEvent`](https://ci.javacord.org/javadoc/org/javacord/api/event/message/reaction/ReactionAddEvent.html). You can, however, interact with these messages without having them in the cache. Every message event has methods like `event.deleteMessage()`, `event.editMessage(\"New Content\")`. If you need the message (e.g. to get its content), you can request it using `event.requestMessage()`.\r\n\r\nAdditionally you can use the static methods in the [`Message`](https://ci.javacord.org/javadoc/org/javacord/api/entity/message/Message.html) class which only require the channel and message id, e.g. `Message.edit(api, channelId, messageId, \"New content\");`. This is very useful if you want to store them in a database.\r\n\r\n#### Webhooks and Invites\r\n\r\nWebhooks and Invites are not kept in the cache at all and won't receive any updates.\r\n\r\n#### Embeds\r\n\r\nEmbeds from `message.getEmbed()` won't receive updates. If a message's embed gets edited, `getEmbed()` will return a completely new embed object.\r\n\r\n## :question: When are cached entities updated?\r\n\r\nJavacord's cache exclusively uses websocket events to keep the cache up to date. This means that the content of your objects might be outdated, even though you modified it yourself:\r\n\r\n```java\r\nMessages message = ...;\r\nSystem.out.println(message.getContent()); // Prints the old content, e.g. \"old content\"\r\nmessage.edit(\"new content\").join(); // Edits the message and waits for success\r\nSystem.out.println(message.getContent()); // Still prints \"old content\"\r\nThread.sleep(1000);\r\nSystem.out.println(message.getContent()); // Most likely prints \"new content\" now\r\n```\r\n\r\n## :watch: How long are cached entities valid?\r\n\r\nEven though entities are usually kept in the cache for a very long time, you should not keep references to theses objects for a longer period of time, but store the id / use event methods:\r\n\r\n```java\r\n// Bad\r\nMessage message = ...;\r\nmessage.addReactionAddListener(event -> {\r\n if (event.getEmoji().equalsEmoji(\"?\")) {\r\n message.delete(); // Prevents \"message\" from being garbage collected\r\n }\r\n});\r\n\r\n// Good\r\nMessage message = ...;\r\nmessage.addReactionAddListener(event -> {\r\n if (event.getEmoji().equalsEmoji(\"?\")) {\r\n event.deleteMessage(); // Does not use the message object\r\n }\r\n});\r\n```\r\n\r\n```java\r\n// Bad\r\nSet<User> usersWithBadMood = new HashSet<>();\r\napi.addReactionAddListener(event -> {\r\n if (event.getEmoji().equalsEmoji(\"?\")) {\r\n usersWithBadMood.add(event.getUser());\r\n }\r\n});\r\n\r\n// Good\r\nSet<Long> usersWithBadMood = new HashSet<>();\r\napi.addReactionAddListener(event -> {\r\n if (event.getEmoji().equalsEmoji(\"?\")) {\r\n usersWithBadMood.add(event.getUser().getId());\r\n }\r\n});\r\n```\r\n\r\nSome examples of when cached entities are invalidated:\r\n* The bot lost its connection to Discord and had to reconnect (not resume)\r\n* You weren't able to receive updates for an entity, e.g. for `Channel`, because you left and rejoined a server",
106 "_strippedContent":"# Entity Cache\r\n\r\nJavacord keeps an internal cache for entities (e.g. Servers, Channels, Users, ...). It is important to know how the cache behaves to properly use it.\r\n\r\n## :crystal_ball: What is in the cache?\r\n\r\nNearly every entity known by the bot is guaranteed to be in the cache. There are a few exceptions though:\r\n\r\n#### Messages\r\n\r\nNot every single message is in the cache, which means you can encounter messages which exist but are not in the cache. This can happen for most message events, e.g. the [`ReactionAddEvent`](https://ci.javacord.org/javadoc/org/javacord/api/event/message/reaction/ReactionAddEvent.html). You can, however, interact with these messages without having them in the cache. Every message event has methods like `event.deleteMessage()`, `event.editMessage(\"New Content\")`. If you need the message (e.g. to get its content), you can request it using `event.requestMessage()`.\r\n\r\nAdditionally you can use the static methods in the [`Message`](https://ci.javacord.org/javadoc/org/javacord/api/entity/message/Message.html) class which only require the channel and message id, e.g. `Message.edit(api, channelId, messageId, \"New content\");`. This is very useful if you want to store them in a database.\r\n\r\n#### Webhooks and Invites\r\n\r\nWebhooks and Invites are not kept in the cache at all and won't receive any updates.\r\n\r\n#### Embeds\r\n\r\nEmbeds from `message.getEmbed()` won't receive updates. If a message's embed gets edited, `getEmbed()` will return a completely new embed object.\r\n\r\n## :question: When are cached entities updated?\r\n\r\nJavacord's cache exclusively uses websocket events to keep the cache up to date. This means that the content of your objects might be outdated, even though you modified it yourself:\r\n\r\n```java\r\nMessages message = ...;\r\nSystem.out.println(message.getContent()); // Prints the old content, e.g. \"old content\"\r\nmessage.edit(\"new content\").join(); // Edits the message and waits for success\r\nSystem.out.println(message.getContent()); // Still prints \"old content\"\r\nThread.sleep(1000);\r\nSystem.out.println(message.getContent()); // Most likely prints \"new content\" now\r\n```\r\n\r\n## :watch: How long are cached entities valid?\r\n\r\nEven though entities are usually kept in the cache for a very long time, you should not keep references to theses objects for a longer period of time, but store the id / use event methods:\r\n\r\n```java\r\n// Bad\r\nMessage message = ...;\r\nmessage.addReactionAddListener(event -> {\r\n if (event.getEmoji().equalsEmoji(\"?\")) {\r\n message.delete(); // Prevents \"message\" from being garbage collected\r\n }\r\n});\r\n\r\n// Good\r\nMessage message = ...;\r\nmessage.addReactionAddListener(event -> {\r\n if (event.getEmoji().equalsEmoji(\"?\")) {\r\n event.deleteMessage(); // Does not use the message object\r\n }\r\n});\r\n```\r\n\r\n```java\r\n// Bad\r\nSet<User> usersWithBadMood = new HashSet<>();\r\napi.addReactionAddListener(event -> {\r\n if (event.getEmoji().equalsEmoji(\"?\")) {\r\n usersWithBadMood.add(event.getUser());\r\n }\r\n});\r\n\r\n// Good\r\nSet<Long> usersWithBadMood = new HashSet<>();\r\napi.addReactionAddListener(event -> {\r\n if (event.getEmoji().equalsEmoji(\"?\")) {\r\n usersWithBadMood.add(event.getUser().getId());\r\n }\r\n});\r\n```\r\n\r\nSome examples of when cached entities are invalidated:\r\n* The bot lost its connection to Discord and had to reconnect (not resume)\r\n* You weren't able to receive updates for an entity, e.g. for `Channel`, because you left and rejoined a server",
107 "path":"/wiki/advanced-topics/entity-cache.html"
108 },
109 {
110 "title":"Proxies",
111 "headers":[
112 {
113 "level":2,
114 "title":"?? Configuring a Proxy ...",
115 "slug":"configuring-a-proxy"
116 },
117 {
118 "level":3,
119 "title":"... using System Properties",
120 "slug":"using-system-properties"
121 },
122 {
123 "level":3,
124 "title":"... using a System Default Proxy Selector",
125 "slug":"using-a-system-default-proxy-selector"
126 },
127 {
128 "level":3,
129 "title":"... using an Explicitly Set Proxy",
130 "slug":"using-an-explicitly-set-proxy"
131 },
132 {
133 "level":3,
134 "title":"... using an Explicitly Set Proxy Selector",
135 "slug":"using-an-explicitly-set-proxy-selector"
136 },
137 {
138 "level":3,
139 "title":"Precedence of the Configuration Options",
140 "slug":"precedence-of-the-configuration-options"
141 },
142 {
143 "level":2,
144 "title":"? Configuring Proxy Authentication ...",
145 "slug":"configuring-proxy-authentication"
146 },
147 {
148 "level":3,
149 "title":"... using a System Default Authenticator",
150 "slug":"using-a-system-default-authenticator"
151 },
152 {
153 "level":3,
154 "title":"... using an Explicitly Set Authenticator",
155 "slug":"using-an-explicitly-set-authenticator"
156 },
157 {
158 "level":2,
159 "title":"? Proxy Types",
160 "slug":"proxy-types"
161 },
162 {
163 "level":3,
164 "title":"HTTP",
165 "slug":"http"
166 },
167 {
168 "level":3,
169 "title":"SOCKS 4",
170 "slug":"socks-4"
171 },
172 {
173 "level":3,
174 "title":"SOCKS 4a",
175 "slug":"socks-4a"
176 },
177 {
178 "level":3,
179 "title":"SOCKS 5",
180 "slug":"socks-5"
181 }
182 ],
183 "content":"# Proxies\r\n\r\nThere are basically two kinds of proxies: HTTP proxies and SOCKS proxies. Both may or may not support or require authentication depending on version, capabilities, and configuration. Due to the underlying libraries used, currently, Javacord fully supports HTTP proxies and partially supports SOCKS proxies.\r\n\r\nJavacord uses HTTPS connections to communicate with the Discord REST API and a WSS connection to communicate with the Discord WebSocket endpoint. Both these protocols are secure protocols and thus do not honor settings for HTTP connections, only settings for HTTPS connections.\r\n\r\n## :man_technologist: Configuring a Proxy ...\r\n\r\n### ... using System Properties\r\n\r\nIf you did not explicitly set a proxy in the `DiscordApiBuilder` and did not set a system default `ProxySelector`, the default proxy selector of the JRE is used. This proxy selector honors, amongst others, the relevant standard system properties `https.proxyHost`, `https.proxyPort`, `socksProxyHost`, `socksProxyPort`, and `socksProxyVersion`. Use the former two to configure an HTTP proxy or the latter three to configure a SOCKS proxy although you will not need `socksProxyVersion`, as SOCKS4 is currently not supported.\r\n\r\n### ... using a System Default Proxy Selector\r\n\r\nYou can use `java.net.ProxySelector.setDefault(ProxySelector)` to set a system default proxy selector that replaces the default one. In its implementation, you can dynamically determine which proxy to use for each connection.\r\n\r\n### ... using an Explicitly Set Proxy\r\n\r\nUsing the method `DiscordApiBuilder.setProxy(Proxy)` you can set a proxy instance directly in the `DiscordApiBuilder` that is solely used for Javacord connections and does not affect the unrelated code running in the JVM.\r\n\r\n### ... using an Explicitly Set Proxy Selector\r\n\r\nUsing the method `DiscordApiBuilder.setProxySelector(ProxySelector)` you can set a proxy selector instance directly in the `DiscordApiBuilder` that is solely used for Javacord connections and does not affect the remaining code running in the JVM. In its implementation, you can dynamically determine which proxy to use for each connection.\r\n\r\n### Precedence of the Configuration Options\r\n\r\n* if an explicit proxy is set, it is used\r\n* if an explicit proxy selector is set, it is used\r\n* if both an explicit proxy and an explicit proxy selector are set, this is a configuration error and will cause an exception to be thrown\r\n* if neither explicit option is set, the system default proxy selector is used\r\n* if no system default proxy selector was explicitly set, the JRE default that honors the system properties is used\r\n\r\n## :key: Configuring Proxy Authentication ...\r\n\r\n### ... using a System Default Authenticator\r\n\r\nYou can use `java.net.Authenticator.setDefault(Authenticator)` to set a system default authenticator that is used to provide username and password pairs for connections. This authenticator is only used if the proxy supports the `Basic` authentication scheme. If you need to support any other authentication scheme, use an explicitly configured authenticator. The `java.net.Authenticator` interface is too inflexible to support this.\r\n\r\n### ... using an Explicitly Set Authenticator\r\n\r\nUsing the method `DiscordApiBuilder.setProxyAuthenticator(Authenticator)`, you can set a custom authenticator that is much more powerful than the `java.net.Authenticator`. You get much more information about the connection to be established, and you can return any HTTP header that is necessary for a successful authentication. This should cover all sorts of available authentication mechanisms.\r\n\r\n## :bulb: Proxy Types\r\n\r\n### HTTP\r\n\r\nHTTP proxies are fully supported.\r\n\r\n### SOCKS 4\r\n\r\nSOCKS 4 is currently not supported.\r\n\r\nThe WebSocket library we use does not support SOCKS proxies at all and the HTTP library we use has a bug that prevents SOCKS 4 to be used. Additionally, you would need to use at least Java 9 or a separate socket factory supporting SOCKS 4, as the JRE implementation is not working in Java 8 and got fixed only in Java 9+.\r\n\r\n### SOCKS 4a\r\n\r\nSOCKS 4a is currently only partially supported.\r\n\r\nThe WebSocket library we use does not support SOCKS proxies at all, so it could be used for the REST connections only. Additionally, you would need to use a separate socket factory supporting SOCKS 4a, as the JRE implementation is not capable of doing SOCKS 4a, only SOCKS 4 and SOCKS 5 are supported at the time of creation of this wiki article.\r\n\r\n### SOCKS 5\r\n\r\nSOCKS 5 is currently only partially supported.\r\n\r\nThe WebSocket library we use does not support SOCKS proxies at all, so it could be used for the REST connections only.",
184 "_strippedContent":"# Proxies\r\n\r\nThere are basically two kinds of proxies: HTTP proxies and SOCKS proxies. Both may or may not support or require authentication depending on version, capabilities, and configuration. Due to the underlying libraries used, currently, Javacord fully supports HTTP proxies and partially supports SOCKS proxies.\r\n\r\nJavacord uses HTTPS connections to communicate with the Discord REST API and a WSS connection to communicate with the Discord WebSocket endpoint. Both these protocols are secure protocols and thus do not honor settings for HTTP connections, only settings for HTTPS connections.\r\n\r\n## :man_technologist: Configuring a Proxy ...\r\n\r\n### ... using System Properties\r\n\r\nIf you did not explicitly set a proxy in the `DiscordApiBuilder` and did not set a system default `ProxySelector`, the default proxy selector of the JRE is used. This proxy selector honors, amongst others, the relevant standard system properties `https.proxyHost`, `https.proxyPort`, `socksProxyHost`, `socksProxyPort`, and `socksProxyVersion`. Use the former two to configure an HTTP proxy or the latter three to configure a SOCKS proxy although you will not need `socksProxyVersion`, as SOCKS4 is currently not supported.\r\n\r\n### ... using a System Default Proxy Selector\r\n\r\nYou can use `java.net.ProxySelector.setDefault(ProxySelector)` to set a system default proxy selector that replaces the default one. In its implementation, you can dynamically determine which proxy to use for each connection.\r\n\r\n### ... using an Explicitly Set Proxy\r\n\r\nUsing the method `DiscordApiBuilder.setProxy(Proxy)` you can set a proxy instance directly in the `DiscordApiBuilder` that is solely used for Javacord connections and does not affect the unrelated code running in the JVM.\r\n\r\n### ... using an Explicitly Set Proxy Selector\r\n\r\nUsing the method `DiscordApiBuilder.setProxySelector(ProxySelector)` you can set a proxy selector instance directly in the `DiscordApiBuilder` that is solely used for Javacord connections and does not affect the remaining code running in the JVM. In its implementation, you can dynamically determine which proxy to use for each connection.\r\n\r\n### Precedence of the Configuration Options\r\n\r\n* if an explicit proxy is set, it is used\r\n* if an explicit proxy selector is set, it is used\r\n* if both an explicit proxy and an explicit proxy selector are set, this is a configuration error and will cause an exception to be thrown\r\n* if neither explicit option is set, the system default proxy selector is used\r\n* if no system default proxy selector was explicitly set, the JRE default that honors the system properties is used\r\n\r\n## :key: Configuring Proxy Authentication ...\r\n\r\n### ... using a System Default Authenticator\r\n\r\nYou can use `java.net.Authenticator.setDefault(Authenticator)` to set a system default authenticator that is used to provide username and password pairs for connections. This authenticator is only used if the proxy supports the `Basic` authentication scheme. If you need to support any other authentication scheme, use an explicitly configured authenticator. The `java.net.Authenticator` interface is too inflexible to support this.\r\n\r\n### ... using an Explicitly Set Authenticator\r\n\r\nUsing the method `DiscordApiBuilder.setProxyAuthenticator(Authenticator)`, you can set a custom authenticator that is much more powerful than the `java.net.Authenticator`. You get much more information about the connection to be established, and you can return any HTTP header that is necessary for a successful authentication. This should cover all sorts of available authentication mechanisms.\r\n\r\n## :bulb: Proxy Types\r\n\r\n### HTTP\r\n\r\nHTTP proxies are fully supported.\r\n\r\n### SOCKS 4\r\n\r\nSOCKS 4 is currently not supported.\r\n\r\nThe WebSocket library we use does not support SOCKS proxies at all and the HTTP library we use has a bug that prevents SOCKS 4 to be used. Additionally, you would need to use at least Java 9 or a separate socket factory supporting SOCKS 4, as the JRE implementation is not working in Java 8 and got fixed only in Java 9+.\r\n\r\n### SOCKS 4a\r\n\r\nSOCKS 4a is currently only partially supported.\r\n\r\nThe WebSocket library we use does not support SOCKS proxies at all, so it could be used for the REST connections only. Additionally, you would need to use a separate socket factory supporting SOCKS 4a, as the JRE implementation is not capable of doing SOCKS 4a, only SOCKS 4 and SOCKS 5 are supported at the time of creation of this wiki article.\r\n\r\n### SOCKS 5\r\n\r\nSOCKS 5 is currently only partially supported.\r\n\r\nThe WebSocket library we use does not support SOCKS proxies at all, so it could be used for the REST connections only.",
185 "path":"/wiki/advanced-topics/proxies.html"
186 },
187 {
188 "title":"Ratelimits",
189 "headers":[
190 {
191 "level":2,
192 "title":"❗️ The Most Important Ratelimits",
193 "slug":"the-most-important-ratelimits"
194 },
195 {
196 "level":2,
197 "title":"? Dealing with Ratelimits",
198 "slug":"dealing-with-ratelimits"
199 },
200 {
201 "level":3,
202 "title":"Example",
203 "slug":"example"
204 },
205 {
206 "level":2,
207 "title":"❌ Can I disable ratelimits?",
208 "slug":"can-i-disable-ratelimits"
209 }
210 ],
211 "content":"# Ratelimits\r\n\r\nRatelimits is a Discord restriction which prevents you from performing actions in a very fast rate.\r\nMost ratelimits are on a per-channel or a per-server basis.\r\n\r\n## :exclamation: The Most Important Ratelimits\r\n\r\n| Action | Ratelimit | Type |\r\n| -------------------- | --------- | ----------- |\r\n| Send Messages | 5 / 5s | per channel |\r\n| Delete Messages | 5 / 1s | per channel |\r\n| Add/Remove Reactions | 1 / 0.25s | per channel |\r\n| Edit Server Members | 10 / 10s | per server |\r\n| Edit Member Nickname | 1 / 1s | per server |\r\n| Edit Bot Username | 2 / 1h | per account |\r\n| All Actions Combined | 50 / 1s | per account |\r\n\r\n## :muscle: Dealing with Ratelimits\r\n\r\nUsually Javacord takes care about these limitations for you. \r\nAs a user, there's nothing you have to do, but you should at least know that ratelimits exist.\r\n\r\n### Example\r\n\r\nThe following code\r\n```java\r\n// Who even needs loops?\r\nchannel.sendMessage(\"Ratelimit Example #1\");\r\nchannel.sendMessage(\"Ratelimit Example #2\");\r\nchannel.sendMessage(\"Ratelimit Example #3\");\r\nchannel.sendMessage(\"Ratelimit Example #4\");\r\nchannel.sendMessage(\"Ratelimit Example #5\");\r\nchannel.sendMessage(\"Ratelimit Example #6\");\r\nchannel.sendMessage(\"Ratelimit Example #7\");\r\nchannel.sendMessage(\"Ratelimit Example #8\");\r\nchannel.sendMessage(\"Ratelimit Example #9\");\r\nchannel.sendMessage(\"Ratelimit Example #10\");\r\nchannel.sendMessage(\"Ratelimit Example #11\");\r\nchannel.sendMessage(\"Ratelimit Example #12\");\r\n```\r\n\r\nwould look like this in the client:\r\n\r\n>\r\n\r\nYou can clearly see the delay between every 5 sent messages.\r\n\r\n## :x: Can I disable ratelimits?\r\n\r\nNo. Ratelimits are a limitation from Discord itself, which you cannot circumvent.",
212 "_strippedContent":"# Ratelimits\r\n\r\nRatelimits is a Discord restriction which prevents you from performing actions in a very fast rate.\r\nMost ratelimits are on a per-channel or a per-server basis.\r\n\r\n## :exclamation: The Most Important Ratelimits\r\n\r\n| Action | Ratelimit | Type |\r\n| -------------------- | --------- | ----------- |\r\n| Send Messages | 5 / 5s | per channel |\r\n| Delete Messages | 5 / 1s | per channel |\r\n| Add/Remove Reactions | 1 / 0.25s | per channel |\r\n| Edit Server Members | 10 / 10s | per server |\r\n| Edit Member Nickname | 1 / 1s | per server |\r\n| Edit Bot Username | 2 / 1h | per account |\r\n| All Actions Combined | 50 / 1s | per account |\r\n\r\n## :muscle: Dealing with Ratelimits\r\n\r\nUsually Javacord takes care about these limitations for you. \r\nAs a user, there's nothing you have to do, but you should at least know that ratelimits exist.\r\n\r\n### Example\r\n\r\nThe following code\r\n```java\r\n// Who even needs loops?\r\nchannel.sendMessage(\"Ratelimit Example #1\");\r\nchannel.sendMessage(\"Ratelimit Example #2\");\r\nchannel.sendMessage(\"Ratelimit Example #3\");\r\nchannel.sendMessage(\"Ratelimit Example #4\");\r\nchannel.sendMessage(\"Ratelimit Example #5\");\r\nchannel.sendMessage(\"Ratelimit Example #6\");\r\nchannel.sendMessage(\"Ratelimit Example #7\");\r\nchannel.sendMessage(\"Ratelimit Example #8\");\r\nchannel.sendMessage(\"Ratelimit Example #9\");\r\nchannel.sendMessage(\"Ratelimit Example #10\");\r\nchannel.sendMessage(\"Ratelimit Example #11\");\r\nchannel.sendMessage(\"Ratelimit Example #12\");\r\n```\r\n\r\nwould look like this in the client:\r\n\r\n>\r\n\r\nYou can clearly see the delay between every 5 sent messages.\r\n\r\n## :x: Can I disable ratelimits?\r\n\r\nNo. Ratelimits are a limitation from Discord itself, which you cannot circumvent.",
213 "path":"/wiki/advanced-topics/ratelimits.html"
214 },
215 {
216 "title":"Sharding",
217 "headers":[
218 {
219 "level":2,
220 "title":"?? Sharding in Javacord",
221 "slug":"sharding-in-javacord"
222 },
223 {
224 "level":3,
225 "title":"Logging in with a single shard",
226 "slug":"logging-in-with-a-single-shard"
227 },
228 {
229 "level":3,
230 "title":"Logging in with a fixed amount of shards",
231 "slug":"logging-in-with-a-fixed-amount-of-shards"
232 },
233 {
234 "level":3,
235 "title":"Using the recommended shard amount",
236 "slug":"using-the-recommended-shard-amount"
237 },
238 {
239 "level":2,
240 "title":"? Behavior of Shards",
241 "slug":"behavior-of-shards"
242 },
243 {
244 "level":3,
245 "title":"Managed servers",
246 "slug":"managed-servers"
247 },
248 {
249 "level":3,
250 "title":"Private messages",
251 "slug":"private-messages"
252 },
253 {
254 "level":3,
255 "title":"When do I need sharding?",
256 "slug":"when-do-i-need-sharding"
257 },
258 {
259 "level":2,
260 "title":"? Sharding for Very Large Bots",
261 "slug":"sharding-for-very-large-bots"
262 }
263 ],
264 "content":"# Sharding\r\n\r\nDiscord allows (and forces) you to \"split\" larger bots into several independent parts. This behavior is called \"sharding\", and the independent parts are called \"shards\". You can think of shards as completely independent bots. Every shard is responsible for a disjoint set of servers.\r\n\r\n## :woman_factory_worker: Sharding in Javacord\r\n\r\n### Logging in with a single shard\r\n\r\nLogging in with a single shard is pretty much the same as logging in without sharding:\r\n```java\r\nDiscordApi api = new DiscordApiBuilder()\r\n .setToken(\"top secret\")\r\n .setCurrentShard(0)\r\n .setTotalShards(2)\r\n .login().join();\r\nSystem.out.println(\"Shard \" + api.getCurrentShard() + \" logged in!\");\r\n```\r\n> **Note**: `current shard` starts counting at `0`! This means in the example above you would have current shard `0` and shard `1` with a `total amount` of `2` shards.\r\n\r\n> **Important**: There must be a > 5-second delay between each shard-login\r\n\r\n### Logging in with a fixed amount of shards\r\n\r\nYou can manually set a fixed amount of total shards and log in all of them:\r\n```java\r\npublic class Main {\r\n\r\n public static void main(String[] args) {\r\n new DiscordApiBuilder()\r\n .setToken(\"top secret\")\r\n .setTotalShards(10)\r\n .loginAllShards()\r\n .forEach(shardFuture -> shardFuture\r\n .thenAcceptAsync(Main::onShardLogin)\r\n .exceptionally(ExceptionLogger.get())\r\n );\r\n }\r\n\r\n private static void onShardLogin(DiscordApi api) {\r\n System.out.println(\"Shard \" + api.getCurrentShard() + \" logged in!\");\r\n // You can treat the shard like a normal bot account, e.g. registering listeners\r\n api.addMessageCreateListener(event -> {\r\n // ...\r\n });\r\n }\r\n\r\n}\r\n```\r\n`loginAllShards()` returns a collection with completable futures (`Collection<CompletableFuture<DiscordApi>>`). This method automatically obeys the > 5-second delay rule.\r\n\r\n### Using the recommended shard amount\r\n\r\nYou can \"ask\" Discord to recommend you a total amount of shards. This is done by using the `DiscordApiBuilder#setRecommendedTotalShards()` method, which returns a `CompletableFuture<DiscordApiBuilder>` after getting the required information.\r\n\r\n```java\r\npublic class Main {\r\n\r\n public static void main(String[] args) {\r\n new DiscordApiBuilder()\r\n .setToken(\"top secret\")\r\n .setRecommendedTotalShards().join()\r\n .loginAllShards()\r\n .forEach(shardFuture -> shardFuture\r\n .thenAccept(Main::onShardLogin)\r\n .exceptionally(ExceptionLogger.get())\r\n );\r\n }\r\n\r\n private static void onShardLogin(DiscordApi api) {\r\n // ...\r\n }\r\n\r\n}\r\n```\r\n\r\n## :bulb: Behavior of Shards\r\n\r\n### Managed servers\r\n\r\nYou can calculate for which servers a shard is responsible using the server id:\r\n```java\r\nboolean isResponsible = (serverId >> 22) % totalShards == currentShard;\r\n```\r\n\r\n### Private messages\r\n\r\nPrivate messages are always sent to the first shard (`currentShard == 0`).\r\n\r\n### When do I need sharding?\r\n\r\nSharding is forced for bots which are in more than 2500 servers.\r\n\r\n## :sunrise_over_mountains: Sharding for Very Large Bots\r\n\r\nSharding for very large bots (> 100'000 servers) is a little bit different from \"normal\" sharding. Discord will contact you once your bot reaches this state. Additional information can be found in the [official Discord api documentation](https://discordapp.com/developers/docs/topics/gateway#sharding-for-very-large-bots).",
265 "_strippedContent":"# Sharding\r\n\r\nDiscord allows (and forces) you to \"split\" larger bots into several independent parts. This behavior is called \"sharding\", and the independent parts are called \"shards\". You can think of shards as completely independent bots. Every shard is responsible for a disjoint set of servers.\r\n\r\n## :woman_factory_worker: Sharding in Javacord\r\n\r\n### Logging in with a single shard\r\n\r\nLogging in with a single shard is pretty much the same as logging in without sharding:\r\n```java\r\nDiscordApi api = new DiscordApiBuilder()\r\n .setToken(\"top secret\")\r\n .setCurrentShard(0)\r\n .setTotalShards(2)\r\n .login().join();\r\nSystem.out.println(\"Shard \" + api.getCurrentShard() + \" logged in!\");\r\n```\r\n> **Note**: `current shard` starts counting at `0`! This means in the example above you would have current shard `0` and shard `1` with a `total amount` of `2` shards.\r\n\r\n> **Important**: There must be a > 5-second delay between each shard-login\r\n\r\n### Logging in with a fixed amount of shards\r\n\r\nYou can manually set a fixed amount of total shards and log in all of them:\r\n```java\r\npublic class Main {\r\n\r\n public static void main(String[] args) {\r\n new DiscordApiBuilder()\r\n .setToken(\"top secret\")\r\n .setTotalShards(10)\r\n .loginAllShards()\r\n .forEach(shardFuture -> shardFuture\r\n .thenAcceptAsync(Main::onShardLogin)\r\n .exceptionally(ExceptionLogger.get())\r\n );\r\n }\r\n\r\n private static void onShardLogin(DiscordApi api) {\r\n System.out.println(\"Shard \" + api.getCurrentShard() + \" logged in!\");\r\n // You can treat the shard like a normal bot account, e.g. registering listeners\r\n api.addMessageCreateListener(event -> {\r\n // ...\r\n });\r\n }\r\n\r\n}\r\n```\r\n`loginAllShards()` returns a collection with completable futures (`Collection<CompletableFuture<DiscordApi>>`). This method automatically obeys the > 5-second delay rule.\r\n\r\n### Using the recommended shard amount\r\n\r\nYou can \"ask\" Discord to recommend you a total amount of shards. This is done by using the `DiscordApiBuilder#setRecommendedTotalShards()` method, which returns a `CompletableFuture<DiscordApiBuilder>` after getting the required information.\r\n\r\n```java\r\npublic class Main {\r\n\r\n public static void main(String[] args) {\r\n new DiscordApiBuilder()\r\n .setToken(\"top secret\")\r\n .setRecommendedTotalShards().join()\r\n .loginAllShards()\r\n .forEach(shardFuture -> shardFuture\r\n .thenAccept(Main::onShardLogin)\r\n .exceptionally(ExceptionLogger.get())\r\n );\r\n }\r\n\r\n private static void onShardLogin(DiscordApi api) {\r\n // ...\r\n }\r\n\r\n}\r\n```\r\n\r\n## :bulb: Behavior of Shards\r\n\r\n### Managed servers\r\n\r\nYou can calculate for which servers a shard is responsible using the server id:\r\n```java\r\nboolean isResponsible = (serverId >> 22) % totalShards == currentShard;\r\n```\r\n\r\n### Private messages\r\n\r\nPrivate messages are always sent to the first shard (`currentShard == 0`).\r\n\r\n### When do I need sharding?\r\n\r\nSharding is forced for bots which are in more than 2500 servers.\r\n\r\n## :sunrise_over_mountains: Sharding for Very Large Bots\r\n\r\nSharding for very large bots (> 100'000 servers) is a little bit different from \"normal\" sharding. Discord will contact you once your bot reaches this state. Additional information can be found in the [official Discord api documentation](https://discordapp.com/developers/docs/topics/gateway#sharding-for-very-large-bots).",
266 "path":"/wiki/advanced-topics/sharding.html"
267 },
268 {
269 "title":"Creating Channels, Invites, etc.",
270 "headers":[
271 {
272 "level":2,
273 "title":"? Create Channels",
274 "slug":"create-channels"
275 },
276 {
277 "level":2,
278 "title":"? Create Webhooks",
279 "slug":"create-webhooks"
280 },
281 {
282 "level":2,
283 "title":"? Create Invites",
284 "slug":"create-invites"
285 },
286 {
287 "level":2,
288 "title":"? Create Servers",
289 "slug":"create-servers"
290 }
291 ],
292 "content":"# Creating Channels, Invites, etc.\r\n\r\nJavacord provides `XyzBuilder` classes to create new Discord entities like channels, webhooks, servers, and many more.\r\n\r\n## :closed_book: Create Channels\r\n\r\nYou can get the channel builders for a specific server using the `Server#createXyzChannelBuilder` or by directly calling the constructor.\r\nCreating a `ServerVoiceChannel` would look like this:\r\n```java\r\nServer server = ...;\r\nServerVoiceChannel channel = new ServerVoiceChannelBuilder(server)\r\n .setName(\"example-channel\")\r\n .setUserlimit(10)\r\n .create().join();\r\n```\r\n\r\n## :green_book: Create Webhooks\r\n\r\nYou can get the `WebhookBuilder` for a specific text channel:\r\n\r\n```java\r\nServerTextChannel channel = ...;\r\nWebhook webhook = new WebhookBuilder(channel)\r\n .setName(\"Captain Hook\")\r\n .setAvatar(new File(\"C:/Users/Bastian/Pictures/puppy.jpg\"))\r\n .create().join();\r\n```\r\n\r\n## :blue_book: Create Invites\r\n\r\nYou can get the `InviteBuilder` for a specific server channel:\r\n```java\r\nServerTextChannel channel = ...;\r\nInvite invite = new InviteBuilder(channel)\r\n .setMaxAgeInSeconds(60*60*24)\r\n .setMaxUses(42)\r\n .create().join();\r\n```\r\n\r\n## :orange_book: Create Servers\r\n\r\nYou can get the `ServerBuilder` from the current api instance:\r\n```java\r\nDiscordApi api = ...;\r\nlong serverId = new ServerBuilder(api)\r\n .setName(\"My Awesome Server\")\r\n .setIcon(api.getYourself().getAvatar())\r\n .setVerificationLevel(VerificationLevel.HIGH)\r\n .setDefaultMessageNotificationLevel(DefaultMessageNotificationLevel.ONLY_MENTIONS)\r\n .setRegion(Region.EU_CENTRAL)\r\n .create().join();\r\n```\r\n\r\n::: warning\r\nBy default, bots can only create servers if they are in less than 10 servers. You can contact the Discord support to request a higher limit.\r\n:::",
293 "_strippedContent":"# Creating Channels, Invites, etc.\r\n\r\nJavacord provides `XyzBuilder` classes to create new Discord entities like channels, webhooks, servers, and many more.\r\n\r\n## :closed_book: Create Channels\r\n\r\nYou can get the channel builders for a specific server using the `Server#createXyzChannelBuilder` or by directly calling the constructor.\r\nCreating a `ServerVoiceChannel` would look like this:\r\n```java\r\nServer server = ...;\r\nServerVoiceChannel channel = new ServerVoiceChannelBuilder(server)\r\n .setName(\"example-channel\")\r\n .setUserlimit(10)\r\n .create().join();\r\n```\r\n\r\n## :green_book: Create Webhooks\r\n\r\nYou can get the `WebhookBuilder` for a specific text channel:\r\n\r\n```java\r\nServerTextChannel channel = ...;\r\nWebhook webhook = new WebhookBuilder(channel)\r\n .setName(\"Captain Hook\")\r\n .setAvatar(new File(\"C:/Users/Bastian/Pictures/puppy.jpg\"))\r\n .create().join();\r\n```\r\n\r\n## :blue_book: Create Invites\r\n\r\nYou can get the `InviteBuilder` for a specific server channel:\r\n```java\r\nServerTextChannel channel = ...;\r\nInvite invite = new InviteBuilder(channel)\r\n .setMaxAgeInSeconds(60*60*24)\r\n .setMaxUses(42)\r\n .create().join();\r\n```\r\n\r\n## :orange_book: Create Servers\r\n\r\nYou can get the `ServerBuilder` from the current api instance:\r\n```java\r\nDiscordApi api = ...;\r\nlong serverId = new ServerBuilder(api)\r\n .setName(\"My Awesome Server\")\r\n .setIcon(api.getYourself().getAvatar())\r\n .setVerificationLevel(VerificationLevel.HIGH)\r\n .setDefaultMessageNotificationLevel(DefaultMessageNotificationLevel.ONLY_MENTIONS)\r\n .setRegion(Region.EU_CENTRAL)\r\n .create().join();\r\n```\r\n\r\n::: warning\r\nBy default, bots can only create servers if they are in less than 10 servers. You can contact the Discord support to request a higher limit.\r\n:::",
294 "path":"/wiki/basic-tutorials/creating-entities.html"
295 },
296 {
297 "title":"Embeds",
298 "headers":[
299 {
300 "level":2,
301 "title":"? Creating an Embed",
302 "slug":"creating-an-embed"
303 },
304 {
305 "level":2,
306 "title":"? Supported Image Sources",
307 "slug":"supported-image-sources"
308 },
309 {
310 "level":2,
311 "title":"? Embed Limits",
312 "slug":"embed-limits"
313 },
314 {
315 "level":2,
316 "title":"❓ FAQ",
317 "slug":"faq"
318 },
319 {
320 "level":3,
321 "title":"What is the second parameter of setAuthor(...)?",
322 "slug":"what-is-the-second-parameter-of-setauthor"
323 },
324 {
325 "level":3,
326 "title":"What's the difference between an inline field and a normal one?",
327 "slug":"what-s-the-difference-between-an-inline-field-and-a-normal-one"
328 },
329 {
330 "level":3,
331 "title":"Can I change the placement of inline fields?",
332 "slug":"can-i-change-the-placement-of-inline-fields"
333 }
334 ],
335 "content":"# Embeds\r\n\r\nEmbeds are attached to messages and have a special design.\r\nThe usually look like this:\r\n\r\n\r\n\r\n## :hammer: Creating an Embed\r\n\r\nJavacord provides an `EmbedBuilder` which can be used to create embeds:\r\n```java\r\n// Create the embed\r\nEmbedBuilder embed = new EmbedBuilder()\r\n .setTitle(\"Title\")\r\n .setDescription(\"Description\")\r\n .setAuthor(\"Author Name\", \"http://google.com/\", \"https://cdn.discordapp.com/embed/avatars/0.png\")\r\n .addField(\"A field\", \"Some text inside the field\")\r\n .addInlineField(\"An inline field\", \"More text\")\r\n .addInlineField(\"Another inline field\", \"Even more text\")\r\n .setColor(Color.BLUE)\r\n .setFooter(\"Footer\", \"https://cdn.discordapp.com/embed/avatars/1.png\")\r\n .setImage(new File(\"C:/Users/Bastian/Pictures/puppy.jpg\"))\r\n .setThumbnail(new File(\"C:/Users/Bastian/Pictures/kitten2.png\"));\r\n// Send the embed\r\nchannel.sendMessage(embed);\r\n```\r\n\r\n## :camera: Supported Image Sources\r\n\r\nBy default, Discord expects embed images to be a link (e.g., the image link used in `setFooter(...)`), but you can also use attachments for images.\r\nIf you provide a non-url image source (e.g. the `puppy.jpg` file used in `setImage(...)`), Javacord automatically uploads them as an attachment to the message and uses this attachment for the embed.\r\n\r\n## :lock: Embed Limits\r\n\r\n| Type | Limit |\r\n| ------------ | --------------- |\r\n| Title | 256 characters |\r\n| Description | 2048 characters |\r\n| Field Amount | Up to 25 fields |\r\n| Field Name | 256 characters |\r\n| Field Value | 1024 characters |\r\n| Footer Text | 2048 characters |\r\n| Author Name | 256 characters |\r\n\r\nIn addition to the limits above, the sum of all characters in an embed structure must not exceed 6000 characters.\r\n\r\n## :question: FAQ\r\n\r\n### What is the second parameter of `setAuthor(...)`?\r\n\r\n```java\r\n.setAuthor(\"Author Name\", \"http://google.com/\", \"https://cdn.discordapp.com/embed/avatars/0.png\")\r\n```\r\n* First parameter: The name of the author\r\n* Second parameter: A link for the author (e.g. their homepage). Can be `null`.\r\n* Third parameter: The avatar of the author\r\n> \r\n\r\n### What's the difference between an inline field and a normal one?\r\nNormal fields always start in a new line, whereas several inline fields can be in the same line.\r\n\r\n### Can I change the placement of inline fields?\r\n\r\nNo, Discord does not allow different embed layouts.",
336 "_strippedContent":"# Embeds\r\n\r\nEmbeds are attached to messages and have a special design.\r\nThe usually look like this:\r\n\r\n\r\n\r\n## :hammer: Creating an Embed\r\n\r\nJavacord provides an `EmbedBuilder` which can be used to create embeds:\r\n```java\r\n// Create the embed\r\nEmbedBuilder embed = new EmbedBuilder()\r\n .setTitle(\"Title\")\r\n .setDescription(\"Description\")\r\n .setAuthor(\"Author Name\", \"http://google.com/\", \"https://cdn.discordapp.com/embed/avatars/0.png\")\r\n .addField(\"A field\", \"Some text inside the field\")\r\n .addInlineField(\"An inline field\", \"More text\")\r\n .addInlineField(\"Another inline field\", \"Even more text\")\r\n .setColor(Color.BLUE)\r\n .setFooter(\"Footer\", \"https://cdn.discordapp.com/embed/avatars/1.png\")\r\n .setImage(new File(\"C:/Users/Bastian/Pictures/puppy.jpg\"))\r\n .setThumbnail(new File(\"C:/Users/Bastian/Pictures/kitten2.png\"));\r\n// Send the embed\r\nchannel.sendMessage(embed);\r\n```\r\n\r\n## :camera: Supported Image Sources\r\n\r\nBy default, Discord expects embed images to be a link (e.g., the image link used in `setFooter(...)`), but you can also use attachments for images.\r\nIf you provide a non-url image source (e.g. the `puppy.jpg` file used in `setImage(...)`), Javacord automatically uploads them as an attachment to the message and uses this attachment for the embed.\r\n\r\n## :lock: Embed Limits\r\n\r\n| Type | Limit |\r\n| ------------ | --------------- |\r\n| Title | 256 characters |\r\n| Description | 2048 characters |\r\n| Field Amount | Up to 25 fields |\r\n| Field Name | 256 characters |\r\n| Field Value | 1024 characters |\r\n| Footer Text | 2048 characters |\r\n| Author Name | 256 characters |\r\n\r\nIn addition to the limits above, the sum of all characters in an embed structure must not exceed 6000 characters.\r\n\r\n## :question: FAQ\r\n\r\n### What is the second parameter of `setAuthor(...)`?\r\n\r\n```java\r\n.setAuthor(\"Author Name\", \"http://google.com/\", \"https://cdn.discordapp.com/embed/avatars/0.png\")\r\n```\r\n* First parameter: The name of the author\r\n* Second parameter: A link for the author (e.g. their homepage). Can be `null`.\r\n* Third parameter: The avatar of the author\r\n> \r\n\r\n### What's the difference between an inline field and a normal one?\r\nNormal fields always start in a new line, whereas several inline fields can be in the same line.\r\n\r\n### Can I change the placement of inline fields?\r\n\r\nNo, Discord does not allow different embed layouts.",
337 "path":"/wiki/basic-tutorials/embeds.html"
338 },
339 {
340 "title":"Emojis and Reactions",
341 "headers":[
342 {
343 "level":2,
344 "title":"? Unicode Emojis",
345 "slug":"unicode-emojis"
346 },
347 {
348 "level":3,
349 "title":"What are Unicode emojis?",
350 "slug":"what-are-unicode-emojis"
351 },
352 {
353 "level":3,
354 "title":"How to use them in messages",
355 "slug":"how-to-use-them-in-messages"
356 },
357 {
358 "level":3,
359 "title":"How to use them for reactions",
360 "slug":"how-to-use-them-for-reactions"
361 },
362 {
363 "level":2,
364 "title":"?♀ Custom Emojis",
365 "slug":"custom-emojis"
366 },
367 {
368 "level":3,
369 "title":"What are custom emojis?",
370 "slug":"what-are-custom-emojis"
371 },
372 {
373 "level":3,
374 "title":"How to use them in messages",
375 "slug":"how-to-use-them-in-messages-2"
376 },
377 {
378 "level":3,
379 "title":"How to use them for reactions",
380 "slug":"how-to-use-them-for-reactions-2"
381 },
382 {
383 "level":3,
384 "title":"How to get the tag",
385 "slug":"how-to-get-the-tag"
386 },
387 {
388 "level":2,
389 "title":"? Javacord Emoji \"Hierarchy\"",
390 "slug":"javacord-emoji-hierarchy"
391 },
392 {
393 "level":3,
394 "title":"What is a KnownCustomEmoji?",
395 "slug":"what-is-a-knowncustomemoji"
396 },
397 {
398 "level":2,
399 "title":"? Recommended libraries",
400 "slug":"recommended-libraries"
401 }
402 ],
403 "content":"# Emojis and Reactions\r\n\r\nThere are two different kinds of emojis in Discord: Unicode emojis and custom emojis.\r\n\r\n## :biking_man: Unicode Emojis\r\n\r\n### What are Unicode emojis?\r\n\r\nUnicode emojis are \"normal\" text emojis which are supported by (nearly) all chat clients, including Discord. You can find a list with all Unicode emojis here: [Full Emoji List](https://unicode.org/emoji/charts/full-emoji-list.html).\r\n\r\n### How to use them in messages\r\n\r\nYou can either directly add them in your code, e.g.\r\n```java\r\nchannel.sendMessage(\"Hi! ?\");\r\n```\r\nor use the normal \"tag\" like you would in the Client:\r\n```java\r\nchannel.sendMessage(\"Hi! :smiley:\");\r\n```\r\n\r\n\r\n### How to use them for reactions\r\n\r\nAdding unicode reactions is only possible by using the \"real\" reaction. It doesn't support tags like `:smiley:`\r\n```java\r\nmessage.addReaction(\"?\"); // works\r\nmessage.addReaction(\":smiley:\"); // doesn't work\r\n```\r\n\r\n\r\n## :woman_cartwheeling: Custom Emojis\r\n\r\n### What are custom emojis?\r\n\r\nCustom emojis are emojis that are created in a server. You can get all custom emojis the bot knows by using `DiscordApi#getCustomEmojis()`.\r\n\r\n\r\n\r\n### How to use them in messages\r\n\r\nTo use custom emojis, you have to know its \"tag\", which has the format `<:name:id>`. You can get it by calling `CustomEmoji#getMentionTag()`:\r\n```java\r\nchannel.sendMessage(\"Hi! <:javacord:415465982715494402>\");\r\n```\r\n```java\r\nCustomEmoji emoji = ...;\r\nchannel.sendMessage(\"Hi! \" + emoji.getMentionTag());\r\n```\r\n\r\n### How to use them for reactions\r\n\r\nYou can either directly use the custom emoji object or use the tag without the `<:` `>` if you don't have access a custom emoji object (e.g., because it's from a different shard):\r\n\r\n```java\r\nCustomEmoji emoji = ...;\r\nmessage.addReaction(emoji);\r\n```\r\n```java\r\nmessage.addReaction(\"javacord:415465982715494402\");\r\n```\r\n\r\n### How to get the tag\r\n\r\nJust add a `\\` in front of the emoji and press `Enter`\r\n\r\n\r\n\r\n\r\n\r\n## :crown: Javacord Emoji \"Hierarchy\"\r\n\r\nIn Javacord, all Emojis are a child of the `Emoji` interface:\r\n\r\n\r\n\r\n### What is a KnownCustomEmoji?\r\n\r\nKnown custom emojis are emojis that the bot knows because it's a member of the server with this emoji. A custom emoji can be unknown if someone adds a reaction with an unknown emoji for example. A `KnownCustomEmoji` has additional methods like `getServer()` or `updateName(String)`.\r\n\r\n## :ok_hand: Recommended libraries\r\n\r\nIf you are working a lot with Unicode emojis, it's recommended to use a library like [emoji-java](https://github.com/vdurmont/emoji-java). It enables you to do things like the following:\r\n```java\r\nmessage.addReaction(EmojiParser.parseToUnicode(\":thumbsup:\"));\r\n```",
404 "_strippedContent":"# Emojis and Reactions\r\n\r\nThere are two different kinds of emojis in Discord: Unicode emojis and custom emojis.\r\n\r\n## :biking_man: Unicode Emojis\r\n\r\n### What are Unicode emojis?\r\n\r\nUnicode emojis are \"normal\" text emojis which are supported by (nearly) all chat clients, including Discord. You can find a list with all Unicode emojis here: [Full Emoji List](https://unicode.org/emoji/charts/full-emoji-list.html).\r\n\r\n### How to use them in messages\r\n\r\nYou can either directly add them in your code, e.g.\r\n```java\r\nchannel.sendMessage(\"Hi! ?\");\r\n```\r\nor use the normal \"tag\" like you would in the Client:\r\n```java\r\nchannel.sendMessage(\"Hi! :smiley:\");\r\n```\r\n\r\n\r\n### How to use them for reactions\r\n\r\nAdding unicode reactions is only possible by using the \"real\" reaction. It doesn't support tags like `:smiley:`\r\n```java\r\nmessage.addReaction(\"?\"); // works\r\nmessage.addReaction(\":smiley:\"); // doesn't work\r\n```\r\n\r\n\r\n## :woman_cartwheeling: Custom Emojis\r\n\r\n### What are custom emojis?\r\n\r\nCustom emojis are emojis that are created in a server. You can get all custom emojis the bot knows by using `DiscordApi#getCustomEmojis()`.\r\n\r\n\r\n\r\n### How to use them in messages\r\n\r\nTo use custom emojis, you have to know its \"tag\", which has the format `<:name:id>`. You can get it by calling `CustomEmoji#getMentionTag()`:\r\n```java\r\nchannel.sendMessage(\"Hi! <:javacord:415465982715494402>\");\r\n```\r\n```java\r\nCustomEmoji emoji = ...;\r\nchannel.sendMessage(\"Hi! \" + emoji.getMentionTag());\r\n```\r\n\r\n### How to use them for reactions\r\n\r\nYou can either directly use the custom emoji object or use the tag without the `<:` `>` if you don't have access a custom emoji object (e.g., because it's from a different shard):\r\n\r\n```java\r\nCustomEmoji emoji = ...;\r\nmessage.addReaction(emoji);\r\n```\r\n```java\r\nmessage.addReaction(\"javacord:415465982715494402\");\r\n```\r\n\r\n### How to get the tag\r\n\r\nJust add a `\\` in front of the emoji and press `Enter`\r\n\r\n\r\n\r\n\r\n\r\n## :crown: Javacord Emoji \"Hierarchy\"\r\n\r\nIn Javacord, all Emojis are a child of the `Emoji` interface:\r\n\r\n\r\n\r\n### What is a KnownCustomEmoji?\r\n\r\nKnown custom emojis are emojis that the bot knows because it's a member of the server with this emoji. A custom emoji can be unknown if someone adds a reaction with an unknown emoji for example. A `KnownCustomEmoji` has additional methods like `getServer()` or `updateName(String)`.\r\n\r\n## :ok_hand: Recommended libraries\r\n\r\nIf you are working a lot with Unicode emojis, it's recommended to use a library like [emoji-java](https://github.com/vdurmont/emoji-java). It enables you to do things like the following:\r\n```java\r\nmessage.addReaction(EmojiParser.parseToUnicode(\":thumbsup:\"));\r\n```",
405 "path":"/wiki/basic-tutorials/emojis-and-reactions.html"
406 },
407 {
408 "title":"Listeners",
409 "headers":[
410 {
411 "level":2,
412 "title":"?? Creating listeners",
413 "slug":"creating-listeners"
414 },
415 {
416 "level":3,
417 "title":"Inline Listeners",
418 "slug":"inline-listeners"
419 },
420 {
421 "level":3,
422 "title":"In their own class",
423 "slug":"in-their-own-class"
424 },
425 {
426 "level":3,
427 "title":"Before logging in",
428 "slug":"before-logging-in"
429 },
430 {
431 "level":3,
432 "title":"Object listeners",
433 "slug":"object-listeners"
434 },
435 {
436 "level":2,
437 "title":"? Removing listeners",
438 "slug":"removing-listeners"
439 },
440 {
441 "level":3,
442 "title":"Using the returned ListenerManager",
443 "slug":"using-the-returned-listenermanager"
444 },
445 {
446 "level":3,
447 "title":"Using the removeListener(...) method",
448 "slug":"using-the-removelistener-method"
449 }
450 ],
451 "content":"# Listeners\r\n\r\n## :man_mechanic: Creating listeners\r\n\r\nCreating listeners is extremely easy in Javacord.\r\nYou can either use Java 8's lambda expressions to register listeners inline or just create a new class for them, if an inline listener would get too messy.\r\n\r\n### Inline Listeners\r\n\r\n```java\r\napi.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n});\r\n```\r\n\r\n### In their own class\r\n\r\n```java\r\napi.addListener(new MyListener());\r\n```\r\nand\r\n```java\r\npublic class MyListener implements MessageCreateListener {\r\n\r\n @Override\r\n public void onMessageCreate(MessageCreateEvent event) {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n }\r\n\r\n}\r\n```\r\n\r\n### Before logging in\r\n\r\nSometimes it might be useful to add listeners before calling the `DiscordApiBuilder#login()` method.\r\n\r\n```java\r\nDiscordApi api = new DiscordApiBuilder()\r\n // An inline listener\r\n .addMessageCreateListener(event -> {\r\n Message message = event.getMessage();\r\n if (message.getContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n })\r\n .addServerBecomesAvailableListener(event -> {\r\n System.out.println(\"Loaded \" + event.getServer().getName());\r\n })\r\n // A listener in their own class\r\n .addListener(new MyListener())\r\n // Alternative syntax that can be used for classes that require a DiscordApi parameter in their constructor\r\n .addListener(MyListener::new)\r\n .setToken(\"top secret\")\r\n .setWaitForServersOnStartup(false)\r\n .login()\r\n .join();\r\n```\r\n\r\n> Note: In most cases, it's enough to add listeners after logging in\r\n\r\n### Object listeners\r\n\r\nAnother cool feature is the ability to attach listeners directly to objects. An example where this can be useful is, for example, reacting to reactions. The following code would delete the message if someone adds a :thumbsdown: reaction.\r\n\r\n```java\r\nmessage.addReactionAddListener(event -> {\r\n if (event.getEmoji().equalsEmoji(\"?\")) {\r\n event.deleteMessage();\r\n }\r\n}).removeAfter(30, TimeUnit.MINUTES);\r\n```\r\n> Seems like the bot is very sensitive to criticism.\r\n\r\n## :bomb: Removing listeners\r\n\r\nThere are two ways to remove a listener:\r\n\r\n### Using the returned ListenerManager\r\n\r\nEvery time you register a listener, a `ListenerManager` is returned which can be used to unregister the listener:\r\n```java\r\nListenerManager<MessageCreateListener> listenerManager = api.addMessageCreateListener(event -> {\r\n // Do stuff\r\n});\r\n\r\nlistenerManager.remove();\r\n```\r\n\r\nThis manager also has some utility methods. You can, for example, remove a listener after a given time, which can be useful for object listeners:\r\n```java\r\nmessage.addReactionAddListener(event -> {\r\n // Do stuff\r\n}).removeAfter(30, TimeUnit.MINUTES);\r\n```\r\n\r\n### Using the `removeListener(...)` method\r\n\r\nYou can remove any listener using the `removeListener(...)` method:\r\n```java\r\nMyListener listener = new MyListener();\r\napi.addListener(listener);\r\n// ...\r\napi.removeListener(listener);\r\n```",
452 "_strippedContent":"# Listeners\r\n\r\n## :man_mechanic: Creating listeners\r\n\r\nCreating listeners is extremely easy in Javacord.\r\nYou can either use Java 8's lambda expressions to register listeners inline or just create a new class for them, if an inline listener would get too messy.\r\n\r\n### Inline Listeners\r\n\r\n```java\r\napi.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n});\r\n```\r\n\r\n### In their own class\r\n\r\n```java\r\napi.addListener(new MyListener());\r\n```\r\nand\r\n```java\r\npublic class MyListener implements MessageCreateListener {\r\n\r\n @Override\r\n public void onMessageCreate(MessageCreateEvent event) {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n }\r\n\r\n}\r\n```\r\n\r\n### Before logging in\r\n\r\nSometimes it might be useful to add listeners before calling the `DiscordApiBuilder#login()` method.\r\n\r\n```java\r\nDiscordApi api = new DiscordApiBuilder()\r\n // An inline listener\r\n .addMessageCreateListener(event -> {\r\n Message message = event.getMessage();\r\n if (message.getContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n })\r\n .addServerBecomesAvailableListener(event -> {\r\n System.out.println(\"Loaded \" + event.getServer().getName());\r\n })\r\n // A listener in their own class\r\n .addListener(new MyListener())\r\n // Alternative syntax that can be used for classes that require a DiscordApi parameter in their constructor\r\n .addListener(MyListener::new)\r\n .setToken(\"top secret\")\r\n .setWaitForServersOnStartup(false)\r\n .login()\r\n .join();\r\n```\r\n\r\n> Note: In most cases, it's enough to add listeners after logging in\r\n\r\n### Object listeners\r\n\r\nAnother cool feature is the ability to attach listeners directly to objects. An example where this can be useful is, for example, reacting to reactions. The following code would delete the message if someone adds a :thumbsdown: reaction.\r\n\r\n```java\r\nmessage.addReactionAddListener(event -> {\r\n if (event.getEmoji().equalsEmoji(\"?\")) {\r\n event.deleteMessage();\r\n }\r\n}).removeAfter(30, TimeUnit.MINUTES);\r\n```\r\n> Seems like the bot is very sensitive to criticism.\r\n\r\n## :bomb: Removing listeners\r\n\r\nThere are two ways to remove a listener:\r\n\r\n### Using the returned ListenerManager\r\n\r\nEvery time you register a listener, a `ListenerManager` is returned which can be used to unregister the listener:\r\n```java\r\nListenerManager<MessageCreateListener> listenerManager = api.addMessageCreateListener(event -> {\r\n // Do stuff\r\n});\r\n\r\nlistenerManager.remove();\r\n```\r\n\r\nThis manager also has some utility methods. You can, for example, remove a listener after a given time, which can be useful for object listeners:\r\n```java\r\nmessage.addReactionAddListener(event -> {\r\n // Do stuff\r\n}).removeAfter(30, TimeUnit.MINUTES);\r\n```\r\n\r\n### Using the `removeListener(...)` method\r\n\r\nYou can remove any listener using the `removeListener(...)` method:\r\n```java\r\nMyListener listener = new MyListener();\r\napi.addListener(listener);\r\n// ...\r\napi.removeListener(listener);\r\n```",
453 "path":"/wiki/basic-tutorials/listeners.html"
454 },
455 {
456 "title":"Glossary",
457 "content":"# Glossary\r\n\r\nThis is a list with the most common Discord-related terms:\r\n* **`Guild`** - A synonym for `server`\r\n* **`Selfbot`** - A client account bot, usually logged in to a user's own account\r\n* **`Sharding`** - Splitting a bot into several independent `shards`, see [Sharding](/wiki/advanced-tutorials/sharding)\r\n* **`Token`** - Used to login instead of requiring a username + password\r\n* **`Embed`** - A \"fancy\" message, see [Embed FAQ](/wiki/miscellaneous/embed-faq)\r\n* **`Ratelimit`** - Prevents you from spamming actions, see [Ratelimit FAQ](/wiki/miscellaneous/ratelimit-faq)\r\n* **`Websocket`** - A [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) \"connection\" to Discord that receives events, see [Wikipedia](https://en.wikipedia.org/wiki/WebSocket)\r\n* **`Gateway`** - The address for the `websocket`\r\n* **`Rest` / `Rest Request`** - [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) is used to perform actions like sending messages. Rest Requests do not require an active websocket connection.\r\n* **`Activity`** - The text underneath the username, usually `Playing Xyz`\r\n* **`Rich Presence`** - A more detailed activity, see [Discord Docs](https://discordapp.com/developers/docs/rich-presence/getting-approved)",
458 "_strippedContent":"# Glossary\r\n\r\nThis is a list with the most common Discord-related terms:\r\n* **`Guild`** - A synonym for `server`\r\n* **`Selfbot`** - A client account bot, usually logged in to a user's own account\r\n* **`Sharding`** - Splitting a bot into several independent `shards`, see [Sharding](/wiki/advanced-tutorials/sharding)\r\n* **`Token`** - Used to login instead of requiring a username + password\r\n* **`Embed`** - A \"fancy\" message, see [Embed FAQ](/wiki/miscellaneous/embed-faq)\r\n* **`Ratelimit`** - Prevents you from spamming actions, see [Ratelimit FAQ](/wiki/miscellaneous/ratelimit-faq)\r\n* **`Websocket`** - A [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) \"connection\" to Discord that receives events, see [Wikipedia](https://en.wikipedia.org/wiki/WebSocket)\r\n* **`Gateway`** - The address for the `websocket`\r\n* **`Rest` / `Rest Request`** - [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) is used to perform actions like sending messages. Rest Requests do not require an active websocket connection.\r\n* **`Activity`** - The text underneath the username, usually `Playing Xyz`\r\n* **`Rich Presence`** - A more detailed activity, see [Discord Docs](https://discordapp.com/developers/docs/rich-presence/getting-approved)",
459 "path":"/wiki/basic-tutorials/glossary.html"
460 },
461 {
462 "title":"Logger Configuration",
463 "headers":[
464 {
465 "level":2,
466 "title":"? Fallback Logger",
467 "slug":"fallback-logger"
468 },
469 {
470 "level":2,
471 "title":"? Using a Proper Logging Framework",
472 "slug":"using-a-proper-logging-framework"
473 },
474 {
475 "level":3,
476 "title":"Adding a Logging Framework",
477 "slug":"adding-a-logging-framework"
478 },
479 {
480 "level":3,
481 "title":"Configure Your Logging Framework",
482 "slug":"configure-your-logging-framework"
483 },
484 {
485 "level":3,
486 "title":"Logging the Relevant Shard",
487 "slug":"logging-the-relevant-shard"
488 }
489 ],
490 "content":"# Logger Configuration\r\n\r\nLogging is an important tool to keep track of what is going on in your application. Javacord uses the [Log4j 2 API](https://logging.apache.org/log4j/2.x/manual/api.html), which allows you to use your favorite logging framework to log messages in your own code and have all logging messages end up in the same destination. In case you do not add your own logging framework, a fallback logger is used that logs to the console. \r\nIf you want more control, add a proper logging framework that supports your needs and configure it accordingly. You can for example configure log messages on a per-class level, change log levels during runtime, or log to a file or database.\r\n\r\n## :2nd_place_medal: Fallback Logger\r\n\r\nJavacord's fallback logger is a simple Log4j logger which always logs `INFO` level and higher. It allows you to enable `DEBUG` and `TRACE` logging manually. As log levels are hierarchical, enabling `TRACE` will also implicitly enable `DEBUG`, and disabling `DEBUG` will also implicitly disable `TRACE`.\r\n\r\n```java\r\n// Enable debug logging\r\nFallbackLoggerConfiguration.setDebug(true);\r\n\r\n// Enable trace logging\r\nFallbackLoggerConfiguration.setTrace(true);\r\n```\r\n\r\nChanging the log level of the fallback logger only affects newly created loggers. Pre-existing loggers will not have their log level changed. So if you want to configure the fallback logger, you should do this as one of the first actions in your bot code. If you want to change log levels during runtime, you should use a proper logging framework like Log4j 2 Core or another library that supports this.\r\n\r\nAll fallback logger messages are printed to the standard output stream (`System.out`) and thus usually to your console. If you want to log to a file, database, or anything else, you should consider using a proper logging framework which allows you to configure this behavior.\r\n\r\nThis is how a log line from the fallback logger will look like:\r\n\r\n```log\r\n<time with date ><level><logger name, usually the logging class > <message > <the thread context, here the shard number>\r\n2018-08-03 20:00:06.080+0200 DEBUG org.javacord.core.util.gateway.DiscordWebSocketAdapter Received HELLO packet {shard=0}\r\n```\r\n\r\n## :1st_place_medal: Using a Proper Logging Framework\r\n\r\n### Adding a Logging Framework\r\n\r\nAdding a logging framework of your choice is very straightforward. You can just add it as a dependency, and it will be detected by Log4j automatically. The following example adds Log4j 2 using Gradle:\r\n\r\n```groovy\r\ndependencies { runtimeOnly 'org.apache.logging.log4j:log4j-core:2.11.0' }\r\n```\r\n\r\nYou can also use an SLF4J compatible logging framework using `log4j-to-slf4j`. The following example adds Logback Classic using Gradle:\r\n\r\n```groovy\r\ndependencies {\r\n runtimeOnly 'org.apache.logging.log4j:log4j-to-slf4j:2.11.0'\r\n runtimeOnly 'ch.qos.logback:logback-classic:1.2.3'\r\n}\r\n```\r\n\r\n### Configure Your Logging Framework\r\n\r\n* **Log4j 2**: [Log4j configuration](https://logging.apache.org/log4j/2.x/manual/configuration.html)\r\n* **Logback Classic**: [Logback configuration](https://logback.qos.ch/manual/configuration.html)\r\n\r\n### Logging the Relevant Shard\r\n\r\nJavacord adds the relevant shard to each log message. The facility that stores this information has a different name depending on which logging framework you use. For Log4j 2, this is called Thread Context Map and can be added in a pattern layout with `%X{shard}`, or you can add the whole thread context map by using `%X`. For Logback Classic, it is called MDC and can be added with the same pattern expressions as for Log4j.",
491 "_strippedContent":"# Logger Configuration\r\n\r\nLogging is an important tool to keep track of what is going on in your application. Javacord uses the [Log4j 2 API](https://logging.apache.org/log4j/2.x/manual/api.html), which allows you to use your favorite logging framework to log messages in your own code and have all logging messages end up in the same destination. In case you do not add your own logging framework, a fallback logger is used that logs to the console. \r\nIf you want more control, add a proper logging framework that supports your needs and configure it accordingly. You can for example configure log messages on a per-class level, change log levels during runtime, or log to a file or database.\r\n\r\n## :2nd_place_medal: Fallback Logger\r\n\r\nJavacord's fallback logger is a simple Log4j logger which always logs `INFO` level and higher. It allows you to enable `DEBUG` and `TRACE` logging manually. As log levels are hierarchical, enabling `TRACE` will also implicitly enable `DEBUG`, and disabling `DEBUG` will also implicitly disable `TRACE`.\r\n\r\n```java\r\n// Enable debug logging\r\nFallbackLoggerConfiguration.setDebug(true);\r\n\r\n// Enable trace logging\r\nFallbackLoggerConfiguration.setTrace(true);\r\n```\r\n\r\nChanging the log level of the fallback logger only affects newly created loggers. Pre-existing loggers will not have their log level changed. So if you want to configure the fallback logger, you should do this as one of the first actions in your bot code. If you want to change log levels during runtime, you should use a proper logging framework like Log4j 2 Core or another library that supports this.\r\n\r\nAll fallback logger messages are printed to the standard output stream (`System.out`) and thus usually to your console. If you want to log to a file, database, or anything else, you should consider using a proper logging framework which allows you to configure this behavior.\r\n\r\nThis is how a log line from the fallback logger will look like:\r\n\r\n```log\r\n<time with date ><level><logger name, usually the logging class > <message > <the thread context, here the shard number>\r\n2018-08-03 20:00:06.080+0200 DEBUG org.javacord.core.util.gateway.DiscordWebSocketAdapter Received HELLO packet {shard=0}\r\n```\r\n\r\n## :1st_place_medal: Using a Proper Logging Framework\r\n\r\n### Adding a Logging Framework\r\n\r\nAdding a logging framework of your choice is very straightforward. You can just add it as a dependency, and it will be detected by Log4j automatically. The following example adds Log4j 2 using Gradle:\r\n\r\n```groovy\r\ndependencies { runtimeOnly 'org.apache.logging.log4j:log4j-core:2.11.0' }\r\n```\r\n\r\nYou can also use an SLF4J compatible logging framework using `log4j-to-slf4j`. The following example adds Logback Classic using Gradle:\r\n\r\n```groovy\r\ndependencies {\r\n runtimeOnly 'org.apache.logging.log4j:log4j-to-slf4j:2.11.0'\r\n runtimeOnly 'ch.qos.logback:logback-classic:1.2.3'\r\n}\r\n```\r\n\r\n### Configure Your Logging Framework\r\n\r\n* **Log4j 2**: [Log4j configuration](https://logging.apache.org/log4j/2.x/manual/configuration.html)\r\n* **Logback Classic**: [Logback configuration](https://logback.qos.ch/manual/configuration.html)\r\n\r\n### Logging the Relevant Shard\r\n\r\nJavacord adds the relevant shard to each log message. The facility that stores this information has a different name depending on which logging framework you use. For Log4j 2, this is called Thread Context Map and can be added in a pattern layout with `%X{shard}`, or you can add the whole thread context map by using `%X`. For Logback Classic, it is called MDC and can be added with the same pattern expressions as for Log4j.",
492 "path":"/wiki/basic-tutorials/logger-config.html"
493 },
494 {
495 "title":"Lambdas",
496 "headers":[
497 {
498 "level":2,
499 "title":"? Further Read",
500 "slug":"further-read"
501 }
502 ],
503 "content":"# Lambdas\r\n\r\nLambdas are used to implement [functional interfaces](https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html).\r\nSimply said, functional interfaces are interfaces with a single method definition.\r\nAll listeners in Javacord are functional interfaces and look like this internally (simplified):\r\n\r\n```java\r\n@FunctionalInterface\r\npublic interface MessageCreateListener {\r\n void onMessageCreate(MessageCreateEvent event);\r\n}\r\n```\r\n\r\nBefore Java 8, you would have implemented this kind of listener as an [anonymous class](https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html), which would look like this:\r\n\r\n```java\r\napi.addMessageCreateListener(new MessageCreateListener() {\r\n @Override\r\n public void onMessageCreate(MessageCreateEvent event) {\r\n // Do stuff\r\n event.pinMessage();\r\n }\r\n});\r\n```\r\n\r\nIn Java 8, this can be replaced with a lambda expression, which does exactly the same thing, but in a more readable fashion. \r\nThe method parameter (in this case `event`) is written in front of the `->` arrow, and the method body is written after it.\r\n\r\n```java\r\napi.addMessageCreateListener(event -> {\r\n // Do stuff\r\n event.pinMessage();\r\n});\r\n```\r\n\r\n::: tip\r\nIf the method has more than one parameter, it would look like this: \r\n```java\r\n(param1, param2) -> { ... }\r\n```\r\n:::\r\n\r\nThere's even a shorter version: If you are only executing one statement, you can get rid of the `{ }` brackets as well:\r\n```java\r\napi.addMessageCreateListener(event -> event.pinMessage());\r\n```\r\n\r\nHowever, the above method can be shortened even more, by replacing the lambda expression with a so called \"[method reference](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html)\".\r\n```java\r\napi.addMessageCreateListener(MessageEvent::pinMessage);\r\n```\r\n\r\nThere are also plenty classes in Java 8, that make use of lambda expressions.\r\nOne example would be the Optional class, which is explained [here](/wiki/essential-knowledge/optionals/).\r\n\r\n## :books: Further Read\r\n\r\nThis tutorial only focused on the absolute basics.\r\nFor an in-depth introduction to lambda expressions, you can take a look at\r\n[Oracle's article about lambda expressions](https://www.oracle.com/technical-resources/articles/java/architect-lambdas-part1.html).\r\n\r\n",
504 "_strippedContent":"# Lambdas\r\n\r\nLambdas are used to implement [functional interfaces](https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html).\r\nSimply said, functional interfaces are interfaces with a single method definition.\r\nAll listeners in Javacord are functional interfaces and look like this internally (simplified):\r\n\r\n```java\r\n@FunctionalInterface\r\npublic interface MessageCreateListener {\r\n void onMessageCreate(MessageCreateEvent event);\r\n}\r\n```\r\n\r\nBefore Java 8, you would have implemented this kind of listener as an [anonymous class](https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html), which would look like this:\r\n\r\n```java\r\napi.addMessageCreateListener(new MessageCreateListener() {\r\n @Override\r\n public void onMessageCreate(MessageCreateEvent event) {\r\n // Do stuff\r\n event.pinMessage();\r\n }\r\n});\r\n```\r\n\r\nIn Java 8, this can be replaced with a lambda expression, which does exactly the same thing, but in a more readable fashion. \r\nThe method parameter (in this case `event`) is written in front of the `->` arrow, and the method body is written after it.\r\n\r\n```java\r\napi.addMessageCreateListener(event -> {\r\n // Do stuff\r\n event.pinMessage();\r\n});\r\n```\r\n\r\n::: tip\r\nIf the method has more than one parameter, it would look like this: \r\n```java\r\n(param1, param2) -> { ... }\r\n```\r\n:::\r\n\r\nThere's even a shorter version: If you are only executing one statement, you can get rid of the `{ }` brackets as well:\r\n```java\r\napi.addMessageCreateListener(event -> event.pinMessage());\r\n```\r\n\r\nHowever, the above method can be shortened even more, by replacing the lambda expression with a so called \"[method reference](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html)\".\r\n```java\r\napi.addMessageCreateListener(MessageEvent::pinMessage);\r\n```\r\n\r\nThere are also plenty classes in Java 8, that make use of lambda expressions.\r\nOne example would be the Optional class, which is explained [here](/wiki/essential-knowledge/optionals/).\r\n\r\n## :books: Further Read\r\n\r\nThis tutorial only focused on the absolute basics.\r\nFor an in-depth introduction to lambda expressions, you can take a look at\r\n[Oracle's article about lambda expressions](https://www.oracle.com/technical-resources/articles/java/architect-lambdas-part1.html).\r\n\r\n",
505 "path":"/wiki/essential-knowledge/lambdas.html"
506 },
507 {
508 "title":"Completable Futures",
509 "headers":[
510 {
511 "level":2,
512 "title":"? What the heck is a future?",
513 "slug":"what-the-heck-is-a-future"
514 },
515 {
516 "level":2,
517 "title":"? Methods",
518 "slug":"methods"
519 },
520 {
521 "level":3,
522 "title":"join()",
523 "slug":"join"
524 },
525 {
526 "level":3,
527 "title":"thenAccept(...)",
528 "slug":"thenaccept"
529 },
530 {
531 "level":3,
532 "title":"exceptionally(...)",
533 "slug":"exceptionally"
534 },
535 {
536 "level":3,
537 "title":"thenCompose()",
538 "slug":"thencompose"
539 },
540 {
541 "level":2,
542 "title":"? Further Read",
543 "slug":"further-read"
544 }
545 ],
546 "content":"# Completable Futures\r\n\r\n::: warning\r\nThis tutorials assumes, that you are familiar with lambda expressions.\r\nTake a look at the [lambda introduction](/wiki/essential-knowledge/lambdas/) first, if you are not!\r\n:::\r\n\r\nAs Javacord is heavily multithreaded, you must understand the concept of\r\n[Futures](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html) \r\nin general, as well as their most common implementation, the \r\n[CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html). \r\nThis little introduction gives you a quick overview of the basics you need to know in order to work with Futures.\r\n\r\n## :thinking: What the heck is a future?\r\n\r\nA future is basically a wrapper, that will contain a value in the future but might not contain it right now.\r\nThis is useful, if a method call requires some time and should not block the execution of your current code.\r\nYou can easily see the difference with a primitive speed comparison:\r\n\r\n```java\r\nlong currentTime = System.currentTimeMillis();\r\nchannel.sendMessage(\"Test 1\");\r\nchannel.sendMessage(\"Test 2\");\r\nchannel.sendMessage(\"Test 3\");\r\nchannel.sendMessage(\"Test 4\");\r\nchannel.sendMessage(\"Test 5\");\r\n// Prints \"4 ms\"\r\nSystem.out.println((System.currentTimeMillis() - currentTime) + \" ms\");\r\n```\r\n\r\n```java\r\nlong currentTime = System.currentTimeMillis();\r\nchannel.sendMessage(\"Test 1\").join();\r\nchannel.sendMessage(\"Test 2\").join();\r\nchannel.sendMessage(\"Test 3\").join();\r\nchannel.sendMessage(\"Test 4\").join();\r\nchannel.sendMessage(\"Test 5\").join();\r\n// Prints \"894 ms\"\r\nSystem.out.println((System.currentTimeMillis() - currentTime) + \" ms\");\r\n```\r\n\r\n::: tip\r\n`join()` blocks the current thread until the method finished. This will be explained later.\r\n:::\r\n\r\n## :open_book: Methods\r\n\r\n### join()\r\n\r\nThe `join` method blocks the current thread until the method finished.\r\nIt returns the method's result or throws a `CompletionException` if anything failed.\r\n\r\nThe following example would create a new text channel in a given `server` and sends a message directly afterwards.\r\n```java\r\n// Create the channel\r\nServerTextChannel channel = new ServerTextChannelBuilder(server)\r\n .setName(\"new-channel\")\r\n .create()\r\n .join();\r\n// Send a message in the new channel\r\nMessage message = channel.sendMessage(\"First!\").join();\r\n// Adds an reaction to the message. Even though this method doesn't return anything,\r\n// join() ensures, that an exception is thrown in case something went wrong\r\nmessage.addReaction(\"?\").join();\r\n```\r\n\r\n::: danger\r\nYou should avoid `join()` for methods which will be called frequently.\r\n:::\r\n\r\n::: tip\r\nWhile `join()` can become a performance issue when you call it very frequently, it is very convenient to use and easy to understand.\r\nIf you are new to programming and just want to get your first bot working, this is a good method to start with.\r\n\r\nOnce you gathered more experience, we highly advise against using `join` as it negatively impacts your bot's performance!\r\n:::\r\n\r\n### thenAccept(...)\r\n\r\nThe `thenAccept` method accepts a `Consumer`, that consumes the result of the method and is executed asynchronously.\r\nIt is the method you usually want to use most of the time.\r\n\r\nThe following example would create a new text channel in a given `server` and send a message directly afterwards.\r\n```java\r\nnew ServerTextChannelBuilder(server)\r\n .setName(\"new-channel\")\r\n .create()\r\n .thenAccept(channel -> {\r\n channel.sendMessage(\"First!\").thenAccept(message -> {\r\n message.addReaction(\"?\");\r\n });\r\n });\r\n```\r\n\r\n::: danger\r\nThe example code above has a major problem: Any exception that might occur will be completely ignored.\r\nThis makes it very hard to find bugs.\r\n\r\nFor example, if your bot doesn't have the permissions to create a new channel, it will just fail silently.\r\n:::\r\n\r\n### exceptionally(...)\r\n\r\nThe `exceptionally` method accepts a `Function` as parameter, which consumes possible exceptions and returns an fallback value.\r\n\r\nThe following example would create a new text channel in a given `server` and send a message directly afterwards.\r\nIf something fails (e.g., if the bot isn't allowed to create a text channel in the server), it will log an exception.\r\n\r\n```java\r\nnew ServerTextChannelBuilder(server)\r\n .setName(\"new-channel\")\r\n .create()\r\n .thenAccept(channel -> {\r\n channel.sendMessage(\"First!\").thenAccept(message -> {\r\n message.addReaction(\"?\").exceptionally(e -> {\r\n e.printStackTrace(); // Adding the reaction failed\r\n return null;\r\n });\r\n }).exceptionally(e -> {\r\n e.printStackTrace(); // Message sending failed\r\n return null;\r\n });\r\n }).exceptionally(e -> {\r\n e.printStackTrace(); // Channel creation failed \r\n return null;\r\n });\r\n```\r\n\r\nWow! This looks ugly ?.\r\nBut worry not! There are many options to improve this code!\r\n\r\nTo make things simpler for you, Javacord has the `ExceptionLogger` class, which can be used here.\r\nIt logs every exception you didn't catch manually.\r\n\r\n```java\r\nnew ServerTextChannelBuilder(server)\r\n .setName(\"new-channel\")\r\n .create()\r\n .thenAccept(channel -> {\r\n channel.sendMessage(\"First!\").thenAccept(message -> {\r\n message.addReaction(\"?\").exceptionally(ExceptionLogger.get());\r\n }).exceptionally(ExceptionLogger.get());\r\n }).exceptionally(ExceptionLogger.get());\r\n```\r\n\r\nOkay! This is at least a little better, but still not really perfect :thinking:.\r\n\r\n### thenCompose()\r\n\r\nThe `thenCompose` methods allows you to chain futures.\r\nIt takes a [Function](https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html) as parameter, that\r\nconsumes the future's value and expects a new future to be returned.\r\n\r\nThe example to create a text channel can now be written like this:\r\n```java\r\nnew ServerTextChannelBuilder(server)\r\n .setName(\"new-channel\")\r\n .create() \r\n .thenCompose(channel -> channel.sendMessage(\"First!\"))\r\n .thenCompose(message -> message.addReaction(\"?\"))\r\n .exceptionally(ExceptionLogger.get());\r\n```\r\n\r\nFinally :tada:! Now we only need a single `exceptionally(...)` call at the end.\r\nWe also got rid of the nested callbacks (usually referred to as \"callback hell\").\r\n\r\nFor better understanding, here's the example with comments that tell you the type at each line:\r\n```java\r\nnew ServerTextChannelBuilder(server) // ServerTextChannelBuilder\r\n .setName(\"new-channel\") // ServerTextChannelBuilder\r\n .create() // CompletableFuture<ServerTextChannel>\r\n .thenCompose(channel -> channel.sendMessage(\"First!\")) // CompletableFuture<Message>\r\n .thenCompose(message -> message.addReaction(\"?\")) // CompletableFuture<Void>\r\n .exceptionally(ExceptionLogger.get()); // CompletableFuture<Void>\r\n```\r\n\r\n## :books: Further Read\r\n\r\nThis tutorial only focused on the absolute basics.\r\nFor a more detailed introduction to CompletableFutures, you can take a look at\r\n[this tutorial](https://www.callicoder.com/java-8-completablefuture-tutorial/).\r\n\r\nYou should also take a look at the JavaDoc for a complete list of methods: [CompletableFuture JavaDoc](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html).\r\n",
547 "_strippedContent":"# Completable Futures\r\n\r\n::: warning\r\nThis tutorials assumes, that you are familiar with lambda expressions.\r\nTake a look at the [lambda introduction](/wiki/essential-knowledge/lambdas/) first, if you are not!\r\n:::\r\n\r\nAs Javacord is heavily multithreaded, you must understand the concept of\r\n[Futures](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html) \r\nin general, as well as their most common implementation, the \r\n[CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html). \r\nThis little introduction gives you a quick overview of the basics you need to know in order to work with Futures.\r\n\r\n## :thinking: What the heck is a future?\r\n\r\nA future is basically a wrapper, that will contain a value in the future but might not contain it right now.\r\nThis is useful, if a method call requires some time and should not block the execution of your current code.\r\nYou can easily see the difference with a primitive speed comparison:\r\n\r\n```java\r\nlong currentTime = System.currentTimeMillis();\r\nchannel.sendMessage(\"Test 1\");\r\nchannel.sendMessage(\"Test 2\");\r\nchannel.sendMessage(\"Test 3\");\r\nchannel.sendMessage(\"Test 4\");\r\nchannel.sendMessage(\"Test 5\");\r\n// Prints \"4 ms\"\r\nSystem.out.println((System.currentTimeMillis() - currentTime) + \" ms\");\r\n```\r\n\r\n```java\r\nlong currentTime = System.currentTimeMillis();\r\nchannel.sendMessage(\"Test 1\").join();\r\nchannel.sendMessage(\"Test 2\").join();\r\nchannel.sendMessage(\"Test 3\").join();\r\nchannel.sendMessage(\"Test 4\").join();\r\nchannel.sendMessage(\"Test 5\").join();\r\n// Prints \"894 ms\"\r\nSystem.out.println((System.currentTimeMillis() - currentTime) + \" ms\");\r\n```\r\n\r\n::: tip\r\n`join()` blocks the current thread until the method finished. This will be explained later.\r\n:::\r\n\r\n## :open_book: Methods\r\n\r\n### join()\r\n\r\nThe `join` method blocks the current thread until the method finished.\r\nIt returns the method's result or throws a `CompletionException` if anything failed.\r\n\r\nThe following example would create a new text channel in a given `server` and sends a message directly afterwards.\r\n```java\r\n// Create the channel\r\nServerTextChannel channel = new ServerTextChannelBuilder(server)\r\n .setName(\"new-channel\")\r\n .create()\r\n .join();\r\n// Send a message in the new channel\r\nMessage message = channel.sendMessage(\"First!\").join();\r\n// Adds an reaction to the message. Even though this method doesn't return anything,\r\n// join() ensures, that an exception is thrown in case something went wrong\r\nmessage.addReaction(\"?\").join();\r\n```\r\n\r\n::: danger\r\nYou should avoid `join()` for methods which will be called frequently.\r\n:::\r\n\r\n::: tip\r\nWhile `join()` can become a performance issue when you call it very frequently, it is very convenient to use and easy to understand.\r\nIf you are new to programming and just want to get your first bot working, this is a good method to start with.\r\n\r\nOnce you gathered more experience, we highly advise against using `join` as it negatively impacts your bot's performance!\r\n:::\r\n\r\n### thenAccept(...)\r\n\r\nThe `thenAccept` method accepts a `Consumer`, that consumes the result of the method and is executed asynchronously.\r\nIt is the method you usually want to use most of the time.\r\n\r\nThe following example would create a new text channel in a given `server` and send a message directly afterwards.\r\n```java\r\nnew ServerTextChannelBuilder(server)\r\n .setName(\"new-channel\")\r\n .create()\r\n .thenAccept(channel -> {\r\n channel.sendMessage(\"First!\").thenAccept(message -> {\r\n message.addReaction(\"?\");\r\n });\r\n });\r\n```\r\n\r\n::: danger\r\nThe example code above has a major problem: Any exception that might occur will be completely ignored.\r\nThis makes it very hard to find bugs.\r\n\r\nFor example, if your bot doesn't have the permissions to create a new channel, it will just fail silently.\r\n:::\r\n\r\n### exceptionally(...)\r\n\r\nThe `exceptionally` method accepts a `Function` as parameter, which consumes possible exceptions and returns an fallback value.\r\n\r\nThe following example would create a new text channel in a given `server` and send a message directly afterwards.\r\nIf something fails (e.g., if the bot isn't allowed to create a text channel in the server), it will log an exception.\r\n\r\n```java\r\nnew ServerTextChannelBuilder(server)\r\n .setName(\"new-channel\")\r\n .create()\r\n .thenAccept(channel -> {\r\n channel.sendMessage(\"First!\").thenAccept(message -> {\r\n message.addReaction(\"?\").exceptionally(e -> {\r\n e.printStackTrace(); // Adding the reaction failed\r\n return null;\r\n });\r\n }).exceptionally(e -> {\r\n e.printStackTrace(); // Message sending failed\r\n return null;\r\n });\r\n }).exceptionally(e -> {\r\n e.printStackTrace(); // Channel creation failed \r\n return null;\r\n });\r\n```\r\n\r\nWow! This looks ugly ?.\r\nBut worry not! There are many options to improve this code!\r\n\r\nTo make things simpler for you, Javacord has the `ExceptionLogger` class, which can be used here.\r\nIt logs every exception you didn't catch manually.\r\n\r\n```java\r\nnew ServerTextChannelBuilder(server)\r\n .setName(\"new-channel\")\r\n .create()\r\n .thenAccept(channel -> {\r\n channel.sendMessage(\"First!\").thenAccept(message -> {\r\n message.addReaction(\"?\").exceptionally(ExceptionLogger.get());\r\n }).exceptionally(ExceptionLogger.get());\r\n }).exceptionally(ExceptionLogger.get());\r\n```\r\n\r\nOkay! This is at least a little better, but still not really perfect :thinking:.\r\n\r\n### thenCompose()\r\n\r\nThe `thenCompose` methods allows you to chain futures.\r\nIt takes a [Function](https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html) as parameter, that\r\nconsumes the future's value and expects a new future to be returned.\r\n\r\nThe example to create a text channel can now be written like this:\r\n```java\r\nnew ServerTextChannelBuilder(server)\r\n .setName(\"new-channel\")\r\n .create() \r\n .thenCompose(channel -> channel.sendMessage(\"First!\"))\r\n .thenCompose(message -> message.addReaction(\"?\"))\r\n .exceptionally(ExceptionLogger.get());\r\n```\r\n\r\nFinally :tada:! Now we only need a single `exceptionally(...)` call at the end.\r\nWe also got rid of the nested callbacks (usually referred to as \"callback hell\").\r\n\r\nFor better understanding, here's the example with comments that tell you the type at each line:\r\n```java\r\nnew ServerTextChannelBuilder(server) // ServerTextChannelBuilder\r\n .setName(\"new-channel\") // ServerTextChannelBuilder\r\n .create() // CompletableFuture<ServerTextChannel>\r\n .thenCompose(channel -> channel.sendMessage(\"First!\")) // CompletableFuture<Message>\r\n .thenCompose(message -> message.addReaction(\"?\")) // CompletableFuture<Void>\r\n .exceptionally(ExceptionLogger.get()); // CompletableFuture<Void>\r\n```\r\n\r\n## :books: Further Read\r\n\r\nThis tutorial only focused on the absolute basics.\r\nFor a more detailed introduction to CompletableFutures, you can take a look at\r\n[this tutorial](https://www.callicoder.com/java-8-completablefuture-tutorial/).\r\n\r\nYou should also take a look at the JavaDoc for a complete list of methods: [CompletableFuture JavaDoc](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html).\r\n",
548 "path":"/wiki/essential-knowledge/completable-futures.html"
549 },
550 {
551 "title":"Optionals",
552 "headers":[
553 {
554 "level":2,
555 "title":"? Motivation",
556 "slug":"motivation"
557 },
558 {
559 "level":3,
560 "title":"The old way of doing it",
561 "slug":"the-old-way-of-doing-it"
562 },
563 {
564 "level":3,
565 "title":"The new way of doing it",
566 "slug":"the-new-way-of-doing-it"
567 },
568 {
569 "level":2,
570 "title":"? Methods",
571 "slug":"methods"
572 },
573 {
574 "level":3,
575 "title":"get()",
576 "slug":"get"
577 },
578 {
579 "level":3,
580 "title":"isPresent()",
581 "slug":"ispresent"
582 },
583 {
584 "level":3,
585 "title":"orElse(...)",
586 "slug":"orelse"
587 },
588 {
589 "level":3,
590 "title":"ifPresent(...)",
591 "slug":"ifpresent"
592 },
593 {
594 "level":3,
595 "title":"filter(...)",
596 "slug":"filter"
597 },
598 {
599 "level":3,
600 "title":"map(...)",
601 "slug":"map"
602 },
603 {
604 "level":3,
605 "title":"flatMap(...)",
606 "slug":"flatmap"
607 },
608 {
609 "level":2,
610 "title":"? Further Read",
611 "slug":"further-read"
612 }
613 ],
614 "content":"# Optionals\r\n\r\n::: warning\r\nThis tutorials assumes, that you are familiar with lambda expressions.\r\nTake a look at the [lambda introduction](/wiki/essential-knowledge/lambdas/) first, if you are not!\r\n:::\r\n\r\n## :muscle: Motivation\r\n\r\nThe Optional class is widely used in Javacord.\r\nBasically, every method that might return a `null` value will return an Optional in Javacord instead.\r\nOptionals help you to avoid `NullPointerExceptions` and make it very clear if a method may not have a result.\r\nHere's a small example:\r\n\r\n### The old way of doing it\r\n\r\n```java\r\nUser user = api.getCachedUserById(123L);\r\nif (user != null) {\r\n user.sendMessage(\"Hi!\");\r\n}\r\n```\r\n\r\n### The new way of doing it\r\n\r\n```java\r\napi.getCachedUserById(123L).ifPresent(user -> \r\n user.sendMessage(\"Hi!\")\r\n);\r\n```\r\n\r\nYou can imagine an `Optional` like a box :package: that may or may not contain a value.\r\nBefore accessing this value, you have to \"unpack\" this box first.\r\n\r\n## :open_book: Methods\r\n\r\nThe Optional class has many useful methods which can all be found in the [JavaDocs](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html).\r\nThis tutorial gives a short introduction to the most common ones.\r\n\r\n### get()\r\n\r\nThe `get` method returns the value of the Optional or throws a `NoSuchElementException` if it does not contain a value.\r\n\r\n```java\r\nTextChannel channel = api.getTextChannelById(123L).get();\r\nchannel.sendMessage(\"Hi\");\r\n```\r\n\r\n::: danger\r\nYou should never use this method blindly but only if you are **100%** sure the optional contains a value.\r\n\r\nEvery time you use this method carelessly, a kitten dies :scream_cat:!\r\nTrue story.\r\n:::\r\n\r\n### isPresent()\r\n\r\nThe `isPresent` methods checks, if the Optional contains a value.\r\n\r\n```java\r\nOptional<TextChannel> channel = api.getTextChannelById(123L);\r\nif (channel.isPresent()) {\r\n // A text channel with the id 123 exists. It's safe to call #get() now\r\n channel.get().sendMessage(\"Hi\");\r\n}\r\n```\r\n\r\n### orElse(...)\r\n\r\nThe `orElse` methods returns the value of the Optional if it is present. Otherwise, it returns the given default value.\r\n\r\n```java\r\n// The user may not have a nickname on the given server. \r\n// In this case, we use the user's \"regular\" name.\r\nString displayName = user.getNickname(server).orElse(user.getName());\r\n```\r\nThe example above is (mostly) equivalent to the example below but much more concise.\r\n```java\r\nString displayName = \"\";\r\nOptional<String> nickname = user.getNickname(server);\r\nif (nickname.isPresent()) {\r\n displayName = nickname.get();\r\n} else {\r\n displayName = user.getName();\r\n}\r\n```\r\n\r\n::: tip\r\nIn this case you can just use `user.getDisplayName(server)` instead.\r\n:::\r\n\r\n### ifPresent(...)\r\n\r\nThe `ifPresent` method is very similar to an `if (value != null) { ... }` check. \r\nIt takes a [Consumer](https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html) as it's argument.\r\nThis consumer is called if the Optional contains a value.\r\nTogether with lambda expressions this can be a very handy method.\r\n\r\n```java\r\napi.getTextChannelById(123L).ifPresent(channel -> {\r\n channel.sendMessage(\"Hi!\");\r\n});\r\n```\r\nThe example above is (mostly) equivalent to the example below but more concise.\r\n```java\r\nOptional<TextChannel> channel = api.getTextChannelById(123L);\r\nif (channel.isPresent()) {\r\n channel.get().sendMessage(\"Hi!\");\r\n}\r\n```\r\n\r\n### filter(...)\r\n\r\nThe `filter` method filters the Optional for a given criteria.\r\n\r\n```java\r\nOptional<User> botUser = api.getCachedUserById(123L).filter(User::isBot);\r\n```\r\nThe example above is equivalent to the example below but more concise.\r\n```java\r\nOptional<User> user = api.getCachedUserById(123L);\r\nOptional<User> botUser;\r\nif (user.isPresent() && user.get().isBot()) {\r\n botUser = user;\r\n} else {\r\n botUser = Optional.empty();\r\n}\r\n```\r\n\r\n### map(...)\r\n\r\nThe `map` method \"converts\" the type of an Optional.\r\nThis is useful, if the type of an Optional does not contain the final value you need.\r\n\r\nThe following example gets the name of the bots current activity (the \"Playing xyz\" status) or \"None\" if the bot has no current activity.\r\n\r\n```java\r\nString activityName = api.getYourself().getActivity().map(Activity::getName).orElse(\"None\");\r\n```\r\nFor better understanding, here's the exact same code but with the types as comments:\r\n```java\r\nString activityName = api.getYourself() // User\r\n .getActivity() // Optional<Activity>\r\n .map(Activity::getName) // Optional<String>\r\n .orElse(\"None\"); // String\r\n```\r\n\r\n### flatMap(...)\r\n\r\nThe `flatMap` method if very similar to the `map` methods.\r\nIt is a used to map values that itself are Optionals to prevent Optional nesting (a \"box in a box\").\r\n\r\n```java\r\nString activityName = api.getCachedUserById(123L) // Optional<User>\r\n .flatMap(User::getActivity) // Optional<Activity>\r\n .map(Activity::getName) // Optional<String>\r\n .orElse(\"None\"); // String\r\n```\r\n\r\nWithout `flatMap`, the code would look like this:\r\n```java\r\nString activityName = api.getCachedUserById(123L) // Optional<User>\r\n .map(User::getActivity) // Optional<Optional<Activity>>\r\n .filter(Optional::isPresent) // Optional<Optional<Activity>>\r\n .map(Optional::get) // Optional<Activity>\r\n .map(Activity::getName) // Optional<String>\r\n .orElse(\"None\"); // String\r\n```\r\n\r\n## :books: Further Read\r\n\r\nThis tutorial only focused on the absolute basics.\r\nFor an in-depth introduction to Optionals, you can take a look at\r\n[Oracle's article about optionals](https://www.oracle.com/technical-resources/articles/java/java8-optional.html).\r\n\r\n",
615 "_strippedContent":"# Optionals\r\n\r\n::: warning\r\nThis tutorials assumes, that you are familiar with lambda expressions.\r\nTake a look at the [lambda introduction](/wiki/essential-knowledge/lambdas/) first, if you are not!\r\n:::\r\n\r\n## :muscle: Motivation\r\n\r\nThe Optional class is widely used in Javacord.\r\nBasically, every method that might return a `null` value will return an Optional in Javacord instead.\r\nOptionals help you to avoid `NullPointerExceptions` and make it very clear if a method may not have a result.\r\nHere's a small example:\r\n\r\n### The old way of doing it\r\n\r\n```java\r\nUser user = api.getCachedUserById(123L);\r\nif (user != null) {\r\n user.sendMessage(\"Hi!\");\r\n}\r\n```\r\n\r\n### The new way of doing it\r\n\r\n```java\r\napi.getCachedUserById(123L).ifPresent(user -> \r\n user.sendMessage(\"Hi!\")\r\n);\r\n```\r\n\r\nYou can imagine an `Optional` like a box :package: that may or may not contain a value.\r\nBefore accessing this value, you have to \"unpack\" this box first.\r\n\r\n## :open_book: Methods\r\n\r\nThe Optional class has many useful methods which can all be found in the [JavaDocs](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html).\r\nThis tutorial gives a short introduction to the most common ones.\r\n\r\n### get()\r\n\r\nThe `get` method returns the value of the Optional or throws a `NoSuchElementException` if it does not contain a value.\r\n\r\n```java\r\nTextChannel channel = api.getTextChannelById(123L).get();\r\nchannel.sendMessage(\"Hi\");\r\n```\r\n\r\n::: danger\r\nYou should never use this method blindly but only if you are **100%** sure the optional contains a value.\r\n\r\nEvery time you use this method carelessly, a kitten dies :scream_cat:!\r\nTrue story.\r\n:::\r\n\r\n### isPresent()\r\n\r\nThe `isPresent` methods checks, if the Optional contains a value.\r\n\r\n```java\r\nOptional<TextChannel> channel = api.getTextChannelById(123L);\r\nif (channel.isPresent()) {\r\n // A text channel with the id 123 exists. It's safe to call #get() now\r\n channel.get().sendMessage(\"Hi\");\r\n}\r\n```\r\n\r\n### orElse(...)\r\n\r\nThe `orElse` methods returns the value of the Optional if it is present. Otherwise, it returns the given default value.\r\n\r\n```java\r\n// The user may not have a nickname on the given server. \r\n// In this case, we use the user's \"regular\" name.\r\nString displayName = user.getNickname(server).orElse(user.getName());\r\n```\r\nThe example above is (mostly) equivalent to the example below but much more concise.\r\n```java\r\nString displayName = \"\";\r\nOptional<String> nickname = user.getNickname(server);\r\nif (nickname.isPresent()) {\r\n displayName = nickname.get();\r\n} else {\r\n displayName = user.getName();\r\n}\r\n```\r\n\r\n::: tip\r\nIn this case you can just use `user.getDisplayName(server)` instead.\r\n:::\r\n\r\n### ifPresent(...)\r\n\r\nThe `ifPresent` method is very similar to an `if (value != null) { ... }` check. \r\nIt takes a [Consumer](https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html) as it's argument.\r\nThis consumer is called if the Optional contains a value.\r\nTogether with lambda expressions this can be a very handy method.\r\n\r\n```java\r\napi.getTextChannelById(123L).ifPresent(channel -> {\r\n channel.sendMessage(\"Hi!\");\r\n});\r\n```\r\nThe example above is (mostly) equivalent to the example below but more concise.\r\n```java\r\nOptional<TextChannel> channel = api.getTextChannelById(123L);\r\nif (channel.isPresent()) {\r\n channel.get().sendMessage(\"Hi!\");\r\n}\r\n```\r\n\r\n### filter(...)\r\n\r\nThe `filter` method filters the Optional for a given criteria.\r\n\r\n```java\r\nOptional<User> botUser = api.getCachedUserById(123L).filter(User::isBot);\r\n```\r\nThe example above is equivalent to the example below but more concise.\r\n```java\r\nOptional<User> user = api.getCachedUserById(123L);\r\nOptional<User> botUser;\r\nif (user.isPresent() && user.get().isBot()) {\r\n botUser = user;\r\n} else {\r\n botUser = Optional.empty();\r\n}\r\n```\r\n\r\n### map(...)\r\n\r\nThe `map` method \"converts\" the type of an Optional.\r\nThis is useful, if the type of an Optional does not contain the final value you need.\r\n\r\nThe following example gets the name of the bots current activity (the \"Playing xyz\" status) or \"None\" if the bot has no current activity.\r\n\r\n```java\r\nString activityName = api.getYourself().getActivity().map(Activity::getName).orElse(\"None\");\r\n```\r\nFor better understanding, here's the exact same code but with the types as comments:\r\n```java\r\nString activityName = api.getYourself() // User\r\n .getActivity() // Optional<Activity>\r\n .map(Activity::getName) // Optional<String>\r\n .orElse(\"None\"); // String\r\n```\r\n\r\n### flatMap(...)\r\n\r\nThe `flatMap` method if very similar to the `map` methods.\r\nIt is a used to map values that itself are Optionals to prevent Optional nesting (a \"box in a box\").\r\n\r\n```java\r\nString activityName = api.getCachedUserById(123L) // Optional<User>\r\n .flatMap(User::getActivity) // Optional<Activity>\r\n .map(Activity::getName) // Optional<String>\r\n .orElse(\"None\"); // String\r\n```\r\n\r\nWithout `flatMap`, the code would look like this:\r\n```java\r\nString activityName = api.getCachedUserById(123L) // Optional<User>\r\n .map(User::getActivity) // Optional<Optional<Activity>>\r\n .filter(Optional::isPresent) // Optional<Optional<Activity>>\r\n .map(Optional::get) // Optional<Activity>\r\n .map(Activity::getName) // Optional<String>\r\n .orElse(\"None\"); // String\r\n```\r\n\r\n## :books: Further Read\r\n\r\nThis tutorial only focused on the absolute basics.\r\nFor an in-depth introduction to Optionals, you can take a look at\r\n[Oracle's article about optionals](https://www.oracle.com/technical-resources/articles/java/java8-optional.html).\r\n\r\n",
616 "path":"/wiki/essential-knowledge/optionals.html"
617 },
618 {
619 "title":"Intoduction",
620 "headers":[
621 {
622 "level":2,
623 "title":"? Structure of the wiki",
624 "slug":"structure-of-the-wiki"
625 },
626 {
627 "level":2,
628 "title":"? Support",
629 "slug":"support"
630 }
631 ],
632 "content":"---\r\npermalink: /wiki\r\n---\r\n\r\n# Intoduction\r\n\r\nWelcome to the Javacord wiki! :wave:\r\n\r\nThis wiki will help you to get started with your first Discord bot as fast as possible.\r\n\r\n## :books: Structure of the wiki\r\n\r\nThe wiki is divided into four groups:\r\n* **Getting Started** focuses on teaching you how to setup up everything to get the most basic bot working.\r\n* **Basic tutorials** contains articles about various concepts and classes of Javacord. Take a look at the headlines of each artcile and decide yourself, if it is relevant for you.\r\n* **Advanced Topics** focuses on some more advanced topics that are not stricly necessary to start working with Javacord, but might become handy later on.\r\n* **Essential Knowlege** teaches you the most important Java features/classes that you should know to comfortably work with Javacord. If you already have decent Java knowlege, you can skip this completely.\r\n\r\n\r\n## :handshake: Support\r\n\r\nWhile the wiki is great and covers many aspects of Javacord, we highly recommended you to join our Discord server if you have any questions:\r\n* Join the **[Javacord server](https://discord.gg/0qJ2jjyneLEgG7y3)** (Invite code: `0qJ2jjyneLEgG7y3`)\r\n\r\n",
633 "_strippedContent":"\r\n# Intoduction\r\n\r\nWelcome to the Javacord wiki! :wave:\r\n\r\nThis wiki will help you to get started with your first Discord bot as fast as possible.\r\n\r\n## :books: Structure of the wiki\r\n\r\nThe wiki is divided into four groups:\r\n* **Getting Started** focuses on teaching you how to setup up everything to get the most basic bot working.\r\n* **Basic tutorials** contains articles about various concepts and classes of Javacord. Take a look at the headlines of each artcile and decide yourself, if it is relevant for you.\r\n* **Advanced Topics** focuses on some more advanced topics that are not stricly necessary to start working with Javacord, but might become handy later on.\r\n* **Essential Knowlege** teaches you the most important Java features/classes that you should know to comfortably work with Javacord. If you already have decent Java knowlege, you can skip this completely.\r\n\r\n\r\n## :handshake: Support\r\n\r\nWhile the wiki is great and covers many aspects of Javacord, we highly recommended you to join our Discord server if you have any questions:\r\n* Join the **[Javacord server](https://discord.gg/0qJ2jjyneLEgG7y3)** (Invite code: `0qJ2jjyneLEgG7y3`)\r\n\r\n",
634 "path":"/wiki/"
635 },
636 {
637 "title":"Using the MessageBuilder",
638 "headers":[
639 {
640 "level":2,
641 "title":"?️♀️ Example",
642 "slug":"example"
643 }
644 ],
645 "content":"# Using the MessageBuilder\r\n\r\nThe `MessageBuilder` class is a more powerful alternative to the `TextChannel#sendMessage(...)` method.\r\n\r\nI can be used to construct more complex messages and supports some additional features that are not possible\r\nwith a simple `TextChannel#sendMessage(...)` call.\r\n\r\n## :female_detective: Example\r\n\r\nThe following code\r\n```java\r\nnew MessageBuilder()\r\n .append(\"Look at these \")\r\n .append(\"awesome\", MessageDecoration.BOLD, MessageDecoration.UNDERLINE)\r\n .append(\" animal pictures! ?\")\r\n .appendCode(\"java\", \"System.out.println(\\\"Sweet!\\\");\")\r\n .addAttachment(new File(\"C:/Users/Bastian/Pictures/kitten.jpg\"))\r\n .addAttachment(new File(\"C:/Users/Bastian/Pictures/puppy.jpg\"))\r\n .setEmbed(new EmbedBuilder()\r\n .setTitle(\"WOW\")\r\n .setDescription(\"Really cool pictures!\")\r\n .setColor(Color.ORANGE))\r\n .send(channel);\r\n```\r\nwill be displayed like this:\r\n\r\n ",
646 "_strippedContent":"# Using the MessageBuilder\r\n\r\nThe `MessageBuilder` class is a more powerful alternative to the `TextChannel#sendMessage(...)` method.\r\n\r\nI can be used to construct more complex messages and supports some additional features that are not possible\r\nwith a simple `TextChannel#sendMessage(...)` call.\r\n\r\n## :female_detective: Example\r\n\r\nThe following code\r\n```java\r\nnew MessageBuilder()\r\n .append(\"Look at these \")\r\n .append(\"awesome\", MessageDecoration.BOLD, MessageDecoration.UNDERLINE)\r\n .append(\" animal pictures! ?\")\r\n .appendCode(\"java\", \"System.out.println(\\\"Sweet!\\\");\")\r\n .addAttachment(new File(\"C:/Users/Bastian/Pictures/kitten.jpg\"))\r\n .addAttachment(new File(\"C:/Users/Bastian/Pictures/puppy.jpg\"))\r\n .setEmbed(new EmbedBuilder()\r\n .setTitle(\"WOW\")\r\n .setDescription(\"Really cool pictures!\")\r\n .setColor(Color.ORANGE))\r\n .send(channel);\r\n```\r\nwill be displayed like this:\r\n\r\n ",
647 "path":"/wiki/basic-tutorials/message-builder.html"
648 },
649 {
650 "title":"Creating a Bot Account",
651 "headers":[
652 {
653 "level":2,
654 "title":"? Create a bot and get its token",
655 "slug":"create-a-bot-and-get-its-token"
656 },
657 {
658 "level":2,
659 "title":"➕ How to add a bot to your server",
660 "slug":"how-to-add-a-bot-to-your-server"
661 },
662 {
663 "level":3,
664 "title":"Use Javacord to create the invite link",
665 "slug":"use-javacord-to-create-the-invite-link"
666 },
667 {
668 "level":3,
669 "title":"Create the invite link manually",
670 "slug":"create-the-invite-link-manually"
671 },
672 {
673 "level":2,
674 "title":"?♂ Use the invite link",
675 "slug":"use-the-invite-link"
676 }
677 ],
678 "content":"# Creating a Bot Account\r\n\r\nAfter you added Javacord as a dependency with your favorite build manager, you should now create a bot account on the Discord website.\r\nThis article will guide you through the process.\r\n\r\n## :bulb: Create a bot and get its token\r\n\r\n#### **1.** Open [https://discord.com/developers/applications/me](https://discordapp.com/developers/applications/me) and click on \"Create an application\".\r\n\r\n\r\n\r\n#### **2.** Switch to `Bot`\r\n\r\n::: tip\r\nIf you want to, you can rename your application first\r\n::: \r\n\r\n\r\n\r\n#### **3.** Click on `Add bot` and confirm the popup\r\n\r\n\r\n\r\n\r\n#### **4.** Copy the bot's token. In this case the token would be `NDc[...]pCs`. You can just click on `Copy`.\r\n\r\n::: danger\r\nThis token is used to login your bot. Keep it secret!\r\n:::\r\n\r\n\r\n\r\n#### **5.** If you want to, you can change the bot's name and avatar on this page, too.\r\n\r\n## :heavy_plus_sign: How to add a bot to your server\r\n\r\nBots cannot join a server on their own like normal Discord users can.\r\nInstead the owner of a sever has to invite the bot using a so called `Invite Link`.\r\nThere are multiple ways to create the invite link:\r\n\r\n### Use Javacord to create the invite link\r\n\r\nThe easiest way to obtain an invite link for you bot is by letting Javacord do it for you.\r\nSimply execute the following code and it will print the invite link to your console:\r\n\r\n```java\r\nDiscordApi api = new DiscordApiBuilder().setToken(\"your token\").login().join();\r\nSystem.out.println(api.createBotInvite());\r\n```\r\n\r\nIf you don't have Javacord setup yet, you can also create the invite link manually.\r\n\r\n### Create the invite link manually\r\n\r\n#### Get the client id\r\n\r\nIn order to add a bot to your server you need its client id.\r\n\r\nYou can get your client id from the [same page](https://discord.com/developers/applications/me) where you created it.\r\n\r\n\r\n\r\nWith this id you can create an invite link for your bot.\r\n\r\nIf you are the owner or admin of the server, you can use this link to add your bot to your server. Otherwise, you have to give the link to the server owner/admins and ask them to add your bot.\r\n\r\n::: tip\r\nUnlike the token, you don't have to keep your client id secret\r\n:::\r\n\r\n#### Create the url\r\n\r\nJust use the following link and replace `123456789` with your own client id.\r\n\r\n**https://discord.com/api/oauth2/authorize?client_id=123456789&scope=bot&permissions=0**\r\n\r\nYou can calculate the permissions (in the link above it's the `0`) on the page where you created the bot:\r\n\r\n\r\n\r\n## :raising_hand_man: Use the invite link\r\n\r\nYou can now open the link and add the bot to your server:\r\n\r\n\r\n\r\n::: tip\r\nOnly the owner and admins of a server can invite bots. If you do not own a server yet, it is recommended to create one for testing.\r\n::: ",
679 "_strippedContent":"# Creating a Bot Account\r\n\r\nAfter you added Javacord as a dependency with your favorite build manager, you should now create a bot account on the Discord website.\r\nThis article will guide you through the process.\r\n\r\n## :bulb: Create a bot and get its token\r\n\r\n#### **1.** Open [https://discord.com/developers/applications/me](https://discordapp.com/developers/applications/me) and click on \"Create an application\".\r\n\r\n\r\n\r\n#### **2.** Switch to `Bot`\r\n\r\n::: tip\r\nIf you want to, you can rename your application first\r\n::: \r\n\r\n\r\n\r\n#### **3.** Click on `Add bot` and confirm the popup\r\n\r\n\r\n\r\n\r\n#### **4.** Copy the bot's token. In this case the token would be `NDc[...]pCs`. You can just click on `Copy`.\r\n\r\n::: danger\r\nThis token is used to login your bot. Keep it secret!\r\n:::\r\n\r\n\r\n\r\n#### **5.** If you want to, you can change the bot's name and avatar on this page, too.\r\n\r\n## :heavy_plus_sign: How to add a bot to your server\r\n\r\nBots cannot join a server on their own like normal Discord users can.\r\nInstead the owner of a sever has to invite the bot using a so called `Invite Link`.\r\nThere are multiple ways to create the invite link:\r\n\r\n### Use Javacord to create the invite link\r\n\r\nThe easiest way to obtain an invite link for you bot is by letting Javacord do it for you.\r\nSimply execute the following code and it will print the invite link to your console:\r\n\r\n```java\r\nDiscordApi api = new DiscordApiBuilder().setToken(\"your token\").login().join();\r\nSystem.out.println(api.createBotInvite());\r\n```\r\n\r\nIf you don't have Javacord setup yet, you can also create the invite link manually.\r\n\r\n### Create the invite link manually\r\n\r\n#### Get the client id\r\n\r\nIn order to add a bot to your server you need its client id.\r\n\r\nYou can get your client id from the [same page](https://discord.com/developers/applications/me) where you created it.\r\n\r\n\r\n\r\nWith this id you can create an invite link for your bot.\r\n\r\nIf you are the owner or admin of the server, you can use this link to add your bot to your server. Otherwise, you have to give the link to the server owner/admins and ask them to add your bot.\r\n\r\n::: tip\r\nUnlike the token, you don't have to keep your client id secret\r\n:::\r\n\r\n#### Create the url\r\n\r\nJust use the following link and replace `123456789` with your own client id.\r\n\r\n**https://discord.com/api/oauth2/authorize?client_id=123456789&scope=bot&permissions=0**\r\n\r\nYou can calculate the permissions (in the link above it's the `0`) on the page where you created the bot:\r\n\r\n\r\n\r\n## :raising_hand_man: Use the invite link\r\n\r\nYou can now open the link and add the bot to your server:\r\n\r\n\r\n\r\n::: tip\r\nOnly the owner and admins of a server can invite bots. If you do not own a server yet, it is recommended to create one for testing.\r\n::: ",
680 "path":"/wiki/getting-started/creating-a-bot-account.html"
681 },
682 {
683 "title":"Download / Installation",
684 "headers":[
685 {
686 "level":2,
687 "title":"? Javacord Dependency",
688 "slug":"javacord-dependency"
689 },
690 {
691 "level":3,
692 "title":"Gradle",
693 "slug":"gradle"
694 },
695 {
696 "level":3,
697 "title":"Maven",
698 "slug":"maven"
699 },
700 {
701 "level":3,
702 "title":"Sbt",
703 "slug":"sbt"
704 },
705 {
706 "level":2,
707 "title":"? Optional Logger Dependency",
708 "slug":"optional-logger-dependency"
709 },
710 {
711 "level":3,
712 "title":"Gradle",
713 "slug":"gradle-2"
714 },
715 {
716 "level":3,
717 "title":"Maven",
718 "slug":"maven-2"
719 },
720 {
721 "level":3,
722 "title":"Sbt",
723 "slug":"sbt-2"
724 }
725 ],
726 "content":"# Download / Installation\r\n\r\nThe recommended way to get Javacord is to use a build manager, like Gradle or Maven. \r\nIf you are not familiar with build managers, you can follow one of the beginner ide setup guides (see navigation) or download Javacord directly from [GitHub](https://github.com/Javacord/Javacord/releases/latest).\r\n\r\n## :package: Javacord Dependency\r\n\r\n<LatestVersionInfo/>\r\n\r\n### Gradle\r\n\r\n```groovy\r\nrepositories { mavenCentral() }\r\ndependencies { implementation 'org.javacord:javacord:$latest-version' }\r\n```\r\n\r\n### Maven\r\n\r\n```\r\n<dependency>\r\n <groupId>org.javacord</groupId>\r\n <artifactId>javacord</artifactId>\r\n <version>$latest-version</version>\r\n <type>pom</type>\r\n</dependency>\r\n```\r\n\r\n### Sbt\r\n\r\n```scala\r\nlibraryDependencies ++= Seq(\"org.javacord\" % \"javacord\" % \"$latest-version\")\r\n```\r\n\r\n## :memo: Optional Logger Dependency\r\n\r\nIn addition to Javacord, it is also recommended to install a Log4j-2-compatible logging framework.\r\nA logging framework can be used to provide a more sophisticated logging experience with being able to configure log format, log targets (console, file, database, Discord direct message, ...), log levels per class, and much more.\r\n\r\nFor example, Log4j Core:\r\n\r\n### Gradle\r\n\r\n```groovy\r\ndependencies { runtimeOnly 'org.apache.logging.log4j:log4j-core:2.11.0' }\r\n```\r\n\r\n### Maven\r\n\r\n```xml\r\n<dependency>\r\n <groupId>org.apache.logging.log4j</groupId>\r\n <artifactId>log4j-core</artifactId>\r\n <version>2.11.0</version>\r\n</dependency>\r\n```\r\n\r\n### Sbt\r\n\r\n```scala\r\nlibraryDependencies ++= Seq(\"org.apache.logging.log4j\" % \"log4j-core\" % \"2.11.0\")\r\n```\r\n\r\nTake a look at the [logger configuration](/wiki/basic-tutorials/logger-config/) wiki article for further information.",
727 "_strippedContent":"# Download / Installation\r\n\r\nThe recommended way to get Javacord is to use a build manager, like Gradle or Maven. \r\nIf you are not familiar with build managers, you can follow one of the beginner ide setup guides (see navigation) or download Javacord directly from [GitHub](https://github.com/Javacord/Javacord/releases/latest).\r\n\r\n## :package: Javacord Dependency\r\n\r\n<LatestVersionInfo/>\r\n\r\n### Gradle\r\n\r\n```groovy\r\nrepositories { mavenCentral() }\r\ndependencies { implementation 'org.javacord:javacord:$latest-version' }\r\n```\r\n\r\n### Maven\r\n\r\n```\r\n<dependency>\r\n <groupId>org.javacord</groupId>\r\n <artifactId>javacord</artifactId>\r\n <version>$latest-version</version>\r\n <type>pom</type>\r\n</dependency>\r\n```\r\n\r\n### Sbt\r\n\r\n```scala\r\nlibraryDependencies ++= Seq(\"org.javacord\" % \"javacord\" % \"$latest-version\")\r\n```\r\n\r\n## :memo: Optional Logger Dependency\r\n\r\nIn addition to Javacord, it is also recommended to install a Log4j-2-compatible logging framework.\r\nA logging framework can be used to provide a more sophisticated logging experience with being able to configure log format, log targets (console, file, database, Discord direct message, ...), log levels per class, and much more.\r\n\r\nFor example, Log4j Core:\r\n\r\n### Gradle\r\n\r\n```groovy\r\ndependencies { runtimeOnly 'org.apache.logging.log4j:log4j-core:2.11.0' }\r\n```\r\n\r\n### Maven\r\n\r\n```xml\r\n<dependency>\r\n <groupId>org.apache.logging.log4j</groupId>\r\n <artifactId>log4j-core</artifactId>\r\n <version>2.11.0</version>\r\n</dependency>\r\n```\r\n\r\n### Sbt\r\n\r\n```scala\r\nlibraryDependencies ++= Seq(\"org.apache.logging.log4j\" % \"log4j-core\" % \"2.11.0\")\r\n```\r\n\r\nTake a look at the [logger configuration](/wiki/basic-tutorials/logger-config/) wiki article for further information.",
728 "path":"/wiki/getting-started/download-installation.html"
729 },
730 {
731 "title":"Eclipse + Maven",
732 "headers":[
733 {
734 "level":2,
735 "title":"? Setup",
736 "slug":"setup"
737 },
738 {
739 "level":2,
740 "title":"?♀ Run the code",
741 "slug":"run-the-code"
742 }
743 ],
744 "content":"# Eclipse + Maven\r\n\r\nThis tutorial provides a beginner-friendly click by click guide to set up Javacord with Eclipse and Maven.\r\nIf you are already familiar with Eclipse and Maven, you can just see the artifact locations at [Download / Installation](/wiki/getting-started/download-installation.md).\r\n\r\n::: tip Info\r\nWe recommend to use [Intellij + Gradle](./intellij-gradle.md) unless you already have experience with one of the other IDEs or build managers.\r\n::: \r\n\r\n## :wrench: Setup\r\n\r\n#### **1.** Start Eclipse\r\n\r\n#### **2.** Create a new project (`File` -> `New` -> `Project`)\r\n\r\n\r\n\r\n#### **3.** Select `Maven Project`\r\n\r\n#### **4.** Click `Next`\r\n\r\n\r\n\r\n#### **5.** Check `Create a simple project`\r\n\r\n#### **6.** Click `Next`\r\n\r\n\r\n\r\n#### **7.** Enter a group id (e.g. `com.github.yourname`)\r\n\r\n#### **8.** Enter an artifact id (e.g. `myfirstbot`)\r\n\r\n#### **9.** Click `Finish`\r\n\r\n\r\n\r\n#### **10.** Double click on the `pom.xml` file\r\n\r\n\r\n\r\n#### **11.** Select `pom.xml`\r\n\r\n\r\n\r\n#### **12.** Now you have to add Javacord as a dependency by editing the pom.xml file. Your file should now look like this:\r\n\r\n<LatestVersionInfo/>\r\n\r\n```xml\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\r\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n <modelVersion>4.0.0</modelVersion>\r\n\r\n <groupId>your.package.name</groupId>\r\n <artifactId>myfirstbot</artifactId>\r\n <version>1.0-SNAPSHOT</version>\r\n\r\n <dependencies>\r\n <dependency>\r\n <groupId>org.javacord</groupId>\r\n <artifactId>javacord</artifactId>\r\n <version>$latest-version</version>\r\n <type>pom</type>\r\n </dependency>\r\n </dependencies>\r\n\r\n</project>\r\n```\r\n\r\n#### **13.** Create a new package inside the `src/main/java` folder\r\n\r\n\r\n\r\n\r\n#### **14.** Create a new class inside this package\r\n\r\n\r\n\r\n\r\n#### **15.** Save the project (you should do this from time to time)\r\n\r\n\r\n\r\n#### **16.** Now you can start coding! Example code:\r\n\r\n```java\r\npackage com.github.yourname.myfirstbot;\r\n\r\nimport org.javacord.api.DiscordApi;\r\nimport org.javacord.api.DiscordApiBuilder;\r\n\r\npublic class Main {\r\n\r\n public static void main(String[] args) {\r\n // Insert your bot's token here\r\n String token = \"your token\";\r\n\r\n DiscordApi api = new DiscordApiBuilder().setToken(token).login().join();\r\n\r\n // Add a listener which answers with \"Pong!\" if someone writes \"!ping\"\r\n api.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n });\r\n\r\n // Print the invite url of your bot\r\n System.out.println(\"You can invite the bot by using the following url: \" + api.createBotInvite());\r\n }\r\n\r\n}\r\n```\r\n\r\n## :running_woman: Run the code\r\n\r\nYou can run your code by clicking on the small green arrow\r\n",
745 "_strippedContent":"# Eclipse + Maven\r\n\r\nThis tutorial provides a beginner-friendly click by click guide to set up Javacord with Eclipse and Maven.\r\nIf you are already familiar with Eclipse and Maven, you can just see the artifact locations at [Download / Installation](/wiki/getting-started/download-installation.md).\r\n\r\n::: tip Info\r\nWe recommend to use [Intellij + Gradle](./intellij-gradle.md) unless you already have experience with one of the other IDEs or build managers.\r\n::: \r\n\r\n## :wrench: Setup\r\n\r\n#### **1.** Start Eclipse\r\n\r\n#### **2.** Create a new project (`File` -> `New` -> `Project`)\r\n\r\n\r\n\r\n#### **3.** Select `Maven Project`\r\n\r\n#### **4.** Click `Next`\r\n\r\n\r\n\r\n#### **5.** Check `Create a simple project`\r\n\r\n#### **6.** Click `Next`\r\n\r\n\r\n\r\n#### **7.** Enter a group id (e.g. `com.github.yourname`)\r\n\r\n#### **8.** Enter an artifact id (e.g. `myfirstbot`)\r\n\r\n#### **9.** Click `Finish`\r\n\r\n\r\n\r\n#### **10.** Double click on the `pom.xml` file\r\n\r\n\r\n\r\n#### **11.** Select `pom.xml`\r\n\r\n\r\n\r\n#### **12.** Now you have to add Javacord as a dependency by editing the pom.xml file. Your file should now look like this:\r\n\r\n<LatestVersionInfo/>\r\n\r\n```xml\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\r\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n <modelVersion>4.0.0</modelVersion>\r\n\r\n <groupId>your.package.name</groupId>\r\n <artifactId>myfirstbot</artifactId>\r\n <version>1.0-SNAPSHOT</version>\r\n\r\n <dependencies>\r\n <dependency>\r\n <groupId>org.javacord</groupId>\r\n <artifactId>javacord</artifactId>\r\n <version>$latest-version</version>\r\n <type>pom</type>\r\n </dependency>\r\n </dependencies>\r\n\r\n</project>\r\n```\r\n\r\n#### **13.** Create a new package inside the `src/main/java` folder\r\n\r\n\r\n\r\n\r\n#### **14.** Create a new class inside this package\r\n\r\n\r\n\r\n\r\n#### **15.** Save the project (you should do this from time to time)\r\n\r\n\r\n\r\n#### **16.** Now you can start coding! Example code:\r\n\r\n```java\r\npackage com.github.yourname.myfirstbot;\r\n\r\nimport org.javacord.api.DiscordApi;\r\nimport org.javacord.api.DiscordApiBuilder;\r\n\r\npublic class Main {\r\n\r\n public static void main(String[] args) {\r\n // Insert your bot's token here\r\n String token = \"your token\";\r\n\r\n DiscordApi api = new DiscordApiBuilder().setToken(token).login().join();\r\n\r\n // Add a listener which answers with \"Pong!\" if someone writes \"!ping\"\r\n api.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n });\r\n\r\n // Print the invite url of your bot\r\n System.out.println(\"You can invite the bot by using the following url: \" + api.createBotInvite());\r\n }\r\n\r\n}\r\n```\r\n\r\n## :running_woman: Run the code\r\n\r\nYou can run your code by clicking on the small green arrow\r\n",
746 "path":"/wiki/getting-started/setup/eclipse-maven.html"
747 },
748 {
749 "title":"IntelliJ + Gradle",
750 "headers":[
751 {
752 "level":2,
753 "title":"? Setup",
754 "slug":"setup"
755 },
756 {
757 "level":2,
758 "title":"?♀ Run the code",
759 "slug":"run-the-code"
760 }
761 ],
762 "content":"# IntelliJ + Gradle\r\n\r\nThis tutorial provides a beginner-friendly click by click guide to set up Javacord with Intellij and Gradle.\r\nIf you are already familiar with IntelliJ and Gradle, you can just see the artifact locations at [Download / Installation](/wiki/getting-started/download-installation.md).\r\n\r\n## :wrench: Setup\r\n\r\n#### **1.** Start IntelliJ\r\n\r\n#### **2.** Create a new project (`File` -> `New` -> `Project`)\r\n\r\n\r\n\r\n#### **3.** Select `Gradle`\r\n\r\n#### **4.** Make sure to select a SDK which is 1.8 (or greater)\r\n\r\n#### **5.** Click `Next`\r\n\r\n\r\n\r\n#### **6.** Enter a group id (e.g. `com.github.yourname`)\r\n\r\nYou can choose whatever you want\r\n\r\n#### **7.** Enter an artifact id (e.g. `myfirstbot`)\r\n\r\nYou can choose whatever you want\r\n\r\n#### **8.** Click `Next`\r\n\r\n\r\n\r\n#### **9.** Check `Use auto-import`\r\n\r\n#### **10.** Click `Next`\r\n\r\n\r\n\r\n#### **11.** Click `Finish`\r\n\r\n\r\n\r\n#### **12.** Locate the `build.gradle` file and open it\r\n\r\n\r\n\r\n#### **12.** Add the Javacord dependency. Your `build.gradle` file should now look like this\r\n\r\n<LatestVersionInfo/>\r\n\r\n```groovy\r\nplugins {\r\n id 'java'\r\n}\r\n\r\ngroup 'com.github.yourname'\r\nversion '1.0-SNAPSHOT'\r\n\r\nsourceCompatibility = 1.8\r\n\r\nrepositories {\r\n mavenCentral()\r\n}\r\n\r\ndependencies {\r\n implementation 'org.javacord:javacord:$latest-version'\r\n}\r\n```\r\n\r\n#### **13.** Create a new package in the `src/main/java` folder\r\n\r\n\r\n\r\n\r\n#### **14.** Create a new class inside this package\r\n\r\n\r\n\r\n\r\n#### **15.** You can now start coding!\r\n\r\nExample code:\r\n```java\r\npackage com.github.yourname;\r\n\r\nimport org.javacord.api.DiscordApi;\r\nimport org.javacord.api.DiscordApiBuilder;\r\n\r\npublic class Main {\r\n\r\n public static void main(String[] args) {\r\n // Insert your bot's token here\r\n String token = \"your token\";\r\n\r\n DiscordApi api = new DiscordApiBuilder().setToken(token).login().join();\r\n\r\n // Add a listener which answers with \"Pong!\" if someone writes \"!ping\"\r\n api.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n });\r\n\r\n // Print the invite url of your bot\r\n System.out.println(\"You can invite the bot by using the following url: \" + api.createBotInvite());\r\n }\r\n\r\n}\r\n```\r\n\r\n## :running_woman: Run the code\r\n\r\nYou can run your code by clicking on the small green arrow\r\n",
763 "_strippedContent":"# IntelliJ + Gradle\r\n\r\nThis tutorial provides a beginner-friendly click by click guide to set up Javacord with Intellij and Gradle.\r\nIf you are already familiar with IntelliJ and Gradle, you can just see the artifact locations at [Download / Installation](/wiki/getting-started/download-installation.md).\r\n\r\n## :wrench: Setup\r\n\r\n#### **1.** Start IntelliJ\r\n\r\n#### **2.** Create a new project (`File` -> `New` -> `Project`)\r\n\r\n\r\n\r\n#### **3.** Select `Gradle`\r\n\r\n#### **4.** Make sure to select a SDK which is 1.8 (or greater)\r\n\r\n#### **5.** Click `Next`\r\n\r\n\r\n\r\n#### **6.** Enter a group id (e.g. `com.github.yourname`)\r\n\r\nYou can choose whatever you want\r\n\r\n#### **7.** Enter an artifact id (e.g. `myfirstbot`)\r\n\r\nYou can choose whatever you want\r\n\r\n#### **8.** Click `Next`\r\n\r\n\r\n\r\n#### **9.** Check `Use auto-import`\r\n\r\n#### **10.** Click `Next`\r\n\r\n\r\n\r\n#### **11.** Click `Finish`\r\n\r\n\r\n\r\n#### **12.** Locate the `build.gradle` file and open it\r\n\r\n\r\n\r\n#### **12.** Add the Javacord dependency. Your `build.gradle` file should now look like this\r\n\r\n<LatestVersionInfo/>\r\n\r\n```groovy\r\nplugins {\r\n id 'java'\r\n}\r\n\r\ngroup 'com.github.yourname'\r\nversion '1.0-SNAPSHOT'\r\n\r\nsourceCompatibility = 1.8\r\n\r\nrepositories {\r\n mavenCentral()\r\n}\r\n\r\ndependencies {\r\n implementation 'org.javacord:javacord:$latest-version'\r\n}\r\n```\r\n\r\n#### **13.** Create a new package in the `src/main/java` folder\r\n\r\n\r\n\r\n\r\n#### **14.** Create a new class inside this package\r\n\r\n\r\n\r\n\r\n#### **15.** You can now start coding!\r\n\r\nExample code:\r\n```java\r\npackage com.github.yourname;\r\n\r\nimport org.javacord.api.DiscordApi;\r\nimport org.javacord.api.DiscordApiBuilder;\r\n\r\npublic class Main {\r\n\r\n public static void main(String[] args) {\r\n // Insert your bot's token here\r\n String token = \"your token\";\r\n\r\n DiscordApi api = new DiscordApiBuilder().setToken(token).login().join();\r\n\r\n // Add a listener which answers with \"Pong!\" if someone writes \"!ping\"\r\n api.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n });\r\n\r\n // Print the invite url of your bot\r\n System.out.println(\"You can invite the bot by using the following url: \" + api.createBotInvite());\r\n }\r\n\r\n}\r\n```\r\n\r\n## :running_woman: Run the code\r\n\r\nYou can run your code by clicking on the small green arrow\r\n",
764 "path":"/wiki/getting-started/setup/intellij-gradle.html"
765 },
766 {
767 "title":"IntelliJ + Maven",
768 "headers":[
769 {
770 "level":2,
771 "title":"? Setup",
772 "slug":"setup"
773 },
774 {
775 "level":2,
776 "title":"?♀ Run the code",
777 "slug":"run-the-code"
778 },
779 {
780 "level":2,
781 "title":"? Possible problems",
782 "slug":"possible-problems"
783 }
784 ],
785 "content":"# IntelliJ + Maven\r\n\r\nThis tutorial provides a beginner-friendly click by click guide to set up Javacord with Intellij and Maven.\r\nIf you are already familiar with IntelliJ and Maven, you can just see the artifact locations at [Download / Installation](/wiki/getting-started/download-installation.md).\r\n\r\n::: tip Info\r\nWe recommend to use [Intellij + Gradle](./intellij-gradle.md) unless you already have experience with one of the other IDEs or build managers.\r\n::: \r\n\r\n## :wrench: Setup\r\n\r\n#### **1.** Start IntelliJ\r\n\r\n#### **2.** Create a new project (`File` -> `New` -> `Project`)\r\n\r\n\r\n\r\n#### **3.** Select `Maven`\r\n\r\n#### **4.** Make sure to select a SDK which is 1.8 (or greater)\r\n\r\n#### *5.** Click `Next`\r\n\r\n\r\n\r\n#### **6.** Enter a group id (e.g. `com.github.yourname`)\r\n\r\n#### **7.** Enter an artifact id (e.g. `myfirstbot`)\r\n\r\n#### **8.** Click `Next`\r\n\r\n\r\n\r\n#### **9.** Click on `Finish`\r\n\r\n\r\n\r\n#### **10.** Your project should now look like this. First click on `Enable Auto-Import`\r\n\r\n\r\n\r\n#### **11.** Now you have to add Javacord as a dependency by editing the pom.xml file. Your file should now look like this:\r\n\r\n<LatestVersionInfo/>\r\n\r\n```xml\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\r\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n <modelVersion>4.0.0</modelVersion>\r\n\r\n <groupId>your.package.name</groupId>\r\n <artifactId>myfirstbot</artifactId>\r\n <version>1.0-SNAPSHOT</version>\r\n\r\n <dependencies>\r\n <dependency>\r\n <groupId>org.javacord</groupId>\r\n <artifactId>javacord</artifactId>\r\n <version>$latest-version</version>\r\n <type>pom</type>\r\n </dependency>\r\n </dependencies>\r\n\r\n</project>\r\n```\r\n\r\n#### **12.** Create a new package\r\n\r\n\r\n\r\n\r\n#### **13.** Create a new class inside this package\r\n\r\n\r\n\r\n\r\n#### **14.** You can now start coding! Example code:\r\n\r\n```java\r\npackage com.github.yourname;\r\n\r\nimport org.javacord.api.DiscordApi;\r\nimport org.javacord.api.DiscordApiBuilder;\r\n\r\npublic class Main {\r\n\r\n public static void main(String[] args) {\r\n // Insert your bot's token here\r\n String token = \"your token\";\r\n\r\n DiscordApi api = new DiscordApiBuilder().setToken(token).login().join();\r\n\r\n // Add a listener which answers with \"Pong!\" if someone writes \"!ping\"\r\n api.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n });\r\n\r\n // Print the invite url of your bot\r\n System.out.println(\"You can invite the bot by using the following url: \" + api.createBotInvite());\r\n }\r\n \r\n}\r\n```\r\n\r\n## :running_woman: Run the code\r\n\r\nYou can run your code by clicking on the small green arrow\r\n\r\n\r\n## :construction: Possible problems\r\n\r\n**Note:** If you get the following error:\r\n\r\n\r\nyou have to change your language level to `1.8`\r\n\r\n",
786 "_strippedContent":"# IntelliJ + Maven\r\n\r\nThis tutorial provides a beginner-friendly click by click guide to set up Javacord with Intellij and Maven.\r\nIf you are already familiar with IntelliJ and Maven, you can just see the artifact locations at [Download / Installation](/wiki/getting-started/download-installation.md).\r\n\r\n::: tip Info\r\nWe recommend to use [Intellij + Gradle](./intellij-gradle.md) unless you already have experience with one of the other IDEs or build managers.\r\n::: \r\n\r\n## :wrench: Setup\r\n\r\n#### **1.** Start IntelliJ\r\n\r\n#### **2.** Create a new project (`File` -> `New` -> `Project`)\r\n\r\n\r\n\r\n#### **3.** Select `Maven`\r\n\r\n#### **4.** Make sure to select a SDK which is 1.8 (or greater)\r\n\r\n#### *5.** Click `Next`\r\n\r\n\r\n\r\n#### **6.** Enter a group id (e.g. `com.github.yourname`)\r\n\r\n#### **7.** Enter an artifact id (e.g. `myfirstbot`)\r\n\r\n#### **8.** Click `Next`\r\n\r\n\r\n\r\n#### **9.** Click on `Finish`\r\n\r\n\r\n\r\n#### **10.** Your project should now look like this. First click on `Enable Auto-Import`\r\n\r\n\r\n\r\n#### **11.** Now you have to add Javacord as a dependency by editing the pom.xml file. Your file should now look like this:\r\n\r\n<LatestVersionInfo/>\r\n\r\n```xml\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\r\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n <modelVersion>4.0.0</modelVersion>\r\n\r\n <groupId>your.package.name</groupId>\r\n <artifactId>myfirstbot</artifactId>\r\n <version>1.0-SNAPSHOT</version>\r\n\r\n <dependencies>\r\n <dependency>\r\n <groupId>org.javacord</groupId>\r\n <artifactId>javacord</artifactId>\r\n <version>$latest-version</version>\r\n <type>pom</type>\r\n </dependency>\r\n </dependencies>\r\n\r\n</project>\r\n```\r\n\r\n#### **12.** Create a new package\r\n\r\n\r\n\r\n\r\n#### **13.** Create a new class inside this package\r\n\r\n\r\n\r\n\r\n#### **14.** You can now start coding! Example code:\r\n\r\n```java\r\npackage com.github.yourname;\r\n\r\nimport org.javacord.api.DiscordApi;\r\nimport org.javacord.api.DiscordApiBuilder;\r\n\r\npublic class Main {\r\n\r\n public static void main(String[] args) {\r\n // Insert your bot's token here\r\n String token = \"your token\";\r\n\r\n DiscordApi api = new DiscordApiBuilder().setToken(token).login().join();\r\n\r\n // Add a listener which answers with \"Pong!\" if someone writes \"!ping\"\r\n api.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n });\r\n\r\n // Print the invite url of your bot\r\n System.out.println(\"You can invite the bot by using the following url: \" + api.createBotInvite());\r\n }\r\n \r\n}\r\n```\r\n\r\n## :running_woman: Run the code\r\n\r\nYou can run your code by clicking on the small green arrow\r\n\r\n\r\n## :construction: Possible problems\r\n\r\n**Note:** If you get the following error:\r\n\r\n\r\nyou have to change your language level to `1.8`\r\n\r\n",
787 "path":"/wiki/getting-started/setup/intellij-maven.html"
788 },
789 {
790 "title":"Writing your first bot",
791 "headers":[
792 {
793 "level":2,
794 "title":"? Log the bot in",
795 "slug":"log-the-bot-in"
796 },
797 {
798 "level":2,
799 "title":"? Adding a listener",
800 "slug":"adding-a-listener"
801 },
802 {
803 "level":2,
804 "title":"?? Putting it all together",
805 "slug":"putting-it-all-together"
806 }
807 ],
808 "content":"# Writing your first bot\r\n\r\nAfter you have sucessfully added Javacord as a dependency, created a bot user, and got its token, you are now ready to create your first simple bot! :tada:\r\n\r\n## :key: Log the bot in\r\n\r\nEverything starts with the `DiscordApiBuilder` class.\r\nIt is used to create a `DiscordApi` object which is the most important class of your bot.\r\n\r\n```java\r\nDiscordApi api = new DiscordApiBuilder()\r\n .setToken(\"<your super secret token>\")\r\n .login().join();\r\n```\r\n\r\nAfter executing this code, you should already see your bot online in Discord.\r\nOf course, just being online is not enough, so let's add some more code!\r\n\r\n## :ear: Adding a listener\r\n\r\nAfter you got your `api` instance, let's continue by adding a listener that answers every `!ping` message with a simple `Pong!`.\r\n\r\n```java\r\napi.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n});\r\n```\r\n\r\n\r\n\r\n## :woman_mechanic: Putting it all together\r\n\r\nA good place for your code is the `main(...)` method that every exectuable Java program must have.\r\nYour complete class may look like this:\r\n\r\n```java\r\npublic class MyFirstBot {\r\n\r\n public static void main(String[] args) {\r\n // Log the bot in\r\n DiscordApi api = new DiscordApiBuilder()\r\n .setToken(\"<your super secret token>\")\r\n .login().join();\r\n\r\n // Add a listener which answers with \"Pong!\" if someone writes \"!ping\"\r\n api.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n });\r\n }\r\n\r\n}\r\n```\r\n\r\nCongratulations, that's already everything you have to know for the beginning.\r\nNow, you can play around a little bit by exploring other listeners and methods.\r\nOr you just continue reading articles in the *Basic Tutorials* category.",
809 "_strippedContent":"# Writing your first bot\r\n\r\nAfter you have sucessfully added Javacord as a dependency, created a bot user, and got its token, you are now ready to create your first simple bot! :tada:\r\n\r\n## :key: Log the bot in\r\n\r\nEverything starts with the `DiscordApiBuilder` class.\r\nIt is used to create a `DiscordApi` object which is the most important class of your bot.\r\n\r\n```java\r\nDiscordApi api = new DiscordApiBuilder()\r\n .setToken(\"<your super secret token>\")\r\n .login().join();\r\n```\r\n\r\nAfter executing this code, you should already see your bot online in Discord.\r\nOf course, just being online is not enough, so let's add some more code!\r\n\r\n## :ear: Adding a listener\r\n\r\nAfter you got your `api` instance, let's continue by adding a listener that answers every `!ping` message with a simple `Pong!`.\r\n\r\n```java\r\napi.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n});\r\n```\r\n\r\n\r\n\r\n## :woman_mechanic: Putting it all together\r\n\r\nA good place for your code is the `main(...)` method that every exectuable Java program must have.\r\nYour complete class may look like this:\r\n\r\n```java\r\npublic class MyFirstBot {\r\n\r\n public static void main(String[] args) {\r\n // Log the bot in\r\n DiscordApi api = new DiscordApiBuilder()\r\n .setToken(\"<your super secret token>\")\r\n .login().join();\r\n\r\n // Add a listener which answers with \"Pong!\" if someone writes \"!ping\"\r\n api.addMessageCreateListener(event -> {\r\n if (event.getMessageContent().equalsIgnoreCase(\"!ping\")) {\r\n event.getChannel().sendMessage(\"Pong!\");\r\n }\r\n });\r\n }\r\n\r\n}\r\n```\r\n\r\nCongratulations, that's already everything you have to know for the beginning.\r\nNow, you can play around a little bit by exploring other listeners and methods.\r\nOr you just continue reading articles in the *Basic Tutorials* category.",
810 "path":"/wiki/getting-started/writing-your-first-bot.html"
811 },
812 {
813 "path":"/404.html"
814 }
815]