# Bot Creator — Full Documentation > Complete function reference for Bot Creator (BDFD). Generated from the docs collection. --- ## Channel ### Deletechannelsbyname # $deleteChannelsByName Deletes channels that match a given name. Supports wildcards (`*`) to target multiple channels at once. ## Syntax ``` $deleteChannelsByName[channelName] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `channelName` | Name of the channel(s) to delete. Supports the wildcard `*` | Yes | ## Description `$deleteChannelsByName` deletes one or multiple channels based on their **name**. Unlike `$deleteChannels` which requires channel IDs, this function allows deletion by name and supports the `*` wildcard to target channels with similar names. The bot must have the `MANAGE_CHANNELS` permission to use this function. Deletion is **irreversible** — deleted channels cannot be recovered. ## Examples ### Delete a specific channel ``` $deleteChannelsByName[general-chat] $sendMessage[Channel deleted.] ``` ### Delete with wildcard ``` $deleteChannelsByName[spam-*] $sendMessage[All spam channels deleted.] ``` ### Ticket cleanup ``` $deleteChannelsByName[ticket-*] $sendMessage[All ticket channels deleted.] ``` ### Conditional deletion ``` $if[$checkContains[$userPerms;Administrator]==true] $deleteChannelsByName[temp-*] $sendMessage[Temporary channels deleted.] $else $sendMessage[Permission denied.] $endif ``` ## Notes - **Irreversible action**: deleted channels cannot be restored. - The wildcard `*` matches any sequence of characters (e.g., `ticket-*` matches `ticket-123`, `ticket-abc`, etc.). - The bot must have the `Manage Channels` permission. - For categories, deletion also removes all child channels. - Use `$deleteChannels` to delete by channel ID instead of name. --- ## Components & Interactions ### Addactionrow # $addActionRow Starts a new action row to contain buttons or select menus. ## Syntax ``` $addActionRow[(id)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `id` | Custom identifier for the action row | No | ## Description An **action row** is a container that groups interactive components (buttons, select menus) on the same horizontal row in a Discord message. Each message can contain up to 5 action rows, and each action row can contain up to 5 buttons or 1 select menu. `$addActionRow` must be called before adding components (buttons, select menus) to organize them on distinct rows. ## Examples ### Simple row ``` $addActionRow $addButtonCV2[btn_1;Click me;primary] $sendMessage[Here is a button!] ``` ### With custom ID ``` $addActionRow[row_buttons] $addButtonCV2[btn_ok;OK;success] $addButtonCV2[btn_cancel;Cancel;danger] $sendMessage[Confirm your choice] ``` ### Multiple rows ``` $addActionRow $addButtonCV2[btn_1;Button 1;primary] $addButtonCV2[btn_2;Button 2;primary] $addActionRow $addButtonCV2[btn_3;Button 3;secondary] $sendMessage[Two rows of buttons] ``` ## Notes - Each `$addActionRow` creates a new row. The components added afterward will be placed on that row. - Without `$addActionRow`, components are placed on a row by default. - An action row can only contain buttons OR a single select menu, not both. - Maximum of 5 action rows per message. --- ### Addbutton # $addButton Adds an interactive button to the message (legacy style). Allows controlling the placement via the `newRow` parameter. ## Syntax ``` $addButton[newRow;customIdOrURL;label;(style);(disabled);(emoji);(messageId)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `newRow` | `"yes"` creates a new row before the button, `"no"` adds it to the current line | Yes | | `customIdOrURL` | Custom ID to handle the click, or URL for a link button | Yes | | `label` | Text displayed on the button | Yes | | `style` | Style of the button: `primary` (default), `secondary`, `success`, `danger`, `link` | No | | `disabled` | `true` to disable the button, `false` (default) | No | | `emoji` | Emoji to display before the label | No | | `messageId` | Target message ID (for editing) | No | ## Available styles | Style | Color | Typical usage | |-------|-------|---------------| | `primary` | Blue/violet | Main action | | `secondary` | Grey | Secondary action | | `success` | Green | Confirmation | | `danger` | Red | Destructive action | | `link` | Grey (link) | External URL | ## Examples ### Simple button ``` $addButton[no;my_button;Click here;primary;false;😊] $sendMessage[Press the button] ``` ### New line with two buttons ``` $addButton[no;btn_ok;✅ Validate;success] $addButton[no;btn_no;❌ Decline;danger] $sendMessage[Choose an option] ``` ### Disabled button with emoji ``` $addButton[no;btn_lock;🔒 Locked;secondary;true] $sendMessage[Action not available] ``` ## Notes - This legacy style is kept for backward compatibility. - For new bots, prefer `$addButtonCV2` which offers a cleaner API. - The `newRow` parameter allows fine-grained control of the layout. - Max 5 buttons per action row. --- ### Addbuttoncv2 # $addButtonCV2 Adds an interactive button to the message using the Component V2 style. This button is always added to the current action row. ## Syntax ``` $addButtonCV2[customIdOrURL;label;(style);(disabled);(emoji)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `customIdOrURL` | Custom ID to handle the click, or URL for a link button | Yes | | `label` | Text displayed on the button | Yes | | `style` | Style: `primary` (default), `secondary`, `success`, `danger`, `link` | No | | `disabled` | `true` to disable the button, `false` (default) | No | | `emoji` | Emoji to display before the label | No | ## Difference from $addButton Unlike `$addButton` (legacy), `$addButtonCV2` does not have a `newRow` parameter. To organize buttons on multiple lines, use `$addActionRow` before each group. ## Examples ### Simple button ``` $addButtonCV2[my_button;Click here;primary] $sendMessage[Press the button] ``` ### Multiple buttons on distinct rows ``` $addActionRow $addButtonCV2[btn_yes;✅ Yes;success] $addButtonCV2[btn_no;❌ No;danger] $addActionRow $addButtonCV2[btn_maybe;🤔 Maybe;secondary] $sendMessage[Make your choice] ``` ### Link button ``` $addButtonCV2[https://discord.com;Discord Website;link;false;🌐] $sendMessage[Visit the website] ``` ### Disabled button ``` $addButtonCV2[btn_disabled;Unavailable;primary;true;🚫] $sendMessage[Feature coming soon] ``` ## Handling interactions Clicks on buttons are handled via the `$onInteraction` event: ``` $onInteraction $if[$customID==my_button] $sendMessage[You clicked!] $endif ``` ## Notes - No `newRow` parameter: use `$addActionRow` for layout control. - Max 5 buttons per action row. - Recommended API for new developments. --- ### Addcategoryselect # $addCategorySelect Creates a select menu of server categories. Allows users to choose one or multiple categories. ## Syntax ``` $addCategorySelect[customId;placeholder;(minValues);(maxValues);(disabled)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `customId` | Custom identifier for the interaction | Yes | | `placeholder` | Text displayed when nothing is selected | Yes | | `minValues` | Minimum number of categories to select (default: 1) | No | | `maxValues` | Maximum number of categories to select (default: 1) | No | | `disabled` | `true` to disable the menu, `false` by default | No | ## Description `$addCategorySelect` adds a **category select menu** to a message. This component is similar to `$addChannelSelect` but is restricted to server **categories** only. The user can select one or multiple categories, and the interaction returns the selected category IDs. This function must be placed after `$addActionRow` to be organized on a specific row. ## Examples ### Category selection ``` $addActionRow $addCategorySelect[menu_cat;Choose a category] $sendMessage[Select a category] ``` ### Multiple categories ``` $addActionRow $addCategorySelect[menu_cats;Select categories;1;5] $sendMessage[Select up to 5 categories] ``` ### Disabled menu ``` $addActionRow $addCategorySelect[menu_cat_disabled;Unavailable;1;1;true] $sendMessage[This menu is currently disabled] ``` ## Handling the interaction ``` $onInteraction $if[$customID==menu_cat] $sendMessage[Selected category: <#$message>] $endif ``` ## Notes - The returned values are Discord category IDs. - Use `<#ID>` to mention a category. - Only server **categories** appear in the menu, not individual channels. - An action row can contain only **one** select menu. --- ### Addchannelselect # $addChannelSelect Creates a select menu of channels. Allows users to choose one or multiple channels on the server. ## Syntax ``` $addChannelSelect[customId;placeholder;(minValues);(maxValues);(disabled);(channelTypes)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `customId` | Custom identifier for the interaction | Yes | | `placeholder` | Text displayed when nothing is selected | Yes | | `minValues` | Minimum number of channels to select (default: 1) | No | | `maxValues` | Maximum number of channels to select (default: 1) | No | | `disabled` | `true` to disable the menu, `false` (default) | No | | `channelTypes` | Types of channels displayed, separated by commas | No | ## Channel types (channelTypes) | Type | Description | |------|-------------| | `text` | Text channels | | `voice` | Voice channels | | `category` | Categories | | `news` | Announcement channels | | `stage` | Stage channels | | `forum` | Forums | | `thread` | Thread channels | By default, all types are displayed. ## Examples ### Channel selection ``` $addChannelSelect[menu_channel;Choose a channel] $sendMessage[Select a channel] ``` ### Text channel only ``` $addChannelSelect[menu_text;Text channel;1;1;false;text] $sendMessage[Choose a text channel] ``` ### Voice and stage channels ``` $addChannelSelect[menu_vocal;Voice channel;1;3;false;voice,stage] $sendMessage[Select voice channels] ``` ### Disabled menu ``` $addChannelSelect[menu_chan_disabled;Unavailable;1;1;true] $sendMessage[This menu is disabled] ``` ## Handling the interaction ``` $onInteraction $if[$customID==menu_channel] $sendMessage[Selected channel: <#$message>] $endif ``` ## Notes - The returned values are Discord channel IDs. - Use `<#ID>` to mention a channel. - The `channelTypes` parameter allows filtering precisely which channels are displayed. - Useful for configuration, logs, or redirection commands. --- ### $addCheckboxGroupOption[] # $addCheckboxGroupOption[] — Checkbox Group Option `$addCheckboxGroupOption[]` adds an option to a checkbox group created with `$addModalCheckboxGroup[]`. Each option appears as a distinct checkbox with its own label. ## Syntax ``` $addCheckboxGroupOption[menuId;label;value;(description);(default)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `menuId` | No | Last group | Identifier of the parent group. | | `label` | Yes | — | Text displayed for this option. | | `value` | Yes | — | Value returned when the option is checked. | | `description` | No | — | Optional description text. | | `default` | No | `no` | `yes` if checked by default. | ## Return value Adds the option to the parent group. No direct return value. ## Usage ### With explicit menuId ```bdfd $newModal[Config;config_modal] $addModalCheckboxGroup[notifications;Notifications;no] $addCheckboxGroupOption[notifications;Private messages;dm;Receive private message notifications;yes] $addCheckboxGroupOption[notifications;Mentions;mentions;Notifications for @mentions;yes] $addCheckboxGroupOption[notifications;Announcements;announce;Server announcements;no] ``` ### Without menuId (last group) ```bdfd $newModal[Preferences;pref_modal] $addModalCheckboxGroup[themes;Visual Themes;no] $addCheckboxGroupOption[;Minimal;minimal;Clean design;no] $addCheckboxGroupOption[;Colored;colorful;Vibrant design;yes] $addCheckboxGroupOption[;Dark;dark;Dark mode;yes] ``` ### Multiple distinct groups ```bdfd $newModal[Full Survey;full_survey] $addModalCheckboxGroup[platform;Platforms;yes] $addCheckboxGroupOption[platform;Discord;discord;;yes] $addCheckboxGroupOption[platform;Twitter;twitter;;no] $addModalCheckboxGroup[content;Content Type;no] $addCheckboxGroupOption[content;Articles;articles] $addCheckboxGroupOption[content;Videos;videos] $addCheckboxGroupOption[content;Podcasts;podcasts] ``` ## Notes - If `menuId` is omitted (empty string), the option is added to the last group created. - Maximum of 25 options per group. - The values of checked options are retrieved via `$input[menuId]`, separated by commas. --- ### $addContainer[] # $addContainer[] — Visual Container `$addContainer[]` creates a container in a Discord message. Containers offer visual structure with an optional colored border and the ability to be hidden behind a spoiler. ## Syntax ``` $addContainer[(id);(accentColor);(spoiler)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `id` | No | — | Container identifier. | | `accentColor` | No | — | Hex color of the border (ex: `#FF0000`). | | `spoiler` | No | `no` | `yes` to mask, `no` otherwise. | ## Return value Initializes a container. Components added afterward (sections, thumbnails, galleries) insert into this container. ## Usage ### Basic container ```bdfd $addContainer $addSection $addField[Status;Online;yes] $addField[Uptime;24h;yes] ``` ### Container with accent color ```bdfd $addContainer[profile;#5865F2;no] $addSection $addThumbnail[$authorAvatar] $addField[User;$username;no] $addField[Joined on;$memberJoinDate;no] ``` ### Spoiler container ```bdfd $addContainer[secret;;yes] $addSection $addTextDisplay[**Spoiler Alert!** Click to reveal the content.] ``` ### Multiple containers ```bdfd $addContainer[header;#2ECC71;no] $addSection $addField[Title;Welcome to the server;no] $addContainer[body;#3498DB;no] $addSection $addField[Description;We are delighted to welcome you!;no] ``` ## Notes - Containers are a visual feature specific to BDFD; they are not part of the native Discord API. - A container can contain multiple sections ($addSection). - The `accentColor` must be a hexadecimal format starting with `#`. - Spoiler mode hides all content in the container until the user clicks on it. --- ### $addMediaGallery[] # $addMediaGallery[] — Media Gallery `$addMediaGallery[]` creates a gallery container allowing the display of multiple images in an interactive component. The user can navigate between the images in the gallery. ## Syntax ``` $addMediaGallery[(id)] ``` ## Parameters | Parameter | Required | Description | |-----------|-------------|-------------| | `id` | No | Optional identifier for the gallery. | ## Return value Initializes a media gallery. Elements are added using `$addMediaGalleryItem[]`. The gallery is displayed as an interactive component with navigation. ## Usage ### Simple gallery ```bdfd $addMediaGallery[portfolio] $addMediaGalleryItem[https://cdn.example.com/work1.png;Project 1] $addMediaGalleryItem[https://cdn.example.com/work2.png;Project 2] $addMediaGalleryItem[https://cdn.example.com/work3.png;Project 3] ``` ### Gallery in a container ```bdfd $addContainer[showcase;#E67E22;no] $addSection $addTextDisplay[**Creation Gallery**] $addMediaGallery[creations] $addMediaGalleryItem[$var[img1];Original Creation] $addMediaGalleryItem[$var[img2];Variant] $addMediaGalleryItem[$var[img3];Final Version] ``` ### Gallery with spoiler ```bdfd $addMediaGallery[spoiler_gallery] $addMediaGalleryItem[https://cdn.example.com/secret.png;Exclusive Content;yes] $addMediaGalleryItem[https://cdn.example.com/bonus.png;Bonus;yes] ``` ### In a complete embed ```bdfd $title[Portfolio] $description[Discover my latest creations] $color[#5865F2] $addMediaGallery[works] $addMediaGalleryItem[https://site.com/img1.jpg;Design A] $addMediaGalleryItem[https://site.com/img2.jpg;Design B] $addMediaGalleryItem[https://site.com/img3.jpg;Design C] $footer[Page 1/1] ``` ## Notes - Gallery elements are added using `$addMediaGalleryItem[]`. - Navigation between images is done using arrows in the Discord interface. - The gallery ID in `$addMediaGalleryItem[]` can be omitted to target the last gallery created. - URLs must point to publicly accessible images. --- ### $addMediaGalleryItem[] # $addMediaGalleryItem[] — Gallery Item `$addMediaGalleryItem[]` adds an image to a media gallery created with `$addMediaGallery[]`. Each element becomes a navigable "page" in the gallery. ## Syntax ``` $addMediaGalleryItem[url;(description);(spoiler);(galleryId)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `url` | Yes | — | URL of the image. | | `description` | No | — | Description / alternative text. | | `spoiler` | No | `no` | `yes` to spoiler. | | `galleryId` | No | Last gallery | ID of the target gallery. | ## Return value Adds the image to the gallery. No direct return value. ## Usage ### With explicit galleryId ```bdfd $addMediaGallery[before_after] $addMediaGalleryItem[https://cdn.example.com/before.jpg;Before renovation;no;before_after] $addMediaGalleryItem[https://cdn.example.com/after.jpg;After renovation;no;before_after] ``` ### Without galleryId (last gallery) ```bdfd $addMediaGallery $addMediaGalleryItem[https://site.com/img1.png;Capture 1] $addMediaGalleryItem[https://site.com/img2.png;Capture 2] $addMediaGalleryItem[https://site.com/img3.png;Capture 3] ``` ### Multiple distinct galleries ```bdfd $addMediaGallery[designs] $addMediaGalleryItem[https://cdn.example.com/d1.png;Mobile design;no;designs] $addMediaGalleryItem[https://cdn.example.com/d2.png;Desktop design;no;designs] $addMediaGallery[logos] $addMediaGalleryItem[https://cdn.example.com/logo_light.png;Light logo;no;logos] $addMediaGalleryItem[https://cdn.example.com/logo_dark.png;Dark logo;no;logos] ``` ### With spoiler ```bdfd $addMediaGallery[nsfw_content] $addMediaGalleryItem[$var[exclusive01];Exclusive Content 1;yes;nsfw_content] $addMediaGalleryItem[$var[exclusive02];Exclusive Content 2;yes;nsfw_content] ``` ## Notes - `galleryId` can be omitted; the element will target the most recently created gallery. - If no gallery has been created, the behavior is undefined. - The `spoiler` parameter hides the image until the user clicks on it (useful for sensitive content). - URLs must be publicly accessible. --- ### Addmentionableselect # $addMentionableSelect Creates a select menu of mentionable entities. Allows users to choose between users and roles on the server. ## Syntax ``` $addMentionableSelect[customId;placeholder;(minValues);(maxValues);(disabled)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `customId` | Custom identifier for the interaction | Yes | | `placeholder` | Text displayed when nothing is selected | Yes | | `minValues` | Minimum number of entities to select (default: 1) | No | | `maxValues` | Maximum number of entities to select (default: 1) | No | | `disabled` | `true` to disable the menu, `false` (default) | No | ## Description A **mentionable select** combines the selection of users and roles in a single menu. The user can choose either members or roles of the server. The returned values are IDs. Use `$roleExists` to determine if an ID corresponds to a role or to a user. ## Examples ### Simple selection ``` $addMentionableSelect[menu_mention;Choose a member or a role] $sendMessage[Select a target] ``` ### Multiple selection ``` $addMentionableSelect[menu_targets;Multiple targets;1;10] $sendMessage[Select up to 10 targets] ``` ### Disabled menu ``` $addMentionableSelect[menu_mention_off;Unavailable;1;1;true] $sendMessage[Menu disabled] ``` ## Handling the interaction ``` $onInteraction $if[$customID==menu_mention] $if[$roleExists[$message]==true] $sendMessage[Selected role: <@&$message>] $else $sendMessage[Selected user: <@$message>] $endif $endif ``` ## Difference from UserSelect and RoleSelect | Function | Selects | |----------|-------------| | `$addUserSelect` | Only users | | `$addRoleSelect` | Only roles | | `$addMentionableSelect` | Users AND roles | ## Notes - Useful for moderation, giveaway, or permission system commands. - Use `$roleExists` to distinguish roles and users in the returned values. - A single select menu per action row. --- ### $addModalCheckbox[] # $addModalCheckbox[] — Modal Checkbox `$addModalCheckbox[]` adds a single checkbox to a modal. Unlike `$addModalCheckboxGroup[]` which creates a group, this function creates a single isolated checkbox. ## Syntax ``` $addModalCheckbox[customId;label;(default)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `customId` | Yes | — | Unique identifier to retrieve the state. | | `label` | Yes | — | Text displayed next to the checkbox. | | `default` | No | `no` | `yes` if checked by default, `no` otherwise. | ## Return value Adds a checkbox to the modal. The submitted value is `yes` or `no`, accessible via `$input[customId]`. ## Usage ### Simple checkbox ```bdfd $newModal[Registration;register_modal] $addModalTextInput[name;Name;short;;;yes;2;50] $addModalCheckbox[newsletter;Subscribe to newsletter;yes] $addModalCheckbox[tos;Accept Terms of Service;no] ``` ### Verifying the state ```bdfd $onInteraction[modal_register] $if[$input[tos]==yes] $sendMessage[Terms accepted ✓] $else $sendMessage[You must accept the terms!] $endif $endInteraction ``` ## Notes - For groups of checkboxes with multiple options, use `$addModalCheckboxGroup[]` and `$addCheckboxGroupOption[]`. - The returned state is a string: `yes` or `no`. - An individual checkbox counts as a component towards the limit of 5 components per modal. --- ### $addModalCheckboxGroup[] # $addModalCheckboxGroup[] — Checkbox Group `$addModalCheckboxGroup[]` creates a container for a checkbox group in a modal. Options are then added using `$addCheckboxGroupOption[]`. The user can check multiple options simultaneously. ## Syntax ``` $addModalCheckboxGroup[customId;label;(required)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `customId` | Yes | — | Unique identifier of the group. | | `label` | Yes | — | Descriptive label above the group. | | `required` | No | `yes` | `yes` if a selection is required. | ## Return value Initializes a checkbox group. Checked values are accessible via `$input[customId]` as a comma-separated list. ## Usage ### Interests group ```bdfd $newModal[Profile;profile_modal] $addModalTextInput[username;Username;short;;;yes;3;32] $addModalCheckboxGroup[hobbies;Hobbies;no] $addCheckboxGroupOption[;Reading;reading;Books and novels] $addCheckboxGroupOption[;Cinema;movies;Movies and series] $addCheckboxGroupOption[;Cooking;cooking;Culinary art] $addCheckboxGroupOption[;Travel;travel;Discover the world] ``` ### Required group ```bdfd $newModal[Survey;sondage_modal] $addModalCheckboxGroup[features;Requested Features;yes] $addCheckboxGroupOption[;Notifications;notif] $addCheckboxGroupOption[;Dark Mode;darkmode] $addCheckboxGroupOption[;Export data;export] ``` ### Retrieving values ```bdfd $onInteraction[profile_submit] $var[hobbies;$input[hobbies]] $sendMessage[Selected hobbies: $var[hobbies]] $endInteraction ``` ## Notes - Options are added using `$addCheckboxGroupOption[]` where the `menuId` can be omitted to target the last group created. - The returned value is a string containing the values of the checked options, separated by commas. - Maximum of 25 options per group (Discord limit). --- ### $addModalFileUpload[] # $addModalFileUpload[] — Modal File Upload `$addModalFileUpload[]` adds a component allowing the user to attach a file directly from a Discord modal. The uploaded file is then accessible in the interaction handler. ## Syntax ``` $addModalFileUpload[customId;label;(required)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `customId` | Yes | — | Unique identifier for the file field. | | `label` | Yes | — | Text displayed above the field. | | `required` | No | `yes` | `yes` if required, `no` otherwise. | ## Return value Adds the upload component to the modal. The URL and metadata of the file are accessible via `$input[customId]` after submission. ## Usage ### Upload required ```bdfd $newModal[Application;apply_modal] $addModalTextDisplay[Please attach your CV in PDF format.] $addModalTextInput[motivation;Cover letter;paragraph;;;yes;50;1000] $addModalFileUpload[cv;Your CV (PDF);yes] ``` ### Optional upload with other fields ```bdfd $newModal[Report;report_modal] $addModalTextInput[description;Description of the problem;paragraph;;;yes;20;1000] $addModalFileUpload[screenshot;Screenshot (optional);no] ``` ### Processing the file ```bdfd $onInteraction[apply_submit] $var[cv_url;$input[cv]] $var[motivation;$input[motivation]] $sendMessage[New application received! CV: $var[cv_url] Motivation: $var[motivation]] $endInteraction ``` ## Notes - The file is temporarily hosted by Discord; the returned URL is a Discord CDN URL. - The `customId` must be unique within the modal. - The maximum size of the file is determined by Discord (usually 25 MB depending on the server's boost level). - This component is only available in modals (not in regular messages). --- ### $addModalRadioGroup[] # $addModalRadioGroup[] — Radio Button Group `$addModalRadioGroup[]` creates a container of radio buttons in a modal. Unlike checkboxes, only a single choice can be selected from the group options. ## Syntax ``` $addModalRadioGroup[customId;label;(required)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `customId` | Yes | — | Unique identifier of the group. | | `label` | Yes | — | Label above the group. | | `required` | No | `yes` | `yes` if required. | ## Return value Initializes a radio group. The value of the selected option is accessible via `$input[customId]`. ## Usage ### Simple radio group ```bdfd $newModal[Registration;signup_modal] $addModalTextInput[name;Name;short;;;yes;2;50] $addModalRadioGroup[gender;Gender;yes] $addRadioGroupOption[gender;Male;male] $addRadioGroupOption[gender;Female;female] $addRadioGroupOption[gender;Non-binary;nb] ``` ### Group with option by default ```bdfd $newModal[Preferences;pref_modal] $addModalRadioGroup[lang;Preferred language;yes] $addRadioGroupOption[;French;fr;;yes] $addRadioGroupOption[;English;en] $addRadioGroupOption[;Spanish;es] ``` ### Retrieving the selection ```bdfd $onInteraction[signup_submit] $var[gender;$input[gender]] $if[$var[gender]==male] $sendMessage[Welcome to the server!] $elseif[$var[gender]==female] $sendMessage[Welcome to the server!] $endif $endInteraction ``` ## Differences: Radio vs Checkbox | Radio Group | Checkbox Group | |-------------|---------------| | Only a single option selectable | Multiple options selectable | | Returns a single value | Returns a list of values | | Ideal for mutually exclusive choices | Ideal for multiple selections | ## Notes - Options are added using `$addRadioGroupOption[]`. - Like with checkbox groups, the `menuId` can be omitted in `$addRadioGroupOption[]` to target the last group created. - Maximum of 25 options per radio group. --- ### $addModalSelect[] # $addModalSelect[] — Modal Dropdown Menu `$addModalSelect[]` adds a dropdown menu (select menu) to a modal. The menu options are defined using `$addSelectMenuOption[]` after this call. ## Syntax ``` $addModalSelect[customId;label;(placeholder);(required)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `customId` | Yes | — | Unique identifier to retrieve the value after submission. | | `label` | Yes | — | Text displayed above the menu. | | `placeholder` | No | — | Placeholder text when the menu is not selected. | | `required` | No | `yes` | `yes` if required, `no` otherwise. | ## Return value Adds the Select component to the current modal. The selected value is accessible via `$input[customId]` in the interaction handler. ## Usage ### Dropdown menu with options ```bdfd $newModal[Preferences;pref_modal] $addModalSelect[language;Language;Choose your language...;yes] $addSelectMenuOption[French;fr;French language] $addSelectMenuOption[English;en;English language] $addSelectMenuOption[Spanish;es;Spanish language] ``` ### Optional menu ```bdfd $newModal[Survey;survey_modal] $addModalTextDisplay[Bonus question (optional):] $addModalSelect[os;Operating system;Select your OS;no] $addSelectMenuOption[Windows;win] $addSelectMenuOption[macOS;mac] $addSelectMenuOption[Linux;linux] ``` ### Retrieving the value ```bdfd $onInteraction[modal_submit] $var[lang;$input[language]] $sendMessage[Selected language: $var[lang]] $endInteraction ``` ## Notes - Must be followed by calls to `$addSelectMenuOption[]` to set the available choices. - The `customId` must be unique within the modal. - Maximum of 25 options per dropdown menu (Discord limitation). - The value returned by `$input[]` is the `value` of the selected option, not its `label`. --- ### $addModalTextDisplay[] # $addModalTextDisplay[] — Modal Text Display `$addModalTextDisplay[]` inserts a block of non-interactive text in a modal. This is the equivalent of an informational paragraph — useful for providing instructions, separating sections, or displaying contextual information. ## Syntax ``` $addModalTextDisplay[content] ``` ## Parameters | Parameter | Required | Description | |-----------|-------------|-------------| | `content` | Yes | The text to display. Supports basic markdown. | ## Return value Adds a text display component to the modal. No interactive value is returned — this component does not produce any form data. ## Usage ### General instructions ```bdfd $newModal[Form;form_modal] $addModalTextDisplay[**Welcome!** Fill out this form to continue.] $addModalTextInput[name;Full name;short;;;yes;2;50] ``` ### Sections with separators ```bdfd $newModal[Full Registration;full_register] $addModalTextDisplay[__Section 1: Identity__] $addModalTextInput[firstname;First Name;short;;;yes;2;30] $addModalTextInput[lastname;Last Name;short;;;yes;2;30] $addModalTextDisplay[__Section 2: Contact__] $addModalTextInput[email;Email;short;;;yes;5;100] $addModalTextInput[phone;Phone;short;;;no;10;15] ``` ### Warnings and notes ```bdfd $newModal[Deletion;delete_modal] $addModalTextDisplay[⚠️ **Warning:** This action is irreversible!] $addModalTextDisplay[All of your data will be permanently deleted.] $addModalTextInput[confirm;Type CONFIRM to continue;short;;;yes;8;8] ``` ### With dynamic variables ```bdfd $newModal[Confirmation;confirm_modal] $addModalTextDisplay[You are about to buy **$var[product_name]** for **$var[price]€**.] $addModalTextDisplay[Estimated delivery date: $var[delivery_date]] ``` ## Notes - The text supports Discord formatting: `**bold**`, `*italic*`, `__underline__`, `~~strikethrough~~`. - Emojis are supported. - This component does not produce any value in `$input[]`. - It does not count towards the limit of 5 interactive components (TextInput, Select) but occupies a placeholder in the component rows of the modal. --- ### $addModalTextInput[] # $addModalTextInput[] — Modal Text Input `$addModalTextInput[]` adds a text input field inside a modal previously initialized with `$newModal[]`. Discord supports two styles of text fields: short (single-line) and paragraph (multi-line). ## Syntax ``` $addModalTextInput[customId;label;(style);(placeholder);(default);(required);(minLength);(maxLength)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `customId` | Yes | — | Unique identifier to retrieve the value after submission. | | `label` | Yes | — | Label text above the field. | | `style` | No | `short` | `short` for a single line, `paragraph` for multiple lines. | | `placeholder` | No | — | Placeholder text in the empty field. | | `default` | No | — | Pre-filled value. | | `required` | No | `yes` | `yes` if required, `no` otherwise. | | `minLength` | No | — | Minimum number of characters. | | `maxLength` | No | — | Maximum number of characters. | ## Return value Adds the TextInput component to the current modal. The input value is accessible via `$input[customId]` in the modal's interaction handler. ## Usage ### Required short field ```bdfd $newModal[Contact;contact_form] $addModalTextInput[name;Full name;short;John Doe;;yes;2;50] $addModalTextInput[email;Email address;short;contact@site.com;;yes;5;100] ``` ### Free text area ```bdfd $newModal[Feedback;feedback_form] $addModalTextInput[comments;Your comments;paragraph;Write your message here...;;yes;10;1000] ``` ### Optional field with placeholder ```bdfd $newModal[Profile;profile_form] $addModalTextInput[website;Website;short;https://...;;no;0;200] ``` ## Validation - `minLength` and `maxLength` apply client-side validation in Discord. - If `required` is `yes`, the modal cannot be submitted without a value. - Discord limits: `label` max 45 characters, `placeholder` max 100 characters, `minLength` 0-4000, `maxLength` 1-4000. ## Notes - Must be called after `$newModal[]` and before any other function that finalizes the modal. - The `customId` must be unique within the modal. - Maximum of 5 rows of components (5 `$addModalTextInput` calls) per modal according to Discord. --- ### $addRadioGroupOption[] # $addRadioGroupOption[] — Radio Group Option `$addRadioGroupOption[]` adds an option to a radio button group created with `$addModalRadioGroup[]`. Only a single option in the group can be selected at a time. ## Syntax ``` $addRadioGroupOption[menuId;label;value;(description);(default)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `menuId` | No | Last group | Identifier of the parent radio group. | | `label` | Yes | — | Text displayed for the option. | | `value` | Yes | — | Value returned if selected. | | `description` | No | — | Optional description. | | `default` | No | `no` | `yes` if selected by default. | ## Return value Adds the option to the parent group. The selected value is accessible via `$input[menuId]`. ## Usage ### Group with detailed options ```bdfd $newModal[Subscription;sub_modal] $addModalRadioGroup[tier;Subscription level;yes] $addRadioGroupOption[tier;Free;free;Basic features;yes] $addRadioGroupOption[tier;Pro;pro;Unlimited access, priority support;no] $addRadioGroupOption[tier;Enterprise;ent;Custom solution, guaranteed SLA;no] ``` ### Without explicit menuId ```bdfd $newModal[Feedback;feedback_modal] $addModalRadioGroup[satisfaction;Satisfaction;yes] $addRadioGroupOption[;Very satisfied;5;Excellent!;no] $addRadioGroupOption[;Satisfied;4;Good;no] $addRadioGroupOption[;Neutral;3;Average;no] $addRadioGroupOption[;Unsatisfied;2;Could do better;no] $addRadioGroupOption[;Very unsatisfied;1;Needs review;no] ``` ### Conditional default option ```bdfd $newModal[Language;lang_modal] $addModalRadioGroup[local;Interface language;yes] $addRadioGroupOption[;French;fr;;yes] $addRadioGroupOption[;English;en;;no] ``` ## Notes - Only a single option can have `default` set to `yes` in the same radio group. - If `menuId` is empty, the option targets the last group created. - The returned value is the `value` of the selected option (not the `label`). - Maximum of 25 options per radio group. --- ### Addroleselect # $addRoleSelect Creates a select menu of roles. Allows users to choose one or multiple roles on the server from a dropdown list. ## Syntax ``` $addRoleSelect[customId;placeholder;(minValues);(maxValues);(disabled)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `customId` | Custom identifier for the interaction | Yes | | `placeholder` | Text displayed when nothing is selected | Yes | | `minValues` | Minimum number of roles to select (default: 1) | No | | `maxValues` | Maximum number of roles to select (default: 1) | No | | `disabled` | `true` to disable the menu, `false` (default) | No | ## Description A **role select** displays the list of roles on the server. The user can select one or several. The IDs of the selected roles are returned in `$onInteraction`. Ideal for self-role systems, department selection, or notification menus. ## Examples ### Role assignment ``` $addRoleSelect[menu_role;Choose your role] $sendMessage[Select your main role] ``` ### Multiple self-roles ``` $addRoleSelect[menu_notifs;Notifications;1;3] $sendMessage[Choose the notifications to receive] ``` ### Disabled menu ``` $addRoleSelect[menu_role_disabled;Selection closed;1;1;true] $sendMessage[Registrations are closed] ``` ## Handling the interaction ``` $onInteraction $if[$customID==menu_role] $giveRole[$authorID;$message] $sendMessage[You have received the role <@&$message>!] $endif ``` ## Notes - The returned values are Discord role IDs. - Use `<@&ID>` to mention a role. - Only the roles that the bot can manage will appear (role hierarchy). - Perfect for self-role systems and registration menus. --- ### $addSection[] # $addSection[] — Section inside a Container `$addSection[]` creates a section inside a container previously initialized with `$addContainer[]`. Sections visually structure content and can contain fields, text, and media. ## Syntax ``` $addSection[(id)] ``` ## Parameters | Parameter | Required | Description | |-----------|-------------|-------------| | `id` | No | Optional identifier for the section. | ## Return value Initializes a section in the current container. Subsequent components are added to this section. ## Usage ### Container with a section ```bdfd $addContainer[user_info;#E67E22;no] $addSection $addField[Username;$username;no] $addField[ID;$authorID;no] $addField[Registration date;$creationDate;no] ``` ### Multi-section container ```bdfd $addContainer[embed;#9B59B6;no] $addSection[header] $addThumbnail[$authorAvatar] $addTextDisplay[**Profile of $username**] $addSection[stats] $addField[Messages;$var[msg_count];yes] $addField[XP;$var[xp];yes] $addSection[footer] $addTextDisplay[📅 Member since $memberJoinDate] ``` ### Sections in a complex message ```bdfd $addContainer[shop;#3498DB;no] $addSection[item1] $addField[Article;Legendary sword;yes] $addField[Price;5000 gold coins;yes] $addSection[item2] $addField[Article;Mystic shield;yes] $addField[Price;3500 gold coins;yes] ``` ## Notes - Must be used inside a container (`$addContainer`). - Multiple sections can coexist in the same container. - Each section can contain fields (`$addField`), text (`$addTextDisplay`), or a thumbnail (`$addThumbnail`). - The order of addition determines the display order in the message. --- ### Addselectmenuoption # $addSelectMenuOption Adds an option to an existing select menu created with `$newSelectMenu`. ## Syntax ``` $addSelectMenuOption[menuId;label;value;(description);(emoji);(default)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `menuId` | Identifier of the target menu (the one from `$newSelectMenu`) | Yes | | `label` | Text displayed for the option | Yes | | `value` | Value sent when the option is chosen | Yes | | `description` | Additional description displayed under the label | No | | `emoji` | Emoji displayed to the left of the label | No | | `default` | `true` to preselect this option, `false` (default) | No | ## Description This function must be called after `$newSelectMenu` to populate the menu. Each call adds an option to the menu specified by `menuId`. ## Examples ### Options with descriptions ``` $newSelectMenu[menu_lang;Choose a language] $addSelectMenuOption[menu_lang;JavaScript;js;Dynamic web language;🟨] $addSelectMenuOption[menu_lang;Python;py;Polyvalent language;🐍] $addSelectMenuOption[menu_lang;Rust;rs;High-performance system language;🦀] $sendMessage[Which language do you prefer?] ``` ### Option by default ``` $newSelectMenu[menu_theme;Theme;1;1] $addSelectMenuOption[menu_theme;Light;light;Light mode;☀️] $addSelectMenuOption[menu_theme;Dark;dark;Dark mode;🌙;true] $sendMessage[Choose your theme] ``` ### Menu with emojis only ``` $newSelectMenu[menu_react;Quick reaction] $addSelectMenuOption[menu_react;Like;like;;👍] $addSelectMenuOption[menu_react;Love;love;;❤️] $addSelectMenuOption[menu_react;Laugh;laugh;;😂] $addSelectMenuOption[menu_react;Wow;wow;;😮] $sendMessage[React to this message] ``` ## Notes - The `menuId` must correspond exactly to the `customId` of `$newSelectMenu`. - Maximum of 25 options per menu. - The `value` fields are the values received in `$onInteraction`. --- ### Addseparator # $addSeparator Adds a visual separator in the current action row. Useful to space out or visually group components. ## Syntax ``` $addSeparator[(divider);(spacing)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `divider` | `"yes"` to display a separation line, `"no"` (default) | No | | `spacing` | Size of the spacing (values: `sm`, `md`, `lg`) | No | ## Description `$addSeparator` inserts a space or a separation line between components of the same action row. It does not create a new row — for that, use `$addActionRow`. ## Spacing options | Value | Approximate size | |--------|---------------------| | `sm` | Small spacing | | `md` | Medium spacing | | `lg` | Large spacing | ## Examples ### Simple separator ``` $addActionRow $addButtonCV2[btn_left;Left;primary] $addSeparator $addButtonCV2[btn_right;Right;secondary] $sendMessage[Spaced buttons] ``` ### With a separation line ``` $addActionRow $addButtonCV2[btn_1;Option A;success] $addSeparator[yes] $addButtonCV2[btn_2;Option B;danger] $sendMessage[Options separated by a line] ``` ### Large spacing ``` $addActionRow $addTextDisplay[Text to the left] $addSeparator[no;lg] $addTextDisplay[Text to the right] $sendMessage[Well-spaced text] ``` ## Notes - The separator is inserted in the current action row. - It does not count towards the limit of 5 components per line. - The separation line (`divider: yes`) is a thin horizontal line. - Compatible with all components: buttons, select menus, text displays. --- ### Addstringselect # $addStringSelect Creates a select menu of type "string" — a dropdown menu with predefined text options. ## Syntax ``` $addStringSelect[customId;placeholder;(minValues);(maxValues);(disabled)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `customId` | Custom identifier for the interaction | Yes | | `placeholder` | Text displayed when nothing is selected | Yes | | `minValues` | Minimum number of options to select (default: 1) | No | | `maxValues` | Maximum number of options to select (default: 1) | No | | `disabled` | `true` to disable the menu, `false` (default) | No | ## Description A **string select** is a select menu where the options are character strings defined by the developer. After creating the menu with `$addStringSelect`, add options using `$addStringSelectOption`. Unlike `$newSelectMenu` + `$addSelectMenuOption`, `$addStringSelect` and `$addStringSelectOption` use a simplified API where the `menuId` is optional in `$addStringSelectOption`. ## Examples ### Simple menu ``` $addStringSelect[menu_pays;Choose a country] $addStringSelectOption[France;fr] $addStringSelectOption[Belgium;be] $addStringSelectOption[Switzerland;ch] $addStringSelectOption[Canada;ca] $sendMessage[Select your country] ``` ### Menu with multiple selection ``` $addStringSelect[menu_hobbies;Your hobbies;1;5] $addStringSelectOption[Reading;reading;;📚] $addStringSelectOption[Sport;sport;;⚽] $addStringSelectOption[Music;music;;🎵] $addStringSelectOption[Video games;gaming;;🎮] $addStringSelectOption[Cinema;cinema;;🎬] $sendMessage[What are your hobbies?] ``` ### Disabled menu ``` $addStringSelect[menu_indispo;Unavailable;1;1;true] $addStringSelectOption[Option A;a] $sendMessage[This menu is temporarily disabled] ``` ## Handling the interaction ``` $onInteraction $if[$customID==menu_pays] $sendMessage[You chose: $message] $endif ``` ## Notes - Options are added using `$addStringSelectOption`. - Maximum of 25 options per menu. - Use `$addActionRow` to place the menu on a specific row. --- ### Addstringselectoption # $addStringSelectOption Adds an option to a select menu of type string, created with `$addStringSelect`. ## Syntax ``` $addStringSelectOption[label;value;(description);(emoji);(default);(menuId)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `label` | Text displayed for the option | Yes | | `value` | Value sent during selection | Yes | | `description` | Description displayed under the label | No | | `emoji` | Emoji displayed to the left of the label | No | | `default` | `true` to preselect, `false` (default) | No | | `menuId` | Identifier of the target menu (if multiple menus) | No | ## Description `$addStringSelectOption` adds an option to the last string select menu created with `$addStringSelect`. If multiple menus are used, specify the `menuId` to target a specific menu. ## Examples ### Simple options ``` $addStringSelect[menu_boisson;Choose a drink] $addStringSelectOption[Coffee;coffee;Hot and strong;☕] $addStringSelectOption[Tea;tea;Flavored infusion;🍵] $addStringSelectOption[Orange juice;oj;Freshly squeezed;🍊] $addStringSelectOption[Water;water;Still or sparkling;💧] $sendMessage[What would you like to drink?] ``` ### Default option ``` $addStringSelect[menu_volume;Volume] $addStringSelectOption[Low;low;;🔈] $addStringSelectOption[Medium;medium;;🔉;true] $addStringSelectOption[High;high;;🔊] $sendMessage[Set the volume] ``` ### Multiple menus with menuId ``` $addStringSelect[menu_entree;Starter] $addStringSelectOption[Salad;salad;;🥗] $addStringSelectOption[Soup;soup;;🍜] $addActionRow $addStringSelect[menu_plat;Main course] $addStringSelectOption[Meat;meat;;🥩;;menu_plat] $addStringSelectOption[Fish;fish;;🐟;;menu_plat] $addStringSelectOption[Vegetarian;veggie;;🥬;;menu_plat] $sendMessage[Compose your menu] ``` ## Notes - If `menuId` is not specified, the option is added to the last `$addStringSelect` created. - Maximum of 25 options per menu. - The `value` fields are accessible via `$message` in `$onInteraction`. --- ### Addtextdisplay # $addTextDisplay Adds a text display component in an action row. Allows displaying static text among interactive components. ## Syntax ``` $addTextDisplay[content] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `content` | Text to display in the component | Yes | ## Description `$addTextDisplay` allows inserting non-interactive text in an action row, alongside buttons and menus. This allows creating richer layouts with labels, descriptions, or indicators. ## Examples ### Label before a button ``` $addActionRow $addTextDisplay[Status:] $addButtonCV2[btn_status;Activate;success] $sendMessage[Controls] ``` ### Label before a select ``` $addActionRow $addTextDisplay[Role:] $addRoleSelect[menu_role;Choose a role] $sendMessage[Configuration] ``` ### Formatted text with multiple components ``` $addActionRow $addTextDisplay[Volume] $addSeparator[no;sm] $addButtonCV2[vol_down;➖;secondary] $addButtonCV2[vol_mute;🔇;secondary] $addButtonCV2[vol_up;➕;secondary] $sendMessage[Volume control] ``` ### Status indicator ``` $addActionRow $addTextDisplay[🔴 Offline] $addSeparator[no;md] $addButtonCV2[btn_refresh;Refresh;primary] $sendMessage[Service status] ``` ## Notes - The text is purely decorative and non-interactive. - It does not count towards the limit of 5 interactive components per line (check BDFD version compatibility). - Useful to add labels or descriptions next to components. - The content can include emojis to enrich the display. --- ### $addTextInput[] # $addTextInput[] — Message Text Input `$addTextInput[]` adds a text input component directly in a Discord message. Unlike `$addModalTextInput[]` which requires a modal, this function inserts the text field as an interactive component of the message. ## Syntax ``` $addTextInput[customId;label;(style);(placeholder);(default);(required);(minLength);(maxLength)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `customId` | Yes | — | Unique identifier of the field. | | `label` | Yes | — | Label text. | | `style` | No | `short` | `short` or `paragraph`. | | `placeholder` | No | — | Placeholder text. | | `default` | No | — | Default value. | | `required` | No | `yes` | `yes` or `no`. | | `minLength` | No | — | Minimum number of characters. | | `maxLength` | No | — | Maximum number of characters. | ## Return value Adds the TextInput to the message. The input value is retrieved via `$input[customId]` in the interaction handler. ## Usage ### Search field ```bdfd $title[Search] $description[Enter your search term below] $addTextInput[query;Search term;short;Search...;;yes;2;100] $addButton[search;Search;Primary;;search_action] ``` ### Feedback form ```bdfd $title[Feedback] $description[We want your opinion!] $addTextInput[name;Your name;short;Anonymous;;no;0;50] $addTextInput[message;Your message;paragraph;Write your feedback here...;;yes;10;1000] $addButton[submit;Send;Success] ``` ### Processing the response ```bdfd $onInteraction[search_action] $var[query;$input[query]] $sendMessage[Results for: **$var[query]**] $endInteraction ``` ## Differences with $addModalTextInput[] | Message TextInput | Modal TextInput | |-------------------|-----------------| | Directly in the message | In a modal (pop-up) | | Often accompanied by buttons | Submitted with the modal's Submit button | | No limit of 5 components | Limited to 5 components per modal | ## Notes - The `customId` must be unique within the message. - The value is retrieved via `$input[customId]` in a `$onInteraction` handler. - `minLength` and `maxLength` are validated on the Discord client side. - Label max 45 characters, placeholder max 100 characters. --- ### Adduserselect # $addUserSelect Creates a select menu of users. Allows users to choose one or multiple members of the server from a dropdown list. ## Syntax ``` $addUserSelect[customId;placeholder;(minValues);(maxValues);(disabled)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `customId` | Custom identifier for the interaction | Yes | | `placeholder` | Text displayed when nothing is selected | Yes | | `minValues` | Minimum number of users to select (default: 1) | No | | `maxValues` | Maximum number of users to select (default: 1) | No | | `disabled` | `true` to disable the menu, `false` (default) | No | ## Description A **user select** displays a list of server members. The user can select one or several. The IDs of the selected users are returned in `$onInteraction`. ## Examples ### Selection of a user ``` $addUserSelect[menu_user;Choose a member] $sendMessage[Select a user] ``` ### Multiple selection ``` $addUserSelect[menu_mods;Choose moderators;1;5] $sendMessage[Select 1 to 5 moderators] ``` ### Disabled menu ``` $addUserSelect[menu_user_disabled;Selection disabled;1;1;true] $sendMessage[This menu is temporarily unavailable] ``` ## Handling the interaction ``` $onInteraction $if[$customID==menu_user] $sendMessage[Selected user: <@$message>] $endif $if[$customID==menu_mods] $sendMessage[Selected moderators: $message] $endif ``` ## Notes - The returned values are Discord user IDs. - Use `<@ID>` to mention the user in a message. - For multiple selection, the IDs are separated by commas (or according to the configuration of the bot). - A single select menu per action row. --- ### Addvoiceselect # $addVoiceSelect Creates a select menu of voice channels. Allows users to choose one or multiple voice channels on the server. ## Syntax ``` $addVoiceSelect[customId;placeholder;(minValues);(maxValues);(disabled)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `customId` | Custom identifier for the interaction | Yes | | `placeholder` | Text displayed when nothing is selected | Yes | | `minValues` | Minimum number of voice channels to select (default: 1) | No | | `maxValues` | Maximum number of voice channels to select (default: 1) | No | | `disabled` | `true` to disable the menu, `false` by default | No | ## Description `$addVoiceSelect` adds a **voice channel select menu** to a message. This component is similar to `$addChannelSelect` but is restricted to **voice channels** only. The user can select one or multiple voice channels, and the interaction returns the selected channel IDs. This function must be placed after `$addActionRow` to be organized on a specific row. ## Examples ### Voice channel selection ``` $addActionRow $addVoiceSelect[menu_voice;Choose a voice channel] $sendMessage[Select a voice channel] ``` ### Multiple voice channels ``` $addActionRow $addVoiceSelect[menu_voices;Voice channels;1;10] $sendMessage[Select up to 10 voice channels] ``` ### Disabled menu ``` $addActionRow $addVoiceSelect[menu_voice_disabled;Unavailable;1;1;true] $sendMessage[This menu is disabled] ``` ## Handling the interaction ``` $onInteraction $if[$customID==menu_voice] $sendMessage[Selected voice channel: <#$message>] $endif ``` ## Notes - The returned values are Discord voice channel IDs. - Use `<#ID>` to mention a voice channel. - Only **voice channels** appear in the menu (no text channels, categories, etc.). - An action row can contain only **one** select menu. --- ### $customID # $customID The `$customID` function returns the **customId** of the component (button, select menu, modal) that triggered an interaction. ## Syntax ``` $customID ``` ## Parameters None. ## Return value - **Type**: String - The customId set during the creation of the component. ## Behavior - Must be used in an `$onInteraction` callback. - Allows differentiating which button/menu was used. ## Examples ### Interaction handler ```bdfd $onInteraction $if[$customID==accept] $sendMessage[Request accepted.] $elseIf[$customID==refuse] $sendMessage[Request denied.] $elseIf[$customID==info] $sendMessage[More information soon.] $endif ``` ### Log interactions ```bdfd $onInteraction $log[Interaction received — customID: $customID — by $username] ``` ### Dynamic switch ```bdfd $onInteraction $switch[$customID; confirm;$sendMessage[✅ Confirmed]; cancel;$sendMessage[❌ Cancelled]; delete;$deleteChannels[$channelID] ] ``` ## Notes - Functional equivalent to `$interactionData[customId]`. - Essential for systems of buttons and interactive menus. - The customId is set by the developer in `$addButton[]`, `$addSelectMenu[]`, etc. --- ### $editButton # $editButton The `$editButton[]` function **modifies a button** that already exists on a message. ## Syntax ``` $editButton[idOrUrl;label;(style);(disabled);(emoji)] ``` ## Parameters | Parameter | Description | |---|---| | `idOrUrl` | Custom ID of the button (or URL for Link buttons). | | `label` | New text displayed on the button. | | `style` | *(Optional)* Style: `primary`, `secondary`, `success`, `danger`, `link`. | | `disabled` | *(Optional)* `true` to disable the button, `false` by default. | | `emoji` | *(Optional)* Emoji to display to the left of the label. | ## Behavior - The target button must exist in the message currently being edited. - The modification is applied during the message editing process (via `$editMessage` or similar). - All parameters except `idOrUrl` and `label` are optional. ## Examples ### Disable a button after click ```bdfd $editButton[accept;✅ Accepted;success;true;✅] $editButton[refuse;❌ Refused;danger;true;❌] ``` ### Changing the style of a button ```bdfd $editButton[action;Processing...;secondary;true;⏳] ``` ### Resetting a button ```bdfd $editButton[reset;🔄 Restart;primary;false;🔄] ``` ## Notes - Works with `$onInteraction` for dynamic updates. - For Link buttons, use the URL as the first parameter. - Use with `$editMessage` to apply the changes. --- ### $editSelectMenu # $editSelectMenu The `$editSelectMenu[]` function **modifies an existing select menu**. ## Syntax ``` $editSelectMenu[customId;placeholder;minValues;maxValues] ``` ## Parameters | Parameter | Description | |---|---| | `customId` | The custom ID of the select menu to modify. | | `placeholder` | Placeholder text displayed before selection. | | `minValues` | Minimum number of required selections. | | `maxValues` | Maximum number of allowed selections. | ## Return value None. The select menu is modified. ## Behavior - The targeted select menu must exist in the message. - `minValues` must be ≤ `maxValues`. - `maxValues` cannot exceed 25 (Discord limit). ## Examples ### Update after selection ```bdfd $editSelectMenu[langMenu;Language chosen!;0;1] ``` ### Lock a select menu ```bdfd $editSelectMenu[closedMenu;Closed;0;0] ``` ### Reset a dynamic select menu ```bdfd $editSelectMenu[categoryMenu;Select a category;1;3] ``` ## Notes - Use with `$editMessage` to apply the modifications. - To modify the menu options, use `$editSelectMenuOption[]`. - `maxValues=1` creates a single-choice menu, `>1` a multi-choice menu. --- ### $editSelectMenuOption # $editSelectMenuOption The `$editSelectMenuOption[]` function **modifies an existing option** in a select menu. ## Syntax ``` $editSelectMenuOption[menuId;label;value;description;default;emoji] ``` ## Parameters | Parameter | Description | |---|---| | `menuId` | Custom ID of the parent select menu. | | `label` | New text displayed for the option. | | `value` | Internal value passed to `$onInteraction`. | | `description` | *(Optional)* Secondary text below the label. | | `default` | *(Optional)* `true` if the option is pre-selected. | | `emoji` | *(Optional)* Decorative emoji. | ## Return value None. The option is modified. ## Behavior - The targeted option is identified by its `value` (or its index). - The parent select menu must exist. - The modification is applied during the message edit. ## Examples ### Mark an option as selected ```bdfd $editSelectMenuOption[langMenu;English;en;English language;true;🇬🇧] ``` ### Update the label ```bdfd $editSelectMenuOption[roleMenu;Moderator;mod;Moderation role;false;🛡️] ``` ### Visually disable an option ```bdfd $editSelectMenuOption[actionMenu;Unavailable;none;This option is no longer available;false;🚫] ``` ## Notes - Use with `$editSelectMenu[]` for a complete update of the menu. - The `value` parameter is used to identify the target option. - To add/remove options, use `$addSelectMenuOption[]` or rebuild the menu. --- ### Ephemeral # $ephemeral Makes the response ephemeral (visible only to the user who triggered the interaction). Used as a flag before `$sendMessage`. ## Syntax ``` $ephemeral ``` ## Description `$ephemeral` is a **flag** (without arguments) that, when placed before `$sendMessage`, makes the message visible only to the target user. The message appears with the label "Only you can see this" and disappears after some time or when the user closes Discord. This function is particularly useful for: - Discrete confirmation messages - Errors or warnings - Responses to interactions on buttons or select menus - Sensitive information ## Examples ### Simple ephemeral response ``` $ephemeral $sendMessage[This message is visible only to you.] ``` ### With embeds ``` $ephemeral $newEmbed[title=Information;description=Private data;color=#9B59B6] $sendMessage[] ``` ### In an interaction ``` $onInteraction $if[$customID==btn_secret] $ephemeral $sendMessage[🔒 Secret action completed!] $endif ``` ### Ephemeral error message ``` $if[$argsCount==0] $ephemeral $sendMessage[❌ You must provide an argument!] $stop $endif ``` ## Notes - Only works in the context of interactions (slash commands, buttons, select menus). - Does NOT work for classic prefix commands (message commands). - The flag must be placed before `$sendMessage`. - Practical for keeping channels clean of system messages. --- ### $getChannelSelectChannelID # $getChannelSelectChannelID The `$getChannelSelectChannelID[]` function allows you to **retrieve the ID of the channel** chosen by the user in a channel select menu. ## Syntax ``` $getChannelSelectChannelID[(index)] ``` ## Parameters | Parameter | Description | |---|---| | `index` | Optional - The index of the channel in the selection (1 = first). Default: 1. | ## Return Value - **Type**: String (Snowflake ID) - The Discord ID of the selected channel. - An empty string if no channel was selected. ## Behavior - Used in interactions of type `$onInteraction[]` or `$selectMenuInteractionID[]`. - Works with channel select menus (type `channel` in `$addChannelSelectMenu[]`). - If the user selects multiple channels, use `$getChannelSelectChannelIDs[]` to retrieve all of them. ## Examples ### Simple retrieval ```bdfd $nomentionMessage $addChannelSelectMenu[channel_select;1;Select a channel to monitor] $sendMessage[Please choose a channel:] $onInteraction[channel_select] $let[channelID;$getChannelSelectChannelID] $title[Selected Channel] $description[ **ID:** $channelID **Name:** $channelName[$channelID] ] $sendMessage[] ``` ### Handling multiple selections ```bdfd $onInteraction[channel_select] $let[count;$length[$splitText[$getChannelSelectChannelIDs[,];,]]] You have selected **$count** channel(s): $textSplit[$getChannelSelectChannelIDs[,];,] > <#[$splitText[$index]]> (ID: $splitText[$index]) $endTextSplit ``` ## Notes - The index starts at 1 (not 0). - Only works in interaction callbacks. - For multiple selections, use `$getChannelSelectChannelIDs[]` instead. - The returned channel can be of any type (text, voice, category, etc.). --- ### $getChannelSelectChannelIDs # $getChannelSelectChannelIDs The `$getChannelSelectChannelIDs[]` function allows you to **retrieve all the channel IDs** chosen by the user in a multi-choice channel select menu. ## Syntax ``` $getChannelSelectChannelIDs[(separator)] ``` ## Parameters | Parameter | Description | |---|---| | `separator` | Optional - The character or string that separates each ID. Default: `, ` (comma + space). | ## Return Value - **Type**: String - The list of all selected channel IDs, separated by the delimiter. - An empty string if no channel was selected. ## Behavior - Used when the channel select menu allows multiple choices (`maxValues > 1`). - Returns all IDs in a single string with the specified separator. - Compatible with `$textSplit[]` to iterate over each channel. ## Examples ### List of selected channels ```bdfd $onInteraction[channel_select] $let[channels;$getChannelSelectChannelIDs[, ]] $title[📋 Selected Channels] $description[ **IDs:** $channels **List:** $textSplit[$channels;, ] > <#[$splitText[$index]]> $endTextSplit ] $color[#5865F2] $sendMessage[] ``` ### Loop through each channel ```bdfd $onInteraction[channel_select] $let[list;$getChannelSelectChannelIDs[,]] $let[count;$length[$splitText[$list;,]]] I have registered **$count** channel(s). $textSplit[$list;,] Channel $index: $channelName[$splitText[$index]] $endTextSplit ``` ## Notes - If the menu only accepts a single choice, use `$getChannelSelectChannelID[]`. - The custom separator allows easy integration with other functions. - Ideal for multi-channel configurations (logs, allowed channels, etc.). --- ### $getMentionableSelectUserID # $getMentionableSelectUserID The function `$getMentionableSelectUserID[]` allows **retrieving the ID of the mentionable entity** selected by the user via a mentionable select menu (users + roles). ## Syntax ``` $getMentionableSelectUserID[(index)] ``` ## Parameters | Parameter | Description | |---|---| | `index` | Optional - The index of the entity in the selection (1 = first). Default 1. | ## Return Value - **Type** : String (Snowflake ID) - The Discord ID of the selected user or role. - Empty string if no mentionable was selected. ## Behavior - Used in interactions with a menu of type `mentionable`. - The mentionable menu accepts both users and roles. - The returned ID can be a user ID or a role ID depending on what the user chose. ## Examples ### Simple retrieval ```bdfd $nominalTrigger $addMentionableSelectMenu[mention_select;1;Choose a user or role] $sendMessage[Select an entity:] $onInteraction[mention_select] $let[id;$getMentionableSelectUserID] $title[Selected entity] $description[ID: $id] $sendMessage[] ``` ### Check the entity type ```bdfd $onInteraction[mention_select] $let[id;$getMentionableSelectUserID] $if[$hasRole[$id;$guildID]==true] This is a role: @&$id $else This is a user: <@$id> $endif ``` ## Notes - The index starts at 1. - For multiple selections, use `$getMentionableSelectUserIDs[]`. - The returned ID may correspond to a user OR a role. --- ### $getMentionableSelectUserIDs # $getMentionableSelectUserIDs The function `$getMentionableSelectUserIDs[]` retrieves all **mentionable entity IDs** (users and roles) selected by the user in a multi-select mentionable menu. ## Syntax ``` $getMentionableSelectUserIDs[(separator)] ``` ## Parameters | Parameter | Description | |---|---| | `separator` | Optional - The separator between each ID. Defaults to `, ` (comma + space). | ## Return Value - **Type**: String - The complete list of selected IDs. - An empty string if no entity was selected. ## Behavior - Returns both user and role IDs. - Compatible with `$textSplit[]` for individual processing. - The menu must allow multiple selections (`maxValues > 1`). ## Examples ### List chosen entities ```bdfd $onInteraction[mention_select] $let[list;$getMentionableSelectUserIDs[, ]] $title[📋 Selected Entities] $description[$list] $sendMessage[] ``` ### Processing loop ```bdfd $onInteraction[mention_select] $let[list;$getMentionableSelectUserIDs[,]] $textSplit[$list;,] $if[$hasRole[$splitText[$index];$guildID]==true] Role: $roleName[$splitText[$index]] $else User: $userName[$splitText[$index]] $endif $endTextSplit ``` ## Notes - For a single selection, use `$getMentionableSelectUserID[]`. - IDs can be mixed (users and roles in the same list). - Use `$hasRole[]` to distinguish a role from a user. --- ### $getRoleSelectRoleID # $getRoleSelectRoleID The function `$getRoleSelectRoleID[]` retrieves the **ID of the role** chosen by the user in a role select menu. ## Syntax ``` $getRoleSelectRoleID[(index)] ``` ## Parameters | Parameter | Description | |---|---| | `index` | Optional - The index of the selected role (1 = first). Defaults to 1. | ## Return Value - **Type**: String (Snowflake ID) - The Discord ID of the selected role. - An empty string if no role was selected. ## Behavior - Used in interactions of type `$onInteraction[]` with a role select menu. - The role menu is created using `$addRoleSelectMenu[]`. - Works with both single and multiple selections (for multiple, use `$getRoleSelectRoleIDs[]`). ## Examples ### Assigning a role via selection ```bdfd $nominalTrigger $addRoleSelectMenu[role_select;1;Choose your role] $sendMessage[Select a role:] $onInteraction[role_select] $let[roleID;$getRoleSelectRoleID] $giveRole[$authorID;$roleID] $title[Role Assigned] $description[You have received the role **$roleName[$roleID]**!] $color[#57F287] $sendMessage[] ``` ### Retrieval with index ```bdfd $onInteraction[role_select] $let[first;$getRoleSelectRoleID[1]] $let[second;$getRoleSelectRoleID[2]] $title[Selected Roles] $description[ **Role 1:** $roleName[$first] **Role 2:** $roleName[$second] ] $sendMessage[] ``` ## Notes - The index starts at 1. - To retrieve all roles from a multiple selection, use `$getRoleSelectRoleIDs[]`. - The returned ID is compatible with all functions that manipulate roles. --- ### $getRoleSelectRoleIDs # $getRoleSelectRoleIDs The function `$getRoleSelectRoleIDs[]` retrieves all **role IDs** selected by the user in a multi-select role menu. ## Syntax ``` $getRoleSelectRoleIDs[(separator)] ``` ## Parameters | Parameter | Description | |---|---| | `separator` | Optional - The separator between each ID. Defaults to `, ` (comma + space). | ## Return Value - **Type**: String - The list of all selected role IDs. - An empty string if no role was selected. ## Behavior - Used with a role select menu configured with `maxValues > 1`. - Returns all IDs in a single string with the specified separator. - Compatible with `$textSplit[]` to iterate over each role. ## Examples ### Assigning multiple roles ```bdfd $onInteraction[role_select] $let[roles;$getRoleSelectRoleIDs[,]] $textSplit[$roles;,] $giveRole[$authorID;$splitText[$index]] + Role added: $roleName[$splitText[$index]] $endTextSplit $sendMessage[✅ All roles have been assigned!] ``` ### Displaying selected roles ```bdfd $onInteraction[role_select] $let[list;$getRoleSelectRoleIDs[, ]] $let[count;$length[$splitText[$list;, ]]] $title[🎭 $count role(s) selected] $description[ $textSplit[$list;, ] $index. $roleName[$splitText[$index]] $endTextSplit ] $color[#5865F2] $sendMessage[] ``` ## Notes - For a single selection, use `$getRoleSelectRoleID[]`. - The separator can be any string of characters. - Useful for auto-role systems with multiple selections. --- ### $getStringSelectValue # $getStringSelectValue The function `$getStringSelectValue[]` retrieves the value of the option chosen by the user in a string select menu. ## Syntax ``` $getStringSelectValue[(index)] ``` ## Parameters | Parameter | Description | |---|---| | `index` | Optional - The index of the selected value (1 = first). Defaults to 1. | ## Return Value - **Type**: String - The value associated with the selected option. - An empty string if no option was chosen. ## Behavior - Works with select menus created via `$addStringSelectMenu[]`. - The returned value corresponds to the second parameter of each option defined in the menu: `$addStringSelectMenu[menuID;placeholder;label1:value1;label2:value2;...]`. - Very useful for triggering specific actions according to the chosen value. ## Examples ### Simple navigation menu ```bdfd $nominalTrigger $addStringSelectMenu[nav;Choose an action;Home:home;Profile:profile;Help:help] $sendMessage[What do you want to do?] $onInteraction[nav] $let[action;$getStringSelectValue] $if[$action==home] $title[🏠 Home] $description[Welcome to the server!] $sendMessage[] $elseif[$action==profile] $title[👤 Profile of $userName] $description[Joined on $creationDate[$authorID]...] $sendMessage[] $elseif[$action==help] $title[❓ Help] $description[Use /help to view the commands.] $sendMessage[] $endif ``` ### Switch based on the value ```bdfd $onInteraction[menu] $let[val;$getStringSelectValue] $switch[$val] $case[option1] Action 1 executed. $break $case[option2] Action 2 executed. $break $default No action matched. $break $endSwitch ``` ## Notes - The index starts at 1. - For multiple-choice select menus, use `$getStringSelectValues[]`. - The value can be any string defined in the menu. --- ### $getStringSelectValues # $getStringSelectValues The function `$getStringSelectValues[]` retrieves all option values chosen by the user in a multi-select string select menu. ## Syntax ``` $getStringSelectValues[(separator)] ``` ## Parameters | Parameter | Description | |---|---| | `separator` | Optional - The separator between each value. Defaults to `, ` (comma + space). | ## Return Value - **Type**: String - The list of all selected values, separated by the delimiter. - An empty string if no option was selected. ## Behavior - Used with a string select menu configured with `maxValues > 1`. - Returns the values (not the labels) of the chosen options. - Allows processing multiple choices in a single interaction. ## Examples ### Processing multiple choices ```bdfd $onInteraction[menu] $let[vals;$getStringSelectValues[,]] You selected: $textSplit[$vals;,] - Option: $splitText[$index] $endTextSplit $sendMessage[] ``` ### Conditional loop ```bdfd $onInteraction[menu] $let[choices;$getStringSelectValues[,]] $textSplit[$choices;,] $if[$splitText[$index]==notif] $sendDM[$authorID;🔔 Notifications enabled!] $elseif[$splitText[$index]==news] $sendDM[$authorID;📰 Newsletter enabled!] $endif $endTextSplit ``` ## Notes - For a single selection, use `$getStringSelectValue[]`. - The separator can be customized to make parsing easier. - The values are defined in `$addStringSelectMenu[]`. --- ### $getUserSelectUserID # $getUserSelectUserID The function `$getUserSelectUserID[]` retrieves the **ID of the user** chosen via a user select menu. ## Syntax ``` $getUserSelectUserID[(index)] ``` ## Parameters | Parameter | Description | |---|---| | `index` | Optional - The index of the user in the selection (1 = first). Defaults to 1. | ## Return Value - **Type**: String (Snowflake ID) - The Discord ID of the selected user. - An empty string if no user was selected. ## Behavior - Used in interactions with a user select menu created via `$addUserSelectMenu[]`. - The selected user can be any member of the server. - For multiple selections, use `$getUserSelectUserIDs[]`. ## Examples ### User verification ```bdfd $nominalTrigger $addUserSelectMenu[user_select;1;Select a user] $sendMessage[Choose a user to check:] $onInteraction[user_select] $let[userID;$getUserSelectUserID] $title[👤 User Profile] $description[ **Name:** $userName[$userID] **ID:** $userID **Joined on:** $memberJoinDate[$userID] **Roles:** $userRoles[$userID] ] $thumbnail[$userAvatar[$userID]] $color[#5865F2] $sendMessage[] ``` ### Warning via selection ```bdfd $onInteraction[user_select] $let[target;$getUserSelectUserID] $sendDM[$target;⚠️ You have received a warning on **$serverName**.] $title[✅ Warning Sent] $description[A DM was sent to **$userName[$target]**.] $sendMessage[] ``` ## Notes - The index starts at 1. - To retrieve all users from a multiple selection, use `$getUserSelectUserIDs[]`. - The user must be a member of the server to be selectable. --- ### $getUserSelectUserIDs # $getUserSelectUserIDs The function `$getUserSelectUserIDs[]` retrieves all **user IDs** selected in a multi-select user select menu. ## Syntax ``` $getUserSelectUserIDs[(separator)] ``` ## Parameters | Parameter | Description | |---|---| | `separator` | Optional - The separator between each ID. Defaults to `, ` (comma + space). | ## Return Value - **Type**: String - The list of all selected user IDs. - An empty string if no user was selected. ## Behavior - Used with a user select menu configured with `maxValues > 1`. - Returns all IDs in a single string. - Ideal for bulk actions (group DMs, role assignments, etc.). ## Examples ### Group DM ```bdfd $onInteraction[user_select] $let[users;$getUserSelectUserIDs[,]] $textSplit[$users;,] $sendDM[$splitText[$index];📢 Important message from **$serverName**!] $endTextSplit $title[✅ Messages Sent] $description[All selected users have received a DM.] $color[#57F287] $sendMessage[] ``` ### Bulk Role Assignment ```bdfd $onInteraction[user_select] $let[users;$getUserSelectUserIDs[,]] $let[count;$length[$splitText[$users;,]]] $textSplit[$users;,] $giveRole[$splitText[$index];$roleID[Member]] $endTextSplit $title[🎭 Role Assigned] $description[The role **Member** was given to **$count** user(s).] $color[#5865F2] $sendMessage[] ``` ## Notes - For a single selection, use `$getUserSelectUserID[]`. - Compatible with `$textSplit[]` to iterate over each user. - Useful for bulk moderation or administration commands. --- ### $newModal[] # $newModal[] — Create a Modal The function `$newModal[]` initializes a new Discord modal. A modal is an interactive pop-up window that overlays the user interface. It must be the first call before adding components such as text fields, selectors, or checkboxes. ## Syntax ``` $newModal[title;customId] ``` ## Parameters | Parameter | Description | |-----------|-------------| | `title` | The title displayed at the top of the modal. Required. | | `customId` | A unique custom identifier for the modal. Used in interactions to identify which modal was submitted. Required. | ## Return Value This function does not return a value directly. It initializes an internal context in which the functions to add components (`$addModalTextInput`, etc.) operate. ## Usage ### Basic Modal ```bdfd $newModal[Registration;signup_modal] $addModalTextInput[username;Username;short;Enter your username...;;yes;3;32] $addModalTextInput[email;Email;short;example@email.com;;yes;5;100] ``` ### Modal with display text ```bdfd $newModal[Confirmation;confirm_modal] $addModalTextDisplay[Please check the information before confirming.] $addModalTextInput[code;Verification Code;short;XXXX;;yes;4;4] ``` ### Modal sent via a slash command or a button ```bdfd $newModal[Product Review;review_modal] $addModalTextInput[rating;Rating (1-5);short;;1;;1;1] $addModalTextInput[review;Your Review;paragraph;Share your experience...;;yes;10;500] ``` ## Important Notes - `$newModal[]` must be the **first** function called when constructing a modal. - All components added after `$newModal[]` belong to that modal until a new `$newModal[]` is called. - The `customId` is essential for processing the submitted data in an interaction handler. - Modals are generally triggered via interactions (buttons, slash commands, select menus). --- ### Newselectmenu # $newSelectMenu Creates a new select menu in the current action row. A select menu allows users to choose from a list of predefined options. ## Syntax ``` $newSelectMenu[customId;placeholder;(minValues);(maxValues)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `customId` | Custom identifier for the interaction | Yes | | `placeholder` | Text displayed when no option is selected | Yes | | `minValues` | Minimum number of options that must be chosen (default: 1) | No | | `maxValues` | Maximum number of options that can be chosen (default: 1) | No | ## Description `$newSelectMenu` initializes a drop-down menu in the message. After creating it, use `$addSelectMenuOption` to add options. The menu is then sent along with a message. ## Examples ### Simple Menu ```bdfd $newSelectMenu[color_menu;Choose a color] $addSelectMenuOption[color_menu;Red;red;The color red;🔴] $addSelectMenuOption[color_menu;Blue;blue;The color blue;🔵] $addSelectMenuOption[color_menu;Green;green;The color green;🟢] $sendMessage[Select your favorite color] ``` ### Multiple Selection Menu ```bdfd $newSelectMenu[fruits_menu;Choose your fruits;1;3] $addSelectMenuOption[fruits_menu;Apple;apple;;🍎] $addSelectMenuOption[fruits_menu;Banana;banana;;🍌] $addSelectMenuOption[fruits_menu;Orange;orange;;🍊] $addSelectMenuOption[fruits_menu;Grape;grape;;🍇] $addSelectMenuOption[fruits_menu;Strawberry;strawberry;;🍓] $sendMessage[Select 1 to 3 fruits] ``` ## Interaction Handling Use `$onInteraction` to process the selection: ```bdfd $onInteraction $if[$customID==color_menu] $sendMessage[You chose: $message] $endif ``` ## Notes - Each menu must have a unique `customId` to identify the interaction. - Only one select menu is allowed per action row. - Up to 25 options can be added per menu. - For specialized select menus (users, roles, channels), use dedicated functions (e.g. `$addUserSelect`, `$addRoleSelect`, etc.). --- ### $removeAllComponents[] # $removeAllComponents[] — Remove All Components `$removeAllComponents[]` removes all interactive components from a message. After this operation, the message becomes purely static — no more buttons, menus, or input fields. ## Syntax ``` $removeAllComponents ``` ## Parameters No parameters. ## Return Value Removes all components from the message, making it non-interactive. ## Usage ### Form finalization ```bdfd $onInteraction[submit_form] $removeAllComponents $var[name;$input[name_input]] $var[email;$input[email_input]] $editMessage[✅ Form submitted! **Name:** $var[name] **Email:** $var[email]] $endInteraction ``` ### Lock after expiration ```bdfd $onInteraction[timeout_event] $removeAllComponents $editMessage[⏰ This panel has expired. Interaction is no longer possible.] $endInteraction ``` ### Complete cleanup ```bdfd $addTextInput[query;Search;short;Search...;;yes;2;100] $addButton[search;Search;Primary;;search_btn] $addButton[cancel;Cancel;Danger;;cancel_btn] $onInteraction[search_btn] $removeAllComponents $var[query;$input[query]] $editMessage[Results for **$var[query]**:\nNo results found.] $endInteraction $onInteraction[cancel_btn] $removeAllComponents $editMessage[Search cancelled] $endInteraction ``` ### Configuration panel ```bdfd $title[Configuration] $description[Modify your settings] $addTextInput[nickname;Nickname;short;$nickname;;no;2;32] $addButton[save;Save;Success;;save_config] $onInteraction[save_config] $removeAllComponents $var[nick;$input[nickname]] $editMessage[✅ Nickname updated: **$var[nick]**] $endInteraction ``` ## Comparison of removal functions | Function | Effect | |----------|--------| | `$removeComponent[id]` | Removes a specific component | | `$removeButtons` | Removes all buttons only | | `$removeAllComponents` | Removes **all** components | ## Notes - After `$removeAllComponents[]`, the message can no longer receive user interactions. - Used to "consume" an interface after processing. - To be used in `$onInteraction` handlers with `$editMessage[]` or `$sendMessage[]`. - Irreversible: once removed, components cannot be restored without sending a new message. --- ### $removeButtons[] # $removeButtons[] — Remove All Buttons `$removeButtons[]` removes all button-type components from a message. This is the simplest method to disable an interface after a user has interacted with it. ## Syntax ``` $removeButtons ``` ## Parameters No parameters. ## Return Value Removes all buttons from the message. Other components (TextInput, Select Menus) are not affected. ## Usage ### Disable after voting ```bdfd $onInteraction[vote_yes] $removeButtons $editMessage[✅ Vote recorded: **Yes**] $endInteraction ``` ### Self-locking interface ```bdfd $onInteraction[poll_choice] $removeButtons $var[choice;$input[poll_choice]] $editMessage[Thank you for your vote: **$var[choice]**] $endInteraction ``` ### Confirmation with removal ```bdfd $addButton[confirm;Confirm;Success;yes;confirm_action] $addButton[cancel;Cancel;Danger;yes;cancel_action] $onInteraction[confirm_action] $removeButtons $editMessage[✅ Action confirmed and executed!] $endInteraction $onInteraction[cancel_action] $removeButtons $editMessage[❌ Action cancelled] $endInteraction ``` ### Temporary admin panel ```bdfd $title[Admin Panel] $description[Choose an action:] $addButton[ban;Ban;Danger;;admin_ban] $addButton[kick;Kick;Secondary;;admin_kick] $addButton[mute;Mute;Primary;;admin_mute] $footer[Single use — the panel disables after use] $onInteraction[admin_ban] $removeButtons $editMessage[User banned] $endInteraction ``` ## Notes - Removes **all** buttons, regardless of their customId. - TextInput, Select Menus, and other non-button components are preserved. - To remove a specific button, use `$removeComponent[customId]`. - To remove absolutely all components, use `$removeAllComponents[]`. - Used primarily in `$onInteraction` handlers after processing. --- ### $removeComponent[] # $removeComponent[] — Remove a Component `$removeComponent[]` removes a specific component from a message based on its `customId`. This allows dynamically disabling or removing buttons, menus, or input fields after an interaction. ## Syntax ``` $removeComponent[customId] ``` ## Parameters | Parameter | Required | Description | |-----------|----------|-------------| | `customId` | Yes | Identifier of the component to remove (defined at its creation). | ## Return Value Removes the component from the message. If no component with this `customId` exists, nothing happens. ## Usage ### Removal after click ```bdfd $onInteraction[confirm_btn] $removeComponent[confirm_btn] $removeComponent[cancel_btn] $editMessage[✅ Action confirmed!] $endInteraction ``` ### Disable a button after use ```bdfd $onInteraction[claim_reward] $removeComponent[claim_reward] $sendMessage[$username has claimed the reward!] $endInteraction ``` ### Remove multiple specific components ```bdfd $onInteraction[reset_form] $removeComponent[name_input] $removeComponent[email_input] $removeComponent[submit_btn] $editMessage[Form reset] $endInteraction ``` ### Menu that disappears after selection ```bdfd $onInteraction[select_role] $removeComponent[role_menu] $var[role;$input[role_menu]] $giveRole[$authorID;$var[role]] $editMessage[Role **$var[role]** assigned!] $endInteraction ``` ## Notes - The `customId` must match exactly the one defined when creating the component (`$addButton[customId;...]`, `$addTextInput[customId;...]`, etc.). - If the component doesn't exist, the function fails silently. - Used primarily in `$onInteraction` handlers to modify the message after a user action. - To remove all buttons at once, use `$removeButtons[]`. - To remove everything, use `$removeAllComponents[]`. --- ### $sendResponse # $sendResponse `$sendResponse` sends a **direct reply** to an interaction (slash command, button, select menu, or modal). It is the recommended way to answer component interactions without building a full embed pipeline first. ## Syntax ``` $sendResponse[content] ``` ### Ephemeral modifier Append `// ephemeral` inside the brackets to make the response visible only to the user who triggered the interaction: ``` $sendResponse[Only you can see this // ephemeral] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:--------:| | `content` | Text content of the response. Supports `((...))` placeholders. | Yes | ## Description `$sendResponse` is optimized for **interaction contexts** (`$onInteraction` handlers and slash commands). Unlike `$sendMessage`, it responds directly to the pending interaction token. Use it when you need a fast confirmation after a button click, select menu choice, or modal submission. ## Examples ### Button verification ```bdfd $if[((interaction.customId))==button_verify] $sendResponse[Your account has been successfully verified! // ephemeral] $giveRole[((interaction.userId));112233445566778899] $endif ``` ### Modal submission ```bdfd $if[((interaction.kind))==modal] $sendResponse[Profile successfully configured, ((user.username))! // ephemeral] $endif ``` ### Public role assignment feedback ```bdfd $if[((interaction.customId))==role_dev] $sendResponse[✅ The **Developer** role has been added to your profile! // ephemeral] $endif ``` ## Related functions - [$ephemeral](/docs/ephemeral/) — flag before `$sendMessage` for ephemeral visibility - [$defer](/docs/defer/) — acknowledge slow interactions before responding - [$reply](/docs/reply/) — reply threading flag used with `$sendMessage` - [$sendMessage](/docs/sendmessage/) — full message with embeds and components - [Interactions overview](/docs/interactions-overview/) — component workflow guide ## Notes - Works in slash commands and `$onInteraction` handlers. - The `// ephemeral` suffix is optional; omit it for public channel responses. - For responses with embeds or multiple components, use `$sendMessage` after [$defer](/docs/defer/) if processing takes longer than 3 seconds. --- ## Control Flow ### $and # $and — Logical AND `$and` performs a logical AND operation across a variable number of conditions. It returns the string `"true"` only if **every** provided condition evaluates to `"true"`. If any condition evaluates to `"false"`, the result is `"false"`. ## Syntax ``` $and[condition1;condition2;...;conditionN] ``` `$and` accepts an **unlimitd number** of arguments (minimum 2). Each argument is a BDFD expression that is expected to resolve to either `"true"` or `"false"`. ## Evaluation Each condition argument is resolved at runtime. Unlike many programming languages, BDFD's `$and` does **not** guarantee short-circuit evaluation — all conditions may be evaluated regardless of whether an earlier one already returned `"false"`. This means you should be cautious about conditions that have side effects (like sending messages or modifying variables), as they may execute even when the overall result is already determined to be false. ## Truth Table | Condition 1 | Condition 2 | Result | |-------------|-------------|----------| | `"true"` | `"true"` | `"true"` | | `"true"` | `"false"` | `"false"`| | `"false"` | `"true"` | `"false"`| | `"false"` | `"false"` | `"false"`| The same logic extends to 3 or more arguments — all must be `"true"` for a `"true"` result. ## Using Conditions `$and` works with any expression that evaluates to `"true"` or `"false"`: - **Direct function results**: `$and[$checkCondition[...];$checkContains[...]]` - **Inline comparisons**: `$and[$getUserVar[a]>0;$getUserVar[b]>0]` - **Nested logical operators**: `$and[$or[...];$or[...]]` Always wrap the `$and` call in an explicit boolean comparison when using inside `$if`: ``` $if[$and[cond1;cond2]==true] ``` ## Use Cases - **Multi-requirement checks**: Verify that all prerequiredites are met before allowing an action. - **Form validation**: Check that multiple fields are non-empty or valid. - **Access control**: Combine role checks with resource availability checks. - **State verification**: Confirm that multiple flags or state variables are all set correctly. ## Common Pitfalls - **Assuming short-circuit**: Do not rely on conditions being evaluated left-to-right or stopping early. Avoid placing side-effect-heavy functions inside `$and`. - **Non-boolean results**: If a condition returns something other than `"true"` or `"false"` (e.g., a number or empty string), the behavior is undefined — always ensure your conditions resolve to `"true"` or `"false"`. - **Single condition**: `$and` requires at least 2 arguments. For a single condition, just use the condition directly without `$and`. - **Forgetting `==true` in $if**: Write `$if[$and[...]==true]`, not `$if[$and[...]]`. --- ### $awaitFunc[] $awaitFunc is a powerful mechanism for creating interactive, multi-step commands. It pauses the command at a specific point and resumes only when the expected event occurs — a button click, a reaction, a message, etc. ## How It Works 1. You send a prompt (message with buttons, reaction request, etc.) to the user. 2. You call `$awaitFunc` specifying what event to wait for. 3. The command **suspends** — no further code runs until the event occurs. 4. When the awaited event fires (matching any filters), execution **resumes** from the next line. 5. Context is preserved: all variables, states, and scopes are maintained across the suspension. ## Awaited Events | functionName | Waits for.. | |--------------|--------------| | `"button"` | A button interaction (created with `$addButton`) | | `"reaction"` | A reaction added to the bot's message | | `"message"` | A new message sent in the channel | The exact set of supported events depends on the Bot Creator implementation. Check your version's documentation for the full list. ## Filters (Optional Parameters) - **userID**: Restricts the await to a specific user. Use `$authorID` to wait for the original command author. - **channelID**: Restricts the await to a specific channel. Use `$channelID` for the current channel. If filters are omitted, the await resolves for **any** matching event from any user in any channel — which is rarely what you want. Always filter by `$authorID` unless you have a specific reason not to. ## Timeout Handling Most `$awaitFunc` implementations have a timeout (typically 60 seconds). If no matching event occurs before the timeout, execution resumes with a timeout flag set. You can check for timeout: ``` $awaitFunc[button;$authorID] $if[$awaitTimedOut==true] $sendMessage[⏰ Await timed out.] $stop $endif ``` The exact timeout flag variable depends on your Bot Creator version. Common names include `$awaitTimedOut` or `$awaitResult`. ## Important: Use with $defer Most `$awaitFunc` use cases involve interaction-based commands. Since the await can take a long time, always place `$defer` at the beginning of the command to prevent Discord's 3-second interaction timeout: ``` $defer $sendMessage[What do you want to do?] $addButton[yes;✅ Yes] $addButton[no;❌ No] $awaitFunc[button;$authorID] $sendMessage[You clicked a button!] ``` --- ### $callWorkflow[] $callWorkflow enables modular command design by allowing one workflow to invoke another as a subroutine. This promotes code reuse, separation of concerns, and cleaner organization of complex bot logic. ## How It Works 1. `$callWorkflow[name;args...]` is encountered during execution. 2. The specified workflow is located in the same bot. 3. Any arguments are passed to the called workflow (accessible via `$args`, `$argCount`, etc.). 4. The called workflow executes from start to finish. 5. If the called workflow uses `$return[value]`, that value becomes the return value of `$callWorkflow`. 6. Execution **resumes** in the calling workflow on the next line. ## Argument Passing Arguments are passed positionally, separated by semicolons: ``` $callWorkflow[myWorkflow;arg1;arg2;arg3] ``` In the called workflow, arguments are accessed exactly like command arguments: - `$args[0]` → `arg1` - `$args[1]` → `arg2` - `$argCount` → `3` ## Return Values The called workflow can return a value using `$return`: ``` $return[resultValue] ``` In the calling workflow, the return value is captured by `$callWorkflow` and can be used directly: ``` $callWorkflow[add;5;3] Result : $callWorkflow[add;5;3] ``` Or stored in a variable: ``` $varSet[total;$callWorkflow[add;5;3]] Total : $var[total] ``` ## Important Rules - **Same bot only**: workflows must exist within the same bot. Cross-bot calls are not supported. - **Workflow must exist**: calling a non-existent workflow causes a runtime error. - **Case-sensitive names**: `myWorkflow` and `myworkflow` are different workflows. - **No recursion limit** (implementation-dependent): some versions may impose recursion depth limits. Avoid infinite recursion. - **Variable scope**: variables set in the called workflow are **local** to that workflow and do not leak into the caller, unless using global variable functions like `$setVar`. ## When to Use - **Reusable logic**: extract common operations (validation, formatting, calculations) into shared workflows. - **Command routing**: dispatch to different workflows based on user input or permissions. - **Separation of concerns**: keep each workflow focused on one task. - **Testing and maintenance**: smaller, single-purpose workflows are easier to test and debug. ## When Not to Use - **Simple branching within a single command**: use `$if`/`$else` or `$jumpToAction` instead. - **One-time logic**: don't extract workflows prematurely. Only create a shared workflow when the logic is reused in 2+ places. ## Comparison with $jumpToAction | Feature | $callWorkflow | $jumpToAction | |---------|---------------|---------------| | Returns to caller | Yes | No | | Passes arguments | Yes | No | | Cross-workflow | Yes | No | | Same-workflow | Yes | Yes | | Best for | Reusable subroutines | Branches and loops | --- ### $changeCooldownTime[] $changeCooldownTime lets you dynamically modify the remaining time of an active cooldown. This is useful for penalty systems, admin overrides, or adaptive rate limiting where the cooldown duration depends on user behavior. ## How It Works 1. A cooldown must already be active (set by `$cooldown`, `$serverCooldown`, or `$globalCooldown` earlier in the same command). 2. Calling `$changeCooldownTime` replaces the **remaining** time — not the total original duration. 3. The new duration is applied immediately. ## Important Notes - **Must be called after a cooldown is set**. If no cooldown is active, calling `$changeCooldownTime` has no meaningful effect. - **Replaces the remaining time**, not the original duration. For example, if a 60s cooldown has 45s left, `$changeCooldownTime[10s]` sets it to 10s remaining (not adds 10s). - **Works with all cooldown scopes**: modifies whichever cooldown was most recently set (user, server, or global). ## Common Use Cases ### Adaptive Rate Limiting Increase the cooldown for users who trigger anti-spam rules: ``` $cooldown[30s] $if[$messageLength>500] $changeCooldownTime[5m] $sendMessage[⚠️ Long messages: cooldown extended to 5 minutes.] $endif ``` ### Admin Bypass Admins can reset their cooldown: ``` $cooldown[60s;⏳ Cooldown active.] $if[$hasPerms[$authorID;Administrator]] $changeCooldownTime[1s] $sendMessage[🔓 Cooldown bypassed (admin).] $endif ``` ## Duration Format Same format as `$cooldown`: `Xs` for seconds, `Xm` for minutes, `Xh` for hours, `Xd` for days, `Xms` for milliseconds. Combined formats like `2m30s` are also supported. --- ### $checkCondition # $checkCondition — Inline Condition Evaluation `$checkCondition` is a compile-time-optimized function that evaluates a comparison between two values and returns the string `"true"` or `"false"`. Unlike the `$if` structural token, `$checkCondition` is a standard function call that can be used anywhere a string value is expected — inside `$if` conditions, combined with `$and`/`$or`, or assigned to variables. ## Operators All six standard comparison operators are supported: | Operator | Meaning | Numeric/String | |----------|----------------------|-----------------| | `==` | Equal to | Both | | `!=` | Not equal to | Both | | `>` | Greater than | Numeric only | | `<` | Less than | Numeric only | | `>=` | Greater or equal | Numeric only | | `<=` | Less or equal | Numeric only | For equality (`==`, `!=`), both string and numeric comparisons work. For ordering operators (`>`, `<`, `>=`, `<=`), values are coerced to numbers. If coercion fails, the result is `"false"`. ## Compile-Time Evaluation When both `value1` and `value2` are literal constants (not referencing variables or functions), `$checkCondition` is evaluated **at compile time**. The result is baked directly into the compiled script, avoiding any runtime overhead. When values contain placeholders or function calls, evaluation falls back to runtime. ## Return Value `$checkCondition` always returns the literal strings `"true"` or `"false"` (lowercase). These are **string values**, not boolean primitives. When using the result in an `$if` condition, compare it explicitly with `==true`: ``` $if[$checkCondition[>;$getUserVar[gold];0]==true] ``` This explicit comparison is the BDFD convention for evaluating conditions. ## Comparison with Direct Conditions in $if You can write conditions inside `$if` directly (e.g., `$if[$getUserVar[gold]>0]`) without using `$checkCondition`. The main reasons to use `$checkCondition` are: 1. **Composability** — pass the result to `$and` / `$or` or store it in a variable. 2. **Clarity** — makes the comparison intent explicit, especially with complex expressions. 3. **Reuse** — evaluate once and reuse the result in multiple places. ## Common Pitfalls - Using a single `=` instead of `==` — BDFD requires double equals for equality. - Comparing the result with `== "true"` (with quotes) — BDFD expressions usually interpret bare `true`, not quoted `"true"`. - Expecting boolean-like truthiness — `$checkCondition` returns a **string**. Empty string checks will not work; always compare with `==true` or `==false`. --- ### $checkContains # $checkContains — Inline Substring Check `$checkContains` tests whether a specified substring exists within a larger string. It is a compile-time-optimized function that returns the string `"true"` or `"false"`. This is one of the most commonly used utility functions in BDFD for command detection, keyword filtering, and data validation. ## How It Works `$checkContains[text;search]` performs a **case-sensitive** substring search: - `$checkContains[Hello World;World]` → `"true"` - `$checkContains[Hello World;world]` → `"false"` (case mismatch) - `$checkContains[Hello World;xyz]` → `"false"` - `$checkContains[Hello;]` → `"true"` (empty string is contained in every string) ## Compile-Time Optimization When both `text` and `search` are literal constants, the check is evaluated at **compile time** and the result is baked in. This means keyword-based command routing can be extremely fast — the parser pre-computes which branch to take before the script ever runs. When either argument contains a variable reference or function call, evaluation falls back to runtime. ## Use in $if Conditions `$checkContains` is most commonly used inside `$if` conditions to route commands based on user input: ``` $if[$checkContains[$message;ping]==true] Pong! $endif ``` Always compare with `==true` or `==false` when using inside `$if`. ## Case-Insensitive Searching `$checkContains` is case-sensitive by design. To perform case-insensitive checks, convert both sides to lowercase: ``` $checkContains[$toLowercase[$message];$toLowercase[Admin]] ``` ## Common Use Cases - **Command detection**: Check if a message contains a trigger word. - **Inventory checks**: See if an item name appears in a list stored as a string. - **Filtering**: Validate that user input contains expected content. - **Multi-keyword matching**: Combine with `$or` to check for any of several keywords. ## Common Pitfalls - **Case sensitivity**: "Hello" does not contain "hello". Use `$toLowercase` if case-insensitive matching is needed. - **Partial matches**: `$checkContains[sword;word]` returns `"true"`. Use exact equality checks or delimiters if you need whole-word matching. - **Empty search string**: An empty needle always returns `"true"`. Guard against empty user input if it matters. - **Type coercion**: Both arguments are treated as strings. If you pass a number, it is converted to its string representation first. --- ### $cooldown[] / $globalCooldown[] / $serverCooldown[] The cooldown family prevents command spam by enforcing a waiting period between successive uses. BDFD provides three variants, each targeting a different scope of enforcement. ## Cooldown Variants | Function | Scope | Description | |----------|-------|-------------| | `$cooldown[duration;(msg)]` | **User** | One cooldown per user. User A on cooldown does not prevent User B from using the command. | | `$serverCooldown[duration;(msg)]` | **Guild** | One cooldown per server (guild). If any user triggers it, all users in that server must wait. | | `$globalCooldown[duration;(msg)]` | **Global** | One cooldown across all servers and all users. The entire bot is locked out until the cooldown expires. | ## Duration Format Durations use a human-readable format. Each unit is a number followed by a letter: | Unit | Letter | Example | |------|--------|---------| | Seconds | `s` | `10s` = 10 seconds | | Minutes | `m` | `5m` = 5 minutes | | Hours | `h` | `1h` = 1 hour | | Days | `d` | `2d` = 2 days | | Milliseconds | `ms` | `500ms` = 500 milliseconds | You can combine units: `2m30s` = 2 minutes and 30 seconds. ## How It Works 1. When the command runs, the function checks if a cooldown is active for the relevant scope (user/guild/global). 2. If **no cooldown is active** → a new cooldown is set for the specified duration, and execution continues normally. 3. If **a cooldown is active** → the optional `errorMessage` is sent to the channel, and execution **stops immediately** with `BotCreatorActionType.cooldown`. No further code runs. ## Error Message The second parameter is optional: - **With message**: `$cooldown[10s;⏳ Please wait 10 seconds.]` — sends the message and stops. - **Without message**: `$cooldown[10s]` — stops silently, and the user sees nothing. Always provide a clear error message for a better user experience. Use `$getCooldown` to display the remaining time dynamically. ## Placement Like `$onlyIf` and `$argsCheck`, place cooldown functions at the **top** of your command, before any side effects (database writes, API calls, etc.). This ensures the cooldown check happens before any work is done. ## Example: Full Command with Cooldown ``` $cooldown[30s;⏳ Cooldown is active. Try again in $getCooldown seconds.] $onlyIf[$message!=;❌ You must provide a message.] Processing your message: $message $sendMessage[✅ Processing complete!] ``` --- ### $defer $defer is essential for any command that may take longer than 3 seconds to execute. Discord enforces a strict 3-second timeout on interaction responses: if your bot doesn't respond within that window, the interaction fails with "This interaction failed." `$defer` tells Discord "I got your command, I'm working on it" — resetting the timeout and giving you up to 15 minutes to complete processing. ## How It Works When called, `$defer` sends a deferred response via `BotCreatorActionType.respondWithMessage` with `deferred: true`. This: 1. Acknowledges the interaction to Discord. 2. Prevents the "This interaction failed" error. 3. Gives you time to perform slow operations (API calls, database queries, file processing, etc.). 4. You can then use `$sendMessage` or embed functions to deliver the actual response. ## Critical Rules - **Must be the FIRST line** of your command. Any code before `$defer` may cause the 3-second timeout to trigger before the defer is sent. - **Only once per command**. Calling `$defer` multiple times has no additional effect. - **Use `$sendMessage` after**, not before. The actual response content is sent after your processing completes. ## Common Use Cases - Commands that make HTTP requests to slow external APIs. - Commands that process large datasets or files. - Commands with artificial delays (`$wait`). - Commands that wait for user input (`$awaitFunc`). ## Example: Without vs With $defer Without `$defer` (will fail): ``` $wait[5s] $sendMessage[Done!] ``` → Discord shows "This interaction failed" because no response was sent within 3 seconds. With `$defer` (works): ``` $defer $wait[5s] $sendMessage[Done!] ``` → The interaction is acknowledged immediately, and the message is sent when ready. ## Note `$defer` is specifically for **interaction-based** commands (slash commands, context menu commands, etc.). In message-based (prefix) commands, Discord does not enforce the same interaction timeout, so `$defer` is not needed — though calling it does no harm. --- ### $embedSuppressErrors $embedSuppressErrors is a focused suppression toggle that only affects errors related to embed construction and rendering. It prevents malformed or invalid embed configuration from producing visible error messages, while still allowing other types of errors to surface normally. ## How It Works - When called, embed error suppression is enabled for the **current command execution**. - Only errors originating from embed functions (missing fields, invalid values, formatting issues) are suppressed. - All other runtime errors continue to be displayed normally — unless `$suppressErrors` is also active. ## When to Use - **Dynamic embeds**: when embed content is built from variables or API responses that may sometimes be empty or invalid. - **Optional embed fields**: when some embed properties are conditionally set and may fail in certain code paths. - **Graceful degradation**: when you prefer embeds to silently fail rather than show error messages, perhaps because you have fallback text responses. ## Comparison with $suppressErrors | Function | Scope | |----------|-------| | `$embedSuppressErrors` | Embed errors only | | `$suppressErrors` | All runtime errors (including embed errors) | If you call `$suppressErrors`, embed errors are already suppressed — you don't need `$embedSuppressErrors` in addition. Use `$embedSuppressErrors` alone when you want to hide embed rendering issues while still seeing other errors (useful during development). ## Example: Graceful Embed Fallback ``` $embedSuppressErrors $title[$var[title]] $description[$var[body]] $footer[$var[footer]] $if[$var[body]==""] $sendMessage[⚠️ No data available for the embed.] $endif ``` If the variables are empty, the embed may fail to render but the fallback text message still appears. --- ### $eval[] $eval is a metaprogramming function that enables **dynamic code execution** in BDFD. It takes a string of BDFD code and runs it as if it were written directly in the command. This opens up powerful patterns like template rendering, code generation, and late-binding of function calls. ## How It Works 1. `$eval[bdfdCode]` is encountered during execution. 2. The `bdfdCode` string is parsed as BDFD code. 3. The parsed code is executed as a sub-script via `BotCreatorActionType.runBdfdScript`. 4. Any output produced by the sub-script is returned by `$eval`. 5. Execution continues in the parent script on the next line. ## Variable Resolution Variables inside the `$eval` string are resolved at **eval time**, not at definition time. This is the key difference between eval and direct execution: ``` $varSet[name;Alice] $eval[$sendMessage[Hello $var[name]!]] ``` In this example, `$var[name]` is resolved when `$eval` executes the code, so it correctly outputs `Hello Alice!`. ## Powerful Patterns ### Dynamic Command Dispatch Build and execute commands based on user input: ``` $varSet[command;$sendMessage[$message]] $eval[$var[command]] ``` ### Template Rendering Define reusable message templates with placeholders: ``` $varSet[template;$title[$var[title]] $description[$var[body]] $color[$var[color]]] $varSet[title;Welcome] $varSet[body;Welcome to the server!] $varSet[color;#00FF00] $eval[$var[template]] ``` ### Late-Binding Logic Defer decisions about what code to run until runtime: ``` $varSet[action;$if[$var[condition]==true $sendMessage[Condition true] $else $sendMessage[Condition false] $endif] $eval[$var[action]] ``` ## Important Warnings - **Security**: `$eval` executes arbitrary code. Never pass unsanitized user input directly to `$eval` — a malicious user could inject destructive BDFD code. - **Performance**: each `$eval` call triggers a parse-and-execute cycle. Avoid using `$eval` in tight loops or high-frequency commands. - **Error handling**: errors inside `$eval` are surfaced like any other runtime error. Use `$suppressErrors` if you expect potential failures. - **Nesting**: `$eval` can contain other `$eval` calls, but deep nesting may cause performance issues and is generally a sign of over-engineering. ## When to Use - **Template systems**: render parameterized messages and embeds. - **Plugin-like architectures**: store code snippets in variables or databases and execute them dynamically. - **Code generation**: build BDFD code programmatically based on complex runtime conditions. - **Late binding**: resolve function names or logic paths at the last possible moment. ## When Not to Use - **Simple conditionals**: use `$if`/`$else` — it's faster and more readable. - **Reusable subroutines**: use `$callWorkflow` — it's cleaner, safer, and easier to debug. - **Direct execution**: if the code is static and known at script-writing time, write it directly. `$eval` is for truly dynamic scenarios. ## Comparison with $callWorkflow | Feature | $eval | $callWorkflow | |---------|-------|---------------| | Code source | String (dynamic) | Named workflow (static) | | Arguments | Embedded in code string | Passed as parameters | | Performance | Slower (parses at runtime) | Faster (pre-parsed) | | Safety | Risk of injection | Safe (static reference) | | Flexibility | Maximum (any code) | Limited to predefined workflows | --- ### $for / $endFor + $loopIndex / $loopCount / $loopIteration # $for / $endFor — For Loop The `$for` token defines a loop that iterates over a semicolon-separated list of values or an array reference. Like `$if`, these are **structural tokens** processed at the BDFD parser level. Every `$for` must be closed with `$endFor`. ## Loop Metadata Variables Inside a `$for...$endFor` block, three special variables provide information about the current iteration: | Variable | Value | Description | |------------------|------------------------------------|--------------------------------------| | `$loopIndex` | 0, 1, 2, 3,.. | Zero-based index of the current item | | `$loopCount` | 1, 2, 3, 4,.. | One-based count of the current item | | `$loopIteration` | same as `$loopIndex` (`0, 1, 2`) | Alias for the zero-based index | These variables are only valid inside the `$for...$endFor` block. Using them outside a loop produces an empty string or may cause an error. ## Iterator Variable The first parameter (`iteratorName`) is a variable name you choose. On each iteration, it receives the current value from the list. Reference it inside the loop with `$iteratorName`: ``` $for[color;red;green;blue] Current color: $color $endFor ``` ## Values Format Values can be: - **A literal semicolon-separated list**: `$for[item;one;two;three]` - **A variable that resolves to a list**: `$for[player;$getGlobalUserVar[partyMembers]]` - The semicolons are the delimiter — avoid using semicolons inside individual values unless you escape them. ## Interaction with $stop and $skipActions - Use `$stop` inside a loop to halt **all** further execution, breaking out of the loop and the entire action sequence. - Use `$skipActions[n]` inside a loop to skip the next `n` actions (which may jump to the next iteration). ## Common Pitfalls - Forgetting `$endFor` causes a parse error — the parser treats everything after `$for` as body content. - Infinite loops are generally impossible since iteration is over a fixed list. - Nested loops are supported; each `$for` tracks its own `$loopIndex` / `$loopCount` scope. - Performance can degrade with very large lists; keep iterations reasonable (a few hundred items at most for responsive bot behavior). --- ### $getCooldown[] $getCooldown retrieves the remaining cooldown time so you can display it to users or use it in conditional logic. The return value is always in **seconds** (as a decimal string), regardless of the original duration format. ## Return Value - If a cooldown is active → returns the remaining time in seconds (e.g., `"45"`, `"2.5"`, `"0.1"`). - If no cooldown is active → returns `"0"`. - The value is always a string but can be used in numeric comparisons. ## Type Parameter The optional `type` parameter lets you query a specific cooldown scope: | Type value | Queries | |------------|---------| | `"user"` | Per-user cooldown (`$cooldown`) | | `"server"` | Per-guild cooldown (`$serverCooldown`) | | `"global"` | Global cooldown (`$globalCooldown`) | If no type is specified, `$getCooldown` returns the remaining time of the **cooldown that was most recently set** in the current command — or `"0"` if none was set. ## Usage in Error Messages The most common use of `$getCooldown` is inside the cooldown error message itself. However, note that **when the cooldown triggers, execution stops before reaching the message**. The value of `$getCooldown` is resolved at the moment `$cooldown` evaluates, so it works: ``` $cooldown[30s;⏳ Try again in $getCooldown seconds.] ``` When the cooldown is active, `$getCooldown` returns the remaining time and embeds it in the error message. ## Conditional Logic You can use `$getCooldown` in `$if` conditions to adjust behavior based on remaining time. For example, offering a reduced-cooldown path for premium users or applying progressive penalties. --- ### $i # $i (alias of $loopIndex) The function `$i` is a **shortened alias** of `$loopIndex`. It returns the current iteration number in progress within a loop. ## Syntax ``` $i ``` ## Parameters None. ## Return Value - **Type**: Number (string) - The current index (1-based for `$forEach`, 0-based for `$while`/`$repeat`). ## Behavior - In `$forEach`: starts at 1. - In `$while` and `$repeat`: starts at 0 or depending on your counter. - Incremented automatically at each iteration. ## Examples ### ForEach with index ```bdfd $forEach[user;$mentioned] $sendMessage[#$i: <@$loopValue>] $endForEach ``` ### Numbered list ```bdfd $title[📋 Member List] $description[ $forEach[member;$membersCount] $if[$i<=10] **#$i** — $username[$member[$i]] $endif $endForEach ] $sendMessage[] ``` ### While loop with index ```bdfd $let[count;0] $while[$var[count]<5] $sendMessage[Iteration #$i] $let[count;$c[$var[count]+1]] $endWhile ``` ## Notes - `$i` is identical to `$loopIndex` — just shorter and faster to type. - Frequently used in loops for numbering. - In `$forEach`, `$i` starts at 1, not 0. --- ### $if / $elseIf / $else / $endif # $if / $elseIf / $else / $endif — Conditional Branching The `$if` family of tokens provides conditional branching in BDFD scripts. These are **structural tokens** handled at the BDFD parser level, not dispatched as regular function calls. They allow you to execute different blocks of commands based on runtime conditions. ## How It Works When the parser encounters a `$if[condition]` token, it evaluates the condition. If the condition is **true**, it executes the block immediately following `$if`, up to the next `$elseIf`, `$else`, or `$endif`. If the condition is **false**, it skips forward: 1. It checks any subsequent `$elseIf[condition]` blocks in order. 2. If no condition matches, the optional `$else` block is executed. 3. `$endif` is **always required** to close the if-block, even if only `$if` and `$else` are used. ## Condition Syntax Conditions are BDFD expressions. They are not traditional programming language booleans — they are evaluated at runtime by the BDFD expression engine. ### Supported Comparison Operators | Operator | Meaning | Example | |----------|----------------------|---------------------------------| | `==` | Equal to | `$getUserVar[score]==100` | | `!=` | Not equal to | `$getUserVar[name]!=Guest` | | `>` | Greater than | `$getUserVar[coins]>0` | | `<` | Less than | `$getUserVar[hp]<25` | | `>=` | Greater or equal | `$getUserVar[level]>=10` | | `<=` | Less or equal | `$getUserVar[wins]<=3` | ### Logical Operators Combine multiple conditions with `$and` and `$or`: ``` $if[$and[$getUserVar[gold]>=100;$getUserVar[rank]>=5]==true] $if[$or[$checkContains[$message;ping];$checkContains[$message;pong]]==true] ``` ### Inline Check Functions Use `$checkCondition` or `$checkContains` inside an `$if`: ``` $if[$checkCondition[>=;$getUserVar[age];18]==true] $if[$checkContains[$message;admin]==true] ``` ## Structural Rules - **`$endif` is mandatory** — every `$if` must have exactly one `$endif`. - **`$else` is optional** — at most one per `$if` block. - **`$elseIf` is optional** — you can chain as many as you need. - **Nesting is supported** — you can place `$if...$endif` inside another `$if` block. - **Conditions are evaluated sequentially** — the first matching branch wins; subsequent branches are skipped. ## Common Pitfalls - Forgetting `$endif` causes a parse error. - Using `=` instead of `==` for equality — BDFD requires double equals. - Comparing strings with numeric operators — make sure the value type matches the comparison intent. --- ### $jumpToAction[] $jumpToAction enables non-linear execution flow within a workflow. Instead of executing actions sequentially from top to bottom, you can jump to any action identified by a target key, creating loops, branches, and reusable action blocks. ## How It Works 1. Each action in a workflow can be assigned a **target key** (identifier). 2. When `$jumpToAction[targetKey]` is called, execution **transfers** to the action with that key. 3. Actions after the `$jumpToAction` call are **not executed** — execution resumes at the target action. 4. The jump is one-way: there is no automatic return. To return, you must use another `$jumpToAction` call. ## Target Keys Target keys are defined on actions in the Bot Creator workflow editor. The exact UI for assigning keys depends on the Bot Creator version. Common conventions: - Use descriptive names: `validationPassed`, `errorHandler`, `mainLoop`. - Keys are case-sensitive. - Jumping to a non-existent key will cause a runtime error. ## Common Patterns ### Conditional Branching ``` $if[$condition] $jumpToAction[branchA] $endif $jumpToAction[branchB] ``` ### Loops ``` $varSet[i;0] [loop] $varSet[i;$math[$var[i]+1]] $if[$var[i]<10] $jumpToAction[loop] $endif ``` ### Error Handling / Early Exit ``` $onlyIf[$message!=;Error] $jumpToAction[processing] $stop [processing] Processing: $message ``` ## Important Notes - **No automatic return**: unlike a function call, `$jumpToAction` does not return to the caller. Use `$callWorkflow` if you need call/return semantics. - **Same workflow only**: jumps are limited to actions within the same workflow. For cross-workflow jumps, use `$callWorkflow`. - **Action placement**: target actions must be defined in the workflow. The exact placement (before or after the jump) depends on the Bot Creator workflow editor. ## Comparison with $callWorkflow | Feature | $jumpToAction | $callWorkflow | |---------|---------------|---------------| | Returns to caller | No | Yes (via `$return`) | | Can pass arguments | No | Yes | | Cross-workflow | No | Yes | | Same-workflow | Yes | Yes | | Use case | Branches, loops | Reusable subroutines | --- ### $onlyIf[] $onlyIf is the fundamental guard function in BDFD. It acts as a gatekeeper: if the condition passes, the command continues; if it fails, the command stops dead. This is the building block for permissions checks, input validation, and any scenario where you need to abort early. ## How It Works 1. The `condition` is evaluated as a boolean expression. 2. If the condition is **true** → execution continues to the next line. 3. If the condition is **false** → the optional `errorMessage` is sent (if provided), then execution **stops immediately** via `BotCreatorActionType.stop`. No further code in the command runs. ## Two-Argument Form ``` $onlyIf[condition;errorMessage] ``` When `errorMessage` is provided and the condition fails, the message is sent to the channel before stopping. This is the recommended form — it gives feedback to the user about why the command failed. ## Single-Argument Form ``` $onlyIf[condition] ``` When no error message is provided and the condition fails, execution stops silently. The user receives no response. Use this when you want to silently reject invalid input without cluttering the chat. ## Common Patterns ### Permission Guards ```bdfd $onlyIf[$hasPerms[$authorID;BanMembers];❌ BanMembers permission required.] $onlyIf[$authorID!=$mentioned[1];❌ You cannot ban yourself.] ``` ### Input Validation ```bdfd $onlyIf[$isNumber[$message]==true;❌ Please enter a number.] $onlyIf[$message>=1;❌ The number must be >= 1.] $onlyIf[$message<=100;❌ The number must be <= 100.] ``` ### Channel/Role Restrictions ```bdfd $onlyIf[$channelID==123456789012345678;❌ This command can only be used in <#123456789012345678>.] ``` ## Comparison with $if / $stop Without `$onlyIf`: ``` $if[$hasPerms[$authorID;Administrator]==false] ❌ Permission denied. $stop $endif ``` With `$onlyIf` (equivalent, cleaner): ``` $onlyIf[$hasPerms[$authorID;Administrator];❌ Permission denied.] ``` `$onlyIf` is the idiomatic way to write guards — it is shorter, more readable, and signals intent clearly: "only continue if this condition holds." --- ### $onlyIfMessageContains[] $onlyIfMessageContains is a convenience guard that checks whether the user's entire message contains a specific substring. It is simpler and more focused than `$onlyIf` — you don't need to write a condition expression; just provide the text you're looking for. ## How It Works 1. The function checks if `text` appears anywhere within `$message` (the full user message). 2. If the text **is found** → execution continues. 3. If the text is **not found** → execution stops silently (no message is sent). The matching is **case-sensitive** and works like a simple substring search. For example, `$onlyIfMessageContains[hello]` will match `hello world` but not `Hello World` or `hell`. ## When to Use - **Quick keyword gates**: require that the message mentions a specific word before processing. - **Format validation**: ensure the message contains expected delimiters or markers (like `@` for mentions, `#` for channels, etc.). - **Category filtering**: route commands based on message content tags. ## When Not to Use - For complex conditions → use `$onlyIf` instead. - For argument count checks → use `$argsCheck`. - When you need to send an error message on failure → use `$onlyIf[$messageContains[$message;text]==true;error]` instead. ## Comparison with Manual Check Without `$onlyIfMessageContains`: ``` $if[$messageContains[$message;!admin]==false] $stop $endif ``` With `$onlyIfMessageContains` (equivalent, cleaner): ``` $onlyIfMessageContains[!admin] ``` --- ### $or # $or — Logical OR `$or` performs a logical OR operation across a variable number of conditions. It returns the string `"true"` if **at least one** provided condition evaluates to `"true"`. Only when all conditions evaluate to `"false"` does it return `"false"`. ## Syntax ``` $or[condition1;condition2;...;conditionN] ``` `$or` accepts an **unlimitd number** of arguments (minimum 2). Each argument is a BDFD expression expected to resolve to either `"true"` or `"false"`. ## Evaluation All condition arguments are resolved at runtime. BDFD's `$or` does **not** guarantee short-circuit evaluation — even if the first condition returns `"true"`, subsequent conditions may still be evaluated. Avoid putting side-effect-producing functions inside `$or` unless you intend for them to always execute. ## Truth Table | Condition 1 | Condition 2 | Result | |-------------|-------------|----------| | `"true"` | `"true"` | `"true"` | | `"true"` | `"false"` | `"true"` | | `"false"` | `"true"` | `"true"` | | `"false"` | `"false"` | `"false"`| The same logic extends to 3 or more arguments — any `"true"` makes the result `"true"`. ## Common Patterns ### Multi-Keyword Matching The most frequent use of `$or` is checking if a message contains any of several trigger words: ``` $or[$checkContains[$message;ping];$checkContains[$message;pong];$checkContains[$message;echo]] ``` ### Multiple Role Checks Grant access to any user with an authorized role: ``` $or[$checkCondition[==;$getUserVar[role];admin];$checkCondition[==;$getUserVar[role];mod]] ``` ### Fallback with Empty Checks Use `$or` to detect empty or unset values and provide defaults: ``` $if[$or[$getUserVar[name]==;$getUserVar[name]==none]==true] $sendMessage[Please set your name first!] $endif ``` ## Nesting with $and `$or` and `$and` can be nested to create arbitrarily complex boolean expressions: ``` $and[$or[condA;condB];$or[condC;condD]] ``` This evaluates to `"true"` when at least one condition from each group is true — (A OR B) AND (C OR D). ## Use Cases - **Keyword detection**: Trigger on any of multiple words or phrases. - **Role-based access control**: Allow multiple roles or permissions. - **Fallback logic**: Proceed when any of several alternative conditions is satisfied. - **Multi-condition tolerance**: Require at least one condition to pass out of many. ## Common Pitfalls - **Assuming short-circuit**: All conditions are evaluated. Do not place commands with side effects inside `$or`. - **Non-boolean results**: Ensure each condition resolves to `"true"` or `"false"`. Non-boolean results produce undefined behavior. - **Single condition**: Use the condition directly. `$or` requires at least 2 arguments. - **Forgetting `==true` in $if**: Always write `$if[$or[...]==true]`. - **Confusing AND/OR logic**: `$or` returns `"true"` when ANY condition is true. For "ALL must be true", use `$and`. --- ### $skipActions # $skipActions — Skip N Actions `$skipActions[count]` causes the execution engine to bypass the next `count` actions. Unlike `$stop` which halts everything, `$skipActions` only jumps forward a set number of steps and then resumes normal execution. Think of it as a "fast-forward" button for your action sequence. ## How It Works When the runtime encounters `$skipActions[count]`: 1. The `count` parameter is resolved (it can be a literal, variable, or expression). 2. The execution pointer advances by `count` positions in the current action list. 3. Any actions between `$skipActions` and the target are completely bypassed. 4. Execution resumes normally after the skipped actions. Actions are counted within the **current execution block**. Nested blocks (inside `$if`, `$for`, or `$try`) have their own action indexing, and `$skipActions` only affects the immediate enclosing block. ## Count Resolution The `count` argument is resolved at runtime as a string and then coerced to an integer: - `$skipActions[3]` — skips 3 actions. - `$skipActions[$getUserVar[n]]` — skips the number of actions stored in variable `n`. - `$skipActions[$sum[$getUserVar[a];$getUserVar[b]]]` — skips a computed amount. If `count` resolves to a non-numeric value or an integer less than 0, behavior is undefined — typically no actions are skipped or an error is raised. ## Use Cases - **Role-based access control**: Skip admin-only actions for regular users. - **Feature flags**: Skip experimental feature blocks when a flag is disabled. - **Error recovery**: Skip a block of actions that depend on a failed prerequisite. - **Loop control**: Skip processing for certain iterations without breaking the loop. ## $skipActions vs $stop | $skipActions[n] | $stop | |---------------------------------------------------|----------------------------| | Skips exactly `n` actions, then resumes | Halts all execution | | Reversible effect (execution continues) | Permanent halt | | Count can be dynamic | No arguments | | Only affects the current block's action list | Affects the entire pipeline | ## Interaction with Structural Blocks - Inside `$if`: `$skipActions` only affects actions within the current branch. It does not skip past `$elseIf`, `$else`, or `$endif`. - Inside `$for`: Actions skipped count toward the current iteration only. The loop still proceeds to the next iteration. - Inside `$try`: Skipping in the `$try` body may cause the `$catch` to be skipped if all remaining actions are bypassed and no error was raised. ## Common Pitfalls - **Skipping past block terminators**: If you `$skipActions` past an `$endif` or `$endFor`, you may get a parse or runtime error. Always ensure your skip count is within the current block's boundaries. - **Over-skipping**: Skipping more actions than remain the block causes execution to move to the next sibling block — behavior that may be unexpected. - **Readability**: Heavy use of `$skipActions` can make action sequences hard to follow. Prefer `$if` blocks for conditional execution when possible. --- ### $stop # $stop — Hard Stop Execution `$stop` is the emergency brake of BDFD scripting. It immediately and unconditionally halts all further action processing. No commands after `$stop` are executed — the action sequence terminates at that exact point. ## Behavior When `$stop` is encountered: 1. The current action completees up to and including `$stop`. 2. All remaining actions in the current block are **skipped**. 3. If inside a loop (`$for`), the loop exits immediately — no further iterations. 4. If inside an `$if`, the enclosing `$endif` is not reached. 5. If inside a `$try`, execution halts **before** the `$catch` block — `$stop` overrides error handling. `$stop` is dispatched as a `BotCreatorActionType.stop` action, which tells the BDFD runtime engine to terminate the execution pipeline. ## No Arguments `$stop` takes no arguments. The syntax is simply: ``` $stop ``` Any arguments provided are ignored. ## Use Cases - **Early exit on invalid state**: Stop immediately if required data is missing or corrupted. - **Content moderation**: Halt execution when forbidden content is detected. - **Guard clauses**: Check preconditions at the start of an action and stop if they fail. - **Loop breaking**: Exit a `$for` loop prematurely based on a condition. - **Rate limiting**: Stop processing if a user has exceeded their quota. ## $stop vs $skipActions | Feature | $stop | $skipActions[n] | |-----------------|---------------------------------|------------------------------| | Scope | Halts **all** remaining actions | Skips only `n` next actions | | Resumable | No | Yes, after skipping `n` | | In loops | Exits the loop completeely | Skips actions within the loop | Use `$stop` for terminal halts; use `$skipActions` for non-terminal jumps. ## Interaction with $try / $catch If `$stop` is called inside a `$try` block, the `$catch` block is **not** executed. `$stop` bypasses error handling entirely. This is intentional — if you want to catch errors and then stop, call `$stop` inside the `$catch` block instead. ## Common Pitfalls - Placing important cleanup or logging code after `$stop` — it will never execute. - Using `$stop` inside a `$try` and expecting the `$catch` to still run. - Confusing `$stop` with `$skipActions[1]` — `$stop` kills the entire action sequence, not just the next command. --- ### $suppressErrorLogging $suppressErrorLogging disables the internal logging of runtime errors for the current command. Unlike `$suppressErrors` (which controls what the user sees) or `$embedSuppressErrors` (which controls embed-specific errors), this function acts on the **server-side** — it prevents errors from being recorded in the bot's internal log system. ## How It Works - When called, error logging is suppressed for the **current command execution**. - If a runtime error occurs after this call, it will **not** be recorded in the bot's error logs. - The user may still see the error message (unless `$suppressErrors` is also called). - The suppression is scoped to the current command only. ## When to Use - **Sensitive commands**: commands that may generate errors containing private data that should not persist in logs. - **High-frequency commands**: commands called very often where logging every error would flood the log system. - **Expected failures**: when you're intentionally trying operations that may fail, and you don't want those failures cluttering your error logs. ## When Not to Use - **During debugging**: error logs are essential for diagnosing problems. Only suppress logging when you're confident the errors are expected and non-actionable. - **As a default**: most commands should keep logging enabled so you can monitor the health of your bot. ## Relationship with Other Suppression Functions | Function | User-visible errors | Embed errors | Internal logging | |----------|--------------------|--------------|------------------| | `$suppressErrors` | Suppressed | Suppressed | Unchanged | | `$embedSuppressErrors` | Unchanged | Suppressed | Unchanged | | `$suppressErrorLogging` | Unchanged | Unchanged | Suppressed | All three can be combined independently to achieve the exact level of error visibility you need. --- ### $suppressErrors $suppressErrors is a toggle that prevents runtime errors from being sent to the user. When active, if your command encounters an error (invalid function call, missing variable, failed HTTP request, etc.), the error message is silently swallowed instead of being displayed in the channel. ## How It Works - When called, error suppression is enabled for the **current command execution**. - Any errors that occur after `$suppressErrors` is called will not produce visible error output. - The suppression applies to **all** types of runtime errors (parsing errors, execution errors, type errors, etc.). ## When to Use - **Unstable external APIs**: when calling endpoints that may fail intermittently, you may not want to spam the channel with error messages. - **User-facing commands**: keep the chat clean by handling errors gracefully with your own fallback logic. - **Variable existence checks**: when you access variables that may or may not exist, suppress the default error and use `$varExists` to check manually. ## When Not to Use - **During development**: error messages are invaluable for debugging. Enable suppression only in production commands. - **As a substitute for proper error handling**: prefer `$onlyIf` guards and proper validation. `$suppressErrors` should be a last resort. ## Scope The suppression applies to the **current command only**. It does not affect other commands, other workflows, or subsequent command invocations. Each command starts with error suppression off. ## Relationship with Other Suppression Functions | Function | What it suppresses | |----------|-------------------| | `$suppressErrors` | All runtime error messages | | `$embedSuppressErrors` | Errors specific to embed rendering | | `$suppressErrorLogging` | Error logging (internal only, not user-visible) | --- ### $try / $catch / $endTry + $error # $try / $catch / $endTry — Error Handling The `$try` family of tokens provides structured error handling in BDFD scripts. Instead of letting a runtime error crash the entire action sequence, you can wrap risky code in a `$try` block and handle failures gracefully inside `$catch`. These are **structural tokens** processed at the parser level. ## Block Structure ``` $try .. risky commands... $catch .. recovery commands... $endTry ``` 1. The parser executes the body between `$try` and `$catch`. 2. If **no error** occurs, the `$catch` block is skipped entirely and execution resumes after `$endTry`. 3. If **any error** occurs inside the `$try` body, execution immediately jumps to `$catch`. The error is consumed — it will not propagate outside the try-catch. **Important:** `$endTry` is always required, even if no `$catch` is provided. ## The $error Variable Inside the `$catch` block, the `$error` variable provides access to the caught error's metadata: | Usage | Returns | |----------------------|-----------------------------------------------| | `$error` | The error message as a string | | `$error[message]` | Same as above — the error message | | `$error[command]` | The name of the command that caused the error | | `$error[source]` | The source line or context of the error | | `$error[row]` | The row number where the error occurred | | `$error[column]` | The column number where the error occurred | Outside the `$catch` block, `$error` is empty or undefined. It only has meaning within the catch scope. ## Nesting `$try` blocks can be nested. Each `$catch` only catches errors from its own `$try` body. An error caught in an inner `$catch` does not propagate to an outer `$catch`. ## Interaction with $stop If `$stop` is called inside a `$try` block, it halts execution **before** the `$catch` is reached — so the error handler does not run. This is by design: `$stop` is an unconditional halt. ## Use Cases - **API calls**: Wrap `$httpGet` / `$httpPost` calls to handle network failures. - **User input parsing**: Catch errors when parsing or coercing user-supplied values. - **Fallback logic**: Try a primary operation, fall back to a secondary on failure. - **Logging**: Use `$catch` to log errors with `$eprint` or save them to a variable for later inspection. ## Common Pitfalls - Forgetting `$endTry` produces a parse error. - Placing `$endTry` before `$catch` — the parser expects `$catch` before `$endTry`. - Assuming `$error` is available outside `$catch` — it is scoped to the catch block only. - Catching an error but doing nothing with it — at minimum, log it to help with debugging. --- ### $wait[] $wait is a simple but essential function for introducing timed delays in command execution. It suspends the command for the exact duration specified, then resumes on the next line. ## How It Works 1. `$wait[duration]` is encountered during execution. 2. The command **pauses** for the specified duration. 3. After the delay, execution continues with the next line. All variables, scopes, and states are preserved during the wait. The delay is applied server-side and does not consume resources on the client. ## Duration Format | Format | Example | Meaning | |--------|---------|---------| | Seconds | `1s`, `10s`, `2s` | Exactly N seconds | | Milliseconds | `500ms`, `100ms`, `2000ms` | Exactly N milliseconds | | Minutes | `1m`, `2m` | Exactly N minutes | | Default (no suffix) | `3` | Treated as "3s" (seconds) | The default unit when no suffix is provided is seconds. `$wait[3]` is equivalent to `$wait[3s]`. ## Important: Use with $defer If your command uses `$wait` and the total execution time may exceed Discord's 3-second interaction timeout, you **must** call `$defer` before any `$wait`: ``` $defer $wait[5s] $sendMessage[Done after 5 seconds.] ``` Without `$defer`, Discord will show "This interaction failed" because no response was sent within the 3-second window. ## When to Use - **Sequential messaging**: Send multiple messages with delays between them. - **Countdowns**: Create a countdown effect with multiple `$wait` and `$sendMessage` calls. - **Rate limiting simulation**: Slow down automated processes. - **UI pacing**: Make bot responses feel more natural by introducing human-like delays. ## When Not to Use - **Waiting for user input**: Use `$awaitFunc` instead — it resumes on an actual event rather than a fixed timer. - **Cooldown enforcement**: Use `$cooldown` instead — it persists across command invocations. - **Long delays (>15 minutes)**: Discord interaction tokens expire, so very long waits may fail. Use alternative approaches like scheduled tasks or workflows. --- ### $workflowResponse # $workflowResponse The `$workflowResponse` function returns the **last response** produced by a BDFD workflow. ## Syntax ``` $workflowResponse ``` ## Parameters None. ## Return Value - **Type**: String - The value returned by the last workflow executed. - Empty string if no workflow has been called yet. ## Behavior - Stores the response of the last `$workflow` called. - The value persists until the end of the command or until the next workflow is called. - Allows chaining of workflows. ## Examples ### Call and retrieve ```bdfd $workflow[calculSalaire;$authorID] $sendMessage[Your calculated salary: $workflowResponse €] ``` ### Chain of workflows ```bdfd $workflow[verifyUser;$authorID] $if[$workflowResponse==ok] $workflow[processOrder;$input] $sendMessage[Order processed: $workflowResponse] $else $sendMessage[Verification failed.] $endif ``` ### Log of workflow ```bdfd $workflow[dailyReward;$authorID] $log[Daily reward for $username: $workflowResponse] $sendMessage[$workflowResponse] ``` ### Conditional workflow ```bdfd $workflow[checkBan;$mentioned[1]] $if[$workflowResponse!="clean"] $sendMessage[This user is banned: $workflowResponse] $else $sendMessage[No ban found.] $endif ``` ## Notes - `$workflowResponse` is overwritten with each new call to `$workflow`. - Store the value in a temporary variable if you need to reuse it: `$let[rep;$workflowResponse]`. - The response depends entirely on what the workflow returns via `$sendMessage` or `$return`. --- ## Cooldown ### Globalcooldown # $globalCooldown Enforces a global cooldown on command execution across all servers and all users. When triggered, the entire bot is locked out of the command until the cooldown expires. ## Syntax ``` $globalCooldown[duration;(errorMessage)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `duration` | The cooldown duration | Yes | | `errorMessage` | Custom error message shown when the cooldown is active | No | ## Duration Format | Unit | Letter | Example | |------|--------|---------| | Seconds | `s` | `10s` = 10 seconds | | Minutes | `m` | `5m` = 5 minutes | | Hours | `h` | `1h` = 1 hour | | Days | `d` | `2d` = 2 days | ## Description `$globalCooldown` locks the command for **all users across all servers** when any user triggers it. This is the most restrictive cooldown scope. **Scope comparison:** | Function | Scope | Behavior | |----------|-------|----------| | `$cooldown[duration;(msg)]` | **User** | One cooldown per user | | `$serverCooldown[duration;(msg)]` | **Guild** | One cooldown per server | | `$globalCooldown[duration;(msg)]` | **Global** | One cooldown for the entire bot | ## How It Works 1. When the command runs, `$globalCooldown` checks if a global cooldown is active. 2. If **no cooldown is active** → a new global cooldown is set and execution continues. 3. If **a cooldown is active** → the optional `errorMessage` is sent, and execution **stops immediately**. No further code runs. ## Place at the Top Always place `$globalCooldown` at the **top** of your command, before any side effects (database writes, API calls, etc.). This ensures the cooldown check happens before any work is done. ## Examples ### Basic Global Cooldown ``` $globalCooldown[1h] $sendMessage[This command can only be used once per hour globally.] ``` ### With Custom Error Message ``` $globalCooldown[30m;⏳ This command is on global cooldown. Please wait.] $sendMessage[Command executed!] ``` ### Displaying Remaining Time ``` $globalCooldown[10m;⏳ Global cooldown! Try again in $getCooldown[global] seconds.] $sendMessage[Processing...] ``` ### Combined with Other Checks ``` $globalCooldown[30s;⏳ Global cooldown active!] $cooldown[10s;⏳ You're on cooldown!] $onlyIf[$message!=;❌ Please provide a message.] $sendMessage[Message received: $message] ``` ## Notes - The global cooldown applies to **all servers** — use sparingly for commands that affect the entire bot. - For per-server restrictions, use `$serverCooldown` instead. - For per-user restrictions, use `$cooldown` instead. - Use `$getCooldown[global]` to retrieve the remaining global cooldown time in seconds. --- ### Servercooldown # $serverCooldown Enforces a per-server (guild) cooldown on command execution. When triggered, all users in that server must wait until the cooldown expires before anyone can run the command again in that server. ## Syntax ``` $serverCooldown[duration;(errorMessage)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `duration` | The cooldown duration | Yes | | `errorMessage` | Custom error message shown when the cooldown is active | No | ## Duration Format | Unit | Letter | Example | |------|--------|---------| | Seconds | `s` | `10s` = 10 seconds | | Minutes | `m` | `5m` = 5 minutes | | Hours | `h` | `1h` = 1 hour | | Days | `d` | `2d` = 2 days | ## Description `$serverCooldown` locks the command for all users **within a single server (guild)** when any user in that server triggers it. Users in other servers are not affected. **Scope comparison:** | Function | Scope | Behavior | |----------|-------|----------| | `$cooldown[duration;(msg)]` | **User** | One cooldown per user | | `$serverCooldown[duration;(msg)]` | **Guild** | One cooldown per server | | `$globalCooldown[duration;(msg)]` | **Global** | One cooldown for the entire bot | ## How It Works 1. When the command runs, `$serverCooldown` checks if a cooldown is active for the current server. 2. If **no cooldown is active** → a new server cooldown is set and execution continues. 3. If **a cooldown is active** → the optional `errorMessage` is sent, and execution **stops immediately**. No further code runs. ## Place at the Top Always place `$serverCooldown` at the **top** of your command, before any side effects (database writes, API calls, etc.). This ensures the cooldown check happens before any work is done. ## Examples ### Basic Server Cooldown ``` $serverCooldown[10s] $sendMessage[Command executed!] ``` ### With Custom Error Message ``` $serverCooldown[5m;⏳ This command is on cooldown for this server. Please wait!] $sendMessage[Processing...] ``` ### Displaying Remaining Time ``` $serverCooldown[1m;⏳ Server cooldown! Try again in $getCooldown[server] seconds.] $sendMessage[Done!] ``` ### Server-Wide Daily Command ``` $serverCooldown[24h;⏳ This command can only be used once per day in this server!] $sendMessage[Daily reward claimed for this server!] ``` ### Combined with User Cooldown ``` $cooldown[30s;⏳ You must wait before using this command again.] $serverCooldown[10s;⏳ This command is on server cooldown.] $sendMessage[Action complete!] ``` ## Notes - Cooldown is **per-server** (guild) — different servers have independent cooldowns. - For bot-wide restrictions across all servers, use `$globalCooldown` instead. - For per-user restrictions, use `$cooldown` instead. - Use `$getCooldown[server]` to retrieve the remaining server cooldown time in seconds. --- ## Date & Time ### $date[] # $date[] The `$date[]` function returns the current date. > **Important:** This function uses the special identifier `((date))` which is resolved at **runtime**, i.e., at each execution of the command. The value can vary from one execution to another. ## Syntax ``` $date ``` > **Note:** This function does not take any parameters. ## Return value The current date, resolved at each execution. ## Difference from specific functions `$date[]` returns the full date. To get specific components of the date, use: | Function | Returns | |----------|----------| | `$day` | The day of the month (1-31) | | `$month` | The month (1-12) | | `$year` | The year (e.g., 2026) | ## Examples ### Simple date ```bdfd The current date is $date ``` ### Date in an embed ```bdfd $title[📅 Information] $description[Current date: $date] $footer[Server time] ``` ## Notes - The date is based on the system clock of the server running the bot. --- ### $day[] # $day[] The `$day[]` function returns the current day of the month (1 to 31). > **Important:** This function uses the special identifier `((day))` which is resolved at **runtime**. ## Syntax ``` $day ``` > **Note:** This function does not take any parameters. ## Return value A number between 1 and 31 representing the current day of the month. ## Examples ### Simple day ```bdfd Day: $day ``` ### Conditional message ```bdfd $if[$day==1] 🎉 This is the first of the month! $else 📅 Today is day $day of the month. $endif ``` ### Day in an embed ```bdfd $title[📅 Today] $description[Today is day **$day** of the month] ``` ## Notes - The value depends on the system date of the server running the bot. - Returns `1` for the first day of the month, and up to `31` for the last day. --- ### $getTimestamp[] # $getTimestamp[] The function `$getTimestamp[]` returns the current Unix timestamp in seconds. The Unix timestamp represents the number of seconds elapsed since January 1, 1970, at 00:00:00 UTC (epoch). > **Important:** This function uses the special identifier `((getTimestamp))` which is resolved at **runtime**. ## Syntax ``` $getTimestamp ``` > **Note:** This function does not take any parameters. ## Return Value An integer representing the current Unix timestamp in seconds. ## Examples ### Simple timestamp ```bdfd Current timestamp: $getTimestamp ``` ### Duration calculation ```bdfd $let[now;$getTimestamp] $let[event;1718697600] Time remaining: $sub[$get[event];$get[now]] seconds ``` ### Store a timestamp ```bdfd $setUserVar[lastCommand;$getTimestamp] ``` ## Notes - The timestamp is in **seconds** (not milliseconds). - Useful for duration calculations, cooldowns, or storing timestamps. --- ### $hour[] # $hour[] The `$hour` function returns the current hour in 24-hour format (from 0 to 23). > **Important:** This function uses the special identifier `((hour))` which is resolved at **runtime**. ## Syntax ``` $hour ``` > **Note:** This function takes no parameters. ## Return Value A number between 0 and 23 representing the current hour. | Value | Meaning | |--------|---------------| | 0 | Midnight | | 12 | Noon | | 23 | 11 PM | ## Examples ### Simple time ```bdfd It is $hour o'clock. ``` ### Message according to the time of day ```bdfd $if[$hour>=6&&$hour<12] ☀️ Good morning! $elseif[$hour>=12&&$hour<18] 🌤️ Good afternoon! $elseif[$hour>=18&&$hour<22] 🌅 Good evening! $else 🌙 Good night! $endif ``` ## Notes - 24-hour format: `0` = midnight, `12` = noon, `23` = 11 PM. - The hour depends on the time zone of the server hosting the bot. --- ### $minute # $minute The function `$minute` returns the current minute (from 0 to 59). > **Important:** This function uses the special identifier `((minute))` which is resolved at **runtime**. ## Syntax ``` $minute ``` > **Note:** This function takes no parameters. ## Return Value A number between 0 and 59 representing the current minute. ## Examples ### Simple Minute ```bdfd Current minute: $minute ``` ### Combined hours and minutes ```bdfd The time is $hour:$minute ``` ### Formatting with a leading zero ```bdfd $if[$minute<10] The time is $hour:0$minute $else The time is $hour:$minute $endif ``` ## Notes - Use `$time` to obtain the full time in the `HH:MM:SS` format. - Combined with `$hour` and `$second`, this function allows you to create custom clocks. --- ### $month # $month The function `$month` returns the number of the current month (from 1 to 12). > **Important:** This function uses the special identifier `((month))` which is resolved at **runtime**. ## Syntax ``` $month ``` > **Note:** This function takes no parameters. ## Return Value A number between 1 and 12 representing the current month: | Value | Month | |--------|------| | 1 | January | | 2 | February | | 3 | March | | 4 | April | | 5 | May | | 6 | June | | 7 | July | | 8 | August | | 9 | September | | 10 | October | | 11 | November | | 12 | December | ## Examples ### Simple Month ```bdfd Current month: $month ``` ### Seasonal Message ```bdfd $if[$month>=6&&$month<=8] ☀️ It is summer! $elseif[$month==12||$month<=2] ❄️ It is winter! $endif ``` ## Notes - The value depends on the system date of the server running the bot. --- ### $second[] # $second[] The function `$second[]` returns the current second (from 0 to 59). > **Important:** This function uses the special identifier `((second))` which is resolved at **runtime**. ## Syntax ``` $second ``` > **Note:** This function does not take any parameters. ## Return Value A number between 0 and 59 representing the current second. ## Examples ### Simple second ```bdfd Current second: $second ``` ### Custom full time ```bdfd It is precisely $hour:$minute and $second seconds. ``` ### Clock in an embed ```bdfd $title[🕐 Clock] $description[$hour:$minute:$second] $footer[Updated at each execution] ``` ## Notes - Use `$time[]` to get the formatted time `HH:MM:SS` directly. --- ### $time[] # $time[] The function `$time[]` returns the current time in `HH:MM:SS` (hours:minutes:seconds) format. > **Important:** This function uses the special identifier `((time))` which is resolved at **runtime**, meaning at each execution of the command. ## Syntax ``` $time ``` > **Note:** This function takes no parameters. ## Return Value A string in the format `HH:MM:SS` (e.g., `14:30:05`). ## Examples ### Simple Time ```bdfd It is $time. ``` ### Embed with Time ```bdfd $title[🕐 Server Clock] $description[Current time: **$time**] $footer[24h Format] ``` ### Complete Timestamp ```bdfd 📅 $date at $time ``` ## Notes - `$time[]` is the equivalent of `$hour:$minute:$second` combined into a single function. - The time is based on the timezone of the server running the bot. - For a Unix timestamp, use `$getTimestamp[]`. --- ### $year[] # $year[] The `$year` function returns the current year. > **Important:** This function uses the special identifier `((year))` which is resolved at **runtime**. ## Syntax ``` $year ``` > **Note:** This function takes no parameters. ## Return Value The current year (for example `2026`), in the form of a string. ## Examples ### Simple year ```bdfd We are in the year $year. ``` ### Age calculation ```bdfd Were you born in 2000? You are $sub[$year;2000] years old! ``` ### Dynamic copyright ```bdfd $footer[© $year - MyBot] ``` ## Notes - The year is based on the system clock of the server running the bot. - Useful for dynamic copyright footers. --- ## Embed & Message ### $addField[] # $addField[] The `$addField[]` function adds a **field** to a Discord embed. Fields are displayed below the description and allow presenting structured data as name/value pairs. ## Syntax ``` $addField[name;value;(inline);(index)] ``` ## Parameters | Parameter | Description | |---|---| | `name` | Title of the field. Max 256 characters. | | `value` | Content of the field. Max 1024 characters. Supports markdown. | | `inline` | Optional. `yes` for inline (side-by-side), `no` by default. | | `index` | Optional. Insertion position (0 = start). Without an index, it is added to the end. | ## Return value Modifies the response currently being constructed. Returns nothing. ## Behavior - An embed can contain up to **25 fields**. - **Inline** fields are displayed side-by-side: up to **3 per row**. - **Non-inline** fields (default) occupy the full width. - The index allows inserting a field at a precise position (0 = very beginning). ## Examples ### Full-width fields (non-inline) ```bdfd $title[User Profile] $description[Detailed Information] $addField[Username;$username] $addField[ID;$authorID] $addField[Creation Date;$creationDate[$authorID]] $color[#5865F2] $sendMessage[] ``` ### Inline fields (3 per row) ```bdfd $title[Scores] $addField[Alice;1500 pts;yes] $addField[Bob;1200 pts;yes] $addField[Charlie;980 pts;yes] $color[#57F287] $sendMessage[] ``` ### Mixed inline and non-inline ```bdfd $title[Server Info] $description[Information about the server] $addField[Name;$serverName] $addField[Members;$membersCount;yes] $addField[Channels;$channelCount;yes] $addField[Server ID;$guildID;yes] $addField[Description;A great community server!] $color[#5865F2] $sendMessage[] ``` ### Insertion at a specific position ```bdfd $addField[First;Content 1] $addField[Third;Content 3] $addField[Second;Content 2;no;1] $title[Field Order] $description[Field 2 has been inserted at position 1.] $color[#5865F2] $sendMessage[] ``` ## Notes - Both the name and value support Discord markdown. - Combine inline and non-inline fields for complex layouts. - Index 0 corresponds to the beginning (before all other fields). - If the index exceeds the number of existing fields, the field is added to the end. --- ### $addFile[] # $addFile[] — File Attachment `$addFile[]` attaches a file (image, PDF, document, etc.) to a message. The file is downloaded from the provided URL and displayed as an attachment in the Discord message. ## Syntax ``` $addFile[url;(spoiler)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `url` | Yes | — | URL of the file to attach. | | `spoiler` | No | `no` | `yes` to spoiler the file. | ## Return value Adds the file as an attachment to the message. Discord displays the file according to its type (preview for images, icon + name for documents). ## Usage ### Attaching an image ```bdfd $addFile[https://cdn.example.com/chart.png] $sendMessage[Here is the requested chart] ``` ### PDF document ```bdfd $addFile[https://docs.example.com/rapport-2024.pdf] $sendMessage[Annual report attached] ``` ### Spoiler file ```bdfd $addFile[https://cdn.example.com/spoiler_endgame.png;yes] $sendMessage[Warning: ending spoiler!] ``` ### Multiple files ```bdfd $addFile[https://files.example.com/logs.txt] $addFile[https://files.example.com/config.json] $sendMessage[Configuration files] ``` ### With embed and file ```bdfd $title[Monthly Report] $description[Here is the detailed report of the month] $color[#5865F2] $addFile[https://reports.example.com/monthly.pdf] ``` ## Supported file types - Images: PNG, JPEG, GIF, WebP - Documents: PDF, TXT, CSV, JSON, XML - Archives: ZIP (limited) - Max size: ~25 MB (depending on the server's boost level) ## Notes - The URL must be publicly accessible. - Multiple `$addFile[]` calls can be used in the same message. - Do not confuse this with `$addModalFileUpload[]`, which is for interactive modals. - The spoiler hides the file until the user clicks to reveal it. --- ### $addThumbnail[] # $addThumbnail[] — Visual Thumbnail `$addThumbnail[]` inserts a thumbnail image in a container section. This function adds a standalone image component — distinct from the traditional embed thumbnail set by `$thumbnail[]`. ## Syntax ``` $addThumbnail[url;(description);(spoiler)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `url` | Yes | — | URL of the image (must be a valid URL). | | `description` | No | — | Alternative text for accessibility. | | `spoiler` | No | `no` | `yes` to hide the image. | ## Return value Adds the thumbnail image to the current section of the container. The image is rendered in a small format. ## Usage ### User avatar ```bdfd $addContainer[profile;#5865F2;no] $addSection $addThumbnail[$authorAvatar;Avatar of $username] $addField[User;$username;no] ``` ### Server icon ```bdfd $addContainer[server_info;#2ECC71;no] $addSection $addThumbnail[$serverIcon;Server icon] $addField[Server;$serverName;yes] $addField[Members;$membersCount;yes] ``` ### Spoiler image ```bdfd $addContainer[secret_content;#E74C3C;no] $addSection $addThumbnail[$var[hidden_image];Secret image;yes] $addTextDisplay[Click to reveal the image...] ``` ### In a complex layout ```bdfd $addContainer[catalog;#9B59B6;no] $addSection $addThumbnail[https://cdn.example.com/item1.png;Fire sword] $addField[Fire sword;5000 gold;yes] $addSection $addThumbnail[https://cdn.example.com/item2.png;Ice shield] $addField[Ice shield;3500 gold;yes] ``` ## Notes - Must be used in a section (`$addSection`) inside a container (`$addContainer`). - Do not confuse this with `$thumbnail[]` which defines the thumbnail of a classic embed. - The URL must point to a publicly accessible image (PNG, JPEG, GIF, WebP). - For a gallery of multiple images, use `$addMediaGallery[]`. --- ### $addTimestamp[] # $addTimestamp[] The `$addTimestamp[]` function adds a **timestamp** to the footer of a Discord embed. By default, it displays the current date and time. The timestamp is displayed at the bottom of the embed, next to the footer if it is present. ## Syntax ``` $addTimestamp[(timestamp);(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `timestamp` | Optional. `now` (by default) for the current time, or a Unix timestamp in seconds for a specific date. | | `embedIndex` | Optional. Index of the targeted embed (0 by default). | ## Return value Modifies the response currently being constructed. Returns nothing. ## Behavior - If no parameter is provided (`$addTimestamp`), the current date and time are used. - The timestamp is displayed at the bottom of the embed, below the fields and the footer. - Discord automatically formats the timestamp in the timezone of the user viewing it. ## Examples ### Current timestamp ```bdfd $title[Logs] $description[A moderation action has been performed.] $addTimestamp $color[#ED4245] $sendMessage[] ``` ### Timestamp with a specific date ```bdfd $title[Past Event] $description[This event took place on November 19, 2023.] $addTimestamp[1700000000] $color[#5865F2] $sendMessage[] ``` ### Timestamp with footer ```bdfd $title[Welcome!] $description[ Welcome to the server **$serverName**, $username! We are delighted to welcome you among us. ] $footer[$serverName;$serverIcon] $addTimestamp $color[#57F287] $sendMessage[] ``` ### Log embed with a dynamic timestamp ```bdfd $title[🔨 Moderation Log] $description[ **Moderator:** $username **Action:** Kick **Reason:** Breaking the rules ] $addField[Target user;$var[target];yes] $addField[ID;$var[targetID];yes] $footer[Moderation Bot v2.0] $addTimestamp $color[#ED4245] $sendMessage[] ``` ## Notes - The timestamp is automatically localized by Discord according to each user's timezone. - Use `$getTimestamp` to obtain the current Unix timestamp to pass as a parameter. - Combine this with `$footer[]` for a complete embed footer (text + icon + timestamp). - The display format (relative like "2 hours ago" or absolute like "11/19/2023") depends on the recipient's Discord client version. --- ### Allowmention # $allowMention Enables mentions in the response. When replying, the user will be explicitly pinged/mentioned. ## Syntax ``` $allowMention ``` ## Description `$allowMention` is a **flag** (without arguments) used before `$sendMessage`, generally in combination with `$reply`. It explicitly enables the mention/ping of the user in a response. Although the default behavior of `$reply` already includes a ping, `$allowMention` allows making the intent explicit and overriding any default configurations. ## Examples ### Response with explicit ping ``` $reply $allowMention $sendMessage[Hey $username, look at this!] ``` ### In an interaction ``` $onInteraction $if[$customID==btn_alert] $reply $allowMention $sendMessage[⚠️ Important alert for you!] $endif ``` ### Response with embeds and mention ``` $reply $allowMention $newEmbed[title=Attention;description=This requires your attention;color=#E74C3C] $sendMessage[] ``` ## Comparison | Flag | Effect | |------|-------| | *(none)* | Default behavior | | `$noMention` | Disables all mentions | | `$allowMention` | Enables mentions (explicit) | ## Notes - `$allowMention` enables the pinging of the user in a response. - Useful for making the intent explicit in the code. - The flag must be placed before `$sendMessage`. - Used in conjunction with `$reply`. --- ### $allowRoleMentions[] # $allowRoleMentions[] — Allow Role Mentions `$allowRoleMentions[]` enables member notifications when a role is mentioned in the message. Without this call, role tags like `<@&roleId>` are displayed but do **not** trigger a notification. ## Syntax ``` $allowRoleMentions ``` ## Parameters No parameters. ## Return value Enables role mentions for the next message sent. Roles mentioned in the content will notify their members. ## Usage ### Announcement with ping ```bdfd $allowRoleMentions $sendMessage[<@&$roleID[Moderator]> A report has been submitted, please check.] ``` ### Event notification ```bdfd $allowRoleMentions $title[🎉 Server Event] $description[<@&$roleID[Event_Ping]> A new event begins in 1 hour!] $addField[Details;Weekly tournament;yes] $addField[Reward;5000 gold coins;yes] $color[#F1C40F] ``` ### Reminder with mention ```bdfd $allowRoleMentions $sendMessage[⏰ <@&$roleID[Staff]> Staff meeting in 10 minutes!] ``` ### Conditional message ```bdfd $if[$var[important]==yes] $allowRoleMentions $sendMessage[<@&$roleID[Everyone_Important]> Critical alert!] $else $noMentions $sendMessage[Minor update available] $endif ``` ## Notes - Without `$allowRoleMentions[]`, mentioned roles appear as text but do not trigger a notification. - The effect only applies to the next message sent (via `$sendMessage` or other sending functions). - To explicitly disable all mentions, use `$noMentions[]`. - `$allowRoleMentions[]` only affects **role mentions**. For users, use `$allowUserMentions[]`. - Useful for important announcements while avoiding accidental pings in ordinary messages. --- ### $allowUserMentions[] # $allowUserMentions[] — Allow User Mentions `$allowUserMentions[]` enables user notifications when they are mentioned in the message. Without this call, tags like `<@userId>` appear visually but do **not** trigger a notification. ## Syntax ``` $allowUserMentions ``` ## Parameters No parameters. ## Return value Enables user mentions for the next message. Mentioned users will receive a notification. ## Usage ### Personal notification ```bdfd $allowUserMentions $sendMessage[<@$authorID> Your profile has been successfully updated!] ``` ### Response to a command ```bdfd $allowUserMentions $title[Confirmation] $description[<@$authorID>, your order #$var[orderId] has been confirmed.] $addField[Status;In preparation;yes] $color[#2ECC71] ``` ### Multiple mentions ```bdfd $allowUserMentions $sendMessage[<@$var[winner1]> and <@$var[winner2]> won the giveaway! 🎉] ``` ### Combination with RoleMentions ```bdfd $allowUserMentions $allowRoleMentions $sendMessage[<@$authorID> suggested an idea. <@&$roleID[Admin]> please check.] ``` ### Conditional ```bdfd $if[$var[notify]==yes] $allowUserMentions $sendMessage[<@$var[targetId]> You have a new message!] $else $noMentions $sendMessage[You have a new message (silent notification)] $endif ``` ## Mention Control | Function | Effect | |----------|-------| | `$allowRoleMentions` | Enables notifications for role mentions | | `$allowUserMentions` | Enables notifications for user mentions | | `$allowMentions` | Enables all mentions (roles + users) | | `$noMentions` | Disables all mention notifications | ## Notes - Without this function, `<@userId>` displays as a visual mention but without an audible ping or notification. - The effect is **one-time**: it only applies to the next message sent. - For important announcements, combine it with `$allowRoleMentions[]`. - To send a completely silent message (even for mentioned users), use `$noMentions[]`. - Respect your server rules regarding excessive pinging. --- ### $author[] # $author[] The `$author[]` function defines the **author** section of a Discord embed. This section appears at the very top of the embed, above the title, and can include a small round icon as well as a clickable link. ## Syntax ``` $author[name;(iconURL);(url);(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `name` | The author name to display. Maximum length: 256 characters. | | `iconURL` | Optional. URL of the avatar image (round icon to the left of the name). | | `url` | Optional. Destination URL. If provided, the name becomes a clickable link. | | `embedIndex` | Optional. Index of the targeted embed (0 by default). | ## Return value Modifies the response in progress. Returns nothing. ## Behavior - The author is displayed at the top of the embed, **above** the title. - The icon is a small round image (~24px diameter). - If `url` is provided, the author's name becomes a hyperlink. - To modify the icon or the URL afterwards, use `$authorIcon[]` and `$authorURL[]`. ## Examples ### Simple author ```bdfd $author[$username] $title[Message from $username] $description[This is an embed message.] $color[#5865F2] $sendMessage[] ``` ### Author with avatar ```bdfd $author[$username;$authorAvatar] $title[Profile] $description[ **Name:** $username **ID:** $authorID ] $color[#5865F2] $sendMessage[] ``` ### Author with clickable link ```bdfd $author[Official Site;https://example.com/logo.png;https://example.com] $title[Welcome] $description[Click on the name above to visit our site!] $color[#57F287] $sendMessage[] ``` ## Notes - The visual order in the embed is: **Author** → Title → Description → Fields → Image → Footer → Timestamp. - If you want to change only the icon after setting the author, use `$authorIcon[]`. - If you want to change only the URL after setting the author, use `$authorURL[]`. --- ### $authorIcon[] # $authorIcon[] The `$authorIcon[]` function **modifies only the icon** of the author of an embed after it has been set with `$author[]`. It avoids repeating the name and the URL when only the image needs to change. ## Syntax ``` $authorIcon[url;(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `url` | URL of the image to use as the author's icon. | | `embedIndex` | Optional. Index of the targeted embed (0 by default). | ## Return value Modifies the response in progress. Returns nothing. ## When to use $authorIcon[] - You have already set the author with `$author[name]` and want to add or change the icon without modifying the name. - The icon depends on a dynamic variable (avatar, role, etc.). - You want a modular and readable structure. ## Examples ### Adding the user's avatar as an icon ```bdfd $author[$username] $authorIcon[$authorAvatar] $title[Profile of $username] $description[ **ID:** $authorID **Account created on:** $creationDate[$authorID] ] $color[#5865F2] $sendMessage[] ``` ### Different icon based on role ```bdfd $author[Moderation Message] $if[$hasRole[$authorID;admin]] $authorIcon[https://cdn.example.com/admin-badge.png] $elseif[$hasRole[$authorID;modo]] $authorIcon[https://cdn.example.com/modo-badge.png] $else $authorIcon[$authorAvatar] $endif $title[Warning] $description[Please respect the server rules.] $color[#ED4245] $sendMessage[] ``` ## Notes - `$authorIcon[]` must be called **after** `$author[]`, otherwise the icon has no author to apply to. - If `$authorIcon[]` is called before `$author[]`, the icon will be ignored. - The URL must point to a publicly accessible image (PNG, JPG, GIF, WebP). - To change the name or add a link, use `$author[]` (which redefines everything) or `$authorURL[]` respectively. --- ### $authorOfMessage # $authorOfMessage The `$authorOfMessage[]` function returns the **author ID** of a given message. ## Syntax ``` $authorOfMessage[messageID] ``` ## Parameters | Parameter | Description | |---|---| | `messageID` | The ID of the target message. | ## Return value - **Type**: Snowflake (string) - The user ID of the author of the message. - Empty string if the message is not found. ## Examples ### Retrieving the author ```bdfd $let[author;$authorOfMessage[$message[1]]] $sendMessage[This message was sent by <@$author>] ``` ### Verify the owner of a message ```bdfd $if[$authorOfMessage[$messageID]==$authorID] $sendMessage[This message belongs to you.] $else $sendMessage[This message does not belong to you.] $endif ``` ### Log of deletion ```bdfd $let[msgID;$message[1]] $let[author;$authorOfMessage[$msgID]] $channelSendMessage[123456789;Message $msgID deleted — Author: <@$author>] ``` ### Message info command ```bdfd $let[msgID;$message[1]] $let[author;$authorOfMessage[$msgID]] $title[📋 Message Info] $description[ **ID**: $msgID **Author**: <@$author> ($author) **Content**: $getMessage[$msgID] ] $sendMessage[] ``` ## Notes - The bot must have access to the channel containing the message. - DM messages can be accessed if the bot has access. - For the current message, `$authorID` is more direct. --- ### $authorUrl[] # $authorUrl[] The `$authorUrl[]` function **modifies only the URL** of the author of an embed. Once defined, the author's name becomes a clickable hyperlink. ## Syntax ``` $authorUrl[url;(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `url` | Destination URL. The author name will point to this address. | | `embedIndex` | Optional. Index of the targeted embed (0 by default). | ## Return value Modifies the response in progress. Returns nothing. ## When to use $authorUrl[] - You have already set the author with `$author[name]` or `$author[name;icon]` and want to make it clickable. - The URL is dynamic (depends on a variable, an ID, etc.). - You want to separate the definition of the name/icon from that of the link for better clarity. ## Examples ### Link to the Discord profile of the user ```bdfd $author[$username;$authorAvatar] $authorUrl[https://discord.com/users/$authorID] $title[User Profile] $description[ Click on the name above to open the Discord profile. ] $color[#5865F2] $sendMessage[] ``` ### Conditional link ```bdfd $author[Website;$serverIcon] $if[$var[page]!=] $authorUrl[https://mysite.com/$var[page]] $else $authorUrl[https://mysite.com] $endif $title[Navigation] $description[Select a page in the menu below.] $color[#5865F2] $sendMessage[] ``` ### Author with all attributes separated ```bdfd $author[Bot Designer for Discord] $authorIcon[https://bdfd.com/icon.png] $authorUrl[https://bdfd.com] $title[Created with BDFD] $description[This bot was created with Bot Designer for Discord.] $footer[Version 2.0] $color[#5865F2] $sendMessage[] ``` ## Notes - `$authorUrl[]` must be called **after** `$author[]`, otherwise there is no author to apply the URL to. - If you call `$authorUrl[]` alone (without `$author[]` beforehand), the URL will be ignored. - The URL must be absolute (starting with `http://` or `https://`). --- ### $color[] # $color[] The `$color[]` function sets the **color** of the left sidebar of a Discord embed. This colored bar helps visually categorize your embeds (success, error, info, etc.). ## Syntax ``` $color[hexColor;(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `hexColor` | Color code in hexadecimal (`FF0000`, `#5865F2`) or decimal integer format. | | `embedIndex` | Optional. Index of the embed to modify (0 by default). | ## Return value This function does not return anything: it modifies the response currently being constructed. ## Accepted Formats | Format | Example | Result | |---|---|---| | Hexadecimal with # | `#5865F2` | Discord Blue | | Hexadecimal without # | `5865F2` | Discord Blue | | Integer decimal | `5793266` | Discord Blue | ## Common Colors | Name | Hex code | Integer | |---|---|---| | Discord Blue | `#5865F2` | 5793266 | | Red | `#ED4245` | 15548997 | | Green | `#57F287` | 5763719 | | Yellow | `#FEE75C` | 16705372 | | Orange | `#F26522` | 15878690 | | White | `#FFFFFF` | 16777215 | | Black | `#000000` | 0 | ## Examples ### Blue embed (information) ```bdfd $title[Information] $description[Your profile has been updated.] $color[#5865F2] $sendMessage[] ``` ### Red embed (error) ```bdfd $title[Error] $description[You do not have permission to use this command.] $color[#ED4245] $sendMessage[] ``` ### Green embed (success) ```bdfd $title[Success] $description[The operation completed successfully!] $color[#57F287] $sendMessage[] ``` ## Notes - If `$color[]` is not called, the embed will not have a colored sidebar (transparent sidebar). - The `#` prefix is optional. - Hexadecimal letters are case-insensitive: `#ff0000` is equivalent to `#FF0000`. --- ### $deleteIn[] # $deleteIn[] — Delayed Message Deletion `$deleteIn[]` schedules the automatic deletion of the message after a given delay. Ideal for temporary notifications, ephemeral messages, or automatic cleanup. ## Syntax ``` $deleteIn[duration] ``` ## Parameters | Parameter | Required | Description | |-----------|-------------|-------------| | `duration` | Yes | Delay before deletion. Format: number + unit. | ## Duration Format | Format | Unit | Example | |--------|-------|---------| | `Xs` | Seconds | `5s`, `30s`, `60s` | | `Xm` | Minutes | `1m`, `5m`, `15m` | | `Xh` | Hours | `1h`, `2h` | ## Return value Schedules the delayed deletion of the message. The message is automatically deleted at expiry. ## Usage ### Temporary notification ```bdfd $sendMessage[✅ Command executed successfully] $deleteIn[5s] ``` ### Ephemeral error message ```bdfd $sendMessage[❌ Error: You do not have the required permission] $deleteIn[10s] ``` ### Self-clearing alert ```bdfd $sendMessage[🔔 New update available!] $deleteIn[30s] ``` ### With embeds ```bdfd $title[Temporary Message] $description[This content will disappear in 10 seconds] $color[#E74C3C] $footer[Auto-deletion...] $deleteIn[10s] ``` ### Ephemeral welcome message ```bdfd $sendMessage[Welcome $username! Please remember to read the rules.] $deleteIn[1m] ``` ## Notes - `$deleteIn[]` deletes the **current** message (the one that was just sent). - The maximum duration is generally 15 minutes. - Once scheduled, the deletion cannot be cancelled. - The deletion fails silently if the bot does not have the `MANAGE_MESSAGES` permission. - Combine with `$sendMessage` for self-destructing messages. --- ### Deletemessage # $deleteMessage Deletes a specific message. The bot must have permission to manage messages in the channel. ## Syntax ``` $deleteMessage[messageId] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `messageId` | ID of the message to delete | Yes | ## Description `$deleteMessage` permanently deletes a Discord message. The bot must have the `MANAGE_MESSAGES` permission to delete other users' messages. It can always delete its own messages. ## Examples ### Deletion of the triggering message ``` $deleteMessage[$messageID] Command executed discreetly. ``` ### Deletion after action ``` $sendMessage[Processing...] $wait[3s] $deleteMessage[$sentMessageId] $sendMessage[Processing complete!] ``` ### Deletion in an interaction ``` $onInteraction $if[$customID==btn_delete] $deleteMessage[$messageID] $sendMessage[Message deleted][ephemeral] $endif ``` ### Deletion of a specific message ``` $deleteMessage[123456789012345678] ``` ## Notes - The `messageId` parameter is required. - The bot must have `MANAGE_MESSAGES` to delete other users' messages. - Deleted messages cannot be recovered. - To delete the user's message that triggered the command, use `$messageID`. - After deletion, it is common to send an ephemeral confirmation. --- ### $description[] # $description[] The `$description[]` function defines the **main body** (description) of a Discord embed. This is the main text area of the embed, displayed below the title. ## Syntax ``` $description[text;(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `text` | The text of the description. Supports Discord markdown, line breaks, emojis, and interpolation of BDFD functions/variables. | | `embedIndex` | Optional. Index of the embed to modify (0 by default). | ## Return value This function returns nothing; it modifies the response currently being constructed. The embed is sent via `$sendMessage[]`. ## Behavior - `$description[]` is a **response mutation**. - The description is the core of the embed's content: this is where you place the bulk of your text. - Maximum length: **4096 characters**. - If the text is empty, the description will not be displayed. ## Examples ### Simple description ```bdfd $title[Information] $description[Here is the requested information. Use the buttons below to navigate.] $color[#5865F2] $sendMessage[] ``` ### Multi-line description with markdown ```bdfd $title[Server Rules] $description[ **Server Rules:** 1. Respect other members 2. No spam 3. No NSFW content *Thank you for your understanding!* ] $color[#ED4245] $sendMessage[] ``` ### Description with dynamic variables ```bdfd $title[Profile] $description[ **Name:** $username **ID:** $authorID **Registration Date:** $creationDate[$authorID] ] $color[#5865F2] $sendMessage[] ``` ## Notes - The description supports full Discord markdown: `**bold**`, `*italics*`, `__underline__`, `~~strikethrough~~`, lists, code blocks, etc. - To structure complex information, combine `$description[]` with `$addField[]`. --- ### $dm # $dm The `$dm[]` function **sends a private message** to a Discord user. ## Syntax ``` $dm[userID;content] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the recipient. | | `content` | The content of the message (markdown and mentions supported). | ## Return value - **Type**: Snowflake (string) - The ID of the message sent. - Empty string if the DM is impossible (user blocked, DMs closed). ## Behavior - The bot must be able to send DMs to the user (not blocked, DMs open). - Embeds defined before `$dm[]` are included. - If the user has closed their DMs, the function fails silently. ## Examples ### Simple DM to the author ```bdfd $dm[$authorID;Thank you for using the command!] ``` ### DM with embed ```bdfd $title[📬 Notification] $description[Your request has been successfully received.\n\nA moderator will reply to you shortly.] $color[#5865F2] $footer[$serverName Team] $dm[$authorID;] ``` ### DM to a mentioned user ```bdfd $if[$mentioned[1]!=] $dm[$mentioned[1];$username sent you this message: $noMentionMessage] $sendMessage[DM sent successfully!] $else $sendMessage[Please mention a user.] $endif ``` ## Notes - Unlike `$sendMessage`, the DM does not appear in the current channel. - Limit of 2000 characters per message. - For welcome DMs, check that the user accepts DMs. --- ### $dmChannelID # $dmChannelID The `$dmChannelID[]` function returns the **DM channel ID** (private conversation) between the bot and a given user. ## Syntax ``` $dmChannelID[userID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user whose DM channel ID is requested. | ## Return value - **Type**: Snowflake (string) - The ID of the DM channel. - Automatically creates the DM channel if necessary. ## Behavior - Creates the DM channel if the conversation does not exist yet. - Useful for combining with `$useChannel[]` or `$channelSendMessage[]`. - Does not fail if the user has closed their DMs (the channel is created, but sending messages may fail). ## Examples ### Retrieving the DM ID ```bdfd $let[dmChannel;$dmChannelID[$authorID]] $sendMessage[Your private conversation with the bot: $dmChannel] ``` ### Sending to the DM via useChannel ```bdfd $useChannel[$dmChannelID[$authorID]] $sendMessage[This message is sent in private.] ``` ### Logging of DM channel ```bdfd $log[DM opened with <@$authorID> - Channel: $dmChannelID[$authorID]] ``` ## Notes - The DM channel is persistent once created by Discord. - To send a private message, `$dm[]` is simpler. - Use `$dmChannelID[]` when you need the ID for other operations. --- ### $editEmbedIn[] # $editEmbedIn[] — Delayed Embed Editing `$editEmbedIn[]` schedules the update of the embed of a message after a delay. Only the embed is modified — the text of the message (sent via `$sendMessage`) is not affected. ## Syntax ``` $editEmbedIn[duration] ``` ## Parameters | Parameter | Required | Description | |-----------|-------------|-------------| | `duration` | Yes | Delay before editing. Format: number + unit. | ## Duration Format | Format | Unit | Example | |--------|-------|---------| | `Xs` | Seconds | `3s`, `10s` | | `Xm` | Minutes | `1m`, `5m` | | `Xh` | Hours | `1h` | ## Return value Schedules the delayed editing of the embed. The new embed is defined after the call to `$editEmbedIn[]`. ## Difference from $editIn[] | $editEmbedIn[] | $editIn[] | |---------------|-----------| | Modifies only the embed | Modifies the entire message (text + embed) | | Preserves the text of the message | Replaces the entire content | | Ideal for visual updates | Ideal for complete transitions | ## Usage ### Progress indicator ```bdfd $sendMessage[Updating...] $title[Progression] $description[🟡 Processing data...] $color[#F1C40F] $editEmbedIn[5s] $title[Progression] $description[🟢 Completed successfully!] $color[#2ECC71] ``` ### Status change ```bdfd $title[🔍 Search in progress] $description[Analyzing database...] $color[#3498DB] $footer[Please wait...] $editEmbedIn[3s] $title[✅ Search completed] $description[3 results found] $color[#2ECC71] $footer[Completed] ``` ### Visual transition ```bdfd $sendMessage[Preparing report...] $title[Monthly Report] $description[📊 Generating...] $color[#E67E22] $editEmbedIn[5s] $title[Monthly Report - June 2026] $description[✅ Report generated successfully\n\n📈 Growth: +15%\n💰 Revenue: 12,450€\n👥 New members: 230] $color[#27AE60] $footer[Generated on $date] ``` ## Notes - `$editEmbedIn[]` only modifies the embed; the text content (first argument of `$sendMessage`) remains intact. - The new embed completely replaces the old one (no merging). - To modify both the text and the embed at the same time, use `$editIn[]`. - The maximum duration is generally 15 minutes. --- ### $editIn[] # $editIn[] — Delayed Message Editing `$editIn[]` schedules the automatic editing of a message after a given delay. This is useful for creating self-updating messages, countdowns, or state transitions. ## Syntax ``` $editIn[duration;(messageId)] ``` ## Parameters | Parameter | Required | Description | |-----------|-------------|-------------| | `duration` | Yes | Delay before editing. Format: number + unit (`s`, `m`, `h`). | | `messageId` | No | ID of the target message. If omitted, the current message. | ## Duration Format | Format | Unit | Example | |--------|-------|---------| | `Xs` | Seconds | `5s`, `30s` | | `Xm` | Minutes | `1m`, `10m` | | `Xh` | Hours | `1h`, `2h` | ## Return value Schedules the delayed editing. The new content is defined after the call to `$editIn[]`. ## Usage ### Loading indicator ```bdfd $sendMessage[⏳ Processing...] $editIn[3s] $sendMessage[✅ Processing complete!] ``` ### Countdown ```bdfd $sendMessage[Starting in 5 seconds...] $editIn[1s] $sendMessage[Starting in 4 seconds...] $editIn[2s] $sendMessage[Starting in 3 seconds...] $editIn[3s] $sendMessage[Starting in 2 seconds...] $editIn[4s] $sendMessage[Starting in 1 second...] $editIn[5s] $sendMessage[🚀 Let's go!] ``` ### Update after action ```bdfd $sendMessage[Search in progress... 🔍] $editIn[2s] $title[Search Results] $description[3 results found for "$var[query]"] $color[#5865F2] ``` ### With specific messageId ```bdfd $var[msgId;$sendMessage[Status: Pending...;yes]] $editIn[10s;$var[msgId]] $sendMessage[Status: Completed ✅] ``` ## Notes - The maximum duration is generally 15 minutes (BDFD/Discord limitation). - The content after `$editIn[]` completely replaces the content of the target message. - If `messageId` is omitted, the message currently being sent is targeted. - To edit only the embed without touching the text, use `$editEmbedIn[]`. --- ### Editmessage # $editMessage Modifies an existing message sent by the bot. Replaces the content and/or the embeds and components of the target message. ## Syntax ``` $editMessage[messageId;newContent] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `messageId` | ID of the message to modify | Yes | | `newContent` | New text content of the message | Yes | ## Description `$editMessage` allows updating a message previously sent by the bot. Just like `$sendMessage`, the embeds and components built before the call are included in the modification. The `messageId` can be obtained via: - `$sentMessageId` after a `$sendMessage` - A stored variable - The ID of the triggering message (`$messageID`) ## Examples ### Simple edit ``` $editMessage[123456789012345678;Updated content!] ``` ### Edit after sending ``` $sendMessage[Original message] $editMessage[$sentMessageId;Modified message!] ``` ### Edit with new embeds ``` $newEmbed[title=Update;description=The information has changed;color=#FFA500] $editMessage[$sentMessageId;] ``` ### Edit with updated buttons ``` $addActionRow $addButtonCV2[btn_done;Done;success;true] $editMessage[$sentMessageId;Action completed ✅] ``` ### In $onInteraction ``` $onInteraction $if[$customID==btn_edit] $editMessage[$messageID;Message edited by interaction] $endif ``` ## Notes - The bot can only modify its own messages. - If `newContent` is empty and no embed/component is provided, the message may become empty (behavior depending on version). - Embeds and components completely replace those of the original message. - Use `$sentMessageId` right after `$sendMessage` to retrieve the ID of the last message sent. --- ### $embeddedURL # $embeddedURL The `$embeddedURL[]` function sets the **clickable URL of the title** of an embed. The title becomes a hyperlink. ## Syntax ``` $embeddedURL[url;(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `url` | The target URL (must start with `http://` or `https://`). | | `embedIndex` | *(Optional)* Index of the embed (1, 2, 3...). Default: 1. | ## Return value None. ## Behavior - The title of the embed (`$title[]`) becomes clickable. - Works only if a `$title[]` is defined. - The URL must be valid and accessible. ## Examples ### Embed with a clickable title ```bdfd $title[Join our server!] $embeddedURL[https://discord.gg/example] $description[Click on the title to join us.] $color[#5865F2] $sendMessage[] ``` ### Informative embed with a link ```bdfd $title[View the documentation] $embeddedURL[https://docs.example.com] $description[ Command: **!help** Category: Utilities ] $footer[Official documentation] $color[#57F287] $sendMessage[] ``` ### Multiple embeds with different URLs ```bdfd $title[Website] $embeddedURL[https://example.com] $description[Our official website.] $addEmbed $title[Discord] $embeddedURL[https://discord.gg/example;2] $description[Our Discord server.] ``` ## Notes - Without `$embeddedURL[]`, the title of the embed is not clickable. - Should be placed after `$title[]` for the URL to be associated. - Works with all styles of embed. --- ### $footer[] # $footer[] The `$footer[]` function defines the **footer** of a Discord embed. The footer appears at the bottom of the embed and can include a small icon to the left of the text. ## Syntax ``` $footer[text;(iconURL);(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `text` | Text of the footer. Maximum length: 2048 characters. | | `iconURL` | Optional. URL of the footer's icon. Must be a valid URL pointing to an image. | | `embedIndex` | Optional. Index of the target embed (Default: 1). | ## Return Value Modifies the response currently being constructed. Returns nothing directly. ## Behavior - The footer is displayed at the bottom of the embed in a smaller font. - If an `iconURL` is provided, a small squared icon appears to the left of the text. - To modify only the icon after defining the footer, use `$footerIcon[]`. ## Examples ### Simple footer ```bdfd $title[User Profile] $description[ **Name:** $username **ID:** $authorID ] $footer[Requested by $username] $color[#5865F2] $sendMessage[] ``` ### Footer with custom icon ```bdfd $title[Information] $description[This bot was created with BDFD.] $footer[Powered by Bot Designer for Discord;https://bdfd.com/logo.png] $color[#5865F2] $sendMessage[] ``` ### Footer with dynamic avatar ```bdfd $title[Command executed] $description[The command was processed successfully.] $footer[Executed by $username;$authorAvatar] $addTimestamp $color[#57F287] $sendMessage[] ``` ## Notes - The footer is often combined with `$addTimestamp[]` to display the date at the bottom of an embed. - If you wish to change the icon without modifying the footer text, use `$footerIcon[]`. - The URL of the icon must be a publicly accessible image (PNG, JPG, GIF, WebP). --- ### $footerIcon[] # $footerIcon[] The `$footerIcon[]` function allows you to **modify only the icon** of a footer already defined with `$footer[]`. It is useful when you want to define a dynamic icon without repeating the footer text. ## Syntax ``` $footerIcon[url;(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `url` | URL of the image to use as the footer's icon. | | `embedIndex` | Optional. Index of the target embed (Default: 1). | ## Return Value Modifies the response currently being constructed. Returns nothing. ## When to use $footerIcon[] - You have already defined the footer with `$footer[text]` and want to add or change the icon. - The icon depends on a dynamic variable (avatar, status, etc.). - You want to separate the logic of the text and the icon for better readability. ## Examples ### Dynamic icon based on the user ```bdfd $title[Profile] $description[ **Name:** $username **Tag:** $discriminator ] $footer[Requested by $username] $footerIcon[$authorAvatar] $color[#5865F2] $sendMessage[] ``` ### Conditional icon ```bdfd $title[Server Status] $description[The server is operational.] $footer[Last check: $time] $if[$var[status]==online] $footerIcon[https://cdn.example.com/green.png] $else $footerIcon[https://cdn.example.com/red.png] $endif $color[#57F287] $sendMessage[] ``` ## Notes - `$footerIcon[]` must be called **after** `$footer[]`, otherwise there is no footer to apply the icon to. - If `$footerIcon[]` is called before `$footer[]`, the icon will be ignored. - The URL must point to a publicly accessible image. --- ### $image[] # $image[] The function `$image[]` defines the **main (large) image** of a Discord embed. The image is displayed at the bottom of the embed in full width, after the description and the fields. ## Syntax ``` $image[url;(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `url` | URL of the image to display. Must be a direct URL to an image file (PNG, JPG, GIF, WebP). | | `embedIndex` | Optional. Index of the targeted embed (defaults to 0). | ## Return Value Modifies the response currently being constructed. Returns nothing. ## Behavior - The image occupies the full width of the embed. - If the URL is invalid or the image is inaccessible, the embed will display without the image. - Only one call to `$image[]` per embed: the last call overwrites any previous ones. ## Difference between $image[] and $thumbnail[] | Function | Position | Size | |---|---|---| | `$image[]` | Bottom of the embed | Large, full width | | `$thumbnail[]` | Top-right corner | Small (square) | ## Examples ### Simple image ```bdfd $title[Photo of the Day] $description[A beautiful photo selected for you.] $image[https://picsum.photos/800/400] $color[#5865F2] $sendMessage[] ``` ### Avatar as a large image ```bdfd $title[Avatar of $username] $description[**ID:** $authorID] $image[$authorAvatar] $color[#5865F2] $sendMessage[] ``` ### Embed combining image and thumbnail ```bdfd $title[New Product] $description[ **Name:** Gaming Pro Headset **Price:** $79.99 **Availability:** In stock ✅ ] $thumbnail[https://cdn.example.com/product-icon.png] $image[https://cdn.example.com/product-banner.png] $color[#57F287] $sendMessage[] ``` ## Notes - The URL must be publicly accessible (no local paths). - Supported formats include PNG, JPEG, GIF (animated or static), and WebP. - For a small image in the top-right corner, use `$thumbnail[]` instead of `$image[]`. --- ### Nomention # $noMention Disables user mentions in the reply. When replying to a message, the user will not be pinged/mentioned. ## Syntax ``` $noMention ``` ## Description `$noMention` is a **flag** (without arguments) that is used before `$sendMessage`, generally in combination with `$reply`. It prevents pinging/mentioning the user in a reply, which is useful for silent replies. By default, `$reply` pings the author of the target message. `$noMention` disables this behavior. ## Examples ### Silent Reply ```bdfd $reply $noMention $sendMessage[Here is your reply, without a notification] ``` ### Discrete reply with embeds ```bdfd $reply $noMention $newEmbed[title=Result;description=Operation completed;color=#2ECC71] $sendMessage[] ``` ### In an interaction ```bdfd $onInteraction $if[$customID==btn_silent] $reply $noMention $sendMessage[Action performed silently] $endif ``` ## Comparison | Flag | Effect | |------|-------| | *(none)* | Default behavior | | `$noMention` | Disables all user mentions | | `$allowMention` | Enables user mentions (explicit) | ## Notes - `$noMention` disables user pings, not other types of mentions (like `@everyone` or `@role`). - Particularly useful with `$reply` for non-intrusive responses. - Flag should be placed before `$sendMessage`. --- ### Reply # $reply Marks the message as a reply to an existing message. Used before `$sendMessage`. ## Syntax ### Reply to the user's message (0 arguments) ``` $reply ``` ### Reply to a specific message ``` $reply[channelId;messageId] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:--------:| | `channelId` | ID of the channel containing the target message | No* | | `messageId` | ID of the message to reply to | No* | *\* Required only to reply to a specific message in a specific channel.* ## Description `$reply` is a **flag** used before `$sendMessage`. It indicates that the message should be sent as a reply (Discord replies), which displays the original message above the reply. Without arguments, `$reply` replies to the message that triggered the command or interaction. ## Examples ### Simple reply ``` $reply $sendMessage[Here is your reply!] ``` ### Reply to a specific message ``` $reply[$channelID;123456789012345678] $sendMessage[Reply to a specific message] ``` ### Reply in $onInteraction ``` $onInteraction $if[$customID==btn_help] $reply $sendMessage[Here is the requested help] $endif ``` ### Reply with embeds ``` $reply $newEmbed[title=Reply;description=Reply details;color=#3498DB] $sendMessage[] ``` ## Notes - Without arguments, `$reply` automatically uses the triggering message. - `$reply` must be placed before `$sendMessage`. - The reply pings the user by default. Use `$noMention` before to disable the ping. - Also works in `$onInteraction`. --- ### $replyIn[] # $replyIn[] — Delayed Response `$replyIn[]` schedules the sending of a response to the message after a delay. The content defined after `$replyIn[]` will be sent as a reply to the original message. ## Syntax ``` $replyIn[duration] ``` ## Parameters | Parameter | Required | Description | |-----------|-------------|-------------| | `duration` | Yes | The delay before the response. Format: number + unit. | ## Duration Format | Format | Unit | Example | |--------|-------|---------| | `Xs` | Seconds | `3s`, `10s` | | `Xm` | Minutes | `1m`, `5m` | | `Xh` | Hours | `1h` | ## Return Value Schedules a delayed response. The subsequent content is sent as a reply to the triggering message. ## Examples ### Simple delayed response ```bdfd $replyIn[3s] $sendMessage[Please wait, processing your request...] ``` ### Information after delay ```bdfd $replyIn[5s] $title[Server Information] $description[**Name:** $serverName\n**Members:** $membersCount] $color[#5865F2] $footer[Requested by $username] ``` ### Simulation of processing ```bdfd $replyIn[2s] $sendMessage[🔍 Search in progress...] $replyIn[5s] $sendMessage[✅ Result found: $var[result]] ``` ### Scheduled notifications ```bdfd $replyIn[1m] $sendMessage[⏰ Reminder: your meeting starts in 5 minutes!] ``` ### With embeds ```bdfd $replyIn[4s] $title[Analysis Complete] $description[Here is the analysis requested by $username] $addField[Status;Completed;yes] $addField[Execution time;$var[exec_time]ms;yes] $color[#27AE60] ``` ## Notes - The message is sent as a **reply** to the original message. - The maximum recommended duration is 15 minutes. - Multiple successive `$replyIn[]` calls will send several delayed responses. - Unlike `$editIn[]`, a new message is created instead of editing the existing one. - If the original message is deleted before the delay expires, the response may fail. --- ### $sendEmbedMessage[] # $sendEmbedMessage[] — Send an Embed `$sendEmbedMessage[]` sends the previously constructed embed to a Discord channel. This is the primary method for sending rich messages (embeds) to a target channel, distinct from `$sendMessage[]`. ## Syntax ``` $sendEmbedMessage[(channelId);(messageId)] ``` ## Parameters | Parameter | Required | Default | Description | |-----------|-------------|--------|-------------| | `channelId` | No | Current channel | ID of the destination channel. | | `messageId` | No | New message | ID of a message to edit. | ## Return Value - **Type**: `string` - Returns the identifier of the message created or edited. Can be used for subsequent operations. ## Usage ### Simple embed in the current channel ```bdfd $title[Server Status] $description[All systems functioning normally] $color[#2ECC71] $addField[Uptime;$uptime;yes] $addField[Players;$var[players];yes] $sendEmbedMessage ``` ### Embed in a specific channel ```bdfd $title[New Member] $description[$username has joined the server!] $addField[ID;$authorID;yes] $thumbnail[$authorAvatar] $color[#5865F2] $sendEmbedMessage[$channelID[welcome]] ``` ### Editing an existing embed ```bdfd $title[Leaderboard - Updated] $description[Updated leaderboard] $addField[1st;$var[top1];yes] $addField[2nd;$var[top2];yes] $addField[3rd;$var[top3];yes] $color[#F1C40F] $footer[Updated at $time] $sendEmbedMessage[$channelID[leaderboard];$var[leaderboard_msg_id]] ``` ### Capturing the ID for later use ```bdfd $title[Editable Message] $description[This message will be updated] $var[msgId;$sendEmbedMessage] $editEmbedIn[10s] $title[Editable Message - Updated] $description[The update was successful] $color[#27AE60] ``` ## Notes - The embed must be constructed **before** calling `$sendEmbedMessage[]` (using `$title[]`, `$description[]`, `$addField[]`, etc.). - If no embed is defined, the message will be empty (which should be avoided). - The return value (message ID) is useful for subsequent edits or deletions. - To send both text and an embed, use `$sendMessage[]` which can combine both. --- ### Sendmessage # $sendMessage Sends a message with its content, embeds, and components (buttons, select menus). ## Syntax ``` $sendMessage[content] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `content` | Text content of the message | Yes | ## Description `$sendMessage` is the main command to send a message in the channel where the command was executed. If embeds (via `$newEmbed`, `$addEmbedField`, etc.) or components (via `$addActionRow`, `$addButtonCV2`, etc.) were constructed before this call, they are automatically included in the message. The text content can be empty (`$sendMessage[]`) if only embeds or components are sent. ## Examples ### Simple message ``` $sendMessage[Hello world!] ``` ### With embeds ``` $newEmbed[title=Announcement;description=This is an important announcement;color=#FF0000] $sendMessage[] ``` ### With buttons ``` $addActionRow $addButtonCV2[btn_yes;Yes;success] $addButtonCV2[btn_no;No;danger] $sendMessage[Do you confirm?] ``` ### Complete message ``` $newEmbed[title=Welcome;description=Welcome to the server!;color=#00FF00] $addActionRow $addButtonCV2[btn_rules;Rules;primary] $addButtonCV2[btn_roles;Roles;secondary] $sendMessage[Welcome $username!] ``` ### Response in $onInteraction ``` $onInteraction $if[$customID==btn_yes] $sendMessage[You have confirmed!] $endif ``` ## Notes - `$sendMessage` sends in the current channel. To send in another channel, use `$sendMessage[content;channelId]` (depending on version) or `$channelSendMessage`. - The content can be empty if you are only sending embeds/components. - In `$onInteraction`, the message is sent in response to the interaction. - Flag functions applicable before `$sendMessage`: `$reply`, `$ephemeral`, `$tts`, `$noMention`, `$allowMention`. --- ### $thumbnail[] # $thumbnail[] The function `$thumbnail[]` sets the **thumbnail** of a Discord embed. The thumbnail is a small square image displayed at the top right corner of the embed. ## Syntax ``` $thumbnail[url;(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `url` | URL of the image to use as the thumbnail. Must be a direct URL to an image file. | | `embedIndex` | Optional. Index of the targeted embed (default is 0). | ## Return Value Modifies the response currently being constructed. Returns nothing. ## Behavior - The thumbnail appears at the top right of the embed. - The image is automatically resized into a small square. - Only one thumbnail is allowed per embed; the last call overwrites the previous one. ## Difference Between $thumbnail[] and $image[] | Function | Position | Size | |---|---|---| | `$thumbnail[]` | Top right | Small (square, ~80x80px) | | `$image[]` | Bottom of the embed | Large, full width | ## Examples ### Thumbnail with User Avatar ```bdfd $title[Profile of $username] $description[ **Username:** $username **ID:** $authorID **Account Created:** $creationDate[$authorID] ] $thumbnail[$authorAvatar] $color[#5865F2] $sendMessage[] ``` ### Thumbnail with Server Icon ```bdfd $title[Welcome to $serverName] $description[ Welcome to the server **$serverName**! We are now **$membersCount** members! ] $thumbnail[$serverIcon] $color[#57F287] $sendMessage[] ``` ### Combining Thumbnail and Image ```bdfd $title[New Update] $description[ **Version 2.0** is now available! - Bug fixes - New features - Performance improvements ] $thumbnail[https://cdn.example.com/update-icon.png] $image[https://cdn.example.com/update-banner.png] $footer[Published at $time] $color[#FEE75C] $sendMessage[] ``` ## Notes - The URL must be publicly accessible. - Supported formats: PNG, JPEG, GIF, WebP. - The thumbnail is ideal for displaying an avatar, a logo, or a representative icon. - For a large full-width image, use `$image[]`. --- ### $title[] # $title[] The function `$title[]` sets the **title** of a Discord embed. The title is the most visible text of the embed, displayed at the top in bold with a larger font. ## Syntax ``` $title[text;(embedIndex)] ``` ## Parameters | Parameter | Description | |---|---| | `text` | The text of the title. You can use Discord markdown syntax (bold, italics, underline, etc.). | | `embedIndex` | Optional. Index of the embed to modify (default is 0). Use this index to build multiple embeds in the same message (maximum of 10). | ## Return Value This function returns nothing; it modifies the response currently being constructed. The embed is sent via `$sendMessage[]`. ## Behavior - `$title[]` is a **response mutation**: it is added to the response currently in progress and will be sent upon the next `$sendMessage[]` call. - If you call `$title[]` multiple times before a `$sendMessage[]`, only the last call will be applied to that specific embed. - The order of calls is important: place `$title[]` before `$description[]`, `$color[]`, etc. ## Examples ### Simple Embed with Title ```bdfd $title[Welcome to the server!] $description[Thank you for joining us 🎉] $color[#5865F2] $sendMessage[] ``` ### Title with Markdown Formatting ```bdfd $title[**Important Announcement** — *Must Read* 📢] $description[Here is the latest news of the server.] $color[#FF0000] $sendMessage[] ``` ### Multi-embed: Different Titles for Each Embed ```bdfd $title[First embed;0] $description[Content of the first embed;0] $color[#5865F2;0] $title[Second embed;1] $description[Content of the second embed;1] $color[#57F287;1] $sendMessage[] ``` ## Notes - The maximum length of the title is **256 characters**. - If the text is empty, the title will not be displayed in the embed. - For an embed without a title, simply omit the call to `$title[]`. --- ### $tts # $tts Enables text-to-speech (TTS) for the sent message. The message will be read aloud to the users in the channel. ## Syntax ``` $tts ``` ## Description `$tts` is a **flag** (without arguments) used before `$sendMessage`. It enables Discord's TTS feature: the message content will be read aloud for all users in the channel who have not disabled TTS. ## Examples ### Simple TTS Message ```bdfd $tts $sendMessage[Attention to all members!] ``` ### With Embeds ```bdfd $tts $newEmbed[title=Voice Announcement;description=This is an important announcement;color=#E74C3C] $sendMessage[Important announcement!] ``` ### TTS Alert ```bdfd $tts $sendMessage[🚨 Alert: maintenance starts in 5 minutes] ``` ## Notes - Works only if the bot has the `SEND_TTS_MESSAGES` permission. - Users can disable TTS in their Discord settings. - `$tts` is a flag, use it before `$sendMessage`. - TTS reads the text content, not the embed content. - Use sparingly to avoid disturbing users. --- ## Entity Info ### $afkChannelID[] # $afkChannelID[] — AFK Channel `$afkChannelID[]` returns the ID of the AFK (Away From Keyboard) voice channel of the server. Inactive members in a voice channel are automatically moved to this channel after the delay set by `$afkTimeout[]`. ## Syntax ``` $afkChannelID ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | None | | | ## Return value - **Type**: `string` - The ID of the AFK channel, or an empty string if not configured. ## Usage ### Displaying the AFK channel ```bdfd $if[$afkChannelID!=] $sendMessage[💤 AFK Channel: <#$afkChannelID> (delay: $afkTimeout seconds)] $else $sendMessage[ℹ️ No AFK channel is configured on this server.] $endif ``` ### Server configuration embed ```bdfd $title[⚙️ Configuration of $serverName] $addField[💤 AFK Channel;$if[$afkChannelID!=]<#$afkChannelID>$elseNot configured$endif;yes] $addField[⏱️ AFK Delay;$afkTimeout seconds;yes] $addField[📋 Rules Channel;$if[$rulesChannelID!=]<#$rulesChannelID>$elseNot configured$endif;yes] $addField[📢 System Channel;$if[$systemChannelID!=]<#$systemChannelID>$elseNot configured$endif;yes] $color[#5865F2] $sendEmbedMessage ``` ### Configuration log ```bdfd $log[Server configuration $serverName | AFK: $afkChannelID | Timeout: $afkTimeout | Rules: $rulesChannelID | System: $systemChannelID] ``` ## Notes - The AFK channel must be a voice channel. - If no AFK channel is configured, the function returns an empty string. - The delay before moving is given by `$afkTimeout[]` (in seconds). - Members in the AFK channel are automatically muted by Discord. --- ### $afkTimeout[] # $afkTimeout[] — AFK Delay `$afkTimeout[]` returns the inactivity delay configured on the server, after which an inactive member in a voice channel is automatically moved to the AFK channel. ## Syntax ``` $afkTimeout ``` ## Parameters No parameters. ## Return value - **Type**: `integer` - The delay in seconds. Possible values are: 60, 300, 900, 1800, 3600. | Seconds | Equivalent | |----------|------------| | 60 | 1 minute | | 300 | 5 minutes | | 900 | 15 minutes | | 1800 | 30 minutes | | 3600 | 1 hour | ## Usage ### Formatted display ```bdfd $var[timeout;$afkTimeout] $if[$var[timeout]>=3600] $var[timeoutText;$round[$divide[$var[timeout];3600]] hour(s)] $elseIf[$var[timeout]>=60] $var[timeoutText;$round[$divide[$var[timeout];60]] minute(s)] $else $var[timeoutText;$var[timeout] second(s)] $endif $sendMessage[💤 AFK Delay: **$var[timeoutText]**] ``` ### Server configuration ```bdfd $title[⚙️ Settings of $serverName] $addField[💤 AFK Channel;$if[$afkChannelID!=]<#$afkChannelID>$elseNone$endif;yes] $addField[⏱️ AFK Delay;$round[$divide[$afkTimeout;60]] minutes;yes] $color[#5865F2] $sendEmbedMessage ``` ### Alert if delay is very short ```bdfd $if[$afkTimeout<=60] $sendMessage[⚠️ The AFK delay is very short (1 minute). Members will be moved quickly.] $endif ``` ## Notes - The AFK channel is configured separately; use `$afkChannelID[]` to retrieve it. - If no AFK channel is configured, the timeout has no effect. - Discord limits the possible values to the list above (no custom values). - Members in the AFK channel are automatically muted. --- ### $allMembersCount # $allMembersCount The `$allMembersCount` function **retrieves the total number of members** on the server, including bots. ## Syntax ``` $allMembersCount ``` ## Parameters No parameters. ## Return value - **Type**: String (number) - The total number of members (users + bots) present on the server. ## Behavior - Counts all members of the server, including bots. - Differs from `$membersCount` which only counts human users. - The value is updated in real time. ## Examples ### Simple display ```bdfd $title[📊 Server Statistics] $description[ **Total Members:** $allMembersCount **Humans:** $membersCount **Bots:** $botCount ] $color[#5865F2] $sendMessage[] ``` ### Comparison of humans vs bots ```bdfd $let[humans;$membersCount] $let[bots;$botCount] $let[total;$allMembersCount] $title[👥 Server Composition] $description[ **Total:** $total members **👤 Humans:** $humans ($math[$humans*100/$total]%) **🤖 Bots:** $bots ($math[$bots*100/$total]%) ] $color[#57F287] $sendMessage[] ``` ### Welcome counter ```bdfd $title[🎉 Welcome to $serverName!] $description[ You are member number **$allMembersCount** of the server! ] $thumbnail[$userAvatar[$authorID]] $sendMessage[$channelID[welcome]] ``` ## Notes - Only includes members currently present on the server. - To get only humans, use `$membersCount`. - To get only bots, use `$botCount`. --- ### $authorAvatar # $authorAvatar The variable `$authorAvatar` returns the **URL of the global avatar** of the author of the message that triggered the command. ## Syntax ``` $authorAvatar ``` ## Return value - **Type**: Character string (URL) - URL of the avatar of the author (Discord CDN) - Default avatar if the author does not have a custom avatar ## Behavior - `$authorAvatar` takes **no arguments**. - Equivalent to `$userAvatar` for text commands. - The URL points to the Discord CDN. ## Examples ### Large avatar ```bdfd $title[Avatar of $authorUsername] $image[$authorAvatar] $color[#5865F2] $sendMessage[] ``` ### Author of embed with avatar ```bdfd $author[$authorUsername;$authorAvatar] $title[Message] $description[Message content...] $color[#5865F2] $sendMessage[] ``` ### Complete profile ```bdfd $author[$authorUsername;$authorAvatar] $title[Profile of $authorUsername] $thumbnail[$authorAvatar] $description[ **Name:** $authorUsername **ID:** $authorID ] $color[#5865F2] $sendMessage[] ``` ## Notes - For the server-specific avatar, use `$userServerAvatar`. - Parameters like `?size=` can be added to the URL to change the resolution. - The avatar can be modified by the user at any time. --- ### $authorBanner # $authorBanner The variable `$authorBanner` returns the **URL of the profile banner** of the author of the message. Banners are reserved for Discord Nitro subscribers. ## Syntax ``` $authorBanner ``` ## Return value - **Type**: Character string (URL) or empty string - Discord CDN URL if the author has a Nitro banner - Empty string if the author does not have a banner ## Behavior - `$authorBanner` takes **no arguments**. - Equivalent to `$userBanner` for text commands. - Only Nitro subscribers can define a banner. ## Examples ### Display the banner ```bdfd $if[$authorBanner!=] $title[Banner of $authorUsername] $image[$authorBanner] $color[$userBannerColor] $sendMessage[] $else $sendMessage[$authorUsername does not have a Nitro banner.] $endif ``` ### Complete profile ```bdfd $author[$authorUsername;$authorAvatar] $title[Profile of $authorUsername] $description[**ID:** $authorID] $image[$authorBanner] $thumbnail[$authorAvatar] $color[$userBannerColor] $sendMessage[] ``` ## Notes - Always check if `$authorBanner` is not empty before using it as an embed image. - For the accent color of the banner, use `$userBannerColor`. --- ### $authorID # $authorID The variable `$authorID` returns the **Discord ID** of the author of the message that triggered the execution of the command. ## Syntax ``` $authorID ``` ## Return value - **Type**: Snowflake (numeric string of 17-19 digits) - The unique ID of the message author ## Behavior - `$authorID` takes **no arguments**. - In the context of a text command, `$authorID` is the ID of the person who sent the message. - In most simple cases, `$authorID` and `$userID` are identical. ## Examples ### Profile of the author ```bdfd $title[Profile of $authorUsername] $author[$authorUsername;$authorAvatar] $description[ **ID:** $authorID **Tag:** $authorTag ] $color[#5865F2] $sendMessage[] ``` ### Owner verification ```bdfd $if[$authorID==123456789012345678] $sendMessage[Hello owner!] $endif ``` ## Notes - `$authorID` is the ID of the **author of the message**, whereas `$userID` is the ID of the **triggering user**. In text commands, they are identical. - Use `$authorID` for better semantic clarity in message-related code. --- ### $authorTag # $authorTag The variable `$authorTag` returns the **complete tag** of the author of the message. This is the equivalent of `$userTag` but explicitly linked to the author of the message. ## Syntax ``` $authorTag ``` ## Return value - **Type**: Character string - Old format: `username#discriminator` for legacy accounts - New format: simply the username for new accounts ## Behavior - `$authorTag` takes **no arguments**. - Equivalent to `$userTag` in the context of a text command. - For new accounts, the tag is identical to the username. ## Examples ### Profile of the author ```bdfd $title[Profile of $authorTag] $author[$authorUsername;$authorAvatar] $description[ **Name:** $authorUsername **Tag:** $authorTag **ID:** $authorID ] $color[#5865F2] $sendMessage[] ``` ## Notes - The `username#discriminator` format is obsolete for new Discord accounts. - For reliable identification, use `$authorID`. - `$authorTag` and `$userTag` are generally identical in text commands. --- ### $authorUsername # $authorUsername The variable `$authorUsername` returns the **global username** of the author of the message that triggered the command. ## Syntax ``` $authorUsername ``` ## Return value - **Type**: Character string - The global username of the author ## Behavior - `$authorUsername` takes **no arguments**. - Equivalent to `$username` for text commands. - Returns the **global** username (not the server nickname). ## Examples ### Message from the author ```bdfd $title[Command executed] $author[$authorUsername;$authorAvatar] $description[ **Author:** $authorUsername#$discriminator **ID:** $authorID ] $color[#5865F2] $sendMessage[] ``` ## Notes - To get the server nickname of the author, use `$nickname` or `$displayName`. - `$authorUsername` is useful for explicitly referencing the author of the message in logs or embeds. - In most cases, `$username` and `$authorUsername` are interchangeable. --- ### $boostCount # $boostCount The `$boostCount` function **retrieves the number of active server boosts** (Nitro server boosts) on the current server. ## Syntax ``` $boostCount ``` ## Parameters No parameters. ## Return value - **Type**: String (number) - The number of Nitro boosts currently active on the server. ## Behavior - Counts the boosts of all members who have boosted the server. - Each user can provide 1 or 2 boosts depending on their Nitro tier. - The value influences the boost level of the server ($boostTier). ## Examples ### Boost Statistics ```bdfd $title[🚀 Server Boosts] $description[ **Number of boosts:** $boostCount **Level:** Level $boostTier **Next level:** $boostRequired boosts required ] $thumbnail[$serverIcon] $color[#F47FFF] $sendMessage[] ``` ### Thank-you message ```bdfd $title[💜 Boost detected!] $description[ Thank you **$username** for your boost! The server now has **$boostCount** boosts and is at **level $boostTier**! ] $color[#9B59B6] $sendMessage[$channelID[boosts]] ``` ### Progress bar ```bdfd $let[current;$boostCount] $let[needed;$boostRequired] $title[📈 Boost Progression] $description[ **$current / $needed** boosts for the next level Progression: $math[$current*100/$needed]% ] $color[#F47FFF] $sendMessage[] ``` ## Notes - Boosts are tied to members' Nitro subscriptions. - The boost is removed if the member leaves the server or stops their subscription. - For the current level, use `$boostTier` (1, 2, or 3). --- ### $boostLevel[] # $boostLevel[] — Server Boost Level `$boostLevel[]` returns the current Nitro boost level of the server, a value between 0 and 3. ## Syntax ``` $boostLevel ``` ## Parameters No parameters. ## Return value - **Type**: `integer` - An integer from 0 to 3: | Level | Boosts required | Main Advantages | |--------|---------------|---------------------| | 0 | 0 | No advantages | | 1 | 2 | +50 emoji slots, animated icon, 128 kbps audio | | 2 | 7 | Server banner, 256 kbps audio, +100 emojis | | 3 | 14 | Custom URL, 384 kbps audio, +150 emojis | ## Usage ### Simple display ```bdfd $sendMessage[🚀 Boost Level: **$boostLevel** ($serverBoostCount boosts)] ``` ### Embed of progression ```bdfd $var[boostsNeeded;0] $if[$boostLevel==0] $var[boostsNeeded;$sub[2;$serverBoostCount]] $var[nextLevel;1] $elseIf[$boostLevel==1] $var[boostsNeeded;$sub[7;$serverBoostCount]] $var[nextLevel;2] $elseIf[$boostLevel==2] $var[boostsNeeded;$sub[14;$serverBoostCount]] $var[nextLevel;3] $else $var[boostsNeeded;0] $var[nextLevel;MAX] $endif $title[🚀 Boost — $serverName] $addField[Current Level;$boostLevel;yes] $addField[Boosts;$serverBoostCount;yes] $if[$boostLevel<3] $addField[Next Level;$var[boostsNeeded] boosts remaining for level $var[nextLevel];yes] $endif $color[#F47FFF] $sendEmbedMessage ``` ### Checking perks ```bdfd $if[$boostLevel>=1] $sendMessage[✅ Animated icon available] $endif $if[$boostLevel>=2] $sendMessage[✅ Server banner available] $endif $if[$boostLevel>=3] $sendMessage[✅ Custom URL available] $endif ``` ### Info server with boost ```bdfd $title[$serverName] $addField[🚀 Boost Level;$boostLevel ($serverBoostCount boosts);yes] $addField[🎨 Emojis;$emojiCount;yes] $addField[🔊 Audio Quality;$if[$boostLevel>=3]384 kbps$elseIf[$boostLevel>=2]256 kbps$elseIf[$boostLevel>=1]128 kbps$elseStandard$endif;yes] $thumbnail[$serverIcon] $color[#F47FFF] $sendEmbedMessage ``` ## Notes - The boost level is calculated automatically depending on the number of Nitro boosts. - Each tier unlocks cumulative perks (level 3 includes level 1 and 2 perks). - Expired boosts are automatically removed. - To get the exact number of boosts, use `$serverBoostCount[]`. --- ### $botCommands # $botCommands The `$botCommands` function **returns the list of names of all commands** registered on the bot, separated by newlines. ## Syntax ``` $botCommands ``` ## Parameters None. ## Return value - **Type**: String - A list of commands, one per line (e.g., `help`, `ping`, `ban`...). ## Behavior - Returns both prefix and slash commands. - Each command appears on a new row. - The order matches the organization in the BDFD console. ## Examples ### Basic help command ```bdfd $title[📚 Commands of $botName] $description[ Here are all my commands: ``` $botCommands ``` ] $footer[Total: $commandsCount commands] $color[#5865F2] $sendMessage[] ``` ### Paged help ```bdfd $var[cmds;$botCommands] $var[lines;$textSplit[$var[cmds];\n]] $var[pages;$math[$arrayLength[$var[lines]]/10]] $var[page;$message[1]] $if[$isInteger[$var[page]]==false] $var[page;1] $endif $title[📚 Commands (page $var[page]/$var[pages])] $description[ $arraySlice[$var[lines];$math[($var[page]-1)*10];10] ] $footer[Total: $commandsCount commands] $sendMessage[] ``` ### Search for a command ```bdfd $var[search;$message[1]] $if[$var[search]==] $sendMessage[❌ Usage: !search ] $stop $endif $var[results;$advancedTextSplit[$botCommands;\n;$var[search]]] $if[$arrayLength[$var[results]]==0] $sendMessage[❌ No commands found for "$var[search]".] $else $title[🔍 Results for "$var[search]"] $description[$arraySlice[$var[results];0;20]] $sendMessage[] $endif ``` ## Notes - Commands are returned as plain text (one per line). - For the total number of commands, use `$commandsCount`. - For the number of slash commands only, use `$slashCommandsCount`. - `$botCommands` can be very large on bots with many commands. --- ### $botCount[] # $botCount[] — Number of Bots `$botCount[]` returns the number of bot accounts present on the Discord server. ## Syntax ``` $botCount ``` ## Parameters No parameters. ## Return value - **Type**: `integer` - The number of bots on the server. ## Usage ### Simple display ```bdfd $sendMessage[🤖 **$botCount** bots on this server.] ``` ### Human/Bot Ratio ```bdfd $var[humans;$sub[$membersCount;$botCount]] $title[📊 Composition of $serverName] $addField[👤 Humans;$var[humans];yes] $addField[🤖 Bots;$botCount;yes] $addField[👥 Total;$membersCount;yes] $color[#5865F2] $sendEmbedMessage ``` ### Alert if too many bots ```bdfd $if[$botCount>$var[humans]] $sendMessage[⚠️ There are more bots ($botCount) than humans ($var[humans])!] $endif ``` ### Complete Statistics ```bdfd $title[📊 Statistics for $serverName] $addField[👥 Total;$membersCount;yes] $addField[👤 Humans;$sub[$membersCount;$botCount];yes] $addField[🤖 Bots;$botCount;yes] $addField[🟢 Online;$onlineMembers;yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ## Notes - A "bot" is determined by the `bot` flag set on the Discord user account. - To get the number of humans, subtract `$botCount` from the total: `$sub[$membersCount;$botCount]`. - The bot running the command is included in this total. --- ### $botID # $botID The `$botID` function **returns the Discord ID (snowflake) of the bot**. This identifier is unique and permanent. ## Syntax ``` $botID ``` ## Parameters None. ## Return value - **Type**: String - The Discord ID of the bot (17-20 digits). E.g., `1234567890123456789`. ## Behavior - The ID is assigned by Discord upon the creation of the application. - It never changes, even if the bot is renamed. - It can be used for mentions (`<@ID>`), invites, and APIs. ## Examples ### Technical Information ```bdfd $title[🔍 Technical Information] $description[ **Name:** $botName **ID:** $botID **Owner:** $botOwnerID **Node:** $botNode ] $footer[Bot ID: $botID] $sendMessage[] ``` ### Custom Invite Link ```bdfd $sendMessage[🔗 **Invite me:** https://discord.com/oauth2/authorize?client_id=$botID&permissions=8&scope=bot%20applications.commands] ``` ### Identity Verification ```bdfd $if[$authorID==$botID] $sendMessage[I do not reply to my own messages!] $stop $endif $sendMessage[Message received, $userName!] ``` ### Mention the Bot ```bdfd $sendMessage[🤖 <@$botID> is online!] ``` ## Notes - `$botID` is constant and never changes. - To get the owner's ID, use `$botOwnerID`. - For the name, use `$botName`. - Mentioning the bot: `<@$botID>`. --- ### $botListDescription # $botListDescription The `$botListDescription[text]` function **sets or returns the description of the bot** as it appears on the public BDFD bot list. ## Syntax ``` $botListDescription[text] ``` To read the current description: ``` $botListDescription ``` ## Parameters | Parameter | Description | |---|---| | `text` | Optional - The new description to set. If omitted, returns the current description. | ## Return value - **Type**: String - If called without a parameter: the current description. - If called with a parameter: nothing (the description is updated). ## Behavior - The description is visible on the bot's public page in the BDFD Bot List. - Character limit: generally 200-300 characters. - Basic markdown may be supported depending on the list. ## Examples ### Set the description ```bdfd $var[desc;$message[1]] $if[$var[desc]==] $sendMessage[❌ Usage: !setdesc ] $stop $endif $botListDescription[$var[desc]] $sendMessage[✅ Bot description updated!] ``` ### Display the current description ```bdfd $title[📋 Description of the bot] $description[ $botListDescription ] $footer[Use !setdesc to modify] $sendMessage[] ``` ### Owner command to manage visibility ```bdfd $if[$authorID!=$botOwnerID] $sendEphemeral[❌ Reserved for the owner.] $stop $endif $var[action;$message[1]] $if[$var[action]==set] $botListDescription[$message[2]] $sendMessage[✅ Description updated.] $elseif[$var[action]==show] $sendMessage[📋 **Current description:** $botListDescription] $else $sendMessage[❌ Usage: !botlist [description]] $endif ``` ## Notes - Without parameters, the function returns the current description. - With a parameter, it overwrites the previous description. - To hide the bot from the list, use `$botListHide`. - The update may take a few minutes before becoming visible. --- ### $botListHide # $botListHide The `$botListHide` function **removes the bot from the public BDFD bot list**. Once hidden, the bot will no longer appear in the community directory. ## Syntax ``` $botListHide ``` ## Parameters None. ## Return value None. The bot is hidden from the public list. ## Behavior - Irreversible action via script (contact support to make the bot visible again). - The bot continues to function normally. - Only visibility in the BDFD directory is affected. ## Examples ### Simple hiding ```bdfd $botListHide $sendMessage[🔒 The bot has been removed from the public BDFD list.] ``` ### Secured owner command ```bdfd $if[$authorID!=$botOwnerID] $sendEphemeral[❌ This command is reserved for the owner.] $stop $endif $botListHide $sendMessage[✅ **$botName** has been hidden from the BDFD bot list. ⚠️ This action is permanent. Contact support to undo.] ``` ### Configuration panel ```bdfd $if[$authorID!=$botOwnerID] $sendEphemeral[❌ Reserved for the owner.] $stop $endif $var[action;$message[1]] $if[$var[action]==hide] $botListHide $sendMessage[🔒 Bot hidden.] $elseif[$var[action]==desc] $botListDescription[$message[2]] $sendMessage[📝 Description updated.] $else $sendMessage[❌ Usage: !botconfig [text]] $endif ``` ## Notes - `$botListHide` is permanent via script. - To manage the description, use `$botListDescription[]`. - The bot remains fully functional even when hidden. - Use this function if you do not want your bot to appear in the public directory. --- ### $botName # $botName The `$botName` function **returns the current username of the bot** as it appears on Discord. ## Syntax ``` $botName ``` ## Parameters None. ## Return value - **Type**: String - The username of the bot (e.g., `MySuperBot`). ## Behavior - Returns the username of the bot, not the server display name (nickname). - The name is the one configured in the Discord Developer Portal. - Updates automatically if the bot is renamed. ## Examples ### Welcome message ```bdfd $title[👋 Welcome to $serverName!] $description[ I am **$botName**, your assistant. Type `!help` to see my commands. ] $thumbnail[$botAvatar] $color[#5865F2] $sendMessage[] ``` ### About page ```bdfd $title[🤖 About $botName] $addField[Name;$botName;yes] $addField[ID;$botID;yes] $addField[Owner;<@$botOwnerID>;yes] $addField[Commands;$commandsCount;yes] $addField[Node;$botNode;yes] $thumbnail[$botAvatar] $color[#57F287] $sendMessage[] ``` ### Introduction ```bdfd $sendMessage[Hello! I am $botName, a versatile bot created with BDFD. 💪] ``` ## Notes - `$botName` is read-only. - To change the name of the bot, use `$changeUsername[]`. - To get the ID of the bot, use `$botID`. - For the avatar, use `$botAvatar`. --- ### $botNode # $botNode The `$botNode` function **returns the identifier of the node (runner)** on which the BDFD bot is currently running. Each bot is assigned to a specific runner of the BDFD infrastructure. ## Syntax ``` $botNode ``` ## Parameters None. ## Return value - **Type**: String - The identifier of the node (e.g., `node-14`, `us-east-3`). ## Behavior - The node is assigned automatically by BDFD. - It can change during a migration or maintenance. - Useful for diagnostics and technical support. ## Examples ### Technical Information Page ```bdfd $title[🔧 Technical Information] $addField[🤖 Bot;$botName;yes] $addField[🆔 ID;$botID;yes] $addField[📦 Node;$botNode;yes] $addField[⚡ Runtime;$nodeVersion;yes] $addField[📝 Language;$scriptLanguage;yes] $footer[Hosting expires: $hostingExpireTime] $color[#5865F2] $sendMessage[] ``` ### Debug command (owner only) ```bdfd $if[$authorID!=$botOwnerID] $sendEphemeral[❌ Reserved for the owner.] $stop $endif $title[🛠️ Debug Bot] $description[ **Name:** $botName **ID:** $botID **Node:** $botNode **Runtime:** $nodeVersion **Language:** $scriptLanguage **Commands:** $commandsCount **CPU:** $cpu **RAM:** $ram ] $sendMessage[] ``` ### Message signature ```bdfd $sendMessage[Message processed by $botName] $footer[Node: $botNode | $nodeVersion] ``` ## Notes - The node is managed automatically by BDFD. - In case of performance issues, provide your `$botNode` to BDFD support. - For the version of the runtime, use `$nodeVersion`. - For the script language, use `$scriptLanguage`. --- ### $botOwnerID # $botOwnerID The `$botOwnerID` function **returns the Discord ID of the bot owner**, as configured in the BDFD console. ## Syntax ``` $botOwnerID ``` ## Parameters None. ## Return value - **Type**: String - The Discord ID of the bot owner. ## Behavior - Returns the ID of the account that registered the bot on BDFD. - Fixed ID, only changes if the bot is transferred. - Can be used for special privileges or notifications. ## Examples ### Owner contact command ```bdfd $var[motif;$message[1]] $if[$var[motif]==] $sendMessage[❌ Usage: !contact ] $stop $endif $sendDM[$botOwnerID;📬 **Contact from $userName** ($authorID) Server: $serverName ($guildID) Message: $var[motif]] $sendMessage[✅ Your message has been forwarded to the bot owner.] ``` ### Owner-only access ```bdfd $if[$authorID!=$botOwnerID] $sendEphemeral[❌ This command is reserved for the bot owner.] $stop $endif ;; Code reserved for the owner $sendMessage[✅ Owner command executed.] ``` ### Information bot ```bdfd $title[🤖 $botName] $addField[Owner;<@$botOwnerID>;yes] $addField[ID;$botID;yes] $addField[Node;$botNode;yes] $addField[Version;$nodeVersion;yes] $thumbnail[$botAvatar] $color[#5865F2] $sendMessage[] ``` ## Notes - Fixed ID, does not change without a transfer of ownership. - Mentioning the owner: `<@$botOwnerID>`. - To get the name of the owner, use `$userName[$botOwnerID]` (requires a shared server). - To send a message to the owner, use `$sendDM[$botOwnerID;message]`. --- ### $byteCount # $byteCount The `$byteCount[]` function **calculates the number of bytes** of a given text. Useful for checking Discord message size limits or evaluating data size. ## Syntax ``` $byteCount[text] ``` ## Parameters | Parameter | Description | |---|---| | `text` | The text of which you want to know the size in bytes. | ## Return value - **Type**: String (number) - The number of bytes that the text represents. ## Behavior - Counts bytes, not characters (a Unicode character can be multiple bytes). - ASCII characters count as 1 byte, while emojis and accented characters count for more. - Useful for validating data before storage or sending. ## Examples ### Checking before sending ```bdfd $let[size;$byteCount[$message]] $if[$size>2000] $sendMessage[⚠️ Message too long ($size bytes). Discord limit: 2000 characters.] $else $sendMessage[$message] $endif ``` ### Checking stored data ```bdfd $let[data;$getVar[userData]] $let[size;$byteCount[$data]] $title[📦 User Data] $description[ **Size:** $size bytes ($math[$size/1024] KB) **Number of characters:** $length[$data] ] $sendMessage[] ``` ### Size comparison ```bdfd $let[ascii;$byteCount[Hello World]] $let[unicode;$byteCount[Héllö Wörld]] $let[emoji;$byteCount[Hello 👋]] ASCII: $ascii bytes Unicode (accents): $unicode bytes With emoji: $emoji bytes ``` ## Notes - `$byteCount` differs from `$length`: `$length` counts characters, `$byteCount` counts bytes. - With pure ASCII text, both values are identical. - Discord limits messages to 2000 characters (not bytes), but this function remains useful for storage calculations. --- ### $categoryChannels # $categoryChannels The `$categoryChannels` function returns a list of channels belonging to a specific category, identified by its ID. ## Syntax ``` $categoryChannels[categoryID;(separator)] ``` ## Parameters | Parameter | Description | |---|---| | `categoryID` | The ID of the category. Required. | | `separator` | Optional. Separator between the channel names. Default is `, `. | ## Return value | Type | Description | |---|---| | `string` | The channel names in the category, separated by the delimiter. | ## Examples ### Channels in the current category ```bdfd $sendMessage[**Channels in this category:** $categoryChannels[$categoryID]] ``` ### List with newlines ```bdfd $sendMessage[ **Channels in the category:** $categoryChannels[$categoryID; ]] ``` ### Channels of a specific category ```bdfd $sendMessage[Admin channels: $categoryChannels[123456789012345678]] ``` ### Check if a category is empty ```bdfd $if[$categoryChannels[$categoryID]==] $sendMessage[This category does not contain any channels.] $endif ``` ## Notes - Only lists channels visible to the bot. - The category itself is not included in the list. - To list all channels on the server, use `$channelNames`. --- ### $categoryCount # $categoryCount The `$categoryCount` function returns the **total number of categories** present on the Discord server. ## Syntax ``` $categoryCount ``` ## Parameters No parameters. ## Return value | Type | Description | |---|---| | `integer` | The number of categories on the server. | ## Examples ### Number of categories ```bdfd $sendMessage[This server has $categoryCount categories.] ``` ### Comparison of channels and categories ```bdfd $sendMessage[ **Server Statistics:** Categories: $categoryCount Channels: $channelCount ] ``` ### Server without categories ```bdfd $if[$categoryCount==0] $sendMessage[This server has no categories.] $endif ``` ## Notes - Only counts channels of type `category`. - Useful for statistics or displaying the server structure. --- ### $categoryID # $categoryID The `$categoryID` function is an **alias** of `$channelCategoryID`. It returns the ID of the category to which the current (or specified) channel belongs. ## Syntax ``` $categoryID[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return value | Type | Description | |---|---| | `snowflake` (string) | The ID of the parent category, or an empty string if the channel is not in a category. | ## Examples ### Get the ID of the category ```bdfd $sendMessage[Category ID: $categoryID] ``` ### Display the name of the category ```bdfd $if[$categoryID!=] $sendMessage[Category: $channelName[$categoryID]] $else $sendMessage[This channel is not in a category.] $endif ``` ### List channels in the same category ```bdfd $sendMessage[Other channels in this category: $categoryChannels[$categoryID]] ``` ## Notes - `$categoryID` and `$parentID` are aliases of `$channelCategoryID`. - Returns an empty string for channels not in a category and DMs. --- ### $channelCategoryID # $channelCategoryID The `$channelCategoryID` function returns the **ID of the parent category** of a Discord channel. If the channel does not belong to any category, the function returns an empty string. ## Syntax ``` $channelCategoryID[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return value | Type | Description | |---|---| | `snowflake` (string) | The ID of the parent category, or `""` if none. | ## Examples ### Get the parent category ```bdfd $sendMessage[Category ID: $channelCategoryID] ``` ### Name of the parent category ```bdfd $sendMessage[Category name: $channelName[$channelCategoryID]] ``` ### Check category membership ```bdfd $if[$channelCategoryID==123456789012345678] $sendMessage[This channel is in the Administration category.] $else $sendMessage[This channel is in another category.] $endif ``` ### Channel not in a category ```bdfd $if[$channelCategoryID==] $sendMessage[This channel does not belong to any category.] $endif ``` ## Notes - `$parentID` and `$categoryID` are aliases of `$channelCategoryID`. - DM channels do not have a parent category. - Categories themselves do not have a parent category. --- ### $channelCount # $channelCount The `$channelCount` function returns the **number of channels** on the Discord server. By providing a category ID, it can also count the channels in a specific category. ## Syntax ``` $channelCount[(categoryID)] ``` ## Parameters | Parameter | Description | |---|---| | `categoryID` | Optional. The ID of a category to count only its channels. If omitted, all channels on the server are counted. | ## Return value | Type | Description | |---|---| | `integer` | The number of channels matching the filter. | ## Examples ### Total number of channels ```bdfd $sendMessage[This server has $channelCount channels.] ``` ### Channels in a category ```bdfd $sendMessage[The category contains $channelCount[123456789012345678] channels.] ``` ### Comparison ```bdfd $if[$channelCount>50] $sendMessage[This server is huge! ($channelCount channels)] $else $sendMessage[This server has $channelCount channels.] $endif ``` ## Notes - Counts all types of channels (text, voice, etc.), except the categories themselves. - To count categories, use `$categoryCount`. - Private channels (not visible to the bot) are not counted. --- ### $channelExists # $channelExists The `$channelExists` function checks if a **Discord channel exists** on the server by its ID. Useful for ensuring a target channel is always valid before interacting with it. ## Syntax ``` $channelExists[channelID] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the channel to check. Required. | ## Return value | Type | Description | |---|---| | `string` | `"true"` if the channel exists on the server, `"false"` otherwise. | ## Examples ### Simple check ```bdfd $if[$channelExists[123456789012345678]==true] $sendMessage[The channel is valid.] $else $sendMessage[The channel does not exist.] $endif ``` ### Check before sending a message ```bdfd $if[$channelExists[123456789012345678]==true] $channelSendMessage[123456789012345678;Automated message] $else $sendMessage[The log channel no longer exists!] $endif ``` ## Notes - The returned value is a string `"true"` or `"false"`. - Only checks channels on the current server. - Useful in log or configuration systems where IDs are stored. --- ### $channelID # $channelID The `$channelID` function returns the **unique identifier** (snowflake) of the Discord channel in which the command is currently executed. ## Syntax ``` $channelID ``` ## Parameters No parameters. ## Return value | Type | Description | |---|---| | `snowflake` | The ID of the current channel, in the form of a numeric string (e.g., `123456789012345678`). | ## Examples ### Display the ID of the channel ```bdfd $sendMessage[ID of this channel: $channelID] ``` ### Link direct vers the channel ```bdfd $sendMessage[Link to the channel: https://discord.com/channels/$guildID/$channelID] ``` ### Compareason with a channel specific ```bdfd $if[$channelID==123456789012345678] $sendMessage[This is the channel principal !] $else $sendMessage[You are in the channel $channelID] $endif ``` ## Notes - The returned ID is that of the channel where the command was **triggered**, even if the bot subsequently interacts with other channels. - In direct messages (DMs), `$channelID` returns the ID of the DM channel. - Useful to combine with `$findChannel` or `$channelSendMessage` for multi-channel operations. --- ### $channelIDFromName # $channelIDFromName The `$channelIDFromName` function returns the **ID** of a Discord channel from its **name**. The search is case-insensitive. ## Syntax ``` $channelIDFromName[name] ``` ## Parameters | Parameter | Description | |---|---| | `name` | The name of the channel to search for. Case-insensitive (e.g. `general` = `General`). | ## Return value | Type | Description | |---|---| | `snowflake` (string) | The ID of the channel found, or `""` if no channel matches. | ## Examples ### Get the ID ```bdfd $sendMessage[ID of general: $channelIDFromName[general]] ``` ### Send to a channel by name ```bdfd $channelSendMessage[$channelIDFromName[announcements];New update available!] ``` ### Check existence ```bdfd $if[$channelIDFromName[logs]!=] $sendMessage[Channel #logs found! ID : $channelIDFromName[logs]] $else $sendMessage[No #logs channel found.] $endif ``` ### Troubleshooting similar names ```bdfd $if[$channelIDFromName[general]!=] $sendMessage[Channel general found.] $else $sendMessage[Error: channel not found. Try another name.] $endif ``` ## Notes - If multiple channels share the same name, only the first one found is returned. - Use `$findChannel` for a more advanced search with partial queries. - The name must not include the `#` prefix. --- ### $channelName # $channelName The `$channelName` function returns the **name** of a Discord channel. By default, it returns the name of the channel where the command is executed, but it can also return the name of a specific channel if an ID is provided. ## Syntax ``` $channelName[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return value | Type | Description | |---|---| | `string` | The name of the channel (e.g., `general`, `announcements`). | ## Examples ### Name of the current channel ```bdfd $sendMessage[Welcome to #$channelName!] ``` ### Name of a specific channel ```bdfd $sendMessage[The channel is: $channelName[123456789012345678]] ``` ### Check the name of a channel ```bdfd $if[$channelName==general] $sendMessage[You are in the general channel.] $endif ``` ## Notes - For text channels, the name is returned without the `#` prefix. Add it manually if needed. - The name of voice channels is displayed in the same way (e.g., `Voice 1`). - To list all channels, use `$channelNames`. --- ### $channelNames # $channelNames The `$channelNames` function returns the **complete list of names** of all channels on the server, separated by a customizable delimiter. ## Syntax ``` $channelNames[(separator)] ``` ## Parameters | Parameter | Description | |---|---| | `separator` | Optional. The separator between each channel name. Default: `, ` (comma + space). | ## Return value | Type | Description | |---|---| | `string` | All channel names concatenated with the chosen separator. | ## Examples ### Simple list ```bdfd $sendMessage[**Server channels:** $channelNames] ``` ### List with newlines ```bdfd $sendMessage[**List of channels:** $channelNames[ ]] ``` ### List with custom separator ```bdfd $sendMessage[Channels: $channelNames[ | ]] ``` ### Count channels by name ```bdfd $sendMessage[The server has $channelCount channels: $channelNames[, ]] ``` ## Notes - Only channels visible to the bot are listed. - Categories are included in the list. - To get IDs instead of names, use a loop with `$findChannel` instead. --- ### $channelNSFW # $channelNSFW The `$channelNSFW` function checks if a Discord channel is marked as **NSFW** (Not Safe For Work). It returns `"true"` or `"false"` in the form of a string. ## Syntax ``` $channelNSFW[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return value | Type | Description | |---|---| | `string` | `"true"` if the channel is NSFW, `"false"` otherwise. | ## Examples ### Simple check ```bdfd $if[$channelNSFW==true] $sendMessage[⚠️ This channel is marked as NSFW. Sensitive content is allowed.] $else $sendMessage[This channel is safe for work (SFW).] $endif ``` ### Block a command in an NSFW channel ```bdfd $if[$channelNSFW==true] $sendMessage[This command cannot be used in NSFW channels.] $stop $endif ``` ### Check a specific channel ```bdfd $if[$channelNSFW[123456789012345678]==true] $sendMessage[The target channel is NSFW.] $endif ``` ## Notes - The returned value is a **string** `"true"` or `"false"`, not a boolean. - Voice channels can also be marked as NSFW. - Useful for restricting access to certain commands depending on the channel type. --- ### $channelPosition # $channelPosition The `$channelPosition` function returns the **position** of a channel in the server's channel list. Position `0` corresponds to the topmost channel, and the numbers increase as you go down. ## Syntax ``` $channelPosition[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return value | Type | Description | |---|---| | `integer` | The position of the channel in the list (0 = at the top). | ## Examples ### Display the position ```bdfd $sendMessage[This channel is at position $channelPosition] ``` ### Comparer les positions ```bdfd $if[$channelPosition==0] $sendMessage[This channel is at the very top of the server!] $else $sendMessage[This channel is at position #$channelPosition] $endif ``` ### Top channel in a category ```bdfd $sendMessage[Position in the category: $channelPosition] ``` ## Notes - The position is relative to the display order in Discord. - Categories have their own positioning system. - The position can change if an administrator reorganizes the channels. - Channels are sorted by position within their parent category. --- ### $channelTopic # $channelTopic The `$channelTopic` function returns the **topic** of a Discord text channel. The topic is the text displayed at the top of the channel, generally used to describe its purpose. ## Syntax ``` $channelTopic[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return value | Type | Description | |---|---| | `string` | The topic of the channel. Returns an empty string if no topic is set or if the channel is not a text channel. | ## Examples ### Display the topic ```bdfd $sendMessage[**Channel Topic:** $channelTopic] ``` ### Check if a topic exists ```bdfd $if[$channelTopic!=] $sendMessage[Topic: $channelTopic] $else $sendMessage[This channel does not have a topic.] $endif ``` ### Topic in an embed ```bdfd $title[#$channelName] $description[Topic: $channelTopic] $color[#5865F2] $sendMessage[] ``` ## Notes - Only works for channels of type `text` and `news`. - For voice channels, categories, etc., the function returns an empty string. - Maximum length of a topic is 1024 characters. --- ### $channelType # $channelType The `$channelType` function returns the **type** of a Discord channel. Possible types include `text`, `voice`, `category`, `news`, `stage`, `forum`, and `dm`. ## Syntax ``` $channelType[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return value | Type | Description | |---|---| | `string` | The type of the channel. Possible values: `text`, `voice`, `category`, `news`, `stage`, `forum`, `dm`, `group_dm`. | ## Examples ### Display the type of the channel ```bdfd $sendMessage[This channel is of type: **$channelType**] ``` ### Check if voice channel ```bdfd $if[$channelType==voice] $sendMessage[You are in a voice channel.] $else $sendMessage[You are not in a voice channel.] $endif ``` ### Check if category ```bdfd $if[$channelType==category] $sendMessage[This command cannot be used on a category.] $stop $endif ``` ## Notes - Channel types are returned in lowercase. - Useful for conditioning the behavior of a command based on the channel type. - Channels of type `dm` do not have a parent category. --- ### $colorRole # $colorRole The `$colorRole` function returns the **hex color** of a user's highest colored role. Very useful for customizing embeds according to a user's role color. ## Syntax ``` $colorRole[userID;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user. Required. | | `guildID` | Optional. The ID of the target server. | ## Return value | Type | Description | |---|---| | `string` | Hex color code (e.g., `#5865F2`), or `""` if they have no colored role. | ## Examples ### Display the color ```bdfd $sendMessage[Your role color: $colorRole[$authorID]] ``` ### Custom embed ```bdfd $title[Profile of $username] $description[ **Role:** $roleName[$getRole[$authorID;1]] **Color:** $colorRole[$authorID] ] $color[$colorRole[$authorID]] $sendMessage[] ``` ### Color of another user ```bdfd $sendMessage[Color of <@$mentioned[1]>: $colorRole[$mentioned[1]]] ``` ### Fallback if no color ```bdfd $if[$colorRole[$authorID]!=] $color[$colorRole[$authorID]] $else $color[#5865F2] $endif $title[Profile] $description[User information] $sendMessage[] ``` ## Notes - Returns an empty string if the user does not have a role with a color. - The color is in the format hexadecimal with `#`. - Perfect for use with `$color[]` in embeds. - Unlike `$roleColor`, `$colorRole` targets a **user**, not a role. --- ### $commandFolder # $commandFolder The `$commandFolder` function **returns the name of the folder** in which the current command is organized in the BDFD console. ## Syntax ``` $commandFolder ``` ## Parameters None. ## Return value - **Type**: String - The name of the folder (e.g., `Moderation`, `Fun`, `Admin`, `Utils`). ## Behavior - Folders are defined in the BDFD command manager. - Useful for organizing logs, help, or permissions. - Returns an empty string if the command is at the root. ## Examples ### Organized log ```bdfd $log[📂 [$commandFolder] $userName executed $commandName] ``` ### Contextual help ```bdfd $title[📖 $commandName] $addField[📂 Category;$commandFolder;yes] $addField[⚡ Type;$commandType;yes] $addField[🔤 Trigger;$commandTrigger;yes] $description[ Complete help for the command... ] $sendMessage[] ``` ### Folder-based permissions ```bdfd $if[$commandFolder==Admin] $if[$hasRole[$roleID[Admin]]==false] $sendEphemeral[❌ Commands in the Admin folder are restricted.] $stop $endif $endif ;; Command executed normally $sendMessage[✅ Command executed.] ``` ### Home page per folder ```bdfd $if[$commandFolder==Moderation] $sendMessage[🛡️ **Moderation** - Server management commands.] $elseif[$commandFolder==Fun] $sendMessage[🎮 **Fun** - Entertainment commands.] $elseif[$commandFolder==Utils] $sendMessage[🔧 **Utility** - Useful commands.] $else $sendMessage[📂 Folder: $commandFolder] $endif ``` ## Notes - The name of the folder is the one set in the BDFD console. - Useful for command structuring and permissions. - Empty string if the command is not in a folder. --- ### $commandName # $commandName The `$commandName` function **returns the name of the command currently being executed**, as defined in the BDFD editor. ## Syntax ``` $commandName ``` ## Parameters None. ## Return value - **Type**: String - The name of the command (e.g., `help`, `ban`, `ping`). ## Behavior - Returns the internal name of the command, not the trigger. - The name is the one set in the BDFD console. - Useful for logs, contextual help, and detection. ## Examples ### Execution log ```bdfd $log[📌 $userName ($authorID) executed /$commandName in #$channelName on $serverName] ``` ### Contextual help ```bdfd $title[❓ Help: $commandName] $description[ **Command:** $commandName **Type:** $commandType **Folder:** $commandFolder **Trigger:** $commandTrigger ] $footer[Used by $userName] $sendMessage[] ``` ### Custom error handling ```bdfd $if[$message[1]==] $sendMessage[❌ Correct usage: $commandTrigger Type `!help $commandName` for more information.] $stop $endif ``` ### Usage statistics (via storage) ```bdfd $var[count;$getVar[usage_$commandName]] $var[count;$math[$var[count]+1]] $setVar[usage_$commandName;$var[count]] $log[📊 $commandName used $var[count] times] ``` ### Detection for specific behavior ```bdfd $if[$commandName==help] $sendMessage[📚 Here is the command list...] $elseif[$commandName==ping] $sendMessage[🏓 Pong! Latency: $ping ms] $else $sendMessage[Command $commandName executed.] $endif ``` ## Notes - `$commandName` returns the internal name, not the trigger (prefix). - For slash commands, the name corresponds to the application command name. - For the type (prefix/slash), use `$commandType`. - For the folder, use `$commandFolder`. --- ### $commandsCount # $commandsCount The `$commandsCount` function **returns the total number of commands** registered for the bot, including both prefix and slash commands. ## Syntax ``` $commandsCount ``` ## Parameters None. ## Return value - **Type**: Integer - The total number of commands (e.g., `42`). ## Behavior - Counts all commands, whether they are prefix or slash. - Updates automatically when commands are added or deleted. - Includes commands in all folders. ## Examples ### Bot information page ```bdfd $title[🤖 $botName] $addField[📊 Statistics;;yes] $addField[Total commands;$commandsCount;yes] $addField[Slash;$slashCommandsCount;yes] $addField[Prefix;$math[$commandsCount-$slashCommandsCount];yes] $thumbnail[$botAvatar] $color[#5865F2] $sendMessage[] ``` ### Comparison of servers and commands ```bdfd $title[📈 Global Statistics] $description[ **Servers:** $guildCount **Users:** $membersCount **Commands:** $commandsCount **Slash:** $slashCommandsCount **Runtime:** $nodeVersion ] $sendMessage[] ``` ### Update announcement ```bdfd $sendMessage[🎉 **New Update!** The bot now has **$commandsCount commands**! Type `/help` to discover them.] ``` ### Command limit (premium) ```bdfd $if[$premiumExpireTime==] $if[$commandsCount>=50] $sendMessage[⚠️ Limit of 50 commands reached (free version). Upgrade to premium to unlock more commands.] $else $sendMessage[📊 $commandsCount/50 commands used.] $endif $else $sendMessage[💎 $commandsCount commands (Premium - unlimited).] $endif ``` ## Notes - Includes all commands (prefix AND slash). - For slash commands only, use `$slashCommandsCount`. - To get the list of names, use `$botCommands`. - The limit varies depending on the subscription (free/premium). --- ### $commandTrigger # $commandTrigger The `$commandTrigger` function **returns the complete trigger** of the current command, including the prefix or the slash. For example, if the command `help` is triggered by `!help`, the returned trigger is `!help`. ## Syntax ``` $commandTrigger ``` ## Parameters None. ## Return value - **Type**: String - The complete trigger of the command (prefix + name, or `/name` for slash). ## Behavior - For prefix commands: returns the prefix + name (e.g., `!help`, `?ban`). - For slash commands: returns `/name` (e.g., `/help`). - The prefix depends on the configuration of the bot. ## Examples ### Error message with usage ```bdfd $if[$message[1]==] $sendMessage[❌ **Usage:** $commandTrigger Example: $commandTrigger @user Spam] $stop $endif ``` ### Contextual help ```bdfd $title[📖 Help: $commandName] $description[ **Command:** $commandTrigger **Type:** $commandType **Folder:** $commandFolder **Usage:** `$commandTrigger [param2]` **Example:** `$commandTrigger value1 optional` ] $sendMessage[] ``` ### Detailed log ```bdfd $log[📌 CMD | User: $username | Trigger: $commandTrigger | Name: $commandName | Type: $commandType | Server: $serverName] ``` ### Information in the embed ```bdfd $title[⚡ Execution] $addField[Command;$commandName;yes] $addField[Trigger;$commandTrigger;yes] $addField[Type;$commandType;yes] $addField[Author;$userName;yes] $addField[Folder;$commandFolder;yes] $footer[Executed on $formatDate[$dateStamp]] $sendMessage[] ``` ## Notes - `$commandTrigger` includes the prefix (e.g., `!help`), unlike `$commandName` (which returns `help`). - For the name without a prefix, use `$commandName`. - To determine if it is a slash command, use `$isSlash` or `$commandType`. - The prefix can be extracted using `$charAt[$commandTrigger;1]`. --- ### $commandType # $commandType The `$commandType` function **returns the type of the command currently being executed**: `prefix` for classic text commands, or `slash` for Discord slash commands. ## Syntax ``` $commandType ``` ## Parameters None. ## Return value - **Type**: String - `prefix`: Command triggered by a text prefix (`!`, `?`, etc.). - `slash`: Command triggered via the Discord slash interface (`/`). ## Behavior - Allows adapting the behavior based on the invocation type. - Functionally equivalent to `$if[$isSlash==true]slash$elseprefix$endif`. ## Examples ### Adaptive response ```bdfd $if[$commandType==slash] $sendEphemeral[✅ Operation successful!] $else $sendMessage[✅ Operation successful!] $endif ``` ### Differentiated log ```bdfd $if[$commandType==slash] $log[🔹 SLASH /$commandName by $username] $else $log[🔸 PREFIX $commandTrigger by $username] $endif ``` ### Contextual help ```bdfd $title[⚙️ Command details] $addField[Name;$commandName;yes] $addField[Trigger;$commandTrigger;yes] $addField[Type;$if[$commandType==slash]🔹 Slash$else🔸 Prefix$endif;yes] $addField[Folder;$commandFolder;yes] $footer[Language: $scriptLanguage] $sendMessage[] ``` ### Hybrid command with arguments ```bdfd ;; Retrieve arguments based on the type $if[$commandType==slash] $var[arg1;$slashOption[target]] $var[arg2;$slashOption[reason]] $else $var[arg1;$message[1]] $var[arg2;$message[2]] $endif $sendMessage[🎯 Target: $var[arg1] | Reason: $var[arg2]] ``` ## Related functions - [$slashOption](/docs/slashoption/) — read slash command option values by name or index ## Notes - Possible values: `prefix` or `slash`. - For a simple boolean check, use `$isSlash`. - Ephemeral responses (`$sendEphemeral[]`) only work with `slash` commands. - The type is configured in the BDFD console when creating the command. --- ### $creationDate # $creationDate The `$creationDate[]` function **retrieves the creation date** of a Discord entity from its ID (Snowflake). It works for users, servers, roles, channels, etc. ## Syntax ``` $creationDate[entityID] ``` ## Parameters | Parameter | Description | |---|---| | `entityID` | The Discord ID of the entity (user, server, role, channel, message, etc.). | ## Return value - **Type**: String - The creation date in the format `DD/MM/YYYY`. - Extracted from the timestamp contained within the Discord Snowflake ID. ## Behavior - Discord IDs (Snowflakes) contain a creation timestamp. - The function extracts this timestamp and formats it into a readable date. - Works for any type of Discord entity that has an ID. ## Examples ### User profile ```bdfd $title[👤 $userName[$authorID]] $description[ **Account created on:** $creationDate[$authorID] **Joined on:** $memberJoinDate[$authorID] **ID:** $authorID ] $thumbnail[$userAvatar[$authorID]] $sendMessage[] ``` ### Server info ```bdfd $title[📋 $serverName] $description[ **Created on:** $creationDate[$guildID] **Owner:** $userName[$ownerID] **Members:** $membersCount ] $thumbnail[$serverIcon] $sendMessage[] ``` ### Account Age ```bdfd $let[creation;$creationDate[$authorID]] Your Discord account was created on **$creation**. ``` ## Notes - Precision is down to the millisecond (the timestamp is included in the Snowflake). - The format may vary depending on the bot's regional settings. - Works only with valid Discord IDs. --- ### $discriminator # $discriminator The variable `$discriminator` returns the **legacy discriminator** of the user, i.e., the 4-digit code that was used to differentiate users with the same username (e.g., `JohnDoe#1234`). ## Syntax ``` $discriminator ``` ## Return value - **Type**: String - Old accounts: a 4-digit number (e.g., `"1234"`, `"0001"`) - New accounts (pomelo): `"0"` ## Behavior - `$discriminator` takes **no arguments**. - Since Discord's migration to unique usernames (pomelo system), new users no longer have a discriminator. - Accounts created before the migration retain their discriminator. ## Examples ### Detecting a legacy account ```bdfd $if[$discriminator!=0] $title[Legacy Account] $description[ **Full Tag:** $userTag **Discriminator:** $discriminator ] $color[#5865F2] $sendMessage[] $else $title[Pomelo Account] $description[ **Name:** $userName (No discriminator) ] $color[#57F287] $sendMessage[] $endif ``` ## Notes - The discriminator system is **deprecated** — Discord no longer assigns them to new accounts. - `$discriminator` returns `"0"` for pomelo accounts. - For reliable identification, always use `$userID`. --- ### $displayName # $displayName The variable `$displayName` returns the **display name** of the user on the server. This is the most relevant name in the server context: the nickname if defined, otherwise the global username. ## Syntax ``` $displayName ``` ## Return value - **Type**: String - Priority: server nickname (`$nickname`) > global username (`$userName`) ## Behavior - `$displayName` takes **no arguments**. - If the user has a **nickname** on the server, `$displayName` returns it. - Otherwise, it returns the **global username**. - This is the name that other members see on the server. ## Examples ### Welcome message ```bdfd $title[Welcome $displayName!] $description[ We are thrilled to welcome you to **$serverName**! ] $thumbnail[$userAvatar] $color[#57F287] $sendMessage[] ``` ### User profile ```bdfd $author[$displayName;$userAvatar] $title[User Profile] $description[ **Display Name:** $displayName **Global Name:** $userName **Server Nickname:** $nickname **ID:** $userID ] $color[#5865F2] $sendMessage[] ``` ## Notes - `$displayName` is the recommended choice to display a user's name in bot messages. - It reflects what members actually see on the server. - Differences: `$userName` (global username only), `$nickname` (server nickname only, can be empty), `$displayName` (the better of the two). --- ### $emojiCount # $emojiCount — Number of Emojis The `$emojiCount` function returns the total number of custom emojis available on the server, including both static and animated emojis. ## Syntax ``` $emojiCount ``` ## Parameters No parameters. ## Return value - **Type**: `integer` - The total number of custom emojis. ## Usage ### Simple display ```bdfd $sendMessage[🎨 There are **$emojiCount** custom emojis on this server!] ``` ### Emoji slots available ```bdfd $var[maxEmojiSlots;50] $if[$boostLevel==1] $var[maxEmojiSlots;100] $elseIf[$boostLevel==2] $var[maxEmojiSlots;150] $elseIf[$boostLevel==3] $var[maxEmojiSlots;250] $endif $var[remainingSlots;$sub[$var[maxEmojiSlots];$emojiCount]] $sendMessage[🎨 $emojiCount/$var[maxEmojiSlots] emoji slots used. $var[remainingSlots] remaining.] ``` ### Server Info Embed ```bdfd $title[📊 $serverName] $addField[🎨 Emojis;$emojiCount;yes] $addField[🏷️ Stickers;$stickerCount;yes] $addField[🚀 Boosts;$serverBoostCount;yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ### Warning if limit is almost reached ```bdfd $if[$emojiCount>=$var[maxEmojiSlots]] $sendMessage[⚠️ All emoji slots are used!] $elseIf[$emojiCount>=$sub[$var[maxEmojiSlots];10]] $sendMessage[⚠️ Only $sub[$var[maxEmojiSlots];$emojiCount] emoji slots are available.] $endif ``` ## Notes - The default emoji limit is 50 static + 50 animated emojis. - The server boost level increases these limits: - Level 1: 100 static + 100 animated - Level 2: 150 static + 150 animated - Level 3: 250 static + 250 animated - To get the complete list of emojis (not just the count), use `$serverEmojis`. --- ### $executionTime # $executionTime The `$executionTime` function **measures the total execution time** of the current command in milliseconds. ## Syntax ``` $executionTime ``` ## Parameters No parameters. ## Return value - **Type**: String (number) - The execution time in milliseconds (ms). - Includes the processing time of the entire command (parsing + execution). ## Behavior - Measures the elapsed time from the start of the command's processing up to the function call. - Useful for debugging and performance optimization. - The value is an integer representing the milliseconds. ## Examples ### Simple display ```bdfd $title[⚡ Performance] $description[ **Execution time:** $executionTime ms **API Ping:** $botPing ms ] $color[#5865F2] $sendMessage[] ``` ### Dynamic footer ```bdfd $title[📊 Statistics] $description[Complex command with a lot of data...] $footer[⏱️ Executed in $executionTime ms] $color[#57F287] $sendMessage[] ``` ### Slowness condition ```bdfd $if[$executionTime>1000] $sendMessage[⚠️ This command is slow (>1s). Optimization recommended.] $else $sendMessage[✅ Normal performance: $executionTime ms] $endif ``` ## Notes - The measured time depends on the complexity of the command and network latency. - `$executionTime` measures the time on the bot side, not the user latency. - For WebSocket/API latency, use `$botPing` or `$ping`. --- ### $findChannel # $findChannel The `$findChannel` function searches for a Discord channel by its **partial or full name** and returns its ID. The search is case-insensitive. ## Syntax ``` $findChannel[query] ``` ## Parameters | Parameter | Description | |---|---| | `query` | The name or part of the name of the channel to search for. | ## Return Value | Type | Description | |---|---| | `snowflake` (string) | The ID of the channel found, or an empty string (`""`) if no channel matches. | ## Examples ### Partial Name Search ```bdfd $sendMessage[Channel matching "gen": $findChannel[gen]] ``` ### Send a message in a found channel ```bdfd $channelSendMessage[$findChannel[logs];New event logged.] ``` ### Verify if the channel exists ```bdfd $if[$findChannel[announcements]!=] $sendMessage[Channel announcements found: <#$findChannel[announcements]>] $else $sendMessage[No channel matches "announcements".] $endif ``` ### Usage as a fallback ```bdfd $if[$channelIDFromName[general]!=] $sendMessage[General channel: $channelIDFromName[general]] $else $sendMessage[Extended search: $findChannel[gen]] $endif ``` ## Notes - If multiple channels match, the **first** one found is returned. - For an exact search, use `$channelIDFromName` instead. - Useful when the user does not know the exact name of the channel. - The `#` prefix should not be included in the query. --- ### $findRole # $findRole The `$findRole` function searches for a Discord role by its **partial or full name** and returns its ID. The search is case-insensitive. ## Syntax ``` $findRole[query;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `query` | The name or part of the name of the role to search for. | | `guildID` | Optional. The ID of the target server. | ## Return Value | Type | Description | |---|---| | `snowflake` (string) | The ID of the role found, or an empty string (`""`) if none is found. | ## Examples ### Partial Name Search ```bdfd $sendMessage[Role matching "mod": $findRole[mod]] ``` ### Assign a found role ```bdfd $if[$findRole[VIP]!=] $roleGrant[$authorID;$findRole[VIP]] $sendMessage[VIP role assigned!] $else $sendMessage[VIP role not found.] $endif ``` ### Verify Existence ```bdfd $if[$findRole[admin]!=] $sendMessage[Role found: $roleName[$findRole[admin]]] $else $sendMessage[No role matches "admin".] $endif ``` ### Fallback with $roleID ```bdfd $if[$roleID[Moderator]!=] $sendMessage[Exact ID: $roleID[Moderator]] $else $sendMessage[Extended search: $findRole[mod]] $endif ``` ## Notes - If multiple roles match, the **first** one found is returned. - For an exact search, use `$roleID` instead. - Very useful when the exact name of the role is uncertain. --- ### $findUser # $findUser The `$findUser[]` function allows you to **search for a user** by their name, mention, or ID. It returns the Discord ID of the user found. ## Syntax ``` $findUser[name/mention/ID] ``` ## Parameters | Parameter | Description | |---|---| | `query` | The search term: username (partial or full), raw mention (`<@ID>`), or numerical ID. | ## Return Value - **Type**: Snowflake (numeric string) or empty string - The ID of the corresponding user - An empty string if no user is found ## Behavior - The search by name is **case-insensitive**. - The search by name can be **partial** (e.g., `"Jean"` matches `"JeanDupont"`). - The search is performed among users known to the bot (shared servers cache). - Priority of match: exact mention > exact ID > username > server nickname. ## Examples ### Search by command argument ```bdfd $let[target;$findUser[$message]] $if[$target!=] $title[User Found] $description[ **ID:** $target **Name:** $userName[$target] ] $thumbnail[$userAvatar[$target]] $color[#5865F2] $sendMessage[] $else $sendMessage[No user found for "$message".] $endif ``` ### Search and action ```bdfd $let[target;$findUser[$message[1]]] $if[$target!=] $if[$checkContains[$userPerms;KickMembers]==true] $kick[$target] $sendMessage[$userName[$target] was kicked.] $endif $else $sendMessage[User not found.] $endif ``` ### Search with fallback ```bdfd $let[target;$findUser[$message]] $if[$target!=] $sendMessage[User: $userName[$target]] $else $sendMessage[User not found. Defaulting to the author.] $let[target;$authorID] $endif ``` ## Notes - `$findUser[]` is more flexible than `$mentioned` because it accepts partial names. - Always check the result (making sure it is not empty) before using the returned ID. - Useful for commands where the user can provide a name, an ID, or a mention. - The search is limited to users that the bot "knows" (present in shared servers). --- ### $getAttachments # $getAttachments The `$getAttachments[]` function allows you to **retrieve the URLs of attachments** (images, files, videos) of a Discord message. ## Syntax ``` $getAttachments[messageID] ``` ## Parameters | Parameter | Description | |---|---| | `messageID` | The ID of the message containing the attachments to retrieve. | ## Return Value - **Type**: String - The full URLs of the attachments, separated by `, `. - An empty string if the message contains no attachments. ## Behavior - Returns all URLs of files attached to the message. - Works with all types of files supported by Discord (images, videos, documents, etc.). - Each URL is a direct link to the file on Discord's servers. ## Examples ### Simple retrieval ```bdfd $let[atts;$getAttachments[$messageID]] $if[$atts!=] Attachments: $atts $else No attachments in this message. $endif ``` ### Loop through attachments ```bdfd $let[atts;$getAttachments[$messageID]] $if[$atts!=] $textSplit[$atts;, ] 📎 Attachment $index: $splitText[$index] $endTextSplit $endif ``` ### Save image ```bdfd $let[url;$getAttachments[$noMentionMessage]] $if[$url!=] $let[first;$splitText[$url;, ;1]] $image[$first] $sendMessage[Image retrieved:] $else $sendMessage[No image found.] $endif ``` ## Notes - Discord attachment URLs expire after some time (a few hours to a few days). - For permanent usage, download and host the files elsewhere. - Use `$textSplit[]` to process each attachment individually. --- ### $getCustomStatus # $getCustomStatus The `$getCustomStatus[]` function allows you to **retrieve the custom status** of a Discord user. The custom status is a custom text (and optionally an emoji) that the user sets in their profile. ## Syntax ``` $getCustomStatus[(userID)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | Optional - The ID of the target user. Default: the command author. | ## Return Value - **Type**: String - The custom status text of the user. - An empty string if the user has not set a custom status. ## Behavior - Reads the custom status from the Discord presence of the user. - Only returns the text, not the optionally associated emoji. - The user must be visible to the bot (shared server, presence accessible). ## Examples ### Simple display ```bdfd $title[💬 Custom Status] $let[status;$getCustomStatus[$authorID]] $if[$status!=] Your custom status: **$status** $else You have not set a custom status. $endif $sendMessage[] ``` ### Rich profile card ```bdfd $title[👤 $userName[$mentioned[1]]] $description[ **Status:** $userStatus[$mentioned[1]] **Custom Status:** $getCustomStatus[$mentioned[1]] **HypeSquad:** $hypeSquad[$mentioned[1]] ] $thumbnail[$userAvatar[$mentioned[1]]] $color[#5865F2] $sendMessage[] ``` ### Status change log ```bdfd $let[newStatus;$getCustomStatus[$authorID]] $if[$newStatus!=] 📝 **$userName** changed their custom status: *$newStatus* $endif ``` ## Notes - The custom status is distinct from the presence status (online, dnd, etc.) which is retrieved via `$userStatus[]`. - If the user has set an emoji in their status, only the text is returned. - The custom status can contain up to 128 characters. --- ### $getEmbedData # $getEmbedData The `$getEmbedData[]` function allows you to **extract data from an embed** present in a Discord message. Extremely useful for reading and reusing the content of existing embeds. ## Syntax ``` $getEmbedData[messageID;embedIndex;field] ``` ## Parameters | Parameter | Description | |---|---| | `messageID` | The ID of the message containing the embed. | | `embedIndex` | The index of the embed (1 = first, 2 = second...). | | `field` | The field to extract, among: `title`, `description`, `footer`, `author`, `color`, `field:`, `image`, `thumbnail`, `url`, `timestamp`. | ## Return Value - **Type**: String - The value of the field extracted from the embed. - An empty string if the field does not exist or if the index is invalid. ## Behavior - Reads embeds from an existing message (including those sent by other bots). - For named fields (`fields`), use the syntax `field:Name of the field`. - The index of the embed starts at 1. ## Examples ### Read the title and description ```bdfd $let[title;$getEmbedData[$messageID;1;title]] $let[desc;$getEmbedData[$messageID;1;description]] $title[📋 Embed detected] $description[ **Title:** $title **Description:** $desc ] $sendMessage[] ``` ### Extract a named field ```bdfd $let[score;$getEmbedData[$messageID;1;field:Score]] $if[$score!=] The score is: **$score** $else Field "Score" not found. $endif ``` ### Retrieve media ```bdfd $let[image;$getEmbedData[$noMentionMessage;1;image]] $let[thumb;$getEmbedData[$noMentionMessage;1;thumbnail]] $if[$image!=] $image[$image] $endif $if[$thumb!=] $thumbnail[$thumb] $endif ``` ### Recreate an embed ```bdfd $let[title;$getEmbedData[$messageID;1;title]] $let[desc;$getEmbedData[$messageID;1;description]] $let[footer;$getEmbedData[$messageID;1;footer]] $let[color;$getEmbedData[$messageID;1;color]] $title[$title] $description[$desc] $footer[$footer] $color[$color] $sendMessage[] ``` ## Notes - Works on messages from any author (users, bots, webhooks). - The message must be in a channel accessible by the bot. - The `color` value is returned in hexadecimal format (#RRGGBB). --- ### $getMembersCount # $getMembersCount The function `$getMembersCount` returns the **total number of members** of the Discord server. ## Syntax ``` $getMembersCount ``` ## Parameters None. ## Return Value - **Type**: Number (string) - The total number of members (humans + bots). ## Examples ### Simple Display ```bdfd $sendMessage[👥 This server has $getMembersCount members!] ``` ### Welcome Message ```bdfd $title[👋 Welcome $username!] $description[ Welcome to **$serverName**! You are member **#$getMembersCount**! ] $thumbnail[$authorAvatar] $color[#57F287] $sendMessage[] ``` ### Size Condition ```bdfd $if[$getMembersCount<100] $sendMessage[We are still a small community of $getMembersCount members 💚] $elseIf[$getMembersCount<1000] $sendMessage[Already $getMembersCount members, thank you all! 🎉] $else $sendMessage[Over 1000 members, incredible! 🚀] $endif ``` ### Server Stats ```bdfd $title[📊 Statistics of $serverName] $description[ **Members:** $getMembersCount **Bots:** $botCount **Channels:** $channelCount **Roles:** $roleCount ] $color[#5865F2] $sendMessage[] ``` ## Notes - Includes bots in the count. For humans only, do `$c[$getMembersCount-$botCount]`. - Functionally equivalent to `$membersCount`. - Updates automatically when members join/leave. --- ### $getRole # $getRole The function `$getRole` returns the **ID of a role** of a user depending on their **position** in their list of roles. The index `1` corresponds to the highest role hierarchically, `2` to the second, and so on. ## Syntax ``` $getRole[userID;index;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user. Required. | | `index` | The position of the role (1 = highest, 2 = second...). Required. | | `guildID` | Optional. The ID of the target server. | ## Return Value | Type | Description | |---|---| | `snowflake` (string) | The ID of the role at the given position, or `""` if the index is invalid. | ## Examples ### Highest role ```bdfd $sendMessage[Your highest role: $roleName[$getRole[$authorID;1]]] ``` ### Check if admin ```bdfd $if[$getRole[$authorID;1]==$roleID[Admin]] $sendMessage[You are an administrator!] $else $sendMessage[You are not an administrator.] $endif ``` ### Secondary role ```bdfd $sendMessage[Your second role: $roleName[$getRole[$authorID;2]]] ``` ### Color of the main role ```bdfd $title[Profile] $description[Color of your main role] $color[$roleColor[$getRole[$authorID;1]]] $sendMessage[] ``` ### Role of another user ```bdfd $sendMessage[Main role of <@$mentioned[1]>: $roleName[$getRole[$mentioned[1];1]]] ``` ## Notes - The index starts at `1` (not `0`). - If the user has no roles (only @everyone), `$getRole` may return an empty string. - To get the color of the highest role, use `$colorRole[$userID]` directly. - To list all roles of a user, iterate with a loop. --- ### $getSlowmode # $getSlowmode The function `$getSlowmode[]` returns the **slowmode value** of a channel in seconds. ## Syntax ``` $getSlowmode[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | *(Optional)* The ID of the channel. Default: current channel. | ## Return Value - **Type**: Number (string) - The slowmode in seconds (`0`, `5`, `10`, `15`, `30`, `60`, `120`, `300`, `600`, `900`, `1800`, `3600`, `7200`, `21600`). ## Examples ### Simple verification ```bdfd $sendMessage[Current slowmode: $getSlowmode seconds] ``` ### Comparison ```bdfd $if[$getSlowmode==0] $sendMessage[This channel does not have slowmode enabled.] $else $sendMessage[This channel has a slowmode of $getSlowmode seconds.] $endif ``` ### Check another channel ```bdfd $sendMessage[Slowmode of the log channel: $getSlowmode[123456789]s] ``` ### Alert if slowmode is active ```bdfd $if[$getSlowmode>0] $title[⏱️ Slowmode Active] $description[The channel <#$channelID> has a slowmode of **$getSlowmode seconds**.] $color[#FEE75C] $sendMessage[] $endif ``` ## Notes - `0` means slowmode is disabled. - The possible values are limited by Discord (5s, 10s, 15s, 30s, 1m, 2m, 5m, 10m, 15m, 30m, 1h, 2h, 6h). - To modify the slowmode, use `$modifyChannel[]`. --- ### $getUserStatus # $getUserStatus The function `$getUserStatus[]` returns the **presence status** of a user on Discord. ## Syntax ``` $getUserStatus[userID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user whose status you want to know. | ## Return Value - **Type**: String - Possible values: - `online` — Online (🟢) - `idle` — Idle (🟡) - `dnd` — Do Not Disturb (🔴) - `offline` — Offline (⚫) - `invisible` — Invisible (appears offline) ## Behavior - Requires the **user ID** as a parameter. - The status reflects the real-time presence on Discord. - The `invisible` status is reported as `offline` to other users. ## Examples ### Display the status with an emoji ```bdfd $let[status;$getUserStatus[$userID]] $if[$status==online] $let[emoji;🟢] $elseif[$status==idle] $let[emoji;🟡] $elseif[$status==dnd] $let[emoji;🔴] $else $let[emoji;⚫] $endif $title[Status of $userName] $description[**Status:** $emoji $status] $color[#5865F2] $sendMessage[] ``` ### Check the status of a mentioned user ```bdfd $if[$mentioned!=] $let[status;$getUserStatus[$mentioned]] $sendMessage[<@$mentioned> is currently: **$status**] $else $sendMessage[Please mention a user.] $endif ``` ### Do not disturb ```bdfd $if[$getUserStatus[$mentioned]==dnd] $sendMessage[⚠️ This user is in Do Not Disturb mode.] $endif ``` ## Notes - The `offline` status can mean that the user is actually disconnected or in invisible mode. - Users can hide their status based on their privacy settings. - Useful for commands that need to know if a user is available (e.g., sending conditional direct messages). --- ### $guildBanner[] # $guildBanner[] — Server Banner (Alias) `$guildBanner[]` is an alias of `$serverBanner[]`. It returns the URL of the banner of the Discord server. > **Prerequisite** : Boost level 2 or higher required. ## Syntax ``` $guildBanner ``` ## Parameters No parameters. ## Return Value - **Type** : `string` - The URL of the banner, or an empty string if not available. ## Usage ### Embed with banner ```bdfd $title[$guildName] $description[$serverDescription] $image[$guildBanner] $thumbnail[$guildIcon] $color[#5865F2] $sendEmbedMessage ``` ### Fallback to icon if no banner ```bdfd $if[$guildBanner!=] $var[headerImage;$guildBanner] $else $var[headerImage;$guildIcon] $endif $title[$guildName] $image[$var[headerImage]] $color[#5865F2] $sendEmbedMessage ``` ## Notes - `$guildBanner[]` and `$serverBanner[]` are interchangeable. - The banner is a horizontal image (ratio ~16:9) displayed at the top of the channel list. - If the server does not have the required level, the function returns an empty string. --- ### $guildCount[] # $guildCount[] — Number of Servers (Alias) `$guildCount[]` is an alias of `$serverCount[]`. It returns the total number of Discord servers the bot is installed on. ## Syntax ``` $guildCount ``` ## Parameters No parameters. ## Return Value - **Type**: `integer` - The number of servers the bot belongs to. ## Usage ### Simple Display ```bdfd $sendMessage[🤖 Present on **$guildCount** servers!] ``` ### Bot Statistics ```bdfd $title[📊 Bot Statistics] $addField[🌐 Guilds;$guildCount;yes] $addField[🔢 Shard;$shardID;yes] $addField[📶 Ping;$ping ms;yes] $color[#5865F2] $sendEmbedMessage ``` ### Popularity Condition ```bdfd $if[$guildCount>=50] $sendMessage[🎉 +$guildCount servers! Thank you all!] $else $sendMessage[Bot present on $guildCount servers.] $endif ``` ## Notes - `$guildCount[]` and `$serverCount[]` are strictly identical. - The count is global (all shards combined). - Updates automatically during bot joins/leaves. --- ### $guildExists[] # $guildExists[] — Check Server Existence `$guildExists[]` determines if a Discord server identified by its ID exists and if the bot is currently present on it. ## Syntax ``` $guildExists[guildId] ``` ## Parameters | Parameter | Required | Description | |-----------|-------------|-------------| | `guildId` | Yes | The ID of the server to check. | ## Return Value - **Type**: `string` - `"true"` if the bot is present on the server, `"false"` otherwise. > **Note**: The return value is a **string** (`"true"` / `"false"`), not a boolean. For conditions, compare with `==true` or `==false`. ## Usage ### Simple Check ```bdfd $sendMessage[Presence on server 123456789: $guildExists[123456789]] ``` ### Condition Before Action ```bdfd $if[$guildExists[$message[1]]==true] $sendMessage[✅ The bot is present on this server.] $else $sendMessage[❌ The bot is not on this server, or the ID is invalid.] $stop $endif ``` ### Multi-Server Check ```bdfd $var[guild1;123456789012345678] $var[guild2;987654321098765432] $if[$guildExists[$var[guild1]]==true] $sendMessage[Server 1: ✅ Present] $else $sendMessage[Server 1: ❌ Absent] $endif $if[$guildExists[$var[guild2]]==true] $sendMessage[Server 2: ✅ Present] $else $sendMessage[Server 2: ❌ Absent] $endif ``` ### Availability Log ```bdfd $if[$guildExists[$var[targetGuild]]==true] $log[Action executed: server $var[targetGuild] found] $else $log[Action blocked: server $var[targetGuild] not found] $endif ``` ## Notes - The function only checks if the bot is present on the server, not if the server exists on Discord. - A server may exist without the bot being on it — in this case, `$guildExists[]` returns `"false"`. - The ID must be a valid numeric string (Snowflake, 18-19 digits). - To get the current server's ID, use `$guildID[]` or `$serverID[]`. --- ### $guildIcon[] # $guildIcon[] — Server Icon (Alias) `$guildIcon[]` is an alias of `$serverIcon[]`. It returns the URL of the Discord server icon. ## Syntax ``` $guildIcon ``` ## Parameters No parameters. ## Return Value - **Type** : `string` - The direct URL of the icon (PNG/WEBP format), or an empty string. ## Usage ### Embed with icon ```bdfd $title[$guildName] $thumbnail[$guildIcon] $description[$serverDescription] $color[#5865F2] $sendEmbedMessage ``` ### Footer with icon ```bdfd $footer[$guildName;$guildIcon] $description[Official message] $color[#2ECC71] $sendEmbedMessage ``` ### Icon check ```bdfd $if[$guildIcon==] $sendMessage[⚠️ This server does not have a custom icon.] $else $sendMessage[✅ Server icon: $guildIcon] $endif ``` ## Notes - `$guildIcon[]` and `$serverIcon[]` are strictly identical. - The URL comes from the Discord CDN and is publicly accessible. - Returns an empty string if the server has no icon. --- ### $guildID[] # $guildID[] — Server Identifier (Alias) `$guildID[]` is an alias of `$serverID[]`. It returns the unique identifier (Snowflake) of the current Discord server. ## Syntax ``` $guildID ``` ## Parameters No parameters. ## Return Value - **Type**: `string` - The ID of the server as a numeric string. ## Usage ### Simple Display ```bdfd $sendMessage[Server ID: $guildID] ``` ### Per-Server Command Restriction ```bdfd $if[$guildID!=123456789012345678] $sendMessage[⛔ This command is reserved for the main server.] $stop $endif $sendMessage[✅ Command executed.] ``` ### Logs ```bdfd $log[Action on server $guildID ($guildName)] ``` ### URL Construction ```bdfd $sendMessage[Server link: https://discord.com/channels/$guildID] ``` ## Notes - `$guildID[]` is strictly identical to `$serverID[]`. Use whichever feels more natural. - The term "guild" is the technical name used by the Discord API to refer to a server. - The ID is permanent and never changes, unlike the name. --- ### $guildName[] # $guildName[] — Server Name (Alias) `$guildName[]` is an alias of `$serverName[]`. It returns the name of the Discord server in which the command is executed. ## Syntax ``` $guildName ``` ## Parameters No parameters. ## Return Value - **Type**: `string` - The current name of the server. ## Usage ### Welcome Message ```bdfd $sendMessage[Welcome to **$guildName**, $username! 🎉] ``` ### Custom Embed ```bdfd $title[$guildName — Information] $description[Everything you need to know about $guildName] $addField[ID;$guildID;yes] $addField[Members;$membersCount;yes] $thumbnail[$guildIcon] $color[#5865F2] $sendEmbedMessage ``` ### Logs ```bdfd $log[New command executed on $guildName ($guildID)] ``` ### Condition ```bdfd $if[$guildName==My Server] $sendMessage[You are on the main server!] $endif ``` ## Notes - `$guildName[]` and `$serverName[]` are interchangeable. - The term "guild" comes from the Discord API (Discord API Guilds). - The name returned is always the current name, reflecting any recent change. --- ### $highestRole # $highestRole The `$highestRole` function returns the **ID of the highest role** in the server's role hierarchy for the current user. ## Syntax ``` $highestRole ``` ## Return Value - **Type**: Snowflake (numeric string) - The ID of the user's highest role. - Includes `@everyone` if the user has no other roles. ## Behavior - `$highestRole` takes **no arguments**. - The hierarchy is determined by the role positions in the Discord server settings. - If the user has multiple roles, it returns the one that is highest in the list. ## Examples ### Display the highest role ```bdfd $title[Profile of $userName] $author[$userName;$userAvatar] $description[ **Highest Role:** <@&$highestRole> **Role Name:** $roleName[$highestRole] ] $color[$roleColor[$highestRole]] $sendMessage[] ``` ### Check hierarchy ```bdfd $if[$highestRole==123456789012345678] $sendMessage[You are a staff member!] $else $sendMessage[Highest role: $roleName[$highestRole]] $endif ``` ### Comparison of roles ```bdfd $let[modRole;123456789012345678] $if[$rolePosition[$highestRole]>=$rolePosition[$modRole]] $sendMessage[You have a role greater than or equal to Moderator.] $endif ``` ## Notes - The role order is defined in the server settings (Drag & Drop in the Discord interface). - The `@everyone` role is always the lowest, unless other roles are placed below it (manual reordering). - For the lowest role, use `$lowestRole`. - Use `$roleName[$highestRole]` to get the name of the role. --- ### $highestRoleWithPerms # $highestRoleWithPerms The `$highestRoleWithPerms` function returns the **ID of the highest role** of the user that has one or more specified permissions. ## Syntax ``` $highestRoleWithPerms[permission1;permission2;...] ``` ## Parameters | Parameter | Description | |---|---| | `permissions` | One or more Discord permissions, separated by semicolons. All listed permissions must be present on the role. | ## Return Value - **Type**: Snowflake (numeric string) or empty string - The ID of the highest matching role. - An empty string if no role has all the requested permissions. ## Behavior - Checks the user's roles from highest to lowest. - Returns the **first** (highest) role that has **all** the specified permissions. - Permission names must be in English (Discord API terminology). ## Examples ### Find a moderator role ```bdfd $let[modRole;$highestRoleWithPerms[ManageMessages]] $if[$modRole!=] $sendMessage[Your moderation role: $roleName[$modRole]] $else $sendMessage[You do not have a moderation role.] $endif ``` ### Check for admin role ```bdfd $if[$highestRoleWithPerms[Administrator]!=] $sendMessage[You have an administrator role.] $endif ``` ### Role with ban permissions ```bdfd $let[banRole;$highestRoleWithPerms[BanMembers]] $if[$banRole!=] $title[Ban Role] $description[ **Role:** $roleName[$banRole] **ID:** $banRole ] $color[#ED4245] $sendMessage[] $endif ``` ## Notes - Permissions are cumulative: the role must have **all** the listed permissions. - If you want a role that has **one or another** permission, make two separate calls. - To get the lowest role with these permissions, use `$lowestRoleWithPerms[]`. --- ### $hostingExpireTime # $hostingExpireTime The `$hostingExpireTime` function **returns the expiration date of the bot's hosting** on the BDFD platform. After this date, the bot will stop running if hosting is not renewed. ## Syntax ``` $hostingExpireTime ``` ## Parameters None. ## Return Value - **Type**: String - The expiration date in timestamp format (e.g., `2026-12-31T23:59:59.000Z`). - Can be formatted with `$formatDate[]`. ## Behavior - Returns the date until which the paid hosting is active. - Free bots may not have an expiration date. - Automatically updates after renewal. ## Examples ### Formatted display ```bdfd $var[expire;$hostingExpireTime] $if[$var[expire]==] $sendMessage[✅ Free hosting - no expiration.] $else $sendMessage[📅 **Hosting:** > Expires on $formatDate[$var[expire];DD/MM/YYYY at HH:mm] > Remaining days: $dateDiff[$var[expire]] days] $endif ``` ### Owner alert ```bdfd $var[expire;$hostingExpireTime] $if[$var[expire]==] $stop $endif $var[days;$dateDiff[$var[expire]]] $if[$var[days]<=3] $sendDM[$botOwnerID;🚨 **URGENT** - Hosting for **$botName** expires in $var[days] days!] $elseif[$var[days]<=7] $sendDM[$botOwnerID;⚠️ Hosting for **$botName** expires in $var[days] days.] $endif ``` ### Information page ```bdfd $title[🤖 Status of $botName] $addField[🟢 Status;Online;yes] $addField[📦 Node;$botNode;yes] $var[expire;$hostingExpireTime] $if[$var[expire]==] $addField[📅 Hosting;✅ Free / Unlimited;yes] $else $addField[📅 Hosting;Expires on $formatDate[$var[expire];DD/MM/YYYY];yes] $endif $addField[💎 Premium;$if[$premiumExpireTime==]No$elseExpires $premiumExpireTime$endif;yes] $color[$if[$var[expire]==]#57F287$else#FEE75C$endif] $sendMessage[] ``` ## Notes - If the hosting is free, the function may return an empty string. - Use `$dateDiff[$hostingExpireTime]` to get the remaining days. - For premium status, use `$premiumExpireTime`. - Returned values are in UTC. --- ### $hypeSquad # $hypeSquad The function `$hypeSquad[]` allows you to **find the HypeSquad house** of a Discord user. Returns `Bravery`, `Brilliance`, `Balance` or `None`. ## Syntax ``` $hypeSquad[(userID)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | Optional - The ID of the user. By default, the author of the command. | ## Return Value - **Type**: String - `Bravery` - House of Courage (purple) - `Brilliance` - House of Brilliance (orange) - `Balance` - House of Balance (green) - `None` - The user has not joined a HypeSquad house. ## Behavior - Checks the Discord profile of the user to determine their HypeSquad house. - Participation in HypeSquad is a Discord profile option, distinct from the HypeSquad Events program. - Returns `None` if the user has not chosen a house. ## Examples ### Simple display ```bdfd $title[🏠 HypeSquad] $description[Your HypeSquad house: **$hypeSquad**] $sendMessage[] ``` ### Custom message according to the house ```bdfd $let[house;$hypeSquad[$authorID]] $if[$house==Bravery] 🟣 House of Courage $elseif[$house==Brilliance] 🟠 House of Brilliance $elseif[$house==Balance] 🟢 House of Balance $else ⚪ No HypeSquad house $endif ``` ### Complete user info ```bdfd $title[👤 $userName[$mentioned[1]]] $description[ **ID:** $mentioned[1] **HypeSquad:** $hypeSquad[$mentioned[1]] **Badges:** $userBadges[$mentioned[1]] ] $thumbnail[$userAvatar[$mentioned[1]]] $sendMessage[] ``` ## Notes - Requires that the user has configured their HypeSquad house in their Discord settings. - Distinct badges (the HypeSquad badge is managed by `$hasBadge` / `$userBadges`). - House names are returned in English (Bravery, Brilliance, Balance). --- ### $isAdmin # $isAdmin The function `$isAdmin` returns `"true"` if the user has the **Administrator** permission on the Discord server. ## Syntax ``` $isAdmin ``` ## Return Value - **Type**: String `"true"` or `"false"` - `"true"`: The user has the `Administrator` permission. - `"false"`: The user does not have this permission. ## Behavior - `$isAdmin` takes **no arguments**. - The `Administrator` permission grants **all** permissions on the server. - The server owner is implicitly an administrator (returns `"true"`). ## Examples ### Restricting a command ```bdfd $if[$isAdmin==true] $ban[$mentioned] $sendMessage[<@$mentioned> was banned.] $else $sendMessage[Only administrators can use this command.] $endif ``` ### Displaying an admin menu ```bdfd $if[$isAdmin==true] $title[Administration Panel] $description[ **Available commands:** `/ban`, `/kick`, `/mute`, `/config` ] $color[#ED4245] $sendMessage[] $endif ``` ### Logging admin actions ```bdfd $if[$isAdmin==true] $log[Admin action performed by $userName (ID: $userID)] $endif ``` ## Notes - `$isAdmin` only checks for the `Administrator` permission, not other individual permissions. - To check for a specific permission (e.g., `BanMembers`, `ManageMessages`), use `$checkContains[$userPerms;PermissionName]`. - Equivalent to `$checkContains[$userPerms;Administrator]==true`. --- ### $isBooster # $isBooster The function `$isBooster` returns `"true"` if the user is a **Nitro Booster** of the current server. ## Syntax ``` $isBooster ``` ## Return Value - **Type**: String `"true"` or `"false"` - `"true"`: The user boosts the server. - `"false"`: The user does not boost the server. ## Behavior - `$isBooster` takes **no arguments**. - Detection is based on the booster role or the member's boost status. - A user can boost multiple servers simultaneously (depending on their Nitro subscription). ## Examples ### Automatic thank you ```bdfd $if[$isBooster==true] $title[Thanks for the boost! 🚀] $description[ Thanks to you, the server benefits from: - More emojis - Better audio quality - Server banner - And much more! ] $color[#F47FFF] $sendMessage[] $endif ``` ### Exclusive channel for boosters ```bdfd $if[$isBooster==true] $sendMessage[Welcome to the exclusive boosters channel!] $else $sendMessage[This channel is reserved for server boosters.] $stop $endif ``` ## Notes - The classic color of the Nitro boost is `#F47FFF` (pink/magenta). - Boosters often have a special badge (visible with `$userBadges`). - Useful for creating exclusive perks for boosters (channels, roles, commands). --- ### $isBot # $isBot The function `$isBot` allows you to know if the user who triggered the command is a **bot account** or a normal user account. ## Syntax ``` $isBot ``` ## Return Value - **Type**: String `"true"` or `"false"` - `"true"`: The account is a bot. - `"false"`: The account is a normal user. ## Behavior - `$isBot` takes **no arguments**. - Detection is based on the `bot` property of the Discord user object. - Webhooks return `"true"` in certain contexts. ## Examples ### Simple detection ```bdfd $if[$isBot==true] $sendMessage[🤖 Detection: you are a bot!] $else $sendMessage[👤 You are a human user.] $endif ``` ### Ignore bots ```bdfd $if[$isBot==true] $stop $endif $sendMessage[Welcome $userName!] ``` ### Conditional logging ```bdfd $if[$isBot==true] $log[Command executed by the bot $userName (ID: $userID)] $else $log[Command executed by the user $userName (ID: $userID)] $endif ``` ## Notes - Very useful for preventing bots from executing certain commands (anti-looping). - Typically used with `$stop` to silently ignore executions triggered by other bots. - `$isBot` is case-insensitive in comparisons (`==true` / `==True` / `==TRUE`). --- ### $isHoisted # $isHoisted The variable `$isHoisted` returns `"true"` if the user's highest role is **displayed separately** (hoisted) in the server member list. ## Syntax ``` $isHoisted ``` ## Return Value - **Type** : String `"true"` or `"false"` - `"true"` : the role is displayed separately in the members sidebar - `"false"` : the role is not hoisted ## Behavior - `$isHoisted` takes **no arguments**. - A "hoisted" role appears in a separate section of the online member list. - The "hoist" property is configured in the role settings on Discord. ## Examples ### Check hoist status ```bdfd $if[$isHoisted==true] $sendMessage[Your highest role is displayed separately.] $else $sendMessage[Your role is in the general members category.] $endif ``` ### Detection for sorting ```bdfd $title[Role status] $description[ **Highest role hoisted:** $isHoisted ] $color[#5865F2] $sendMessage[] ``` ## Notes - "Hoist" is a property of the **role**, not directly of the user. - `$isHoisted` checks if the user's **highest role** is hoisted. - Useful for rankings or visual hierarchy systems. --- ### $isMentionable # $isMentionable The function `$isMentionable` checks if a Discord role is **mentionable** by server members. A mentionable role can be used in messages with `@Role`. ## Syntax ``` $isMentionable[roleID;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the role. Required. | | `guildID` | Optional. The ID of the target server. | ## Return Value | Type | Description | |---|---| | `string` | `"true"` if the role is mentionable, `"false"` otherwise. | ## Examples ### Check a role ```bdfd $if[$isMentionable[$roleID[Announcements]]==true] $sendMessage[The Announcements role is mentionable.] $else $sendMessage[The Announcements role is not mentionable.] $endif ``` ### List mentionable roles ```bdfd $sendMessage[The Admin role is $isMentionable[$roleID[Admin]].] ``` ### Alert if not mentionable ```bdfd $if[$isMentionable[$roleID[Modo]]==false] $sendMessage[⚠️ The Modo role is not mentionable. Members cannot ping it.] $endif ``` ### Retrieve via $roleInfo ```bdfd $sendMessage[Mentionable: $roleInfo[123456789012345678;mentionable]] ``` ## Notes - Returns a string `"true"` or `"false"`. - Equivalent to `$roleInfo[roleID;mentionable]`. - Useful for checking before sending a role mention. --- ### $isMentioned # $isMentioned The variable `$isMentioned` returns `"true"` if the user who triggered the command was **mentioned** in the message (via `@mention`). ## Syntax ``` $isMentioned ``` ## Return Value - **Type** : String `"true"` or `"false"` - `"true"` : the triggering user is mentioned in the message - `"false"` : the triggering user is not mentioned ## Behavior - `$isMentioned` takes **no arguments**. - Checks if the **triggering user** is part of the message mentions. - Detects direct mentions (`@user`), not `@everyone`/`@here`. ## Examples ### React to a mention ```bdfd $if[$isMentioned==true] $sendMessage[Hey <@$userID>, you were mentioned!] $endif ``` ### Command with mention required ```bdfd $if[$isMentioned==true] $sendMessage[What can I do for you, $userName?] $else $sendMessage[Mention me to get my attention!] $endif ``` ## Notes - `$isMentioned` checks if the **triggering** user is mentioned, not if the bot is mentioned. - To know who was mentioned, use `$mentioned` (first mention) or `$mentions` (all mentions). - Does not detect `@everyone` or `@here` mentions. --- ### $isMessageEdited # $isMessageEdited The function `$isMessageEdited` checks if the triggering message was **edited** by its author. It returns `"true"` or `"false"`. ## Syntax ``` $isMessageEdited ``` ## Parameters No parameters. ## Return Value | Type | Description | |---|---| | `string` | `"true"` if the message was edited, `"false"` otherwise. | ## Examples ### Simple check ```bdfd $if[$isMessageEdited==true] $sendMessage[⚠️ This message was modified.] $else $sendMessage[Original message.] $endif ``` ### Edit log ```bdfd $if[$isMessageEdited==true] $channelSendMessage[$channelIDFromName[logs];$username edited their message $messageURL] $endif $sendMessage[Command executed.] ``` ### User warning ```bdfd $if[$isMessageEdited==true] $sendMessage[Warning: your command comes from an edited message.] $stop $endif ``` ## Notes - Returns a string `"true"` or `"false"`, not a boolean. - To get the edit date, use `$messageEditedTimestamp`. - Useful for detecting if a command was modified after sending. --- ### $isTimedOut # $isTimedOut The variable `$isTimedOut` returns `"true"` if the user is currently **timed out** (temporarily muted) on the server. ## Syntax ``` $isTimedOut ``` ## Return Value - **Type**: String `"true"` or `"false"` - `"true"`: The user is timed out - `"false"`: The user is not timed out ## Behavior - `$isTimedOut` takes **no arguments**. - The timeout is a Discord feature that temporarily prevents a member from speaking or sending messages. - The duration of the timeout is defined by the moderators (up to 28 days). ## Examples ### Block commands for timed-out users ```bdfd $if[$isTimedOut==true] $sendMessage[⏳ You are currently timed out. Please wait.] $stop $endif $sendMessage[Command executed successfully!] ``` ### Moderation check ```bdfd $title[Timeout Check] $description[ **User:** $userName **Timed Out:** $isTimedOut ] $color[#ED4245] $sendMessage[] ``` ## Notes - The timeout is a **temporary** sanction (maximum 28 days). - A timed-out user cannot send messages, join voice channels, or react. - Useful for preventing sanctioned users from using the bot's commands. --- ### $lastMessageID # $lastMessageID The function `$lastMessageID` returns the **ID of the last message** sent in a Discord channel. By default, it targets the current channel. ## Syntax ``` $lastMessageID[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return Value | Type | Description | |---|---| | `snowflake` (string) | The ID of the last message in the channel. | ## Examples ### Last message of the current channel ```bdfd $sendMessage[Last message in this channel: $lastMessageID] ``` ### Last message of a specific channel ```bdfd $sendMessage[Activity in #announcements: last message $lastMessageID[123456789012345678]] ``` ### Check recent activity ```bdfd $if[$lastMessageID==$messageID] $sendMessage[Your message is the last one in this channel!] $endif ``` ### Link to the last message ```bdfd $sendMessage[Last message: https://discord.com/channels/$guildID/$channelID/$lastMessageID] ``` ## Notes - If the channel is empty (no messages), the behavior may vary. - Useful for monitoring activity or linking to the last message. - The bot must have access to the channel to retrieve this information. --- ### $lastPinTimestamp # $lastPinTimestamp The function `$lastPinTimestamp` returns the **timestamp of the last pinned message** in a Discord channel. If no message is pinned, it returns an empty string. ## Syntax ``` $lastPinTimestamp[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return Value | Type | Description | |---|---| | `integer` or `""` | Timestamp in milliseconds of the last pin, or an empty string if none. | ## Examples ### Display the date of the last pin ```bdfd $if[$lastPinTimestamp!=] $sendMessage[Last pinned message on $formatDate[$lastPinTimestamp;MM/DD/YYYY at HH:mm]] $else $sendMessage[No pinned messages in this channel.] $endif ``` ### Discord relative format ```bdfd $if[$lastPinTimestamp!=] $sendMessage[Last pin ] $endif ``` ### Check another channel ```bdfd $if[$lastPinTimestamp[123456789012345678]!=] $sendMessage[The channel has pinned messages.] $endif ``` ## Notes - The timestamp is in **milliseconds** (divide by 1000 for seconds). - Returns an empty string (`""`) if no message is pinned. - Useful for checking pinning activity in a channel. --- ### $lowestRole # $lowestRole The function `$lowestRole` returns the **ID of the lowest role** in the role hierarchy of the user on the server (generally excluding `@everyone`). ## Syntax ``` $lowestRole ``` ## Return Value - **Type** : Snowflake (numeric string) - The ID of the lowest role of the user (excluding `@everyone`) ## Behavior - `$lowestRole` takes **no arguments**. - Returns the lowest non-`@everyone` role in the hierarchy. - If the user has only the `@everyone` role, the behavior may vary. ## Examples ### Show the role hierarchy ```bdfd $title[Role Hierarchy] $description[ **User:** $userName **Highest Role:** $roleName[$highestRole] **Lowest Role:** $roleName[$lowestRole] ] $color[#5865F2] $sendMessage[] ``` ### Check the lowest role ```bdfd $sendMessage[Your lowest role is: $roleName[$lowestRole] (ID: $lowestRole)] ``` ## Notes - `$lowestRole` generally excludes the `@everyone` role. - The role hierarchy is defined in the server's settings. - To retrieve a role with specific permissions, use `$lowestRoleWithPerms[]`. --- ### $lowestRoleWithPerms # $lowestRoleWithPerms The function `$lowestRoleWithPerms[]` returns the **ID of the lowest role** of the user that possesses one or more specific permissions. ## Syntax ``` $lowestRoleWithPerms[permission1;permission2;...] ``` ## Parameters | Parameter | Description | |---|---| | `permissions` | One or more Discord permissions, separated by semicolons. All listed permissions must be present on the role. | ## Return Value - **Type** : Snowflake (numeric string) or empty string - The ID of the lowest role possessing all requested permissions - Empty string if no role matches ## Behavior - Scans the user's roles from lowest to highest. - Returns the **first** (lowest) role that possesses **all** specified permissions. - Permission names are in English (matching the Discord API nomenclature). ## Examples ### Find the lowest role with voice access ```bdfd $let[voiceRole;$lowestRoleWithPerms[Connect;Speak]] $if[$voiceRole!=] $sendMessage[Your lowest voice role: $roleName[$voiceRole]] $endif ``` ### Check basic permissions ```bdfd $let[basicRole;$lowestRoleWithPerms[SendMessages;ReadMessageHistory]] $if[$basicRole!=] $sendMessage[The role $roleName[$basicRole] grants you message access.] $endif ``` ### Comparison between highest/lowest ```bdfd $let[highest;$highestRoleWithPerms[ManageMessages]] $let[lowest;$lowestRoleWithPerms[ManageMessages]] $title[Moderation Permissions] $description[ **Highest Role:** $roleName[$highest] **Lowest Role:** $roleName[$lowest] ] $color[#5865F2] $sendMessage[] ``` ## Notes - Useful for determining the minimum level at which a permission is granted. - If `$highestRoleWithPerms[]` and `$lowestRoleWithPerms[]` return the same ID, only a single role possesses those permissions. - Ideal for permission hierarchy and granular verification systems. --- ### $memberCount[] # $memberCount[] — Number of Members `$memberCount` returns the total number of members present on the Discord server, including both human users and bots. ## Syntax ``` $memberCount ``` ## Parameters None. ## Return Value - **Type** : `integer` - The total number of members (users + bots). ## Usage ### Simple display ```bdfd $sendMessage[👥 **$memberCount** members on this server!] ``` ### Statistics embed ```bdfd $title[📊 $serverName Statistics] $addField[👥 Total Members;$memberCount;yes] $addField[🟢 Online;$onlineMembers;yes] $addField[🤖 Bots;$botCount;yes] $addField[👤 Humans;$sub[$memberCount;$botCount];yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ### Custom welcome message ```bdfd $sendMessage[Welcome $username! You are member #$memberCount! 🎉] ``` ### Server size check ```bdfd $if[$memberCount>=1000] $sendMessage[🌟 This server has more than 1000 members!] $elseIf[$memberCount>=100] $sendMessage[👍 This server has more than 100 members.] $else $sendMessage[🌱 This server is still growing!] $endif ``` ### Milestone checks ```bdfd $if[$memberCount==100] $sendMessage[🎉 **100 MEMBERS!** Congratulations to the entire community!] $elseIf[$memberCount==500] $sendMessage[🚀 **500 MEMBERS!** Thank you all for your support!] $elseIf[$memberCount==1000] $sendMessage[🌟 **1000 MEMBERS!** What an incredible milestone!] $endif ``` ## Notes - `$memberCount` and `$membersCount` are identical. - The count includes all members, including bots. - To get only the number of human users, use `$sub[$memberCount;$botCount]`. - To get the number of online members, use `$onlineMembers`. --- ### $memberID # $memberID The function `$memberID` returns the **Discord ID** of the member who triggered the command. It is functionally equivalent to `$userID` but explicitly tied to the concept of a "member of the server". ## Syntax ``` $memberID ``` ## Return Value - **Type** : Snowflake (numeric string of 17-19 digits) - The unique ID of the member on Discord ## Behavior - `$memberID` takes **no arguments**. - In most cases, `$memberID` and `$userID` return the same value. - The distinction is conceptual: `$memberID` refers to the **member of the server**, whereas `$userID` refers to the **Discord user**. ## Examples ### Member profile ```bdfd $title[Member: $memberNick] $description[ **Member ID:** $memberID **Permissions:** $memberPerms ] $color[#5865F2] $sendMessage[] ``` ## Notes - In BDFD, `$memberID` and `$userID` are interchangeable for the triggering user. - `$memberID` is useful for semantic clarity in the code (when working explicitly with members). - For uniqueness and permanence, the member ID is identical to the user ID. --- ### $memberNick # $memberNick The function `$memberNick` returns the **nickname** of the member on the current server. It is equivalent to `$nickname`. ## Syntax ``` $memberNick ``` ## Return Value - **Type** : String of characters - The server nickname of the member if set, otherwise an **empty string** ## Behavior - `$memberNick` takes **no arguments**. - Functionally identical to `$nickname`. - Returns only the nickname **specific to the server**. ## Examples ### Message with nickname ```bdfd $if[$memberNick!=] $sendMessage[Hello $memberNick!] $else $sendMessage[Hello $userName!] $endif ``` ### Member embed ```bdfd $title[Member Information] $author[$memberNick;$userAvatar] $description[ **ID:** $memberID **Permissions:** $memberPerms ] $color[#5865F2] $sendMessage[] ``` ## Notes - `$memberNick` and `$nickname` are interchangeable. - For general display, `$displayName` is recommended because it never returns an empty string. --- ### $memberPerms # $memberPerms The function `$memberPerms` returns the **list of effective permissions** of the member on the current server. It is equivalent to `$userPerms`. ## Syntax ``` $memberPerms ``` ## Return Value - **Type** : List of permission names, separated by commas - Example: `SendMessages, ReadMessageHistory, AddReactions, ManageMessages` ## Behavior - `$memberPerms` takes **no arguments**. - Returns the combined permissions of all roles of the member, including channel overrides. - Functionally identical to `$userPerms` for the triggering user. ## Examples ### Display permissions ```bdfd $title[Permissions of $memberNick] $description[ **Permissions of the member:** $memberPerms ] $color[#5865F2] $sendMessage[] ``` ### Moderation command ```bdfd $if[$checkContains[$memberPerms;KickMembers]==true] $kick[$mentioned] $sendMessage[<@$mentioned> was kicked.] $else $sendMessage[KickMembers permission required.] $endif ``` ## Notes - `$memberPerms` and `$userPerms` are interchangeable. - Permission names are in **English** (matching the Discord API nomenclature). - For a simple check of administrator status, use `$isAdmin`. --- ### $membersCount[] # $membersCount[] — Number of Members `$membersCount` returns the total number of members on the Discord server. This function is strictly identical to `$memberCount`. ## Syntax ``` $membersCount ``` ## Parameters None. ## Return Value - **Type** : `integer` - The total number of members. ## Usage ### Simple display ```bdfd $sendMessage[👥 **$membersCount** members!] ``` ### Statistics embed ```bdfd $title[📊 $serverName] $addField[👥 Members;$membersCount;yes] $addField[🟢 Online;$onlineMembers;yes] $addField[🤖 Bots;$botCount;yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ### Comparison ```bdfd $if[$membersCount>$var[previousCount]] $sendMessage[📈 The server has gained members!] $endif ``` ## Notes - `$membersCount` and `$memberCount` are interchangeable. - Includes both humans and bots. - To get the count of human users only, use `$sub[$membersCount;$botCount]`. --- ### $mentioned # $mentioned The function `$mentioned` returns the **ID of the first user mentioned** in the command message. ## Syntax ``` $mentioned ``` ## Return Value - **Type** : Snowflake (numeric string) or empty string - ID of the first user mentioned - Empty string if no user mention is present ## Behavior - `$mentioned` takes **no arguments**. - Returns only the **first** user mention. - To retrieve all mentions, use `$mentions`. ## Examples ### Act on the mentioned user ```bdfd $if[$mentioned!=] $title[Information on <@$mentioned>] $description[ **ID:** $mentioned **Name:** $username[$mentioned] ] $thumbnail[$userAvatar[$mentioned]] $color[#5865F2] $sendMessage[] $else $sendMessage[You must mention a user.] $endif ``` ### Kick the first mentioned user ```bdfd $if[$mentioned!=] $if[$checkContains[$userPerms;KickMembers]==true] $kick[$mentioned] $sendMessage[<@$mentioned> was kicked.] $else $sendMessage[Permission denied.] $endif $else $sendMessage[Mention the user to kick.] $endif ``` ## Notes - `$mentioned` is convenient for commands that target a single user. - If multiple users are mentioned, only the first is returned. - Use `$userExists[$mentioned]` to validate that the mentioned user exists. - Does not detect `@everyone` or `@here` mentions. --- ### $mentionedChannels # $mentionedChannels The function `$mentionedChannels` returns the **list of channel IDs mentioned** in the message, via the `#channel` syntax. ## Syntax ``` $mentionedChannels ``` ## Return Value - **Type** : List of snowflakes separated by commas - Example: `123456789,987654321` - Empty string if no channels are mentioned ## Behavior - `$mentionedChannels` takes **no arguments**. - Detects channel mentions formatted as `#channel-name`. - Returns the IDs of the mentioned channels. ## Examples ### Check mentioned channels ```bdfd $if[$mentionedChannels!=] $let[channels;$splitText[$mentionedChannels;,]] $let[count;$arrayCount[$channels]] $sendMessage[$count channel(s) mentioned.] $else $sendMessage[No channels mentioned in this message.] $endif ``` ### Act on the first mentioned channel ```bdfd $if[$mentionedChannels!=] $let[firstChannel;$splitText[$mentionedChannels;,;1]] $sendMessage[First channel mentioned: <#$firstChannel>] $endif ``` ### Move a message ```bdfd $if[$mentionedChannels!=] $let[target;$splitText[$mentionedChannels;,;1]] $sendMessage[Message to <#$target>] $endif ``` ## Notes - Channel mentions use the `#channel-name` format in Discord. - The returned IDs are numeric snowflakes. - To get the name of a channel from its ID, use `$channelName[ID]`. --- ### $mentionedRoles # $mentionedRoles The function `$mentionedRoles` returns the **list of role IDs mentioned** in the message, via the `@role` syntax. ## Syntax ``` $mentionedRoles ``` ## Return Value - **Type** : List of snowflakes separated by commas - Example: `123456789,987654321` - Empty string if no roles are mentioned ## Behavior - `$mentionedRoles` takes **no arguments**. - Detects role mentions formatted as `@role-name`. - Only mentionable roles (where the role's "@mention this role" setting is enabled) are detected. ## Examples ### Check mentioned roles ```bdfd $if[$mentionedRoles!=] $let[roles;$splitText[$mentionedRoles;,]] $let[count;$arrayCount[$roles]] $sendMessage[$count role(s) mentioned.] $else $sendMessage[No roles mentioned.] $endif ``` ### Add a mentioned role ```bdfd $if[$mentionedRoles!=] $let[firstRole;$splitText[$mentionedRoles;,;1]] $giveRole[$mentioned;$firstRole] $sendMessage[Role <@&$firstRole> added to <@$mentioned>!] $else $sendMessage[Mention a role to assign.] $endif ``` ### List mentioned roles ```bdfd $if[$mentionedRoles!=] $let[roles;$splitText[$mentionedRoles;,]] $let[i;0] $let[total;$arrayCount[$roles]] $let[output;] $while[$i<$total] $let[roleID;$arrayGet[$roles;$i]] $let[output;$output - <@&$roleID> ] $let[i;$sum[$i;1]] $endwhile $sendMessage[Mentioned roles: $output] $endif ``` ## Notes - A role must have the "Allow anyone to @mention this role" option enabled to be detected. - The returned IDs are numeric snowflakes. - To get the name of a role from its ID, use `$roleName[ID]`. --- ### $mentions # $mentions The function `$mentions` returns the **list of all user IDs mentioned** in the command message. ## Syntax ``` $mentions ``` ## Return Value - **Type** : List of snowflakes separated by commas - Example: `123456789,987654321,555555555` - Empty string if no users are mentioned ## Behavior - `$mentions` takes **no arguments**. - Returns all user mentions of the message. - To retrieve only the first mention, use `$mentioned`. ## Examples ### Process all mentions ```bdfd $if[$mentions!=] $let[count;$arrayCount[$splitText[$mentions;,]]] $sendMessage[$count user(s) mentioned: $mentions] $else $sendMessage[No users mentioned.] $endif ``` ### Loop through mentions ```bdfd $let[mentionsList;$splitText[$mentions;,]] $let[i;0] $let[total;$arrayCount[$mentionsList]] $while[$i<$total] $let[target;$arrayGet[$mentionsList;$i]] $sendMessage[User: <@$target>] $let[i;$sum[$i;1]] $endwhile ``` ### Multi-target command ```bdfd $if[$mentions!=] $let[list;$splitText[$mentions;,]] $let[i;0] $let[total;$arrayCount[$list]] $while[$i<$total] $let[id;$arrayGet[$list;$i]] $kick[$id] $let[i;$sum[$i;1]] $endwhile $sendMessage[$total user(s) kicked.] $else $sendMessage[Mention at least one user.] $endif ``` ## Notes - `$mentions` returns all IDs at once, separated by commas. - To iterate, use `$splitText[$mentions;,]` to create an array. - Does not detect `@everyone` or `@here` mentions. --- ### $message # $message The function `$message` returns the **raw text content** of the message that triggered the execution of the command. This includes all arguments after the prefix and command name. ## Syntax ``` $message ``` ## Parameters None. ## Return Value | Type | Description | |---|---| | `string` | The full text of the triggering message (excluding the command name and prefix). | ## Examples ### Display the message received ```bdfd $sendMessage[Message received: $message] ``` ### Check specific content ```bdfd $if[$message==hello] $sendMessage[Hello to you!] $else $sendMessage[You said: $message] $endif ``` ### Log the message ```bdfd $channelSendMessage[$channelIDFromName[logs];$username said: $message] ``` ### Usage with $argsCheck ```bdfd $argsCheck[>;Text;Your message after the command] $sendMessage[Argument: $message] ``` ## Notes - `$message` contains the **full** text of the arguments, not just individual words. - If you only want a slice of the arguments, use `$messageSlice[]`. - In interactions (buttons, select menus), `$message` may not return the expected content. --- ### $messageEditedTimestamp # $messageEditedTimestamp The function `$messageEditedTimestamp` returns the **timestamp of the last edit** of the triggering message. If the message has never been edited, it returns an empty string. ## Syntax ``` $messageEditedTimestamp ``` ## Parameters None. ## Return Value | Type | Description | |---|---| | `integer` or `""` | Timestamp in milliseconds, or an empty string if the message has not been edited. | ## Examples ### Display the edit date ```bdfd $if[$messageEditedTimestamp!=] $sendMessage[Message edited on $formatDate[$messageEditedTimestamp;MM/DD/YYYY at HH:mm]] $else $sendMessage[Original message (not edited).] $endif ``` ### Display in relative format ```bdfd $if[$messageEditedTimestamp!=] $sendMessage[Edited ] $endif ``` ### Log edits ```bdfd $if[$messageEditedTimestamp!=] $channelSendMessage[$channelIDFromName[logs];$username edited their message (ID: $messageID) on $formatDate[$messageEditedTimestamp;MM/DD/YYYY HH:mm]] $endif ``` ## Notes - Returns an **empty** string (`""`) if never edited, not `0`. - Use `$isMessageEdited` for a simpler boolean test. - The timestamp is in milliseconds; divide by `1000` for seconds. --- ### $messageID # $messageID The function `$messageID` returns the **unique identifier** (snowflake) of the message that triggered the execution of the command. ## Syntax ``` $messageID ``` ## Parameters None. ## Return Value | Type | Description | |---|---| | `snowflake` (string) | The ID of the triggering message. | ## Examples ### Display the message ID ```bdfd $sendMessage[Message ID: $messageID] ``` ### Direct link to the message ```bdfd $sendMessage[Link to the message: https://discord.com/channels/$guildID/$channelID/$messageID] ``` ### Log the ID ```bdfd $channelSendMessage[$channelIDFromName[logs];Message $messageID processed by $username.] ``` ### Delete the message after processing ```bdfd $deleteMessage[$channelID;$messageID] $sendMessage[Message processed and deleted.] ``` ## Notes - The ID is unique and allows you to precisely identify a message. - Can be used with `$deleteMessage`, `$editMessage`, or `$messageURL`. - In interactions (buttons), `$messageID` returns the ID of the original message. --- ### $messageTimestamp # $messageTimestamp The function `$messageTimestamp` returns the creation **timestamp** of the triggering message, in milliseconds since the Unix epoch. ## Syntax ``` $messageTimestamp ``` ## Parameters None. ## Return Value | Type | Description | |---|---| | `integer` | Unix timestamp in milliseconds. | ## Examples ### Display the raw timestamp ```bdfd $sendMessage[Message timestamp: $messageTimestamp] ``` ### Format the date ```bdfd $sendMessage[Message sent on $formatDate[$messageTimestamp;MM/DD/YYYY at HH:mm:ss]] ``` ### Calculate the age of the message ```bdfd $sendMessage[Message age: $truncate[$sub[$dateNow;$messageTimestamp]/1000] seconds.] ``` ### Display in Discord relative format ```bdfd $sendMessage[Message sent ] ``` ## Notes - The timestamp is returned in **milliseconds**. Divide by `1000` to get seconds. - Use with `$formatDate` for a human-readable display. - `$dateNow` returns the current timestamp, useful for calculating durations. - For the edit timestamp, use `$messageEditedTimestamp`. --- ### $messageType # $messageType The function `$messageType` returns the **type** of the triggering message as an integer. Type `0` corresponds to a normal user message, while other types correspond to Discord system messages. ## Syntax ``` $messageType ``` ## Parameters None. ## Return Value | Type | Description | |---|---| | `integer` | The type of the message. | ## Common Types | Type | Meaning | |---|---| | `0` | Normal message (DEFAULT) | | `1` | Member added to group DM (RECIPIENT_ADD) | | `2` | Member removed from group DM (RECIPIENT_REMOVE) | | `3` | Voice call message (CALL) | | `4` | Channel name changed (CHANNEL_NAME_CHANGE) | | `5` | Channel icon changed (CHANNEL_ICON_CHANGE) | | `6` | Pinned message notification (CHANNEL_PINNED_MESSAGE) | | `7` | New member joined (GUILD_MEMBER_JOIN) | | `8` | Server boost (USER_PREMIUM_GUILD_SUBSCRIPTION) | | `9` | Boost level 1 reached (GUILD_TIER_1) | | `10` | Boost level 2 reached (GUILD_TIER_2) | | `11` | Boost level 3 reached (GUILD_TIER_3) | ## Examples ### Display the type ```bdfd $sendMessage[Message type: $messageType] ``` ### Ignore system messages ```bdfd $if[$messageType!=0] $stop $endif $sendMessage[User message processed.] ``` ### React to new joins ```bdfd $if[$messageType==7] $sendMessage[Welcome $username!] $endif ``` ## Notes - Useful for filtering system messages to process only user messages. - Returns an integer, not a descriptive string. --- ### $messageURL # $messageURL The function `$messageURL` returns the **jump URL** (direct link) to the message that triggered the command. This link allows users to navigate directly to the message in Discord. ## Syntax ``` $messageURL ``` ## Parameters None. ## Return Value | Type | Description | |---|---| | `string` | URL format: `https://discord.com/channels/{guildID}/{channelID}/{messageID}`. | ## Examples ### Direct link ```bdfd $sendMessage[Original message: $messageURL] ``` ### In an embed ```bdfd $title[Reported Message] $description[ **Author:** $username **Content:** $message **Link:** [Click here]($messageURL) ] $color[#ED4245] $sendMessage[] ``` ### Log with link ```bdfd $channelSendMessage[$channelIDFromName[logs];Message by $username: $messageURL] ``` ## Notes - Format: `https://discord.com/channels/{guildID}/{channelID}/{messageID}`. - In DMs, the format uses the DM channel ID. - The link only works if the user has access to the channel. --- ### $nickname # $nickname The variable `$nickname` returns the **nickname** of the user on the current server. Unlike `$displayName`, it returns an empty string if the user does not have a custom nickname. ## Syntax ``` $nickname ``` ## Return Value - **Type** : String - The server nickname if set, otherwise an **empty string** ## Behavior - `$nickname` takes **no arguments**. - Returns only the nickname **specific to the server**. - If the user uses their global username (no nickname set), it returns `""` (an empty string). - The maximum length of a nickname is 32 characters. ## Examples ### Detecting if a nickname is set ```bdfd $if[$nickname!=] $sendMessage[Hello $nickname! (nickname: $nickname, username: $userName)] $else $sendMessage[Hello $userName!] $endif ``` ### Displaying name details ```bdfd $title[Names of $userName] $description[ **Global Username:** $userName **Server Nickname:** $nickname **Display Name:** $displayName ] $color[#5865F2] $sendMessage[] ``` ## Notes - Do not confuse `$nickname` (server nickname only) with `$displayName` (nickname or global name). - For displaying names in messages, `$displayName` is generally preferred because it will never be empty. - Useful for commands where you want to explicitly check if the user has set a server nickname. --- ### $nodeVersion # $nodeVersion The function `$nodeVersion` **returns the current Node.js runtime version** on which the BDFD bot is running. ## Syntax ``` $nodeVersion ``` ## Parameters None. ## Return Value - **Type** : String - The Node.js version (e.g. `v18.15.0`, `v20.10.0`). ## Behavior - Returns the full version prefixed with `v`. - The version is determined by the BDFD infrastructure (cannot be modified). - Useful for debugging and checking feature compatibility. ## Examples ### Feature Compatibility Check ```bdfd $var[version;$nodeVersion] $var[major;$textSplit[$var[version];v]] $var[major;$textSplit[$var[major];.;1]] $if[$var[major]>=18] $sendMessage[✅ Your runtime supports the latest features.] $else $sendMessage[⚠️ Outdated runtime. Some features may be limited.] $endif ``` ### Technical Info ```bdfd $title[🛠️ Technical Environment] $description[ **Bot :** $botName **Node :** $botNode **Runtime :** $nodeVersion **Language :** $scriptLanguage **Commands :** $commandsCount ] $footer[BDFD Infrastructure] $sendMessage[] ``` ### Startup Log ```bdfd $log[🚀 $botName started | Node: $botNode | Runtime: $nodeVersion | Lang: $scriptLanguage] ``` ## Notes - Read-only version managed by BDFD. - Automatically updated by the BDFD infrastructure. - For information on the bot node, use `$botNode`. - For the script language, use `$scriptLanguage`. --- ### $onlineMembers # $onlineMembers — Online Members `$onlineMembers` returns the number of members currently online on the server. Members with the statuses Online, Idle, and Do Not Disturb (dnd) are considered "online". ## Syntax ``` $onlineMembers ``` ## Parameters No parameters. ## Return Value - **Type** : `integer` - The number of online members. ## Usage ### Simple display ```bdfd $sendMessage[🟢 **$onlineMembers** members online ($onlineMembers/$membersCount)] ``` ### Stats Embed ```bdfd $title[📊 Activity on $serverName] $addField[🟢 Online;$onlineMembers;yes] $addField[👥 Total;$membersCount;yes] $addField[📊 Ratio;$round[$multi[$divide[$onlineMembers;$membersCount];100]]%;yes] $thumbnail[$serverIcon] $color[#2ECC71] $sendEmbedMessage ``` ### Calculating activity rate ```bdfd $var[activityRate;$round[$multi[$divide[$onlineMembers;$membersCount];100]]] $if[$var[activityRate]>=50] $sendMessage[🔥 $var[activityRate]% of members are online!] $else $sendMessage[💤 Only $var[activityRate]% of members are online.] $endif ``` ### Minimal Dashboard ```bdfd $title[📋 Dashboard — $serverName] $addField[🟢 Online;$onlineMembers;yes] $addField[👥 Total;$membersCount;yes] $addField[🤖 Bots;$botCount;yes] $addField[🚀 Boosts;$serverBoostCount;yes] $color[#5865F2] $sendEmbedMessage ``` ## Notes - Includes the statuses "online", "idle", and "do not disturb" (dnd). - Does not include invisible members (offline or invisible status), as Discord does not expose this information. - Useful for evaluating server activity in real-time. - To calculate the ratio, use `$onlineMembers / $membersCount * 100`. --- ### $parentID # $parentID The `$parentID` function is an **alias** of `$channelCategoryID`. It returns the ID of a Discord channel's parent category. ## Syntax ``` $parentID[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return Value | Type | Description | |---|---| | `snowflake` (string) | The parent category ID, or `""` if none. | ## Examples ### Category ID ```bdfd $sendMessage[Category ID: $parentID] ``` ### Parent category name ```bdfd $sendMessage[Parent category: $channelName[$parentID]] ``` ### Check if in a category ```bdfd $if[$parentID!=] $sendMessage[This channel is in the $channelName[$parentID] category] $else $sendMessage[This channel is not in a category.] $endif ``` ## Notes - `$parentID` and `$categoryID` are both aliases of `$channelCategoryID`. - Functioning identical to `$channelCategoryID`. --- ### $premiumExpireTime # $premiumExpireTime The `$premiumExpireTime` function **returns the expiration date of the bot's BDFD premium subscription**. Premium unlocks advanced features (more commands, more servers, etc.). ## Syntax ``` $premiumExpireTime ``` ## Parameters None. ## Return Value - **Type**: String - Expiration date in timestamp format if the bot is premium. - Empty string if the bot has no premium subscription. ## Behavior - Returns a date only if a premium subscription is active. - After expiration, premium features are disabled. - The format is an ISO 8601 timestamp. ## Examples ### Status check ```bdfd $var[premium;$premiumExpireTime] $if[$var[premium]==] $sendMessage[❌ This bot has no active premium subscription.] $else $var[days;$dateDiff[$var[premium]]] $sendMessage[💎 **Premium active!** > Expires on: $formatDate[$var[premium];DD/MM/YYYY] > Days remaining: $var[days] days] $endif ``` ### Renewal alert ```bdfd $var[premium;$premiumExpireTime] $if[$var[premium]==] $stop $endif $var[days;$dateDiff[$var[premium]]] $if[$var[days]<=3] $sendDM[$botOwnerID;🚨 **$botName Premium** expires in $var[days] days! Remember to renew.] $endif ``` ### Owner dashboard ```bdfd $if[$authorID!=$botOwnerID] $sendEphemeral[❌ Reserved for the owner.] $stop $endif $title[📊 $botName Dashboard] $addField[🟢 Status;Online;yes] $addField[📅 Hosting;$if[$hostingExpireTime==]Free$else$hostingExpireTime$endif;yes] $addField[💎 Premium;$if[$premiumExpireTime==]❌ None$elseExpires $formatDate[$premiumExpireTime;DD/MM/YYYY]$endif;yes] $addField[⚡ Runtime;$nodeVersion;yes] $addField[📝 Language;$scriptLanguage;yes] $color[$if[$premiumExpireTime==]#ED4245$else#57F287$endif] $sendMessage[] ``` ## Notes - Empty string = no premium. - For hosting, use `$hostingExpireTime`. - BDFD premium offers: more commands, more servers, exclusive features. - `$dateDiff[$premiumExpireTime]` returns the number of days remaining. --- ### $repliedMessageID # $repliedMessageID The `$repliedMessageID` function allows **retrieving the source message ID** when a user replies to a message with a command. ## Syntax ``` $repliedMessageID ``` ## Parameters No parameters. ## Return Value - **Type**: String (Snowflake ID) - The ID of the message the user replied to. - Empty string if the command was not triggered via reply. ## Behavior - Works when the user right-clicks → "Reply" on a message and types the command. - Returns the ID of the original message, not the command message. - Useful for contextual moderation commands. ## Examples ### Quote the replied message ```bdfd $if[$repliedMessageID!=] $let[msg;$getMessage[$channelID;$repliedMessageID]] $title[📝 Reply to a message] $description[ **Original author:** $userName[$messageAuthorID[$channelID;$repliedMessageID]] **Message:** $msg ] $sendMessage[] $else $sendMessage[Please reply to a message to use this command.] $endif ``` ### Moderation by reply ```bdfd $if[$repliedMessageID!=] $let[author;$messageAuthorID[$channelID;$repliedMessageID]] $title[⚠️ Report] $description[ **Reported message:** ||$getMessage[$channelID;$repliedMessageID]|| **Author:** $userName[$author] **Reported by:** $userName[$authorID] ] $color[#ED4245] $sendMessage[$channelID[mod-logs]] $else $sendMessage[Reply to a message to report it.] $endif ``` ### Quote and delete ```bdfd $if[$repliedMessageID!=] $let[msg;$getMessage[$channelID;$repliedMessageID]] $title[🗑️ Message deleted] $description[Message from **$userName[$messageAuthorID[$channelID;$repliedMessageID]]** deleted.\nContent: ||$msg||] $deleteMessage[$channelID;$repliedMessageID] $sendMessage[] $endif ``` ## Notes - Only works if the command is triggered via Discord reply. - Returns an empty string in other cases (normal message, slash command, etc.). - Convenient for contextual commands without having to manually provide an ID. --- ### $roleColor # $roleColor The function `$roleColor` returns the **color** of a Discord role in hexadecimal format. If the role does not have a defined color, it returns an empty string. ## Syntax ``` $roleColor[roleID;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the role. Required. | | `guildID` | Optional. The ID of the target server. | ## Return Value | Type | Description | |---|---| | `string` | The color in hexadecimal (e.g., `#5865F2`), or `""` if there is no color. | ## Examples ### Display the color ```bdfd $sendMessage[Color of the Admin role: $roleColor[$roleID[Admin]]] ``` ### Embed colored according to the role ```bdfd $title[Role $roleName[$getRole[$authorID;1]]] $description[Here is your primary role.] $color[$roleColor[$getRole[$authorID;1]]] $sendMessage[] ``` ### Check if the role has a color ```bdfd $if[$roleColor[$roleID[Member]]!=] $sendMessage[Color: $roleColor[$roleID[Member]]] $else $sendMessage[This role does not have a color.] $endif ``` ### Color of the role of a user ```bdfd $sendMessage[Your role color: $colorRole[$authorID]] ``` ## Notes - The color is returned with the `#` prefix. - If the role does not have a color, the value is an empty string (`""`). - To get the color of the highest role of a user, use `$colorRole`. --- ### $roleCount # $roleCount The function `$roleCount` returns the **total number of roles** present on the Discord server, including the `@everyone` role. ## Syntax ``` $roleCount[(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `guildID` | Optional. The ID of the target server. If omitted, the current server is used. | ## Return Value | Type | Description | |---|---| | `integer` | The number of roles on the server. | ## Examples ### Number of roles ```bdfd $sendMessage[This server has $roleCount roles.] ``` ### Server statistics ```bdfd $sendMessage[ **Server Stats:** Members: $memberCount Roles: $roleCount Channels: $channelCount ] ``` ### Check role limit ```bdfd $if[$roleCount>=250] $sendMessage[⚠️ Warning: This server is approaching the Discord limit of 250 roles.] $endif ``` ## Notes - Includes the `@everyone` role in the count. - The Discord limit is 250 roles per server. - Useful for statistics or administrative checks. --- ### $roleExists # $roleExists The function `$roleExists` checks if a **Discord role exists** on the server using its ID. ## Syntax ``` $roleExists[roleID;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the role to check. Required. | | `guildID` | Optional. The ID of the target server. If omitted, the current server is used. | ## Return Value | Type | Description | |---|---| | `string` | `"true"` if the role exists, `"false"` otherwise. | ## Examples ### Simple Check ```bdfd $if[$roleExists[123456789012345678]==true] $sendMessage[The role $roleName[123456789012345678] exists.] $else $sendMessage[This role does not exist.] $endif ``` ### Check before granting a role ```bdfd $if[$roleExists[$roleID[Member]]==true] $roleGrant[$authorID;$roleID[Member]] $sendMessage[Member role granted!] $else $sendMessage[The Member role does not exist. Please contact an administrator.] $endif ``` ### On another server ```bdfd $if[$roleExists[123456789012345678;987654321098765432]==true] $sendMessage[Role valid.] $endif ``` ## Notes - Returns a string of `"true"` or `"false"`. - Useful before using `$roleGrant` or other functions that manipulate roles. --- ### $roleID # $roleID The function `$roleID` returns the **ID** of a Discord role from its **name** or **mention**. The search is case-insensitive. ## Syntax ``` $roleID[name;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `name` | The name of the role or a raw mention (`<@&id>`). | | `guildID` | Optional. The ID of the target server. If omitted, the current server is used. | ## Return Value | Type | Description | |---|---| | `snowflake` (string) | The ID of the role, or `""` if not found. | ## Examples ### Get the ID of a role ```bdfd $sendMessage[ID of the Admin role: $roleID[Admin]] ``` ### Check if a role exists ```bdfd $if[$roleID[Member]!=] $sendMessage[The Member role exists!] $else $sendMessage[Member role not found.] $endif ``` ### From a mention ```bdfd $sendMessage[ID extracted from the mention: $roleID[<@&123456789012345678>]] ``` ### On another server ```bdfd $sendMessage[Role ID on another server: $roleID[Mod;987654321098765432]] ``` ## Notes - If multiple roles have the exact same name, only the first found is returned. - A raw mention (`<@&id>`) is accepted as a parameter. - Use `$findRole` for a partial name search. --- ### $roleInfo # $roleInfo The function `$roleInfo` returns a **specific property** of a Discord role. It allows you to access various information such as the name, color, position, or permissions. ## Syntax ``` $roleInfo[roleID;property;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the target role. Required. | | `property` | The property to retrieve (see below). Required. | | `guildID` | Optional. The ID of the target server. | ## Properties Available | Property | Description | Return Type | |---|---|---| | `name` | Name of the role | `string` | | `color` | Color in hexadecimal | `string` | | `position` | Hierarchical position | `integer` | | `permissions` | Raw permissions | `integer` | | `mentionable` | Whether the role is mentionable | `string` (`"true"`/`"false"`) | | `hoist` | Whether the role is displayed separately | `string` (`"true"`/`"false"`) | | `managed` | Whether the role is managed by an integration | `string` (`"true"`/`"false"`) | | `id` | ID of the role | `snowflake` | ## Return Value The type depends on the requested property (string, integer, or boolean represented as a string). ## Examples ### Basic Information ```bdfd $sendMessage[ **Role:** $roleInfo[$roleID[Admin];name] **Color:** $roleInfo[$roleID[Admin];color] **Position:** $roleInfo[$roleID[Admin];position] ] ``` ### Check if a role is displayed separately ```bdfd $if[$roleInfo[$roleID[Admin];hoist]==true] $sendMessage[This role is displayed separately in the member list.] $endif ``` ### Role managed by an integration ```bdfd $if[$roleInfo[123456789012345678;managed]==true] $sendMessage[This role is managed by an integration (bot).] $endif ``` ## Notes - The properties `mentionable`, `hoist`, and `managed` return strings `"true"` or `"false"`. - For permissions, the raw integer format is returned. Use `$rolePerms` for a more readable format. --- ### $roleName # $roleName The function `$roleName` returns the **name** of a Discord role from its **ID**. ## Syntax ``` $roleName[roleID;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the role. Required. | | `guildID` | Optional. The ID of the target server. If omitted, the current server is used. | ## Return Value | Type | Description | |---|---| | `string` | The name of the role (e.g., `Admin`, `Moderator`). | ## Examples ### Get the name of a role ```bdfd $sendMessage[The role ID 123456789012345678 is: $roleName[123456789012345678]] ``` ### Display the name of the first role of a user ```bdfd $sendMessage[Your first role: $roleName[$getRole[$authorID;1]]] ``` ### Verify a role name ```bdfd $if[$roleName[123456789012345678]==Admin] $sendMessage[This is indeed the Admin role.] $endif ``` ### On another server ```bdfd $sendMessage[Role: $roleName[123456789012345678;987654321098765432]] ``` ## Notes - The ID of the role must be valid on the server. - To get the ID from a name, use `$roleID`. - To list all roles, use `$roleNames`. --- ### $roleNames # $roleNames The function `$roleNames` returns the **complete list of names** of all roles on the server, separated by a customizable delimiter. ## Syntax ``` $roleNames[(separator);(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `separator` | Optional. The separator between each role name. Default: `, `. | | `guildID` | Optional. The ID of the target server. Default: current server. | ## Return Value | Type | Description | |---|---| | `string` | All role names concatenated with the chosen separator. | ## Examples ### Simple list ```bdfd $sendMessage[**Roles on the server:** $roleNames] ``` ### List with line breaks ```bdfd $sendMessage[**List of roles:** $roleNames[ ]] ``` ### With custom separator ```bdfd $sendMessage[Roles: $roleNames[ | ]] ``` ### Count and list ```bdfd $sendMessage[The server has $roleCount roles: $roleNames[, ]] ``` ## Notes - The `@everyone` role is generally included in the list. - Roles are listed according to their hierarchical order (from highest to lowest). - To get IDs instead of names, use a different approach. --- ### $rolePerms # $rolePerms The function `$rolePerms` returns the **permissions** of a Discord role, either as a text list or as a raw integer value. ## Syntax ``` $rolePerms[roleID;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the role. Required. | | `guildID` | Optional. The ID of the target server. | ## Return Value | Type | Description | |---|---| | `string` | The list of permissions of the role. | ## Common Permissions | Permission | Description | |---|---| | `Administrator` | All permissions | | `ManageGuild` | Manage the server | | `ManageRoles` | Manage roles | | `ManageChannels` | Manage channels | | `KickMembers` | Kick members | | `BanMembers` | Ban members | | `ManageMessages` | Manage messages | | `MentionEveryone` | Mention @everyone | | `SendMessages` | Send messages | | `ReadMessages` | View channels | | `Connect` | Connect to voice channels | ## Examples ### Display permissions ```bdfd $sendMessage[Permissions of the Admin role: $rolePerms[$roleID[Admin]]] ``` ### Check a permission ```bdfd $if[$checkContains[$rolePerms[$roleID[Member]];Administrator]] $sendMessage[⚠️ The Member role has the Administrator permission!] $else $sendMessage[Standard permissions.] $endif ``` ### Check if a role can manage messages ```bdfd $if[$checkContains[$rolePerms[$roleID[Mod]];ManageMessages]] $sendMessage[Moderators can manage messages.] $endif ``` ### Formatted list ```bdfd $sendMessage[**Permissions of $roleName[$roleID[Admin]]:** $rolePerms[$roleID[Admin]]] ``` ## Notes - The exact format may vary depending on the version of BDFD. - To obtain the raw integer value, use `$roleInfo[ID;permissions]`. - Use with `$checkContains` to test for specific permissions. --- ### $rolePosition # $rolePosition The function `$rolePosition` returns the **hierarchical position** of a Discord role. The higher the position, the higher the role is in the server's hierarchy. ## Syntax ``` $rolePosition[roleID;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the role. Required. | | `guildID` | Optional. The ID of the target server. | ## Return Value | Type | Description | |---|---| | `integer` | The position of the role in the hierarchy. | ## Examples ### Display the position ```bdfd $sendMessage[Position of the Admin role: $rolePosition[$roleID[Admin]]] ``` ### Compare two roles ```bdfd $if[$rolePosition[$roleID[Admin]]>$rolePosition[$roleID[Mod]]] $sendMessage[The Admin role is hierarchically superior to Mod.] $else $sendMessage[Mod is superior or equal to Admin.] $endif ``` ### Check if one role can manage another ```bdfd $if[$rolePosition[$getRole[$authorID;1]]>$rolePosition[$roleID[Target]]] $sendMessage[Your role is superior.] $else $sendMessage[You cannot act because your role is inferior or equal.] $endif ``` ### Get the highest role ```bdfd $sendMessage[Highest role of the server: $roleName[$roleID[$roleNames]]] ``` ## Notes - `@everyone` always has the position `0`. - Positions are unique: two roles cannot have the same position. - A bot cannot modify roles that are hierarchically higher than its own. --- ### $rulesChannelID[] # $rulesChannelID[] — Rules Channel `$rulesChannelID[]` returns the ID of the rules channel configured on a Discord Community server. This channel is shown to new members when they join the server. > **Prerequisite**: The server must have the "Community" feature enabled in its settings. ## Syntax ``` $rulesChannelID ``` ## Parameters No parameters. ## Return Value - **Type**: `string` - The ID of the rules channel, or an empty string if not configured. ## Usage ### Simple Display ```bdfd $if[$rulesChannelID!=] $sendMessage[📋 Server Rules: <#$rulesChannelID>] $else $sendMessage[ℹ️ This server does not have a dedicated rules channel.] $endif ``` ### Welcome message with rules link ```bdfd $sendMessage[Welcome $username! Please read the rules here: <#$rulesChannelID> 📋] ``` ### Server configuration embed ```bdfd $title[⚙️ Configuration — $serverName] $addField[📋 Rules;$if[$rulesChannelID!=]<#$rulesChannelID>$elseNot configured$endif;yes] $addField[📢 System;$if[$systemChannelID!=]<#$systemChannelID>$elseNot configured$endif;yes] $addField[💤 AFK;$if[$afkChannelID!=]<#$afkChannelID>$elseNot configured$endif;yes] $color[#5865F2] $sendEmbedMessage ``` ### Redirection to rules ```bdfd $if[$rulesChannelID!=$channelID] $sendMessage[⚠️ Please use commands in an appropriate channel. The rules are available here: <#$rulesChannelID>] $endif ``` ## Notes - The rules channel is configured in the Community server settings. - If the server is not a Community server, this function returns an empty string. - Use `$serverFeatures[]` to check if the server has the `COMMUNITY` feature enabled. - The channel is generally read-only for standard members. --- ### $scriptLanguage # $scriptLanguage The function `$scriptLanguage` **returns the scripting language** configured for the bot on the BDFD platform. The possible values are `bdscript` (native BDFD language) or `bdjs` (JavaScript-like). ## Syntax ``` $scriptLanguage ``` ## Parameters None. ## Return Value - **Type**: String - `bdscript`: the bot uses the native BDScript language. - `bdjs`: the bot uses BDJS (JavaScript syntax). ## Behavior - The language is defined in the bot's settings on the BDFD console. - BDJS allows the use of JavaScript structures (variables, functions, etc.). - BDScript is the traditional language based on `$` functions. ## Examples ### Check the mode ```bdfd $if[$scriptLanguage==bdjs] $sendMessage[📝 This bot uses **BDJS** (JavaScript). You can use JavaScript syntax: ```js var x = 5; if (x > 3) { ... } ```] $else $sendMessage[📝 This bot uses **BDScript**. Traditional syntax: ```bdfd $var[x;5] $if[$var[x]>3] ... $endif ```] $endif ``` ### Information Page ```bdfd $title[⚙️ Bot Configuration] $addField[🤖 Name;$botName;yes] $addField[📝 Language;$if[$scriptLanguage==bdjs]BDJS (JavaScript)$elseBDScript$endif;yes] $addField[⚡ Runtime;$nodeVersion;yes] $addField[📦 Node;$botNode;yes] $footer[BDFD Bot Creator] $color[#5865F2] $sendMessage[] ``` ### Contextual Help ```bdfd ;; Example of a function adapting to the language $if[$scriptLanguage==bdjs] $sendMessage[💡 In BDJS, use `var` to declare variables. Example: `var x = 10;`] $else $sendMessage[💡 In BDScript, use `$var[]` to declare variables. Example: `$var[x;10]`] $endif ``` ## Notes - Possible values: `bdscript` or `bdjs`. - The choice of language is made when creating the bot and can be modified in the settings. - BDJS allows the use of JavaScript `if/else`, `for`, and `while` in addition to `$` functions. - BDScript is recommended for beginners. - Full JavaScript API reference: [JavaScript API](/docs/javascript/). --- ### $serverBanner[] # $serverBanner[] — Server Banner `$serverBanner[]` returns the URL of the Discord server banner. The banner is a horizontal image displayed at the top of the channel list on desktop clients. > **Prerequisite**: The server must be boost level 2 or higher to be able to set a custom banner. ## Syntax ``` $serverBanner ``` ## Parameters No parameters. ## Return Value - **Type**: `string` - The URL of the server banner, or an empty string if the server does not have one. ## Usage ### Display in an embed ```bdfd $title[$serverName] $description[$serverDescription] $image[$serverBanner] $color[#5865F2] $sendEmbedMessage ``` ### Server welcome page ```bdfd $title[🏠 Welcome to $serverName] $description[$serverDescription] $image[$serverBanner] $addField[Members;$membersCount;yes] $addField[Boosts;$serverBoostCount;yes] $thumbnail[$serverIcon] $color[#2ECC71] $footer[$serverName] $sendEmbedMessage ``` ### Check and fallback ```bdfd $if[$serverBanner==] $var[bannerURL;$serverIcon] $else $var[bannerURL;$serverBanner] $endif $title[$serverName] $image[$var[bannerURL]] $sendEmbedMessage ``` ## Notes - `$serverBanner[]` is an alias of `$guildBanner[]`. - Requires a server boost level of 2 or 3. - The banner is different from the icon (the icon is square, while the banner is rectangular with a ~16:9 ratio). - If the server does not have a banner, plan a fallback (such as the server icon or a default image). --- ### $serverBoostCount[] # $serverBoostCount[] — Number of Server Boosts `$serverBoostCount[]` returns the total number of Nitro boosts applied to the server. Boosts unlock perks for the server (more emojis, better audio quality, banner, etc.). ## Syntax ``` $serverBoostCount ``` ## Parameters No parameters. ## Return Value - **Type**: `integer` - The number of active Nitro boosts on the server. ## Usage ### Simple display ```bdfd $sendMessage[🚀 **$serverBoostCount** Nitro boosts on this server!] ``` ### Thank you embed ```bdfd $title[🚀 Boosters of $serverName] $description[Thank you to the $serverBoostCount boosters supporting the server!] $addField[Current Level;$boostLevel;yes] $addField[Next Tier;$if[$boostLevel<3]Only $sub[$var[boostsNeeded];$serverBoostCount] boosts to go!$elseMaximum level reached 🎉$endif;yes] $color[#F47FFF] $sendEmbedMessage ``` ### Complete server info ```bdfd $title[📊 Statistics for $serverName] $addField[👥 Members;$membersCount;yes] $addField[🟢 Online;$onlineMembers;yes] $addField[🤖 Bots;$botCount;yes] $addField[🚀 Boosts;$serverBoostCount (Level $boostLevel);yes] $addField[🎨 Emojis;$emojiCount;yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ### Tier progression check ```bdfd $if[$serverBoostCount>=14] $sendMessage[🌟 Level 3 reached! Enjoy all the perks.] $elseIf[$serverBoostCount>=7] $sendMessage[🎈 Level 2! Only $sub[14;$serverBoostCount] boosts left to reach level 3.] $elseIf[$serverBoostCount>=2] $sendMessage[🎀 Level 1! Only $sub[7;$serverBoostCount] boosts left to reach level 2.] $else $sendMessage[💪 No boost level reached yet. $sub[2;$serverBoostCount] boosts required for level 1.] $endif ``` ## Notes - Each boost counts as 1, regardless of who applied it. - The number of boosts determines the boost level of the server: - Level 1: 2 boosts - Level 2: 7 boosts - Level 3: 14 boosts - Use `$boostLevel[]` to get the level (0-3) directly without calculating the tiers manually. --- ### $serverChannelExists # $serverChannelExists The function `$serverChannelExists[]` checks if a **channel exists on a given server** (by its name). ## Syntax ``` $serverChannelExists[name;guildID] ``` ## Parameters | Parameter | Description | |---|---| | `name` | Name of the channel to search for. Case-sensitive. Wildcards (*) supported. | | `guildID` | ID of the server. If omitted, uses the current server. | ## Return Value - **Type**: Boolean (string) - `"true"` if the channel exists. - `"false"` otherwise. ## Examples ### Simple Check ```bdfd $if[$serverChannelExists[logs]==true] $sendMessage[The #logs channel already exists.] $else $createChannel[logs] $sendMessage[#logs channel created.] $endif ``` ### Check with wildcard ```bdfd $if[$serverChannelExists[ticket-*]==true] $sendMessage[Ticket channels already exist.] $else $sendMessage[No ticket channels found.] $endif ``` ### Check on another server ```bdfd $if[$serverChannelExists[welcome;$guildID[Partner Server]]==true] $sendMessage[The welcome channel exists on the partner server.] $endif ``` ## Notes - Different from `$channelExists[]` which checks by ID, not by name. - Useful to avoid duplicate channels before creating one. - The `guildID` parameter is optional (defaults to the current server). --- ### $serverCount[] # $serverCount[] — Bot Server Count `$serverCount[]` returns the total number of Discord servers the bot is installed on. ## Syntax ``` $serverCount ``` ## Parameters No parameters. ## Return Value - **Type**: `integer` - The number of servers the bot belongs to. ## Usage ### Simple display ```bdfd $sendMessage[🤖 I am currently on **$serverCount** servers!] ``` ### Bot statistics ```bdfd $title[📊 Bot Statistics] $addField[🌐 Servers;$serverCount;yes] $addField[🔢 Shard;$shardID;yes] $color[#5865F2] $sendEmbedMessage ``` ### Custom status message ```bdfd $title[🤖 My Bot] $description[Thank you for using me!] $addField[Servers;$serverCount;yes] $addField[Latency;$ping ms;yes] $footer[Developed with BDFD] $color[#2ECC71] $sendEmbedMessage ``` ### Popularity message ```bdfd $if[$serverCount>=100] $sendMessage[🎉 Thank you to the $serverCount servers that trust me!] $else $sendMessage[I am on $serverCount servers. Help me grow!] $endif ``` ## Notes - `$serverCount[]` is an alias of `$guildCount[]`. - The count includes all servers the bot is present in, regardless of the shard. - The number is updated automatically when the bot joins or leaves a server. - Useful for statistics commands and "About" pages of the bot. --- ### $serverDescription[] # $serverDescription[] — Server Description `$serverDescription[]` returns the text description of the Discord server as configured in the server settings (under the "Overview" section). ## Syntax ``` $serverDescription ``` ## Parameters No parameters. ## Return Value - **Type**: `string` - The description of the server, or an empty string if no description is set. ## Usage ### Display the description ```bdfd $sendMessage[📝 Description: $serverDescription] ``` ### Informational Embed ```bdfd $title[$serverName] $description[$serverDescription] $addField[Owner;<@$serverOwner>;yes] $addField[Members;$membersCount;yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ### Check if a description exists ```bdfd $if[$serverDescription==] $sendMessage[This server does not have a description.] $else $sendMessage[**$serverName**: $serverDescription] $endif ``` ### Filter by keyword in the description ```bdfd $if[$toLowercase[$serverDescription]$contains[gaming]] $sendMessage[This server is dedicated to gaming!] $else $sendMessage[This server is not categorized as gaming.] $endif ``` ## Notes - The description is optional; not all servers have one. - The maximum length of a server description is 1,000 characters. - Useful for displaying contextual information about the server in embeds or help commands. - Can be combined with other functions for more complete server information. --- ### $serverEmojis[] # $serverEmojis[] — Server Emojis List `$serverEmojis[]` returns the complete list of custom emojis on the server, formatted to be displayed in Discord. ## Syntax ``` $serverEmojis ``` ## Parameters No parameters. ## Return Value - **Type**: `string` - A string containing all custom emojis on the server, each in the format `<:name:id>` (or `` for animated emojis). ## Usage ### Display all emojis ```bdfd $sendMessage[🎨 Emojis of the server: $serverEmojis] ``` ### Emoji catalog embed ```bdfd $title[Emojis of $serverName] $description[$serverEmojis] $footer[Total: $emojiCount emojis] $color[#F1C40F] $sendEmbedMessage ``` ### Check emoji count ```bdfd $if[$emojiCount>=50] $sendMessage[🎉 This server has a rich collection of emojis! ($emojiCount)] $else $sendMessage[The server has $emojiCount custom emojis.] $endif ``` ### Server info with emojis ```bdfd $title[$serverName] $addField[👥 Members;$membersCount;yes] $addField[🎨 Emojis;$emojiCount;yes] $addField[🚀 Boosts;$serverBoostCount;yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ## Notes - The list can be very long if the server has many emojis — watch out for the Discord 2,000-character message limit. - Animated emojis are prefixed with `] ``` ### Retrieve all information ```bdfd $title[Complete Server Information] $description[Raw server data] $addField[Server Object;$serverInfo;no] $color[#5865F2] $sendEmbedMessage ``` ### Dynamic usage ```bdfd $var[prop;$message[1]] $if[$var[prop]!=] $sendMessage[$serverInfo[$var[prop]]] $else $sendMessage[Usage: !serverinfo ] $endif ``` ### Summary Embed ```bdfd $title[$serverInfo[name]] $description[$serverInfo[description]] $addField[🆔 ID;$serverInfo[id];yes] $addField[👑 Owner;<@$serverInfo[ownerID]>;yes] $addField[👥 Members;$serverInfo[memberCount];yes] $addField[🚀 Boosts;$serverInfo[boostCount] (Lvl. $serverInfo[boostLevel]);yes] $addField[🎨 Emojis;$serverInfo[emojiCount];yes] $addField[🔒 Verification;$serverInfo[verificationLevel];yes] $thumbnail[$serverInfo[icon]] $image[$serverInfo[banner]] $color[#5865F2] $sendEmbedMessage ``` ## Notes - `$serverInfo[]` without arguments returns a raw JSON object — useful for debugging or logging. - Property names are case-sensitive (camelCase). - Prefer dedicated functions (`$serverName`, `$serverID`, etc.) for simple usage — `$serverInfo[]` is best for dynamic access. - Not all properties are always available (e.g. `banner` if the boost level is insufficient). --- ### $serverName[] # $serverName[] — Name of the Server `$serverName[]` returns the name of the Discord server in which the command is executed. ## Syntax ``` $serverName ``` ## Parameters None. ## Return Value - **Type**: `string` - The current name of the server. ## Usage ### Welcome message ```bdfd $sendMessage[Welcome to **$serverName**! We are glad to have you with us.] ``` ### Embed with the server name ```bdfd $title[$serverName — Rules] $description[Please read the rules of $serverName carefully.] $color[#E74C3C] $sendEmbedMessage ``` ### Logs ```bdfd $log[The command was executed on the server: $serverName] ``` ### Condition on the name ```bdfd $if[$serverName==My Server] $sendMessage[Welcome to the main server!] $else $sendMessage[Welcome to $serverName!] $endif ``` ## Notes - `$serverName[]` is an alias of `$guildName[]`. - The returned value is dynamic: it reflects the current name of the server, even if it was recently changed. - Useful for customizing messages based on the server. --- ### $serverNames[] # $serverNames[] — Names of All Servers `$serverNames[]` returns the complete list of names of all Discord servers where the bot is installed. ## Syntax ``` $serverNames ``` ## Parameters None. ## Return Value - **Type**: `string` - A string containing all server names, separated by commas (e.g., `"Server A, Server B, Server C"`). ## Usage ### Simple display ```bdfd $sendMessage[🌐 My servers: $serverNames] ``` ### Embed list of servers ```bdfd $title[🌐 Servers of the Bot] $description[$serverNames] $footer[Total: $serverCount servers] $color[#5865F2] $sendEmbedMessage ``` ### Check presence on a server ```bdfd $if[$serverNames$contains[Gaming Community]] $sendMessage[✅ The bot is indeed on the Gaming Community!] $else $sendMessage[❌ The bot is not on the Gaming Community.] $endif ``` ### Statistics with server list ```bdfd $title[📊 Bot Statistics] $addField[🌐 Total servers;$serverCount;yes] $addField[📋 List;$serverNames;no] $addField[🔢 Shard;$shardID;yes] $color[#2ECC71] $sendEmbedMessage ``` ## Notes - The list can be very long if the bot is on many servers — watch out for the Discord message limit of 2000 characters. - The names are separated by `", "` (comma + space). - To get the total number of servers without the list, use `$serverCount[]`. - Use `$contains[]` to check the presence of a specific name, but be careful with partial matches. - The names can contain special characters and emojis. --- ### $serverOwner[] # $serverOwner[] — Owner of the Server `$serverOwner[]` returns the Discord identifier (ID) of the owner of the server. This ID can be used to mention the owner, check permissions, or restrict commands. ## Syntax ``` $serverOwner ``` ## Parameters None. ## Return Value - **Type**: `string` - The ID (Snowflake) of the owner of the server. ## Usage ### Mention the owner ```bdfd $sendMessage[👑 Owner of the server: <@$serverOwner>] ``` ### Restrict a command to the owner ```bdfd $if[$authorID!=$serverOwner] $sendMessage[⛔ Only the server owner can use this command.] $stop $endif $sendMessage[Owner command executed.] ``` ### Informative embed ```bdfd $title[Information on $serverName] $description[Server managed by <@$serverOwner>] $addField[Server ID;$serverID;yes] $addField[Owner;$serverOwner;yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ### Notification to the owner ```bdfd $sendMessage[<@$serverOwner>, a user is requesting your attention.] ``` ## Notes - The owner is the user who created the server or to whom the ownership was transferred. - The ID of the owner remains unchanged as long as the ownership is not transferred. - Use `$username[$serverOwner]` to get the name of the owner without mentioning them. - To check if the current user is the owner, you can also use `$isOwner[]`. --- ### $serverRegion[] # $serverRegion[] — Server Region `$serverRegion[]` returns the configured voice region for the Discord server. > **Note**: Since Discord's 2023 update, the region is no longer configured at the server level but at the individual voice channel level instead. This function may therefore return "automatic" on most modern servers. ## Syntax ``` $serverRegion ``` ## Parameters None. ## Return Value - **Type**: `string` - The region of the server (e.g., `"europe"`, `"us-west"`, `"automatic"`, etc.). ## Usage ### Simple display ```bdfd $sendMessage[🌍 Region: $serverRegion] ``` ### Informative embed ```bdfd $title[Information on $serverName] $addField[Region;$serverRegion;yes] $addField[Verification Level;$serverVerificationLevel;yes] $addField[Boost Level;$boostLevel;yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ### Logs ```bdfd $log[Server $serverName — Region: $serverRegion] ``` ## Notes - The region determines the geographical location of voice servers, which affects latency. - **Deprecated**: Discord migrated to a system of automatic regions per voice channel. The returned value may no longer be relevant. - Historically possible values: `brazil`, `europe`, `hongkong`, `india`, `japan`, `russia`, `singapore`, `southafrica`, `sydney`, `us-central`, `us-east`, `us-south`, `us-west`. - For recent servers, the value will generally be `"automatic"`. --- ### $serverSplash[] # $serverSplash[] — Server Invite Splash Image `$serverSplash[]` returns the URL of the background image that appears on the Discord invite page of the server (when a user clicks an invite link). > **Prerequisite**: This feature is reserved for Discord partnered or verified servers, or servers with a sufficient boost level. ## Syntax ``` $serverSplash ``` ## Parameters None. ## Return Value - **Type**: `string` - The URL of the splash image, or an empty string if not available. ## Usage ### Simple display ```bdfd $if[$serverSplash!=] $sendMessage[Invite splash: $serverSplash] $else $sendMessage[This server does not have an invite splash image.] $endif ``` ### Embed with splash ```bdfd $title[$serverName — Join us!] $description[$serverDescription] $image[$serverSplash] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ### Custom invite page ```bdfd $title[🌟 Invite — $serverName] $description[You are invited to join $serverName!] $image[$serverSplash] $addField[Invite Link;discord.gg/$serverVanityURL;yes] $addField[Members;$membersCount;yes] $color[#9B59B6] $sendEmbedMessage ``` ## Notes - The splash image is distinct from the server banner: it specifically appears on the invite page. - Reserved for partnered or verified servers (Partner or Verified badge), or those with sufficient boosts. - If the server is not eligible or has no splash image, the function returns an empty string. - Recommended dimensions: 1920x1080px (16:9 ratio). --- ### $serverVanityURL[] # $serverVanityURL[] — Custom URL of the Server `$serverVanityURL[]` returns the custom URL code (vanity URL) of the server. This short URL allows creating an easy-to-remember invite link (e.g., `discord.gg/my-server`). > **Prerequisite**: Server boost level 3, or Discord partnered/verified server. ## Syntax ``` $serverVanityURL ``` ## Parameters None. ## Return Value - **Type**: `string` - The code of the custom URL (e.g., `"my-server"`), or an empty string if not available. ## Usage ### Invite link ```bdfd $if[$serverVanityURL!=] $sendMessage[🔗 Join us: **discord.gg/$serverVanityURL**] $else $sendMessage[This server does not have a custom URL.] $endif ``` ### Invite embed ```bdfd $title[🌟 $serverName] $description[$serverDescription] $addField[Join;discord.gg/$serverVanityURL;yes] $addField[Members;$membersCount;yes] $thumbnail[$serverIcon] $image[$serverSplash] $color[#9B59B6] $sendEmbedMessage ``` ### Welcome page ```bdfd $title[Information on $serverName] $addField[🌟 URL;discord.gg/$serverVanityURL;yes] $addField[👑 Owner;<@$serverOwner>;yes] $addField[👥 Members;$membersCount;yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ## Notes - The complete URL is `discord.gg/` or `https://discord.gg/`. - The code is configured in the server settings (under "Overview" → "Custom Invite Link"). - Requires boost level 3 or Partnered/Verified status. - The code is unique across all of Discord. - If the server does not have a custom URL, use `$createInvite[]` to generate a standard invite link. --- ### $serverVerificationLevel[] # $serverVerificationLevel[] — Verification Level `$serverVerificationLevel[]` returns the verification level of the server, which determines the criteria that a member must meet before being able to send messages. ## Syntax ``` $serverVerificationLevel ``` ## Parameters None. ## Return Value - **Type**: `integer` - An integer from 0 to 4 representing the verification level: | Value | Level | Description | |--------|--------|-------------| | 0 | None | No restrictions | | 1 | Low | Accounts with a verified email | | 2 | Medium | Accounts registered for more than 5 minutes | | 3 | High | Members of the server for more than 10 minutes | | 4 | Very High | Accounts with a verified phone number | ## Usage ### Simple display ```bdfd $sendMessage[🔒 Verification level: $serverVerificationLevel] ``` ### Interpreted message ```bdfd $var[verifLevel;$serverVerificationLevel] $if[$var[verifLevel]==0] $var[verifText;No restrictions] $elseIf[$var[verifLevel]==1] $var[verifText;Verified email required] $elseIf[$var[verifLevel]==2] $var[verifText;Account older than 5 minutes] $elseIf[$var[verifLevel]==3] $var[verifText;Member for over 10 minutes] $else $var[verifText;Verified phone number required] $endif $sendMessage[🔒 Verification level: **$var[verifText]**] ``` ### Server info embed ```bdfd $title[Configuration of $serverName] $addField[Verification level;$serverVerificationLevel;yes] $addField[AFK Timeout;$afkTimeout seconds;yes] $color[#5865F2] $sendEmbedMessage ``` ## Notes - A higher level offers better protection against spam and raids. - Level 4 (verified phone number) is the most restrictive and requires that Discord has verified the account's phone number. - This information is useful for moderation commands or contextual welcome messages. --- ### $shardID[] # $shardID[] — Shard ID `$shardID[]` returns the Discord shard ID on which the bot is executing the command. Sharding is a technique used by Discord to distribute the load of popular bots across several processes. ## Syntax ``` $shardID ``` ## Parameters None. ## Return Value - **Type**: `integer` - The ID of the current shard, starting at 0. ## Usage ### Simple display ```bdfd $sendMessage[🔢 Shard: **$shardID**] ``` ### Bot statistics ```bdfd $title[📊 Bot Statistics] $addField[🔢 Shard;$shardID;yes] $addField[🌐 Servers (on this shard);$serverCount;yes] $addField[📶 Ping;$ping ms;yes] $color[#2ECC71] $sendEmbedMessage ``` ### Log with shard ```bdfd $log[Shard $shardID — Command executed on $serverName] ``` ### Debug ```bdfd $title[🐛 Debug Info] $addField[Shard;$shardID;yes] $addField[Server;$serverName ($serverID);yes] $addField[Channel;$channelID;yes] $addField[User;$username ($authorID);yes] $color[#E74C3C] $sendEmbedMessage ``` ## Notes - If your bot is not sharded (less than ~2500 servers), `$shardID[]` will probably return `0`. - Sharding becomes necessary when the bot reaches a large number of servers (more than 2500). - Each shard manages a subset of the bot's servers. - The shard ID is useful for debugging and identifying problems on specific shards. - Commands are always executed in the context of a single shard. --- ### $slashCommandsCount # $slashCommandsCount The function `$slashCommandsCount` **returns the number of slash commands** registered on the bot (excluding prefix commands). ## Syntax ``` $slashCommandsCount ``` ## Parameters None. ## Return Value - **Type**: Integer - The number of slash commands (e.g., `25`). ## Behavior - Counts only slash commands. - Does not count prefix commands. - Useful for checking Discord limits (100 slash commands per application). ## Examples ### Statistics dashboard ```bdfd $title[📊 Commands] $addField[🔹 Slash;$slashCommandsCount;yes] $addField[🔸 Prefix;$math[$commandsCount-$slashCommandsCount];yes] $addField[📦 Total;$commandsCount;yes] $footer[Discord Limit: 100 slash commands] $color[#5865F2] $sendMessage[] ``` ### Checking Discord limit ```bdfd $if[$slashCommandsCount>=100] $sendMessage[⚠️ **Warning:** You have reached the limit of 100 Discord slash commands. New slash commands might not register.] $else $var[restant;$math[100-$slashCommandsCount]] $sendMessage[✅ $slashCommandsCount/100 slash commands used ($var[restant] remaining).] $endif ``` ### Bot information ```bdfd $title[🤖 $botName - Statistics] $description[ **Total commands:** $commandsCount **Slash:** $slashCommandsCount **Prefix:** $math[$commandsCount-$slashCommandsCount] **Servers:** $guildCount **Users:** $membersCount ] $thumbnail[$botAvatar] $color[#57F287] $sendMessage[] ``` ## Notes - Counts only slash commands. - For the total (prefix + slash), use `$commandsCount`. - Discord limits to 100 slash commands per application. - For the ID of a slash command, use `$slashID`. --- ### $slashID # $slashID The function `$slashID` **returns the Discord ID (snowflake) of the slash command** currently being executed. If the command is not a slash command, it returns an empty string. ## Syntax ``` $slashID ``` ## Parameters None. ## Return Value - **Type**: String - The Discord ID of the slash command (e.g., `1234567890123456789`). - An empty string if the current command is a prefix command. ## Behavior - The ID is assigned by Discord during the registration of the command. - Useful for logging, debugging, or unique identification. - Returns empty for prefix commands. ## Examples ### Detailed log ```bdfd $if[$slashID!=] $log[🔹 SLASH | ID: $slashID | Name: $commandName | User: $userName ($authorID) | Server: $serverName] $else $log[🔸 PREFIX | Name: $commandName | Trigger: $commandTrigger | User: $userName] $endif ``` ### Debug command ```bdfd $if[$authorID!=$botOwnerID] $stop $endif $title[🔍 Debug Command] $description[ **Name:** $commandName **Trigger:** $commandTrigger **Type:** $commandType **Folder:** $commandFolder **Slash ID:** $if[$slashID!=]$slashID$elseN/A (prefix)$endif **Author:** $userName ($authorID) **Server:** $serverName ($guildID) **Channel:** $channelName ($channelID) ] $color[#5865F2] $sendMessage[] ``` ### Conditional behavior ```bdfd $if[$slashID!=] $var[mode;slash] $var[args;$slashOption[1]] $else $var[mode;prefix] $var[args;$message[1]] $endif $sendMessage[📌 Mode: $var[mode] | Args: $var[args]] ``` ### Command information for support ```bdfd $if[$slashID!=] $sendMessage[🆔 **Slash Command ID:** $slashID ┗ Name: $commandName] $else $sendMessage[📝 **Prefix Command** ┗ Trigger: $commandTrigger] $endif ``` ## Related functions - [$slashOption](/docs/slashoption/) — read slash command option values ## Notes - Returns an empty string for prefix commands. - The ID is unique and assigned by Discord. - Useful for technical support (provide the ID in case of a bug). - To check if a command is a slash command, use `$isSlash` or `$commandType`. --- ### $slashOption # $slashOption `$slashOption` retrieves the value of a **slash command option** while a slash interaction is executing. Use it in hybrid commands that also support prefix invocations. ## Syntax ### Named option ``` $slashOption[optionName] ``` ### Positional option (1-based index) ``` $slashOption[1] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:--------:| | `optionName` or `index` | Option name as defined in the slash command builder, or a 1-based positional index | Yes | ## Return value - **Type**: String (or type-appropriate value for the option) - Empty string if the option was not provided or the command is not a slash command. ## Description When [$isSlash](/docs/isslash/) or [$commandType](/docs/commandtype/) is `slash`, options are passed by Discord as structured fields rather than raw message text. `$slashOption` reads those values. Pair it with `$message[n]` in hybrid commands so prefix and slash modes share the same processing logic. ## Examples ### Hybrid command arguments ```bdfd $if[$isSlash==true] $var[args;$slashOption[1]] $else $var[args;$message[1]] $endif $sendMessage[You provided: $var[args]] ``` ### Named slash options ```bdfd $if[$commandType==slash] $var[target;$slashOption[target]] $var[reason;$slashOption[reason]] $else $var[target;$message[1]] $var[reason;$message[2]] $endif ``` ### Slash command logging ```bdfd $if[$isSlash==true] $log[Slash /$commandName — option 1: $slashOption[1]] $endif ``` ## Related functions - [$isSlash](/docs/isslash/) — detect slash vs prefix invocation - [$commandType](/docs/commandtype/) — returns `slash` or `prefix` - [$slashID](/docs/slashid/) — Discord snowflake of the slash command - [$args](/docs/args/) — prefix command arguments ## Notes - Only meaningful when the command runs as a slash interaction. - Option names must match the names configured in the Bot Creator slash command editor. - For subcommands, use the subcommand option names as defined in the command tree. --- ### $slowmode # $slowmode The function `$slowmode` returns the current **slowmode delay** of a Discord channel, expressed in seconds. This is a **read-only** function (getter). ## Syntax ``` $slowmode[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional. The ID of the target channel. If omitted, the current channel is used. | ## Return Value | Type | Description | |---|---| | `integer` | The delay in seconds. `0` means slowmode is disabled. | ## Possible Values Discord allows the following slowmode values (in seconds): `0`, `5`, `10`, `15`, `30`, `60`, `120`, `300`, `600`, `900`, `1800`, `3600`, `7200`, `21600`. ## Examples ### Display the slowmode ```bdfd $sendMessage[Current slowmode: $slowmode second(s)] ``` ### Check if slowmode is active ```bdfd $if[$slowmode>0] $sendMessage[⏳ This channel has a slowmode of $slowmode second(s).] $else $sendMessage[No slowmode in this channel.] $endif ``` ### Alert on high slowmode ```bdfd $if[$slowmode>=300] $sendMessage[⚠️ Warning: this channel has a very high slowmode ($slowmode seconds).] $endif ``` ## Notes - `$slowmode` is a **getter**: it does not modify the slowmode. - Returns `0` if the channel has no slowmode. - Only works on text channels. --- ### $stickerCount[] # $stickerCount[] — Number of Stickers `$stickerCount[]` returns the number of custom stickers available on the Discord server. ## Syntax ``` $stickerCount ``` ## Parameters None. ## Return Value - **Type**: `integer` - The number of custom stickers on the server. ## Usage ### Simple display ```bdfd $sendMessage[🏷️ **$stickerCount** custom stickers on this server.] ``` ### Statistics embed ```bdfd $title[📊 Content of $serverName] $addField[🏷️ Stickers;$stickerCount;yes] $addField[🎨 Emojis;$emojiCount;yes] $addField[🚀 Boosts;$serverBoostCount;yes] $thumbnail[$serverIcon] $color[#5865F2] $sendEmbedMessage ``` ### Availability check ```bdfd $if[$stickerCount==0] $sendMessage[ℹ️ This server does not have any custom stickers yet.] $else $sendMessage[✅ $stickerCount stickers available!] $endif ``` ### Comparison of emojis and stickers ```bdfd $title[Content of the server] $addField[🎨 Emojis;$emojiCount;yes] $addField[🏷️ Stickers;$stickerCount;yes] $addField[📦 Total content;$sum[$emojiCount;$stickerCount];yes] $color[#5865F2] $sendEmbedMessage ``` ## Notes - Stickers are different from emojis: they are larger images, often animated (APNG or Lottie). - The sticker limit depends on the server boost level: - Level 0: 5 stickers (standard), 0 custom - Level 1: 15 custom slots - Level 2: 30 custom slots - Level 3: 60 custom slots - Custom stickers can only be used on the server where they were created (except for partnered/verified servers). --- ### $systemChannelID[] # $systemChannelID[] — System Messages Channel `$systemChannelID[]` returns the ID of the channel where Discord sends automatic system messages: new member announcements, Nitro boost messages, etc. ## Syntax ``` $systemChannelID ``` ## Parameters No parameters. ## Return Value - **Type**: `string` - The ID of the system channel, or an empty string if not configured. ## Usage ### Simple Display ```bdfd $if[$systemChannelID!=] $sendMessage[📢 System messages are sent in <#$systemChannelID>] $else $sendMessage[ℹ️ No system channel is configured.] $endif ``` ### Embed Configuration ```bdfd $title[⚙️ Configuration of $serverName] $addField[📢 System Channel;$if[$systemChannelID!=]<#$systemChannelID>$elseNot configured$endif;yes] $addField[📋 Rules Channel;$if[$rulesChannelID!=]<#$rulesChannelID>$elseNot configured$endif;yes] $addField[💤 AFK Channel;$if[$afkChannelID!=]<#$afkChannelID>$elseNot configured$endif;yes] $color[#5865F2] $sendEmbedMessage ``` ### Configuration Log ```bdfd $log[Configuration $serverName | System: $systemChannelID | Rules: $rulesChannelID | AFK: $afkChannelID] ``` ### Contextual Help Message ```bdfd $if[$systemChannelID==$channelID] $sendMessage[ℹ️ You are in the system messages channel. New members and boosts are announced here.] $endif ``` ## Notes - The system channel is configured in the server settings ("Overview" tab). - Messages regarding new members and Nitro boosts are automatically posted in this channel. - If the channel is not configured, system messages are not sent. - This channel is distinct from the rules channel (`$rulesChannelID[]`). --- ### $userAvatar # $userAvatar The variable `$userAvatar` returns the **global avatar URL** of the user who triggered the command. ## Syntax ``` $userAvatar ``` ## Return Value - **Type**: String (URL) - URL of the Discord avatar image in PNG or WebP format - If the user does not have a custom avatar, returns the default Discord avatar (color based on the discriminator/ID) ## Behavior - `$userAvatar` takes **no arguments**. - The returned URL points to the Discord CDN (`cdn.discordapp.com`). - The avatar is the **global** image of the user, not the server-specific one (see `$userServerAvatar`). ## Examples ### Display Avatar in Large ```bdfd $title[Avatar of $userName] $image[$userAvatar] $color[#5865F2] $sendMessage[] ``` ### Display Avatar as Thumbnail in a Profile ```bdfd $author[$userName;$userAvatar] $title[User Profile] $thumbnail[$userAvatar] $description[ **Name:** $userName **ID:** $userID ] $color[#5865F2] $sendMessage[] ``` ## Notes - Discord avatar URLs can be modified by adding `?size=256` or `?size=1024` to change the resolution. - For the server-specific avatar (if set), use `$userServerAvatar`. - The user can change their avatar at any time. --- ### $userBadges # $userBadges The variable `$userBadges` returns the **list of public badges** (public flags) of the user. These badges are visible on the Discord profile and indicate various statuses (Nitro, HypeSquad, developer, etc.). ## Syntax ``` $userBadges ``` ## Return Value - **Type**: List/array of strings - Possible badges: `Discord Employee`, `Partnered Server Owner`, `HypeSquad Events`, `Bug Hunter Level 1`, `House Bravery`, `House Brilliance`, `House Balance`, `Early Supporter`, `Bug Hunter Level 2`, `Early Verified Bot Developer`, `Active Developer`, `Moderator Programs Alumni` ## Behavior - `$userBadges` takes **no arguments**. - Returns only **public** badges (displayed on the profile). - Internal or hidden badges are not included. ## Examples ### Display Badges in an Embed ```bdfd $title[Profile of $userName] $author[$userName;$userAvatar] $description[ **ID:** $userID **Badges:** $userBadges ] $color[#5865F2] $sendMessage[] ``` ### Check a Specific Badge ```bdfd $if[$checkContains[$userBadges;Early Supporter]==true] $sendMessage[Thank you for supporting Discord since the beginning! 💎] $endif ``` ## Notes - Not all users have badges — the list can be empty. - Badges are assigned by Discord and cannot be modified. - Use `$checkContains[]` to check for the presence of a specific badge. --- ### $userBanner # $userBanner The `$userBanner` function returns the **URL of the profile banner** of the user. The banner is the background image that appears on Discord profiles (reserved for Nitro subscribers). ## Syntax ``` $userBanner ``` ## Return Value - **Type**: String (URL) or empty string - If the user has a Nitro banner, it returns its Discord CDN URL. - If the user does not have a banner, it returns an empty string. ## Behavior - `$userBanner` takes **no arguments**. - Banners are a feature reserved for **Discord Nitro** subscribers. - If no banner is set, the function returns an empty string. ## Examples ### Display the banner if it exists ```bdfd $if[$userBanner!=] $title[Banner of $userName] $image[$userBanner] $color[$userBannerColor] $sendMessage[] $else $sendMessage[$userName does not have a profile banner.] $endif ``` ### Complete profile with banner ```bdfd $title[Profile of $userName] $description[ **Name:** $userName **ID:** $userID ] $image[$userBanner] $thumbnail[$userAvatar] $color[$userBannerColor] $sendMessage[] ``` ## Notes - Only users with a **Discord Nitro** subscription can set a banner. - Always check if `$userBanner` is not empty before using it as an image. - `$userBannerColor` returns the accent color associated with the banner. --- ### $userBannerColor # $userBannerColor The `$userBannerColor` function returns the **accent color** associated with the profile banner of the user. This color is automatically extracted by Discord from the banner. ## Syntax ``` $userBannerColor ``` ## Return Value - **Type**: String (hexadecimal) - Format: `#RRGGBB` (e.g., `#5865F2`) - If the user does not have a banner, it returns an empty string. ## Behavior - `$userBannerColor` takes **no arguments**. - The color is determined by Discord from the user's Nitro banner. - Can be used directly in `$color[]` to visually match the embed to the profile's theme. ## Examples ### Themed embed ```bdfd $if[$userBannerColor!=] $title[Profile of $userName] $description[The colors of this embed match your banner!] $color[$userBannerColor] $author[$userName;$userAvatar] $sendMessage[] $else $title[Profile of $userName] $description[You do not have a banner.] $color[#5865F2] $sendMessage[] $endif ``` ## Notes - Coupled with `$userBanner`, it allows you to create embeds with a custom theme for each user. - If the user does not have a banner, make sure to provide a fallback color. --- ### $userExists # $userExists The `$userExists` function checks if a Discord user exists, based on an **ID** or a **mention**. ## Syntax ``` $userExists[userID/mention] ``` ## Parameters | Parameter | Description | |---|---| | `userID/mention` | The numerical ID (snowflake) or the mention (`<@ID>`) of the user to check. | ## Return Value - **Type**: String `"true"` or `"false"` - `"true"` if the user exists and is known to the bot. - `"false"` if the ID is invalid or the user is not found. ## Behavior - The verification is based on the users accessible to the bot (shared server cache). - A user can exist on Discord without being on the bot's server — in this case, the result depends on the context. ## Examples ### Check a mention ```bdfd $if[$userExists[$mentioned]==true] $title[Information on <@$mentioned>] $description[ **ID:** $mentioned **Name:** $userName[$mentioned] ] $color[#5865F2] $sendMessage[] $else $sendMessage[I cannot find this user.] $endif ``` ### Check a static ID ```bdfd $if[$userExists[123456789012345678]==true] $sendMessage[The owner still exists!] $endif ``` ## Notes - Use `$userExists` to validate user inputs before executing actions that might fail. - `$userExists` does not check if the user is a **member of the server**, only if they exist on Discord and are known to the bot. - This function is useful for preventing errors in commands that use user-provided IDs. --- ### $userID # $userID The `$userID` function returns the **Discord ID** (snowflake) of the user who triggered the execution of the command or interaction. ## Syntax ``` $userID ``` ## Return Value - **Type**: Snowflake (numerical string of 17-19 digits) - Returns the unique ID of the user on Discord. ## Behavior - `$userID` takes **no arguments**. - Always returns the ID of the user who **interacted** with the bot (via command, button, menu, modal, etc.). - The ID is a permanent numerical string — it never changes, unlike the username. ## Examples ### Display the user ID ```bdfd $title[Your User ID] $description[**ID:** `$userID`] $color[#5865F2] $sendMessage[] ``` ### Use the ID in a condition ```bdfd $if[$userID==123456789012345678] $sendMessage[Hello administrator!] $else $sendMessage[Hello user!] $endif ``` ## Difference with $authorID - `$userID`: the user who triggered the interaction. - `$authorID`: the author of the message (in the case of a message command). In most simple cases, both are identical. In advanced contexts (workflows, interactions), `$userID` is recommended. ## Notes - The Discord ID is a permanent and unique **snowflake**. - It is not possible to modify or delete a Discord ID. - Use `$userID` in comparisons with `$if[]` to create commands reserved for specific users. --- ### $userInfo # $userInfo The `$userInfo` function returns a **JSON object** containing detailed information about a Discord user, or a specific property extracted from that object. ## Syntax ``` $userInfo[userID;(property)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | Optional. The ID of the target user. If omitted, uses the triggering user. | | `property` | Optional. The name of a property to extract from the JSON object. If omitted, returns the complete object. | ## Return Value - **Type**: JSON object or string depending on the requested property. - Available properties: `id`, `username`, `discriminator`, `avatar`, `bot`, `system`, `banner`, `accent_color`, `global_name`, `display_name`, `public_flags` ## Examples ### Get the complete JSON object ```bdfd $sendMessage[```json $userInfo ```] ``` ### Extract the global name of a user ```bdfd $title[User Search] $description[ **ID:** $mentioned **Global Name:** $userInfo[$mentioned;global_name] **Is Bot:** $userInfo[$mentioned;bot] ] $color[#5865F2] $sendMessage[] ``` ### Use with JSON parsing ```bdfd $let[info;$userInfo] $let[name;$jsonParse[$info;username]] $sendMessage[Name: $name] ``` ## Notes - `$userInfo` provides unified access to all properties of a user. - The available properties are the same as those of the Discord API User Object. - Useful for advanced integrations requiring structured data. --- ### $userJoined # $userJoined The `$userJoined` function returns the **join date** of the user on the Discord server where the command is executed. ## Syntax ``` $userJoined ``` ## Return Value - **Type**: Date/String - Format: depends on the context (readable date or timestamp) ## Behavior - `$userJoined` takes **no arguments**. - Returns the date when the user joined the **current server**. - Requires the user to be a member of the server. ## Examples ### Welcome message ```bdfd $title[New member!] $author[$userName;$userAvatar] $description[ Welcome to the server **$serverName**! You joined on **$userJoined**. ] $color[#57F287] $sendMessage[] ``` ### Member tenure ```bdfd $title[Your Join Date] $description[ You have been a member since **$userJoined**. ] $color[#5865F2] $sendMessage[] ``` ## Notes - `$userJoined` gives the join date on the **server**. - For the creation date of the Discord account, use `$userJoinedDiscord`. - Useful for member information commands and welcome messages. --- ### $userJoinedDiscord # $userJoinedDiscord The `$userJoinedDiscord` function returns the **creation date** of the user's Discord account — that is to say, the date they registered on the Discord platform. ## Syntax ``` $userJoinedDiscord ``` ## Return Value - **Type**: Date/String - The registration date of the account on Discord. ## Behavior - `$userJoinedDiscord` takes **no arguments**. - The date is derived from the user ID **snowflake** (the first bits encode an Epoch timestamp). - Works for any user whose ID is known, even without server membership. ## Examples ### Display account age ```bdfd $title[Account Information] $description[ **Name:** $userName **Account created on:** $userJoinedDiscord **Member since:** $userJoined ] $color[#5865F2] $sendMessage[] ``` ### Check for a recent account ```bdfd $if[$userJoinedDiscord < 01/01/2024] $sendMessage[Account created before 2024.] $else $sendMessage[Recent account.] $endif ``` ## Notes - `$userJoinedDiscord` = creation date of the **account** on Discord. - `$userJoined` = join date on the **server**. - The Discord ID (snowflake) encodes the creation date, therefore this information is always available. --- ### $userName # $userName The `$userName` function returns the **global Discord username** of the user who triggered the command. ## Syntax ``` $userName ``` ## Return Value - **Type**: String - The global Discord username (e.g., "JeanDupont") ## Behavior - `$userName` takes **no arguments**. - Returns the **global** username (the one visible everywhere on Discord, without the discriminator). - If the user has a nickname on the server, `$userName` still returns their global username. Use `$nickname` for the server nickname, or `$displayName` for the display name (nickname if set, otherwise global username). ## Examples ### Welcome message ```bdfd $title[Welcome $userName!] $description[We are delighted to welcome you to the server 🎉] $color[#57F287] $sendMessage[] ``` ### Create a custom embed ```bdfd $author[$userName;$userAvatar] $title[User Profile] $description[ **Name:** $userName **ID:** $userID **Tag:** $userTag ] $color[#5865F2] $sendMessage[] ``` ## Notes - The username is set by the user and can be modified at any time. - Maximum length: 32 characters. - For reliable identification, use `$userID` rather than `$userName`. - Do not confuse with `$nickname` (server-specific nickname) and `$displayName` (the best of both). --- ### $userPerms # $userPerms The `$userPerms` function returns the **list of effective permissions** of the user on the server. The permissions are calculated by combining the permissions of all their roles and channel overrides. ## Syntax ``` $userPerms ``` ## Return Value - **Type**: List of permission names, separated by commas - Example: `SendMessages, ReadMessageHistory, AddReactions, UseExternalEmojis` - Standard permission list from the Discord API. ## Behavior - `$userPerms` takes **no arguments**. - Returns the **effective permissions** (resulting from all roles). - If the user has the `Administrator` permission, all other permissions are implicitly included. ## Examples ### Display permissions ```bdfd $title[Permissions of $userName] $description[ **Permissions:** $userPerms ] $color[#5865F2] $sendMessage[] ``` ### Restrict a command to moderators ```bdfd $if[$checkContains[$userPerms;BanMembers]==true] $ban[$mentioned] $sendMessage[<@$mentioned> was banned.] $else $sendMessage[You do not have permission to ban members.] $endif ``` ### Check multiple permissions ```bdfd $if[$checkContains[$userPerms;ManageMessages]==true] $deleteMessage[$messageID[$mentioned]] $sendMessage[Message deleted.] $else $sendMessage[ManageMessages permission required.] $endif ``` ## Notes - Permission names are in **English** (Discord API nomenclature). - For a simple admin check, use `$isAdmin` or `$checkContains[$userPerms;Administrator]`. - `$userPerms` and `$memberPerms` return the same result for the triggering user. --- ### $userReacted # $userReacted The `$userReacted` function checks if a user has reacted with a specific emoji on a given message. ## Syntax ``` $userReacted[messageID;userID;emoji] ``` ## Parameters | Parameter | Description | |---|---| | `messageID` | The ID of the message on which to check the reaction. | | `userID` | The ID of the user to check. | | `emoji` | The emoji to check (Unicode or `name:ID` for custom emojis). | ## Return Value - **Type**: String (boolean) - `true` if the user has reacted with the specified emoji. - `false` if the user has not reacted or has reacted with a different emoji. ## Behavior - Checks the reaction list of the message for the given emoji. - Works with standard Unicode emojis (✅, ❌, 👍, etc.). - Works with custom server emojis. - The message must be accessible to the bot. ## Examples ### Verification system via reaction ```bdfd $nominalTrigger $let[msgID;$sendMessage[✅ React to accept the rules.]] $addCmdReactions[✅] $onReactionAdd[✅] $if[$userReacted[$msgID;$authorID;✅]==true] $giveRole[$authorID;$roleID[Member]] $sendDM[$authorID;Welcome! You have accepted the rules.] $endif ``` ### Interactive poll ```bdfd $let[pollMsg;$sendMessage[Vote for your choice!]] $addCmdReactions[👍;👎] $let[voted;$userReacted[$pollMsg;$authorID;👍]] $if[$voted==true] $sendMessage[Thanks for your vote 👍!] $else $sendMessage[You have not voted 👍 yet.] $endif ``` ### Condition for a giveaway ```bdfd $if[$userReacted[$giveawayMsg;$authorID;🎉]==true] $sendMessage[✅ You are participating in the giveaway!] $else $sendMessage[❌ You must react with 🎉 to participate.] $endif ``` ## Notes - For custom emojis, use the `name:ID` format. - The function is case-sensitive for custom emoji names. - The bot must have access to the message (in the same channel) to check reactions. --- ### $userRoles # $userRoles The `$userRoles` function returns the **list of role IDs** assigned to the user on the server where the command is executed. ## Syntax ``` $userRoles ``` ## Return Value - **Type**: List of snowflakes (numerical strings), separated by commas - Example: `123456789,987654321,555555555` - Includes the `@everyone` role and all assigned roles. ## Behavior - `$userRoles` takes **no arguments**. - Returns the IDs of **all** the roles of the user on the server. - The order may correspond to the hierarchy (from lowest to highest). ## Examples ### Display role IDs ```bdfd $title[Roles of $userName] $description[ The user has the following roles: `$userRoles` ] $color[#5865F2] $sendMessage[] ``` ### Check for a specific role ```bdfd $if[$checkContains[$userRoles;123456789012345678]==true] $sendMessage[You have the VIP role!] $else $sendMessage[You do not have the VIP role.] $endif ``` ### Count roles ```bdfd $let[count;$arrayCount[$splitText[$userRoles;,]]] $sendMessage[You have $count roles on this server.] ``` ## Notes - The IDs are numerical snowflakes, not role names. - Use `$roleName[ID]` to get the name of a role from its ID. - To check permissions, use `$userPerms` which is more directly exploitable. --- ### $userServerAvatar # $userServerAvatar The `$userServerAvatar` function returns the **URL of the server-specific avatar** of the user. Discord Nitro subscribers can set a different avatar for each server. ## Syntax ``` $userServerAvatar ``` ## Return Value - **Type**: String (URL) - The URL of the server-specific avatar, or the global avatar if the user has not set a per-server avatar. ## Behavior - `$userServerAvatar` takes **no arguments**. - If the user has set a specific avatar for this server (a Nitro feature), that URL is returned. - Otherwise, it returns the global avatar (identical to `$userAvatar`). ## Examples ### Compare global and server avatars ```bdfd $title[Avatars of $userName] $description[ **Global avatar:** **Server avatar:** ] $thumbnail[$userAvatar] $image[$userServerAvatar] $color[#5865F2] $sendMessage[] ``` ### Detect a custom server avatar ```bdfd $if[$userServerAvatar!=$userAvatar] $sendMessage[You have a custom avatar for this server!] $else $sendMessage[You are using your global avatar.] $endif ``` ## Notes - Customizing avatars per server is a **Discord Nitro** feature. - If the user does not have Nitro or has not set a server avatar, `$userServerAvatar` is identical to `$userAvatar`. - Useful for logs and moderation commands where the per-server appearance is relevant. --- ### $usersWithRole # $usersWithRole The `$usersWithRole` function returns the **list of members** who have a specific role on the server. ## Syntax ``` $usersWithRole[roleID;(separator);(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the role. Required. | | `separator` | Optional. Separator between the members. Default: `, `. | | `guildID` | Optional. The ID of the target server. | ## Return Value | Type | Description | |---|---| | `string` | List of members having the role (format depends on configuration). | ## Examples ### List admins ```bdfd $sendMessage[**Administrators:** $usersWithRole[$roleID[Admin]]] ``` ### List with line breaks ```bdfd $sendMessage[ **Members with the VIP role:** $usersWithRole[$roleID[VIP]; ]] ``` ### Count members ```bdfd $sendMessage[There are $length[$usersWithRole[$roleID[Member];,]] members with the Member role.] ``` ### Check if a role is empty ```bdfd $if[$usersWithRole[$roleID[Old]]==] $sendMessage[No member has the Old role.] $endif ``` ### Notify admins ```bdfd $sendMessage[$usersWithRole[$roleID[Admin]] New important alert!] ``` ## Notes - Members are generally returned in the form of mentions. - The exact format may vary depending on the version of BDFD. - Useful for targeted announcements or community management. --- ### $userTag # $userTag The `$userTag` function returns the **complete tag** of the user. Historically, Discord used the `username#discriminator` format (e.g., "JeanDupont#1234"). Since the migration to unique usernames (the new system), the tag is simply the username. ## Syntax ``` $userTag ``` ## Return Value - **Type**: String - Legacy format: `username#discriminator` (e.g., `JeanDupont#1234`) - New format (unique usernames): simply the username. ## Behavior - `$userTag` takes **no arguments**. - For accounts created before the username migration, the tag may still include the 4-digit discriminator. - For new accounts, the returned value is identical to `$userName`. ## Examples ### Display the tag ```bdfd $title[Profile of $userTag] $description[ **Name:** $userName **Tag:** $userTag **ID:** $userID ] $color[#5865F2] $sendMessage[] ``` ### Check if the user has a legacy discriminator ```bdfd $if[$discriminator!=0] $sendMessage[You have a legacy account: $userTag] $else $sendMessage[You have a new account format: $userTag] $endif ``` ## Notes - The legacy `username#discriminator` format is being phased out by Discord. - For new users, `$userTag` is equivalent to `$userName`. - Prefer `$userName` or `$displayName` for future compatibility. --- ## Flags & Debug ### $alternativeParsing # $alternativeParsing The `$alternativeParsing` function enables an **alternative parsing mode** for the current command. This mode uses a different processing logic that can resolve compatibility issues. ## Syntax ``` $alternativeParsing ``` ## Parameters None. ## Return value None. ## Behavior - Changes how BDFD interprets and executes the command code. - Can resolve bugs related to nested brackets `[]` or special characters. - Effect is limited to the current command. ## Examples ### Resolving a bracket conflict ```bdfd $alternativeParsing $sendMessage[$replaceText[Hello [World];[ ];-]] ``` ### Command with complex syntax ```bdfd $alternativeParsing $if[$checkContains[$message;[;]==true] $sendMessage[Content detected.] $else $sendMessage[No content.] $endif ``` ## Notes - Use when standard parsing causes unexplained errors. - Can slightly slow down execution. - To be placed at the beginning of the command, before any other code. - Alternative to `$optOff` for purely syntax-related issues. --- ### $debug # $debug The `$debug` function **enables debug mode** for the currently executing command. ## Syntax ``` $debug ``` ## Parameters None. ## Return value None. ## Behavior - Once enabled, BDFD displays additional diagnostic information. - Helps to trace errors, variable values, and execution flow. - Debug mode is automatically disabled at the end of the command. ## Examples ### Simple debug ```bdfd $debug $let[result;$calculate[2+2]] $sendMessage[Result: $result] ``` ### Conditional debug ```bdfd $if[$message[1]==--debug] $debug $endif $sendMessage[Debug enabled for this execution.] ``` ### Debug in a complex command ```bdfd $debug $var[userData;$getGlobalUserVar[$authorID;xp]] $sendMessage[XP: $userData] ``` ## Notes - Debugging consumes logging resources; avoid enabling it in production. - Combine with `$log[]` for custom logs. - Useful for troubleshooting unexpected behaviors. --- ### $disableInnerSpaceRemoval # $disableInnerSpaceRemoval The `$disableInnerSpaceRemoval` function **disables the automatic removal of spaces** in parameters. By default, BDFD trims spaces at the beginning and end of parameters. ## Syntax ``` $disableInnerSpaceRemoval ``` ## Parameters None. ## Return value None. ## Behavior - Without this function: `$sendMessage[ Hello ]` becomes `Hello` - With this function: leading, trailing, and internal spaces are preserved. - Useful for text formatting (ASCII art, indentation, etc.). ## Examples ### Preserving indentation ```bdfd $disableInnerSpaceRemoval $sendMessage[ ╔══════════════╗ ║ Welcome ║ ╚══════════════╝ ] ``` ### Preserving spaces in text ```bdfd $disableInnerSpaceRemoval $let[codeBlock; function hello() { return "world"; }] $sendMessage[```js $codeBlock ```] ``` ### Comparison ```bdfd ; Without $disableInnerSpaceRemoval $sendMessage[ Hello World ] ; Result: Hello World $disableInnerSpaceRemoval $sendMessage[ Hello World ] ; Result: Hello World ``` ## Notes - Effect is limited to the current command. - Place at the beginning if the entire command requires space preservation. - Does not disable the processing of special characters (see `$disableSpecialEscaping`). --- ### $disableSpecialEscaping # $disableSpecialEscaping The `$disableSpecialEscaping` function **disables the automatic escaping** of special characters in the command. This allows using `[`, `]`, `;`, etc. without them being interpreted as BDFD syntax delimiters. ## Syntax ``` $disableSpecialEscaping ``` ## Parameters None. ## Return value None. ## Behavior - Without this function, `[` and `]` trigger BDFD function syntax. - With it, these characters are treated as raw text. - **Warning**: actual BDFD functions are no longer interpreted after `$disableSpecialEscaping`. ## Examples ### Displaying literal brackets ```bdfd $disableSpecialEscaping $sendMessage[The format is [optional] in the doc] ; Displays: The format is [optional] in the doc ``` ### Message with code syntax ```bdfd $disableSpecialEscaping $sendMessage[Use $if[condition] for conditions.] ``` ### Combination with other flags ```bdfd $disableSpecialEscaping $disableInnerSpaceRemoval $sendMessage[Raw format: [value]; parameter = true] ``` ## Notes - Irreversible in the command: all functions after `$disableSpecialEscaping` are disabled. - Place this function at the **end of the code**, after all other BDFD functions. - Alternative: use `$unEscape[]` for specific portions of text. --- ### $enableDecimals # $enableDecimals The `$enableDecimals` function **enables decimal display** in calculations for the current command. ## Syntax ``` $enableDecimals ``` ## Parameters None. ## Return value None. ## Behavior - Without `$enableDecimals`, BDFD rounds the results of `$calculate[]`. - With `$enableDecimals`, the results include decimals. - The effect is limited to the current command. ## Examples ### Calculation with decimals ```bdfd $enableDecimals $sendMessage[10 ÷ 3 = $calculate[10/3]] ; Displays: 10 ÷ 3 = 3.3333333333333335 ``` ### Without decimals (default) ```bdfd $sendMessage[10 ÷ 3 = $calculate[10/3]] ; Displays: 10 ÷ 3 = 3 ``` ### Comparison before/after ```bdfd $let[without;$calculate[10/3]] $enableDecimals $let[with;$calculate[10/3]] $sendMessage[Without: $without | With: $with] ``` ## Notes - Place before the calculations concerned. - To round to N decimals, use `$round[$calculate[...];N]`. - Also affects divisions in `$if[]` conditions. --- ### $logQuota # $logQuota The function `$logQuota` returns the **log quota information** of your BDFD application. ## Syntax ``` $logQuota ``` ## Parameters None. ## Return Value - **Type** : String / Number - The number of remaining logs or the percentage of used quota. ## Behavior - Returns log consumption statistics. - Useful for monitoring if you are approaching your plan's limit. - The exact value depends on the BDFD plan (free, premium, etc.). ## Examples ### Display the quota ```bdfd $sendMessage[Logs remaining: $logQuota] ``` ### Low quota alert ```bdfd $if[$logQuota<100] $sendMessage[⚠️ Warning: low log quota ($logQuota remaining).] $else $sendMessage[Logs remaining: $logQuota] $endif ``` ### Admin dashboard ```bdfd $title[📊 Bot Status] $description[ **Logs Remaining**: $logQuota **RAM Used**: $ram **Uptime**: $uptime ] $color[#FEE75C] $sendMessage[] ``` ## Notes - The log quota varies according to your BDFD subscription. - Every `$log[]` call consumes a log. - Monitor your quota to avoid losing logs in production. --- ### $optOff # $optOff The `$optOff` function **disables code optimization** for the current command. BDFD then executes the code in a strictly linear manner. ## Syntax ``` $optOff ``` ## Parameters None. ## Return Value None. ## Behavior - Without `$optOff`, BDFD may reorganize the code to optimize execution. - With `$optOff`, the execution order is exactly that of the source code. - Useful when optimization causes execution order bugs. ## Examples ### Force execution order ```bdfd $optOff $var[x;1] $sendMessage[x = $var[x]] $var[x;2] $sendMessage[x = $var[x]] ``` ### Avoid optimization bugs ```bdfd $optOff $let[a;1] $onlyIf[$let[a]!=;Missing value] $sendMessage[$let[a]] ``` ## Notes - Impacts performance: only use when necessary. - Some complex functions may require `$optOff` to work correctly. - Should be placed at the beginning of the command. --- ## HTTP & JSON ### $httpAddHeader[] $httpAddHeader sets a custom HTTP header that is included on all subsequent HTTP requests until cleared or overwritten. Call it multiple times to set multiple headers. Headers are applied to every request made via $httpGet, $httpPost, $httpPut, $httpPatch, and $httpDelete. Common use cases include setting Content-Type for JSON APIs, Authorization for authenticated endpoints, and custom headers for API-specific requirements. Headers persist for the duration of the command execution context. --- ### $httpDelete[] $httpDelete sends a synchronous HTTP DELETE request to remove the resource identified by the URL. The response body is often empty or contains a confirmation message. Use $httpStatus to verify whether the deletion succeeded (typically a 200 or 204 status code). Custom headers such as Authorization can be set beforehand with $httpAddHeader. --- ### $httpGet[] $httpGet sends a synchronous HTTP GET request to the provided URL. The function blocks the command execution until a response is received or the request times out. Custom headers can be added before the call using $httpAddHeader. After the request completees, the raw response body is stored internally and can be accessed via $httpResult. Use $httpStatus to check the HTTP status code of the response. The URL must be a fully qualified URL including the scheme (https:// or http://). For best results with JSON APIs, use $httpResult with dot or bracket notation to extract specific fields from the parsed JSON response. --- ### $httpPatch[] $httpPatch sends a synchronous HTTP PATCH request, used to apply a partial update to a resource. Unlike PUT (which replaces the entire resource), PATCH only modifies the fields provided in the request body. Set the Content-Type header via $httpAddHeader before sending JSON payloads. After the request, use $httpResult to access the response and $httpStatus to check the outcome. --- ### $httpPost[] $httpPost sends a synchronous HTTP POST request to the provided URL. This is typically used to create resources, submit form data, or send data to an API endpoint. Always set the Content-Type header via $httpAddHeader when sending JSON bodies. The response body is stored internally and can be accessed with $httpResult; use $httpStatus to check the response status code. --- ### $httpPut[] $httpPut sends a synchronous HTTP PUT request, used to replace an entire resource at the given URL. Unlike POST (which creates), PUT is idempotent and should fully replace the target resource. Always set the appropriate Content-Type header via $httpAddHeader before sending. Use $httpResult to access structured JSON responses and $httpStatus to verify the request outcome. --- ### $httpResult[] $httpResult provides access to the response from the most recent HTTP request. When called without arguments, it returns the raw response body as a string. When a key path is provided, it parses the response as JSON and navigates to the specified field using semicolons (;) as path separators. Numeric indices access array elements. Use $httpResult to extract meaningful data from API responses and display it with other BDFD functions. --- ### $httpStatus[] $httpStatus returns the numeric HTTP status code from the last HTTP request executed by any of the HTTP functions. This is essential for error handling: check whether the request succeeded (200–299), was redirected (300–399), failed due to client error (400–499), or encountered a server error (500–599). Combine $httpStatus with $if conditionals to build robust API interactions that gracefully handle failures. --- ### $json[] The $json function is the entry point for all JSON operations. It initialises an internal JSON context that all subsequent JSON functions operate on. If called without a value, an empty object `{}` is created. If a value is provided, it must be valid JSON. The internal JSON structure persists until it is cleared with $jsonClear or overwritten by calling $json again. --- ### $jsonArray[] $jsonArray converts a delimited string value into a JSON array by splitting on the given separator. This is particularly useful when working with data that arrives as delimited text (CSV lines, path segments, tagged values) and needs to be manipulated as an array. The key must already exist and contain a string value. --- ### $jsonArrayAppend[] $jsonArrayAppend adds a value to the end of an existing JSON array. It is the JSON equivalent of JavaScript's `Array.push()`. The key must exist and must contain an array. Use $jsonArrayUnshift to add to the beginning, and $jsonArrayPop to remove from the end. --- ### $jsonArrayCount[] $jsonArrayCount returns the number of elements in a JSON array. This is useful for pagination, boundary checks, conditional logic based on array size, or displaying counts to users. For iteration over all elements, prefer $jsonForEach. --- ### $jsonArrayIndex[] $jsonArrayIndex retrieves a single element from a JSON array by its zero-based index. It returns the value as a string. For nested objects, use dot notation with $jsonValue after extracting the element. Out-of-bounds indices return an empty string rather than throwing an error. --- ### $jsonArrayPop[] $jsonArrayPop removes the last element from a JSON array and returns it — equivalent to JavaScript's `Array.pop()`. This is useful for stack-based processing (LIFO — Last In, First Out). Popping from an empty array returns an empty string. --- ### $jsonArrayReverse[] $jsonArrayReverse reverses the order of elements in a JSON array. It operates in-place — the original array is modified. This is useful for displaying data in reverse chronological order or changing the sort direction after an ascending sort. Pair with $jsonArraySort for descending sorts. --- ### $jsonArrayShift[] $jsonArrayShift removes and returns the first element from a JSON array — equivalent to JavaScript's `Array.shift()`. This is ideal for FIFO (First In, First Out) queue processing. All remaining elements shift down by one index. Shifting from an empty array returns an empty string. --- ### $jsonArraySort[] $jsonArraySort sorts the elements of a JSON array in-place. The default order is ascending ('asc'). For alphabetical sorting, strings are compared lexicographically. For numerical sorting, values are compared as numbers. To get descending order, either pass 'desc' or sort ascending and then reverse with $jsonArrayReverse. --- ### $jsonArrayUnshift[] $jsonArrayUnshift adds a value to the front of a JSON array — equivalent to JavaScript's `Array.unshift()`. Existing elements shift up by one index. This is useful for priority queues, where high-priority items are inserted at the front and processed before normal items via $jsonArrayShift. --- ### $jsonClear[] $jsonClear resets the internal JSON state entirely. This is useful when you need to reuse JSON variables in a loop, or when switching between different JSON data sources to avoid data leakage. After clearing, the context is equivalent to calling $json[] with no arguments — an empty object ready for new data. --- ### $jsonExists[] $jsonExists is essential for safely navigating JSON data, especially when working with external API responses that may have optional fields. It returns 'true' or 'false' as a string, making it directly usable in $if conditions. Always check for key existence before accessing values with $jsonValue to avoid ambiguity between missing keys and genuinely empty values. --- ### $jsonForEach[] $jsonForEach is the primary iteration mechanism for JSON data. When iterating over an object, $jsonKey[] returns the current key name and $jsonValue[] returns the value. When iterating over an array, $jsonIndex[] returns the zero-based index and $jsonValue[] returns the element. Every $jsonForEach must be matched with a corresponding $endJsonForEach — nesting is supported. --- ### $jsonIndex[] $jsonIndex returns the current iteration index (0-based) when used inside a $jsonForEach block. This is useful for numbered lists, conditional logic based on position (e.g., treating the first or last element differently), or limiting output to the first N items. Outside of $jsonForEach, it returns 0. --- ### $jsonJoinArray[] $jsonJoinArray combines all elements of a JSON array into a single string with a separator between each element — equivalent to JavaScript's `Array.join()`. This is the inverse of $jsonArray which splits a string into an array. Use \n for line breaks in embeds, or custom separators like bullets or HTML tags. --- ### $jsonKey[] $jsonKey returns the current key name during $jsonForEach iteration. It is only meaningful inside a $jsonForEach.. $endJsonForEach block. Pair with $jsonValue[] (no arguments) to access the corresponding value. This is the primary way to process key-value pairs in JSON objects. --- ### $jsonKeys[] $jsonKeys returns all top-level key names from the JSON object as a comma-separated string. This is useful for introspection, debugging, or dynamic key access. For nested objects, it only returns keys at the current depth. When used inside a $jsonForEach block, it can also reference the current iteration's key context. --- ### $jsonParse[] $jsonParse is the primary way to load external JSON data — such as API responses, file contents, or user input — into the BDFD JSON system. It replaces whatever internal JSON structure currently exists. Use $jsonStringify to convert back to a string when done. The input must be strictly valid JSON; malformed input will produce an error. --- ### $jsonPretty[] $jsonPretty is useful for debugging JSON data or displaying it to users in a readable format. Unlike $jsonStringify which produces compact output, $jsonPretty adds line breaks and indentation. Use inside code blocks (```json) for embed descriptions. If no JSON context exists, returns an empty string. --- ### $jsonSet[] $jsonSet is the primary way to build and modify JSON objects. It stores values while preserving their type — numbers remain numeric, booleans remain boolean. Dot notation allows setting deeply nested values: `$jsonSet[user.profile.avatar;url]` creates the intermediate objects automatically. Use $jsonSetString to force a value to be stored as a string. --- ### $jsonSetString[] $jsonSetString forces the value to be stored as a JSON string type. This is important when you need to preserve leading zeros in IDs, ensure phone numbers aren't parsed as integers, or when an API expects a string-typed field. In contrast, $jsonSet infers the type from the value content. --- ### $jsonStringify[] $jsonStringify returns the internal JSON as a compact, minified string — ideal for sending in API requests, storing in variables, or logging. For human-readable output, use $jsonPretty instead. If no JSON has been initialised (via $json or $jsonParse), the function returns an empty string. --- ### $jsonUnset[] $jsonUnset removes a key-value pair from the JSON object. It works with dot notation for nested keys. If the specified key does not exist, no error is thrown — the operation is silently ignored. This is useful for cleaning API responses, removing sensitive fields (like passwords) before logging, or pruning empty configuration options. --- ### $jsonValue[] $jsonValue retrieves values from the JSON object. Use dot notation to traverse nested objects, and semicolons (;) to access array elements. If a key does not exist, an empty string is returned rather than throwing an error — use $jsonExists to check for key existence before retrieval if you need to distinguish between genuine empty strings and missing keys. --- ## Image & Canvas ### $attachImage[] $attachImage is the terminal operation for every canvas block. It triggers the deferred block flush: all queued drawing operations are executed in order, the result is rendered to a PNG, and the image is attached to the response. The `name` parameter becomes the filename (without extension) and is available at runtime via `((temp._canvasAttachment_name))`. You can produce multiple images in a single command by creating multiple canvas blocks, each terminated by its own $attachImage call. Without $attachImage, the canvas block is never flushed and no image is produced. --- ### $attachImage # $attachImage The `$attachImage[name;url;(spoiler)]` function **attaches a remote image** to the next message sent via `$sendMessage[]`. The image is downloaded from the provided URL and attached as a Discord attachment. ## Syntax ``` $attachImage[name;url;(spoiler)] ``` ## Parameters | Parameter | Description | |---|---| | `name` | File name as it will appear in Discord (e.g., `photo.png`, `avatar.gif`). | | `url` | URL of the image to download. Must be a publicly accessible HTTPS URL. | | `spoiler` | Optional - `true` to mark the image as a spoiler (blurred until clicked). | ## Return value None. The image is queued for the next `$sendMessage[]`. ## Behavior - The image is downloaded by the bot from the provided URL. - The file name must include a valid extension (.png, .jpg, .gif, .webp, etc.). - Spoiler images are blurred in Discord until the user clicks on them. - Supports PNG, JPEG, GIF, WebP formats (size limit according to the bot's limit). ## Examples ### Attaching a simple image ```bdfd $attachImage[logo.png;https://mysite.com/logo.png] $sendMessage[Here is our logo!] ``` ### Image as a spoiler ```bdfd $attachImage[spoiler_alert.png;https://mysite.com/spoiler.png;true] $sendMessage[⚠️ Spoiler warning below:] ``` ### Avatar of a user ```bdfd $attachImage[avatar_$username.png;$userAvatar[$mentioned[1]]] $sendMessage[Avatar of <@$mentioned[1]>:] ``` ### Multiple images ```bdfd $attachImage[before.png;$attachment[1]] $attachImage[after.png;$attachment[2]] $sendMessage[Comparison before/after:] ``` ### Integration with Canvas ```bdfd $canvasLoad[$attachment] $canvasGrayscale $attachCanvas[result.png] $attachImage[original.png;$attachment] $sendMessage[🔲 Original vs Grayscale:] ``` ## Notes - The URL must start with `https://` and be accessible without authentication. - The maximum size depends on the bot's limit (generally 8 MB). - To attach the current canvas, use `$attachCanvas[]`. - To attach a local file (non-image), use `$attachFile[]`. - Attachments are only consumed by the next `$sendMessage[]`. --- ### $canvasChartBar[] Bar width is calculated automatically by dividing the chart area width by the number of data values, minus barSpacing. Without a maxValue override, the tallest bar is scaled to fill the full chart height. Labels are parsed but not rendered — use separate $canvasDrawText calls below each bar if you need labels. Use $canvasChartLine for datasets better suited to trends over discrete categories. --- ### $canvasChartLine[] At least 2 data values are required to draw a line. The chart auto-scales vertically based on the maximum value in the dataset. When `fill` is true, the area under the line is filled with a semi-transparent version of the line color, creating an area chart effect. Data points are rendered as small circles at each data position; disable them with `showPoints:false` for a cleaner look. --- ### $canvasChartPie[] Each data value is converted to a slice proportional to the sum of all values. If you provide fewer colors than data values, the runtime cycles through a built-in 12-color palette. Labels are accepted syntactically but are not drawn by the current runtime — they exist for forward compatibility. The default startAngle of -90° places the first slice at the 12 o'clock position. --- ### $canvasCompositeImage[] Unlike $canvasLoadImage, this function requires an existing canvas and always composites on top. Shape masks (circle, rounded, triangle, etc.) apply anti-aliased clipping — pixels outside the mask are fully transparent. The `rounded:N` and `roundrect:N` variants let you specify a corner radius in pixels (e.g., `rounded:20`). Blend modes use standard canvas compositing per the CSS spec. --- ### $canvasContainer[] Containers are the primary layout mechanism for complex canvas compositions. When a drawing operation specifies a `container` parameter, the operation's (x, y) coordinates become offsets relative to the container's top-left corner. Containers themselves don't render immediately — their background color is drawn lazily only if a child operation requires it. Multiple containers can be defined and nested conceptually, though the runtime treats all coordinates relative to the referenced container only. --- ### $canvasCreate[] Canvas dimensions are clamped to a maximum of 4096 pixels in either direction. The canvas operates in a deferred rendering model: drawing operations are queued and only executed when the block is flushed — either when a non-canvas function is encountered or when $attachImage is called. Always pair $canvasCreate with a matching $attachImage to produce visible output. --- ### $canvasDrawArc[] Angles follow standard mathematical convention: 0° points right (3 o'clock), 90° points down (6 o'clock), and -90° points up (12 o'clock). The arc is drawn counterclockwise from startAngle to endAngle. When `fill` is true, the result is a wedge (pie slice) connected to the center. For full circles, prefer $canvasDrawCircle which is more efficient. --- ### $canvasDrawCircle[] Circles are drawn using the midpoint algorithm for pixel-precise rendering. When `fill` is true, the circle is filled solid; when false, only a 1-pixel outline is drawn. Specifying a blend mode triggers per-pixel blending instead of the default fast-path, which may be slightly slower but enables compositing effects like multiply, screen, and overlay. --- ### $canvasDrawLine[] Lines are drawn using Bresenham's algorithm for precision. When thickness is greater than 1, the line expands perpendicular to its direction, creating a band. Thickness is clamped between 1 and 100 pixels. Use blend modes like `overlay` or `multiply` to create subtle dividers and accent lines without fully opaque colors. --- ### $canvasDrawRect[] When `fill` is false, the rectangle is drawn as a 1-pixel wide outline — there is no thickness parameter. For thicker outlines, use multiple overlapping rectangles or $canvasDrawLine calls. For rectangles with rounded corners, prefer $canvasDrawRoundedRect. The blend mode enables per-pixel compositing for effects like shadows and overlays. --- ### $canvasDrawRoundedRect[] The corner radius is automatically clamped to at most half the smaller dimension (min(width, height) / 2) to prevent overlap between adjacent corners. This makes it ideal for card backgrounds, button shapes, and UI containers. For outline-only mode, the outline follows the rounded path at 1-pixel width. --- ### $canvasDrawText[] Text outside the canvas boundaries is clipped and will not appear in the output. The font is selected automatically based on font size: arial14 for sizes under 20px, arial24 for 20–39px, and arial48 for 40px and above. Multi-line text is not supported — each call draws a single line. Use template variable syntax `((varName))` to embed dynamic values in the text string. --- ### $canvasLoadImage[] $canvasLoadImage is dual-purpose: when no canvas exists, it creates one from the loaded image. When a canvas already exists, it composites the image on top. HTTP images are cached in a 50 MB LRU cache that persists for the lifetime of the current deferred block. If the URL fails to load within 15 seconds, the operation silently fails and the canvas remains unchanged. --- ### $canvasProgressBar[] The `value` parameter should be a number between 0 and 100 representing the fill percentage. If `bgColor` is omitted, the unfilled portion is left transparent. Note: the `borderRadius` parameter is accepted by the transpiler but is not yet rendered at runtime — rounded progress bars will appear with sharp corners. Horizontal bars fill left-to-right; vertical bars fill bottom-to-top. --- ### $canvasGrayscale # $canvasGrayscale The `$canvasGrayscale` function **converts the current canvas to grayscale**, removing all color information (saturation) while preserving the brightness. ## Syntax ``` $canvasGrayscale ``` ## Parameters None. ## Return value None. The canvas is modified directly. ## Behavior - Each pixel of the canvas is converted to a shade of gray depending on its luminance. - The formula typically uses a weighted average of the RGB channels (30% red, 59% green, 11% blue). - The operation is irreversible (unless you save the state beforehand). ## Examples ### Simple conversion to black and white ```bdfd $canvasLoad[$attachment] $canvasGrayscale $attachCanvas[] $sendMessage[🎨 Image converted to grayscale!] ``` ### Old photo effect ```bdfd $canvasLoad[$attachment] $canvasGrayscale $canvasColor[#6b4c2a] ;; Sepia effect via tinting $attachCanvas[] $sendMessage[🕰️ Vintage effect applied!] ``` ### Before/After comparison ```bdfd $var[original;$attachment] $canvasLoad[$var[original]] $attachCanvas[before.png] $canvasGrayscale $attachCanvas[after.png] $sendMessage[⚫ Original vs Grayscale:] ``` ## Notes - The canvas must be created or loaded before calling this function (via `$canvasCreate[]`, `$canvasLoad[]`, etc.). - To invert the colors, use `$canvasInvert` instead. - For rotation, use `$canvasRotate[degrees]`. --- ### $canvasInvert # $canvasInvert The `$canvasInvert` function **inverts the colors of the current canvas**, producing a negative effect. Each pixel has its R, G, B components replaced by `255 - value`. ## Syntax ``` $canvasInvert ``` ## Parameters None. ## Return value None. The canvas is modified directly. ## Behavior - Each RGB channel is inverted: white becomes black, red becomes cyan, etc. - Calling `$canvasInvert` twice in a row restores the original image. - Transparent pixels are not affected. ## Examples ### Simple inversion ```bdfd $canvasLoad[$attachment] $canvasInvert $attachCanvas[] $sendMessage[🔄 Image inverted!] ``` ### Temporary negative effect ```bdfd $canvasLoad[$attachment] $canvasInvert $attachCanvas[negative.png] $canvasInvert ;; Return to original $attachCanvas[original.png] $sendMessage[🔁 Original + Negative:] ``` ### Combination of effects ```bdfd $canvasLoad[$attachment] $canvasGrayscale $canvasInvert $attachCanvas[] $sendMessage[🎞️ Grayscale + Negative!] ``` ## Notes - The canvas must be created or loaded beforehand. - Inversion is reversible (re-call the function). - For a partial effect, use `$canvasSetPixel[]` to invert specific pixels. --- ### $canvasRotate # $canvasRotate The `$canvasRotate[degrees]` function **rotates the current canvas** by a specified angle in degrees. The canvas is automatically resized to contain the entire image after rotation. ## Syntax ``` $canvasRotate[degrees] ``` ## Parameters | Parameter | Description | |---|---| | `degrees` | Angle of rotation in degrees. Positive values = clockwise. Negative values = counterclockwise. | ## Return value None. The canvas is rotated and resized if necessary. ## Behavior - The rotation is done around the center of the canvas. - The canvas is automatically expanded to avoid clipping the image. - Pixels outside the original image become transparent. - Angle values are normalized modulo 360. ## Examples ### Simple 90° rotation ```bdfd $canvasLoad[$attachment] $canvasRotate[90] $attachCanvas[] $sendMessage[↪️ Image rotated by 90°!] ``` ### Complete flip (180°) ```bdfd $canvasLoad[$attachment] $canvasRotate[180] $attachCanvas[] $sendMessage[🔃 Image flipped!] ``` ### Counterclockwise rotation ```bdfd $canvasLoad[$attachment] $canvasRotate[-45] $attachCanvas[] $sendMessage[↩️ Counterclockwise rotation of 45°!] ``` ### User-controlled rotation ```bdfd $canvasLoad[$attachment] $canvasRotate[$message[1]] $attachCanvas[] $sendMessage[The image has been rotated by $message[1]°!] ``` ## Notes - The canvas must be created or loaded before rotation. - Rotations of 90°, 180°, or 270° are optimized and do not degrade the quality. - Non-orthogonal rotations (e.g., 45°) require resampling. --- ### $canvasSetPixel # $canvasSetPixel The `$canvasSetPixel[x;y;color]` function **sets the color of a single pixel** on the canvas at the specified coordinates. ## Syntax ``` $canvasSetPixel[x;y;color] ``` ## Parameters | Parameter | Description | |---|---| | `x` | X coordinate of the pixel. 0 = the left edge of the canvas. | | `y` | Y coordinate of the pixel. 0 = the top edge of the canvas. | | `color` | Color to apply, in hexadecimal format (`#RRGGBB`) or color name (`red`, `blue`, etc.). | ## Return value None. The pixel is modified directly on the canvas. ## Behavior - Coordinates outside the canvas boundaries are ignored (no error). - The alpha channel of the pixel is kept as is. - Works on any canvas previously created or loaded. ## Examples ### Single pixel ```bdfd $canvasCreate[100;100] $canvasSetPixel[50;50;#FF0000] $attachCanvas[] $sendMessage[🔴 Red pixel placed at the center!] ``` ### Draw a horizontal line ```bdfd $canvasCreate[200;100] $for[x;0;199;1] $canvasSetPixel[$for[x];50;#5865F2] $endfor $attachCanvas[] $sendMessage[📏 Blue line drawn!] ``` ### Cross at the center ```bdfd $canvasCreate[100;100] $for[i;30;70;1] $canvasSetPixel[$for[i];50;#FF0000] $canvasSetPixel[50;$for[i];#FF0000] $endfor $attachCanvas[] $sendMessage[➕ Red cross drawn!] ``` ### Draw where the user clicks (interaction) ```bdfd $canvasSetPixel[$mouseX;$mouseY;$message[1]] $attachCanvas[] ``` ## Notes - Coordinates start at 0 (not 1). - To fill an entire area, use `$canvasFill[]` or `$canvasDrawRect[]`. - To read a pixel, use `$canvasGetPixel[]`. - Modifying many pixels one by one can be slow; prefer vector drawing functions. --- ## JavaScript API ### Autocomplete Autocomplete lets slash commands suggest options as the user types. The `interaction` global is available in autocomplete handlers. ## Responding with choices ### `await interaction.respond(choices)` Send up to **25** suggestions. Each choice needs `name` (display) and `value` (stored value): ```javascript const focused = interaction.options.getFocused(); const filtered = fruits .filter((f) => f.toLowerCase().includes(focused.toLowerCase())) .slice(0, 25) .map((f) => ({ name: f, value: f })); await interaction.respond(filtered); ``` Return an empty array when no matches: ```javascript await interaction.respond([]); ``` ## Reading the focused option ### `interaction.options.getFocused(required?)` Returns the partial string the user has typed so far. ```javascript const query = interaction.options.getFocused(true); ``` ## When autocomplete runs - Triggered when a user types in a slash option configured for autocomplete. - You must respond within Discord's interaction timeout. - Use `interaction.isAutocomplete()` to distinguish from command execution. ## Related - [interaction](/docs/javascript/interaction/) — slash command replies - [Interactions overview](/docs/interactions-overview/) — BDScript autocomplete with `((interaction.kind))` --- ### canvas Generate images in JavaScript with `require('canvas')`. Remote `http(s)` and `data:` URLs are supported; local file paths are blocked. ## Module exports | Export | Description | |--------|-------------| | `createCanvas(width, height, type?)` | Create a drawing surface | | `loadImage(url)` | Load image from URL or buffer | | `registerFont(url, { family })` | Register a remote font | | `createImageData(array, w, h?)` | Raw pixel buffer | PNG filter constants: `PNG_NO_FILTERS`, `PNG_ALL_FILTERS`, `PNG_FILTER_NONE`, etc. ## Canvas methods `getContext('2d')`, `toBuffer()`, `toDataURL()`, `createPNGStream()`, `createJPEGStream()` ## Context2D drawing Common methods: `fillRect`, `strokeRect`, `fillText`, `strokeText`, `drawImage`, `arc`, `fill`, `stroke`, `beginPath`, `closePath`, `moveTo`, `lineTo`, `save`, `restore`, `translate`, `rotate`, `scale` ## Example ```javascript const { createCanvas } = require('canvas'); const canvas = createCanvas(400, 200); const ctx = canvas.getContext('2d'); ctx.fillStyle = '#5865f2'; ctx.fillRect(0, 0, 400, 200); ctx.fillStyle = '#ffffff'; ctx.font = '32px sans-serif'; ctx.fillText('Hello!', 20, 100); const buffer = canvas.toBuffer('image/png'); const { AttachmentBuilder } = require('discord.js'); const file = new AttachmentBuilder(buffer, { name: 'banner.png' }); await interaction.reply({ files: [file] }); ``` ## BDFD equivalent BDScript uses deferred canvas blocks (`$canvasCreate`, drawing ops, `$attachImage`). See the [Canvas functions guide](/advanced-topics/2026/06/11/image-creation-canvas-functions-in-bdfd/) and [Image & Canvas](/docs/#image-canvas) function reference. ## Restrictions - Local filesystem paths are blocked for images and fonts. - WebP images are normalized to PNG internally. --- ### client, guild, channel ## client Proxy to the Discord.js client. Dangerous nested properties are blocked. ```javascript const botId = client.user?.id; const botName = client.user?.username; ``` ## guild Current guild context, or `null` in DMs. | Property | Description | |----------|-------------| | `id` | Guild ID | | `name` | Guild name | ## channel Current channel context. | Property | Description | |----------|-------------| | `id` | Channel ID | | `name` | Channel name (nullable) | ## member Current member object (dynamic proxy) when available in guild context. ## config Bot configuration as a key/value object. The bot token is **never** exposed. ## variables Runtime variables defined in the Bot Creator UI, as a plain object. ## webhook When the script runs from a webhook context: `{ path, payload, headers }`. Otherwise `null`. --- ### Components Component interactions (buttons, select menus, modals) expose the same `interaction` global as slash commands, with additional type guards and properties. ## Type guards | Method | Returns `true` when | |--------|---------------------| | `interaction.isButton()` | Button click | | `interaction.isStringSelectMenu()` | String select menu | | `interaction.isUserSelectMenu()` | User select menu | | `interaction.isChannelSelectMenu()` | Channel select menu | | `interaction.isRoleSelectMenu()` | Role select menu | | `interaction.isMentionableSelectMenu()` | Mentionable select menu | | `interaction.isModalSubmit()` | Modal form submitted | | `interaction.isAutocomplete()` | Autocomplete request | | `interaction.isChatInputCommand()` | Slash command | ```javascript if (interaction.isButton()) { if (interaction.customId === 'verify') { await interaction.reply({ content: 'Verified!', ephemeral: true }); } } ``` ## Common properties | Property | Description | |----------|-------------| | `customId` | Developer-defined component ID | | `user` | User who triggered the interaction | | `member` | Guild member (in servers) | | `guild` | Guild object | | `channel` | Channel object | | `id` | Interaction snowflake | | `guildId` | Guild ID string | | `channelId` | Channel ID string | | `deferred` | Whether deferReply was called | | `replied` | Whether a reply was sent | | `ephemeral` | Whether the reply is ephemeral | ## Select menu values String select menus expose `values` — an array of selected option values: ```javascript if (interaction.isStringSelectMenu()) { const choice = interaction.values[0]; await interaction.reply(`You picked: ${choice}`); } ``` ## Building components Create buttons, selects, and modals with [discord.js builders](/docs/javascript/discordjs-builders/): ```javascript const { ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); const row = new ActionRowBuilder().addComponents( new ButtonBuilder() .setCustomId('ping') .setLabel('Ping') .setStyle(ButtonStyle.Primary), ); await interaction.reply({ content: 'Click a button:', components: [row] }); ``` ## Modals Show a modal from a button handler: ```javascript const { ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder } = require('discord.js'); const modal = new ModalBuilder() .setCustomId('profile_modal') .setTitle('Edit profile'); const input = new TextInputBuilder() .setCustomId('name') .setLabel('Display name') .setStyle(TextInputStyle.Short); modal.addComponents(new ActionRowBuilder().addComponents(input)); await interaction.showModal(modal); ``` Read submitted fields in a modal handler: ```javascript if (interaction.isModalSubmit()) { const name = interaction.fields.getTextInputValue('name'); await interaction.reply(`Updated name: ${name}`); } ``` ## Related - [interaction](/docs/javascript/interaction/) — reply, defer, followUp - [Autocomplete](/docs/javascript/autocomplete/) — dynamic slash suggestions - [Interactions overview](/docs/interactions-overview/) — BDScript component workflow --- ### config The `config` global exposes the bot's runtime configuration. The bot token is stripped before scripts can access it. ## Properties | Property | Type | Description | |----------|------|-------------| | `intents` | `string[]` | Discord gateway intents | | `prefix` | `string` | Prefix command trigger | | `autoRestart` | `boolean` | Auto-restart on crash | | `presence` | `object` | Bot presence settings | | `commands` | `array` | Registered command definitions | | `events` | `array` | Registered event workflows | | `scheduled` | `array` | Scheduled task definitions | | `inboundWebhooks` | `array` | Inbound webhook configs | | `globalVariables` | `object` | Default global variable values | | `scopedVariableDefinitions` | `array` | User/guild/channel variable schemas | | `scriptTimeoutMs` | `number` | Script execution timeout (default 30000) | ## Example ```javascript const prefix = config.prefix; const timeout = config.scriptTimeoutMs; const defaults = config.globalVariables; ``` ## Related - [db.global](/docs/javascript/db-global/) — `get` falls back to `config.globalVariables` - [variables](/docs/javascript/variables/) — merged runtime variable object - [sandbox](/docs/javascript/sandbox/) — script timeout behavior --- ### console & fetch ## console Standard logging routed to bot logs. ```javascript console.log('Command ran'); console.warn('Missing option'); console.error('Something failed'); ``` ## fetch Proxied `fetch` for HTTP requests (same restrictions as the runner sandbox). ```javascript const res = await fetch('https://api.example.com/data'); const data = await res.json(); ``` Use [$httpGet](/docs/httpget/) and related BDFD functions for equivalent behavior in BDScript. --- ### db — Storage API The `db` global provides async persistent storage for JavaScript command scripts. It mirrors BDFD variable functions (`$getUserVar`, `$setVar`, etc.) with a Promise-based API. ## Namespaces | Namespace | Scope | BDFD equivalent | |-----------|-------|-----------------| | `db.global` | Bot-wide keys | `$getVar` / `$setVar` (global) | | `db.user` | Per Discord user | `$getUserVar` / `$setUserVar` | | `db.guild` | Per guild (server) | `$getGuildVar` / `$setGuildVar` | | `db.channel` | Per channel | `$getChannelVar` / `$setChannelVar` | | `db.message` | Per message | `$getMessageVar` / `$setMessageVar` | | `db.guildMember` | Per user in a guild | `$getMemberVar` / `$setMemberVar` | ## Common methods (scoped namespaces) | Method | Description | |--------|-------------| | `get(key, id?)` | Read a value | | `set(key, value, id?)` | Write a value | | `delete(key, id?)` | Remove a key | | `list(key, order?, limit?, offset?, filter?)` | Leaderboard-style list | | `find(filter?)` | Search entries | | `reset(key)` | Reset a key to default | `db.global` only exposes `get`, `set`, and `delete`. ## Examples ```javascript // User coins (current user from context) const coins = await db.user.get('coins'); await db.user.set('coins', (Number(coins) || 0) + 5); // Global counter await db.global.set('counter', 1); const count = await db.global.get('counter'); // Leaderboard top 10 const top = await db.user.list('coins', 'desc', 10, 0); ``` ## Detail pages - [db.user](/docs/javascript/db-user/) - [db.global](/docs/javascript/db-global/) - [db.guild](/docs/javascript/db-guild/) - [db.channel](/docs/javascript/db-channel/) - [db.message](/docs/javascript/db-message/) - [db.guildMember](/docs/javascript/db-guild-member/) --- ### db.channel `db.channel` stores values per Discord channel. **BDFD equivalent:** [$getChannelVar](/docs/getchannelvar/) / [$setChannelVar](/docs/setchannelvar/). ## Methods | Method | Description | |--------|-------------| | `await db.channel.get(key, channelId?)` | Read value for channel | | `await db.channel.set(key, value, channelId?)` | Write value | | `await db.channel.delete(key, channelId?)` | Delete key | | `await db.channel.list(key, order?, limit?, offset?, filter?)` | Leaderboard-style list | | `await db.channel.find(filter)` | Search `{ key, id, value }[]` | | `await db.channel.reset(key)` | Purge values and remove definition | ```javascript const count = await db.channel.get('msgCount'); await db.channel.set('msgCount', Number(count) + 1); ``` --- ### db.global `db.global` stores bot-wide keys shared across all users and guilds. **BDFD equivalent:** [$getVar](/docs/getvar/) / [$setVar](/docs/setvar/) (global scope). ## Methods | Method | Description | |--------|-------------| | `await db.global.get(key)` | Read value (falls back to `config.globalVariables`) | | `await db.global.set(key, value)` | Write value | | `await db.global.delete(key)` | Delete key | ```javascript await db.global.set('maintenance', true); const mode = await db.global.get('maintenance'); ``` --- ### db.guild `db.guild` stores values per Discord guild (server). **BDFD equivalent:** [$getGuildVar](/docs/getguildvar/) / [$setGuildVar](/docs/setguildvar/). ## Methods Same as `db.user`: `get`, `set`, `delete`, `list`, `find`, `reset`. Optional second argument is `guildId`. ```javascript const level = await db.guild.get('level'); await db.guild.set('level', 5, guild.id); ``` --- ### db.guildMember `db.guildMember` stores values per user within a guild (composite `guildId:userId` scope). **BDFD equivalent:** [$getMemberVar](/docs/getmembervar/) / [$setMemberVar](/docs/setmembervar/). In guild contexts, [db.user](/docs/javascript/db-user/) routes here automatically. ## Methods ### `await db.guildMember.get(key, userId?, guildId?)` Returns the stored value. When IDs are omitted, uses the current interaction/message context. ### `await db.guildMember.set(key, value, userId?, guildId?)` Writes `value` for `key`. ```javascript await db.guildMember.set('xp', 100, interaction.user.id, guild.id); const xp = await db.guildMember.get('xp'); ``` ### `await db.guildMember.delete(key, userId?, guildId?)` Removes the key for the guild member. ### `await db.guildMember.list(key, order?, limit?, offset?, filter?)` Returns `{ id, value }[]`. Filter runs client-side after fetching up to 10,000 rows. ### `await db.guildMember.find(filter)` Returns `{ key, id, value }[]`. Requires a filter function. ### `await db.guildMember.reset(key)` Purges all values and removes the variable definition. --- ### db.message `db.message` stores values tied to a specific message ID. **BDFD equivalent:** [$getMessageVar](/docs/getmessagevar/) / [$setMessageVar](/docs/setmessagevar/). ## Methods | Method | Description | |--------|-------------| | `await db.message.get(key, messageId?)` | Read value for message | | `await db.message.set(key, value, messageId?)` | Write value | | `await db.message.delete(key, messageId?)` | Delete key | | `await db.message.list(key, order?, limit?, offset?, filter?)` | List entries | | `await db.message.find(filter)` | Search `{ key, id, value }[]` | | `await db.message.reset(key)` | Purge values and remove definition | ```javascript const flag = await db.message.get('processed'); await db.message.set('processed', true); ``` --- ### db.user `db.user` stores values per Discord user. **BDFD equivalent:** [$getUserVar](/docs/getuservar/) / [$setUserVar](/docs/setuservar/). ## Guild context routing When the script runs **inside a guild** (server channel, slash command, or component interaction), `db.user.*` automatically routes to **`guildMember` scope** — the same storage as [db.guildMember](/docs/javascript/db-guild-member/). ```javascript // In a guild: writes to guildMember scope (user + guild composite key) await db.user.set('xp', 50); // Equivalent explicit call: await db.guildMember.set('xp', 50); ``` In DMs or non-guild contexts, `db.user.*` uses global user scope. This matches BDFD behavior where user variables in servers are per-member. ## Variable registration Scoped keys must be registered in the Bot Creator variable panel before `get` returns stored values. `set` auto-creates the definition if missing. ## Methods ### `await db.user.get(key, userId?)` Returns the stored value for `key`. When `userId` is omitted, uses the command author from context. ```javascript const coins = await db.user.get('coins'); const other = await db.user.get('coins', '123456789012345678'); ``` ### `await db.user.set(key, value, userId?)` Writes `value` for `key`. Value can be any JSON-serializable type. ```javascript await db.user.set('coins', 100); await db.user.set('coins', 0, interaction.user.id); ``` ### `await db.user.delete(key, userId?)` Removes the key for the user. ### `await db.user.list(key, order?, limit?, offset?, filter?)` Returns `{ id, value }[]` sorted by `key` values. `order` is `'asc'` or `'desc'`. When a `filter` function is provided, the runtime fetches up to **10,000 rows** first, then filters client-side before applying `offset` and `limit`. ```javascript const leaderboard = await db.user.list('coins', 'desc', 10, 0); const rich = await db.user.list('coins', 'desc', 10, 0, (e) => e.value > 100); ``` **BDFD equivalent:** [$userLeaderboard](/docs/userleaderboard/) / [$globalUserLeaderboard](/docs/globaluserleaderboard/). ### `await db.user.find(filter)` Returns `{ key, id, value }[]` for all matching entries. Requires a filter function. ```javascript const matches = await db.user.find((entry) => entry.value > 500); ``` ### `await db.user.reset(key)` Purges all stored values for `key` and removes the variable definition. **BDFD equivalent:** [$resetUserVar](/docs/resetuservar/). --- ### discord.js builders Import builders via `require('discord.js')`. Only **builder classes and constants** are allowed — not `Client`, `REST`, or `WebhookClient`. ## Allowed builders | Export | Use | |--------|-----| | `EmbedBuilder` | Rich embed messages | | `AttachmentBuilder` | File attachments | | `ActionRowBuilder` | Component row container | | `ButtonBuilder` | Interactive buttons | | `StringSelectMenuBuilder` | Text dropdown | | `UserSelectMenuBuilder` | User picker | | `ChannelSelectMenuBuilder` | Channel picker | | `RoleSelectMenuBuilder` | Role picker | | `MentionableSelectMenuBuilder` | User or role picker | | `ModalBuilder` | Popup forms | | `TextInputBuilder` | Modal text fields | | `SlashCommandBuilder` | Slash command definitions | | `ContextMenuCommandBuilder` | Context menu definitions | ## Constants `ChannelType`, `ButtonStyle`, `ComponentType`, `TextInputStyle`, `PermissionFlagsBits`, `ActivityType` ## Embed example ```javascript const { EmbedBuilder } = require('discord.js'); const embed = new EmbedBuilder() .setTitle('Stats') .setColor(0x5865f2) .addFields({ name: 'Coins', value: '100', inline: true }); await interaction.reply({ embeds: [embed] }); ``` ## Button row example ```javascript const { ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); const row = new ActionRowBuilder().addComponents( new ButtonBuilder() .setCustomId('yes') .setLabel('Yes') .setStyle(ButtonStyle.Success), new ButtonBuilder() .setCustomId('no') .setLabel('No') .setStyle(ButtonStyle.Danger), ); await interaction.reply({ content: 'Confirm?', components: [row] }); ``` ## Blocked exports These throw at runtime: - `Client` — use the global `client` object instead - `ShardingManager` - `WebhookClient` - `REST` ## Related - [Components](/docs/javascript/components/) — handling button/select/modal callbacks - [require()](/docs/javascript/require/) — all allowed modules --- ### interaction The `interaction` global is available when a command runs from a slash command or component interaction. ## Properties | Property | Type | Description | |----------|------|-------------| | `commandName` | `string` | Name of the slash command | | `customId` | `string` | Component custom ID (buttons, selects, modals) | | `user` | `object` | User who triggered the interaction | | `member` | `object` | Guild member (in servers) | | `guild` | `object` | Guild object | | `channel` | `object` | Channel object | ## Methods ### `await interaction.reply(content)` Reply to the interaction. `content` can be a string or `{ content, ephemeral?, embeds?, components? }`. ```javascript await interaction.reply('Hello!'); await interaction.reply({ content: 'Only you see this', ephemeral: true }); ``` ### `await interaction.editReply(content)` Edit the initial reply (after `deferReply` or first reply). ### `await interaction.deferReply(options?)` Acknowledge the interaction; follow up with `editReply` or `followUp`. ```javascript await interaction.deferReply(); await interaction.editReply('Done!'); ``` ### `await interaction.followUp(content)` Send an additional message in the interaction thread. ### `await interaction.deleteReply()` Delete the initial reply. ### `await interaction.fetchReply()` Fetch the reply message object. ## interaction.options | Method | Description | |--------|-------------| | `getString(name, required?)` | String option | | `getInteger(name, required?)` | Integer option | | `getNumber(name, required?)` | Number option | | `getBoolean(name, required?)` | Boolean option | | `getUser(name)` | User option | | `getMember(name)` | Guild member option | | `getChannel(name)` | Channel option | | `getRole(name)` | Role option | | `getAttachment(name)` | Attachment option | | `getMentionable(name)` | User or role option | | `getSubcommand(required?)` | Active subcommand name | | `getSubcommandGroup(required?)` | Active subcommand group | | `getFocused(required?)` | Autocomplete typed value | ```javascript const name = interaction.options.getString('name', true); const target = interaction.options.getUser('target'); await interaction.reply(`Hello, ${name}!`); ``` ## Related - [Components](/docs/javascript/components/) — buttons, selects, modals - [Autocomplete](/docs/javascript/autocomplete/) — dynamic slash suggestions --- ### message The `message` global is available when a command runs from a text message trigger. ## Properties | Property | Description | |----------|-------------| | `content` | Message text | | `author.id` | Author user ID | | `author.username` | Author username | ## Methods ### `await message.reply(content)` Reply in the same channel. ```javascript const args = message.content.split(' '); const body = args.slice(1).join(' '); await message.reply(body || 'Usage: !echo '); ``` --- ### JavaScript API Overview Bot Creator supports two scripting modes: **BDScript** (`$functions`) and **BDJS** (JavaScript). When your bot uses BDJS, command handlers run as async JavaScript with a sandboxed set of globals. Check your bot's mode with [$scriptLanguage](/docs/scriptlanguage/) — it returns `bdjs` or `bdscript`. ## Available globals | Global | Description | |--------|-------------| | `db` | Persistent storage (`db.user`, `db.global`, …) | | `interaction` | Slash command / component interaction (when applicable) | | `message` | Text message context (when applicable) | | `client` | Discord client proxy | | `guild`, `channel`, `member` | Context entities | | `config` | Bot configuration (token stripped) | | `variables` | Runtime variables object | | `webhook` | Webhook payload context or `null` | | `console` | `log`, `info`, `warn`, `error`, `debug` | | `fetch` | HTTP requests (proxied) | | `require(name)` | Whitelisted Node modules | ## Quick example ```javascript const coins = await db.user.get('coins'); await db.user.set('coins', (Number(coins) || 0) + 10); await interaction.reply(`You now have ${Number(coins) + 10} coins!`); ``` ## BDFD equivalent Many BDJS features map to BDFD `$functions`. See the [BDFD Variables](/docs/#variables) category for `$getUserVar`, `$setUserVar`, and related functions. ## Sections - [db — Storage API](/docs/javascript/db/) - [interaction](/docs/javascript/interaction/) — slash commands and replies - [Components](/docs/javascript/components/) — buttons, selects, modals - [Autocomplete](/docs/javascript/autocomplete/) — dynamic slash suggestions - [discord.js builders](/docs/javascript/discordjs-builders/) — embeds and UI components - [config](/docs/javascript/config/) and [variables](/docs/javascript/variables/) - [canvas](/docs/javascript/canvas/) and [voice](/docs/javascript/voice/) - [sandbox](/docs/javascript/sandbox/) — limits and restrictions - [require()](/docs/javascript/require/) - [Placeholders](/docs/javascript/placeholders/) - [Events & placeholders](/docs/events-and-placeholders/) — `((...))` in BDScript --- ### Placeholders Placeholders inject runtime context into BDScript templates. In BDJS you typically use the `interaction`, `message`, `guild`, and `channel` globals directly, but placeholders remain available in mixed BDScript/BDJS workflows. ## Syntax ``` ((variable.path)) ``` ## Common placeholders | Placeholder | Description | |-------------|-------------| | `((author.id))` | User who triggered the command | | `((author.username))` | Username | | `((guild.id))` | Current guild ID | | `((channel.id))` | Current channel ID | | `((interaction.customId))` | Component custom ID | | `((interaction.stringSelect.value))` | Select menu value | ## BDScript example ```bdfd $sendMessage[Hello <@((author.id))>!] ``` ## Full reference See the [Available Variables per Event](/blog/) guide for an exhaustive event-variable list. For component interactions, see [Handling Rich Interactions](/blog/) — buttons, select menus, and modals. --- ### require() `require(moduleId)` loads sandbox-approved modules. ## Allowed modules | Module | Purpose | |--------|---------| | `canvas` | Image drawing (node-canvas) | | `@discordjs/voice` | Voice connections | | `crypto` / `node:crypto` | Cryptographic utilities | | `util` / `node:util` | Node utilities | | `url` / `node:url` | URL parsing | | `querystring` / `node:querystring` | Query string helpers | | `discord.js` | Builders only — `Client` is **denied** | ## Examples ```javascript const { EmbedBuilder } = require('discord.js'); const crypto = require('crypto'); const { createCanvas } = require('canvas'); ``` ## Module reference | Module | Documentation | |--------|---------------| | `discord.js` | [discord.js builders](/docs/javascript/discordjs-builders/) | | `canvas` | [canvas](/docs/javascript/canvas/) | | `@discordjs/voice` | [voice](/docs/javascript/voice/) | | `crypto` | `randomBytes`, `randomUUID`, `randomInt`, `createHash`, `createHmac`, `timingSafeEqual` | | `util` | `inspect`, `format`, `formatWithOptions`, `types.is*` predicates | | `url` | `URL`, `URLSearchParams` | | `querystring` | `parse`, `stringify` | ## crypto example ```javascript const crypto = require('crypto'); const id = crypto.randomUUID(); const hash = crypto.createHash('sha256').update('data').digest('hex'); ``` See [sandbox](/docs/javascript/sandbox/) for the full whitelist and restrictions. --- ### sandbox BDJS scripts run in an isolated sandbox with security restrictions and resource limits. ## Script timeout Each script has a maximum execution time controlled by `config.scriptTimeoutMs` (default **30 seconds**). Long-running scripts are terminated when the deadline is reached. ## Timers `setTimeout` and `clearTimeout` are available in the sandbox for short delays within the script timeout window. ```javascript await new Promise((resolve) => setTimeout(resolve, 1000)); ``` ## require() whitelist Only these modules can be imported: | Module | Purpose | |--------|---------| | `discord.js` | Builders and constants only | | `canvas` | Image generation | | `@discordjs/voice` | Voice audio | | `crypto` / `node:crypto` | Hashing, random bytes | | `util` / `node:util` | inspect, format, type checks | | `url` / `node:url` | URL parsing | | `querystring` / `node:querystring` | Query string encode/decode | Any other module throws at runtime. ## Blocked operations | Restriction | Details | |-------------|---------| | `new Client()` | Use the global `client` object | | `client.token` | Token access is blocked | | Local file paths | Canvas, voice, and fetch assets must use `http(s)` or `data:` URLs | | Nested `client` | Dynamic proxy blocks recursive client access | ## Discord.js dynamic proxies Most discord.js methods on `client`, `interaction`, `message`, `guild`, `channel`, and `member` work through a sandbox bridge. Method calls cross the isolate boundary asynchronously. ## fetch restrictions `fetch()` supports HTTP requests. Asset URLs loaded into canvas or voice must not point to local filesystem paths. ## Related - [require()](/docs/javascript/require/) — module reference - [config](/docs/javascript/config/) — `scriptTimeoutMs` setting --- ### variables The `variables` global is a plain object containing resolved variable values for the current execution context. ## What it contains At runtime, the runner merges: 1. `config.globalVariables` defaults 2. Stored global values from the database 3. Scoped values for the current user/guild/channel/message context ```javascript console.log(variables.coins); console.log(variables.welcomeMessage); ``` ## Aliases Each registered variable is accessible under multiple keys: - The storage key (e.g. `coins`) - The reference key from variable definitions - A `bc_` prefixed alias (e.g. `bc_coins`) ## Relationship to db.* Writing through `db.user.set()`, `db.global.set()`, etc. updates `variables` in-place for the current context, so reads from `variables` reflect recent writes within the same script execution. ```javascript await db.user.set('coins', 100); console.log(variables.coins); // 100 ``` ## Variable registration Variables must be registered in the Bot Creator app panel before scoped `db.*.get()` returns stored values. See the [Database variables guide](/advanced-topics/2026/05/30/mastering-persistent-database-variables-in-bdfd/). ## BDFD equivalent BDScript uses `$getUserVar`, `$getVar`, etc. See [Variables](/docs/#variables) function category. ## Related - [db — Storage API](/docs/javascript/db/) - [Events & placeholders](/docs/events-and-placeholders/) — `((...))` template variables --- ### voice Play audio in voice channels with `require('@discordjs/voice')`. Remote audio URLs are supported; local file paths are blocked. HTTP URLs require FFmpeg on the runner host. ## Key exports | Export | Description | |--------|-------------| | `joinVoiceChannel(options)` | Connect to a voice channel | | `joinVoiceChannelReady(channel, adapterCreator)` | Connect and wait until ready | | `createAudioPlayer()` | Playback controller | | `createAudioResource(source)` | Audio source from URL or stream | | `playAudio(player, resource)` | Start playback helper | | `getVoiceConnection(guildId)` | Get active connection | | `entersState(resource, status, timeout)` | Wait for state transition | ## Constants `AudioPlayerStatus`, `VoiceConnectionStatus`, `StreamType`, `NoSubscriberBehavior`, `EndBehaviorType` ## Example ```javascript const { joinVoiceChannel, createAudioPlayer, createAudioResource } = require('@discordjs/voice'); const connection = joinVoiceChannel({ channelId: channel.id, guildId: guild.id, adapterCreator: guild.voiceAdapterCreator, }); const player = createAudioPlayer(); const resource = createAudioResource('https://example.com/audio.mp3'); player.play(resource); connection.subscribe(player); ``` ## BDFD equivalent BDScript music functions (`$playMusic`, `$joinVoice`, etc.) use Lavalink. See the [Music](/docs/#music) function category. ## Restrictions - Local filesystem paths are blocked for audio sources. - FFmpeg must be available for HTTP audio URLs. --- ## Math & Text ### $c # $c (alias of $calculate) The `$c[]` function is a **shortened alias** of `$calculate[]`. It performs mathematical calculations and returns the result. ## Syntax ``` $c[expression] ``` ## Parameters | Parameter | Description | |---|---| | `expression` | Mathematical expression to evaluate. | ## Supported Operators | Operator | Description | Example | |---|---|---| | `+` | Addition | `$c[2+3]` → `5` | | `-` | Subtraction | `$c[10-4]` → `6` | | `*` | Multiplication | `$c[6*7]` → `42` | | `/` | Division | `$c[15/3]` → `5` | | `%` | Modulo | `$c[10%3]` → `1` | | `^` | Exponentiation (Power) | `$c[2^10]` → `1024` | ## Examples ### Basic calculations ```bdfd $sendMessage[5 + 3 = $c[5+3]] $sendMessage[100 / 4 = $c[100/4]] $sendMessage[2^8 = $c[2^8]] ``` ### Calculation with decimals ```bdfd $enableDecimals $sendMessage[22/7 = $c[22/7]] ``` ### Levels system ```bdfd $let[xp;$getVar[xp]] $let[level;$c[$var[xp]/100]] $sendMessage[Level: $round[$var[level];0]] ``` ### Calculation with variables ```bdfd $var[price;49] $var[quantity;3] $let[total;$c[$var[price]*$var[quantity]]] $sendMessage[Total: $var[total]€] ``` ## Notes - `$c[]` is strictly identical to `$calculate[]` — just shorter. - Without `$enableDecimals`, the results are rounded. - Supports parentheses for priorities: `$c[(2+3)*4]` → `20`. --- ### $calculate[] # $calculate[] The `$calculate[]` function is the most powerful mathematical function in BDFD. It allows you to evaluate complex mathematical expressions using an integrated math parser. ## Syntax ``` $calculate[expression] ``` ## Parameters | Parameter | Type | Required | Description | |-------------|--------|-------------|----------------------------------------------------------------| | `expression`| string | Yes | The mathematical expression to evaluate. | ## Supported Operators | Operator | Description | Example | |-----------|-------------------|--------------------| | `+` | Addition | `5 + 3` → `8` | | `-` | Subtraction | `10 - 4` → `6` | | `*` | Multiplication | `6 * 7` → `42` | | `/` | Division | `15 / 3` → `5` | | `%` | Modulo | `17 % 5` → `2` | | `^` | Exponentiation | `2 ^ 8` → `256` | ## Supported Functions `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `abs`, `sqrt`, `log`, `log10`, `floor`, `ceil`, `round`, `min`, `max`, `exp` ## Comparisons Comparisons return `"true"` or `"false"`: - `>` strictly greater than - `<` strictly less than - `>=` greater than or equal to - `<=` less than or equal to - `==` equal to - `!=` not equal to ## Notes - The expression is evaluated with a server-side math parser. - The result is always returned as a character string (even for numbers). - The function supports the use of BDFD variables like `$getVar[]` in the expression. - In case of an invalid expression, the behavior depends on the parser (usually a silent error or an empty result). --- ### $ceil[] # $ceil[] The `$ceil[]` function returns the smallest integer greater than or equal to the given value. It always rounds up to the next integer. ## Syntax ``` $ceil[value] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|----------------------------------------| | `value` | number | Yes | The number to round up. | ## Behavior - For a positive number: rounds up to the next integer if there is any decimal part. `$ceil[3.1]` → `4`. - For a negative number: rounds up toward zero (less negative). `$ceil[-3.9]` → `-3`. - For an integer: returns the integer itself. ## Examples **Positive number:** ``` $ceil[3.1] → 4 $ceil[3.9] → 4 ``` **Negative number:** ``` $ceil[-3.9] → -3 $ceil[-3.1] → -3 ``` **Integer:** ``` $ceil[5] → 5 ``` ## Comparison of floor / ceil / round | Value | $floor[] | $ceil[] | $round[] | |--------|----------|---------|----------| | `3.2` | `3` | `4` | `3` | | `3.5` | `3` | `4` | `4` | | `3.9` | `3` | `4` | `4` | | `-3.2` | `-4` | `-3` | `-3` | | `-3.5` | `-4` | `-3` | `-3`* | *The exact behavior of `$round[]` for values ending in `.5` may depend on the implementation. ## Notes - The result is always an integer (in the form of a string). - Useful when you need the "next integer," for example, to calculate the number of pages needed. --- ### $charCount[] # $charCount — Count Characters `$charCount` returns the number of characters in a string. Every character counts — letters, digits, spaces, punctuation, and newlines. It is useful for validation, truncation decisions, and displaying string length to users. ## Syntax ``` $charCount[text] ``` ## Parameters - **text** *(string, required)* — The text to count. ## Return Value - **Type**: `string` (representing a number) - Returns the total character count as a numeric string: `"5"`, `"42"`, `"0"`, etc. ## Usage ``` $charCount[Hello] → "5" $charCount[Hello World] → "11" (space counts) $charCount[A\nB] → "3" (newline counts as 1) $charCount[] → "0" $charCount[$message] → character count of user's message ``` ## Common Patterns ### Character Limit Enforcement ``` $if[$charCount[$message]>2000] $sendMessage[Your message exceeds Discord's 2000 character limit!] $stop $endif ``` ### Progress Display ``` $sendMessage[Bio: $charCount[$getUserVar[bio]]/500 characters used] ``` ### Input Validation ``` $if[$charCount[$message]<10] $sendMessage[Please write at least 10 characters.] $endif ``` ### Conditional Truncation ``` $if[$charCount[$text]>100] $var[text;$cropText[$text;100]] $endif ``` ## Important Notes - **Unicode**: Multi-byte characters like emojis may count as more than 1 character depending on the BDFD runtime. - **Newlines**: `\n` counts as 1 character. - **Empty input**: Returns `"0"`, not an error. - **Return type**: The return value is a string, but can be used in `$math` or `$checkCondition` for numeric comparisons. --- ### $cropText[] # $cropText — Truncate Text `$cropText` limits a string to a maximum character length. If the text exceeds the limit, it is cut at `maxLength` characters and a suffix (default `"..."`) is appended to indicate truncation. If the text is within the limit, it is returned unchanged. ## Syntax ``` $cropText[text;maxLength;(suffix)] ``` ## Parameters - **text** *(string, required)* — The source text. - **maxLength** *(integer, required)* — The maximum character count. Text longer than this is truncated. - **suffix** *(string, optional)* — String appended after truncation. Default: `"..."`. Pass an empty value for a hard cut with no indicator. ## Return Value - **Type**: `string` - If `text.length ≤ maxLength`: returns `text` unchanged (no suffix). - If `text.length > maxLength`: returns the first `maxLength` characters + `suffix`. ## Usage ``` $cropText[Hello World;5] → "Hello..." $cropText[Hello World;20] → "Hello World" (no truncation) $cropText[Hello World;5;~] → "Hello~" $cropText[Hello World;3;] → "Hel" (hard cut) ``` ## Common Patterns ### Embed Field Truncation Discord embed fields have character limits. Use `$cropText` to ensure compliance: ``` $cropText[$getUserVar[bio];1024] ``` ### Message Preview Show a snippet of a long message: ``` $sendMessage[Latest post: $cropText[$getUserVar[lastPost];100; [...]] ``` ### Title Formatting ``` $var[title;$cropText[$message;50]] ``` ## Important Notes - **Suffix is not included in maxLength**: The `maxLength` value controls how many characters of the *original text* are kept. The suffix is added on top. For example, `$cropText[abcdef;3;...]` produces `"abc..."` (6 total characters). - **Hard cut with empty suffix**: `$cropText[text;5;]` with an empty third argument simply returns the first 5 characters. - **Works with numbers/symbols**: All characters count equally — no special handling of Unicode or emoji width. --- ### $divide[] # $divide[] The `$divide[]` function performs a division: `a / b`. It is protected against division by zero: instead of generating an error, it simply returns `0`. ## Syntax ``` $divide[a;b] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|----------------------------------| | `a` | number | Yes | The dividend (numerator). | | `b` | number | Yes | The divisor (denominator). | ## Behavior - Returns the quotient `a / b`. - The result can be a decimal number. - **If `b = 0`, it returns `0`** without generating an error. This is a built-in protection. ## Examples **Simple division:** ``` $divide[10;2] → 5 ``` **Decimal result:** ``` $divide[10;3] → 3.333333... ``` **Division by zero (protected):** ``` $divide[42;0] → 0 ``` **Average calculation:** ``` $divide[$sum[12;15;18];3] → 15 ``` ## Notes - Protection against division by zero prevents accidental crashes, but note: `0` can be a legitimate result or an error indicator depending on the context. - For finer control, use `$calculate[a / b]` (which may behave differently). --- ### $editSplitText[] # $editSplitText — Modify Spreads Element `$editSplitText` replaces the value of a specific element in the current text spreads array. Use it to transform, correct, or update individual spreads pieces before rejoining or further processing. ## Syntax ``` $editSplitText[index;newValue] ``` ## Parameters - **index** *(integer, required)* — The zero-based position of the element to edit. Negative indices count from the end (`-1` = last element). - **newValue** *(string, required)* — The replacement text. Can be any string, including empty. ## Behavior - **Action-only**: `$editSplitText` is not an inline function. It modifies the internal spreads array directly. - The change is permanent for the remainder of the current command execution. - Subsequent calls to `$splitText[index]` or `$joinSplitText` reflect the modification. - Editing an out-of-bounds index has no effect (no error emitted). ## Usage ``` $textSplit[John;Jane;Bob;Alice;] $editSplitText[0;Jonathan] $splitText[0] → "Jonathan" ``` ``` $textSplit[red;green;blue;] $editSplitText[-1;purple] $joinSplitText[, ] → "red, green, purple" ``` ## Common Patterns ### Title-Casing Names ``` $textSplit[$message; ] $editSplitText[0;$toTitlecase[$splitText[0]]] ``` ### Fixing Specific Values ``` $textSplit[$getUserVar[permissions];,] $editSplitText[2;admin] $var[updated;$joinSplitText[,]] ``` ### Clearing Sensitive Data ``` $editSplitText[3;***REDACTED***] ``` ## Important Notes - **In-place mutation**: The spreads array is modified directly. The original value is lost. - **Works with any index**: Both positive and negative indices are supported. - **No return value**: Do not use `$editSplitText` inside expressions expecting a value. - **Requires prior split**: Must be called after `$textSplit`, otherwise nothing happens. --- ### $floor[] # $floor[] The `$floor[]` function returns the greatest integer less than or equal to the given value. It always rounds down to the lower integer. ## Syntax ``` $floor[value] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|----------------------------------------| | `value` | number | Yes | The number to round down. | ## Behavior - For a positive number: removes the decimal part. `$floor[3.9]` → `3`. - For a negative number: rounds down to the next lower integer (more negative). `$floor[-3.1]` → `-4`. - For an integer: returns the integer itself. ## Examples **Positive number:** ``` $floor[3.9] → 3 $floor[3.1] → 3 ``` **Negative number:** ``` $floor[-3.1] → -4 $floor[-3.9] → -4 ``` **Integer:** ``` $floor[5] → 5 ``` ## Comparison floor / ceil / round | Value | $floor[] | $ceil[] | $round[] | |--------|----------|---------|----------| | `3.2` | `3` | `4` | `3` | | `3.5` | `3` | `4` | `4` | | `3.9` | `3` | `4` | `4` | | `-3.2` | `-4` | `-3` | `-3` | | `-3.5` | `-4` | `-3` | `-3`* | *The exact behavior of `$round[]` for values ending in `.5` may depend on the implementation. ## Notes - The result is always an integer (as a string). - Useful for calculations of pagination, levels, or any situation requiring an integer. --- ### $getTextSplitIndex # $getTextSplitIndex — Current Split Text Iteration Index `$getTextSplitIndex` returns the current position (index) during split text iteration. It is typically used inside a split text loop to know which element is being processed. ## Syntax ``` $getTextSplitIndex ``` This function takes **no parameters**. ## Return Value - **Type**: `string` (representing a number) - Returns the zero-based index of the current element in a split text iteration. - Returns `"0"` if called outside a split text loop context. ## Usage When iterating over split text elements, `$getTextSplitIndex` tells you the position: ``` $textSplit[red;green;blue;yellow;] ``` During iteration, `$getTextSplitIndex` produces: | Element | Index | |---------|-------| | `red` | `0` | | `green` | `1` | | `blue` | `2` | | `yellow`| `3` | ## Common Patterns ### Numbered List Output ``` $textSplit[First;Second;Third;] $sendMessage[$math[$getTextSplitIndex+1]. $splitText] ``` ### Conditional Logic Based on Position ``` $if[$getTextSplitIndex==0] This is the first element: $splitText $endif ``` ### Select First N Elements ``` $if[$getTextSplitIndex<5] $sendMessage[Element $math[$getTextSplitIndex+1]: $splitText] $endif ``` ## Important Notes - **Zero-based**: The first element is at index `0`, not `1`. Add 1 for human-readable numbering. - **Loop context only**: Meaningful values are only available inside a split text iteration loop. - **No parameter**: This function takes no arguments — calling it with any brackets `$getTextSplitIndex[]` may cause unexpected behavior. --- ### $getTextSplitLength # $getTextSplitLength — Count Split Text Elements `$getTextSplitLength` returns the number of elements in the current split text array — the total count of pieces produced by the most recent `$textSplit` call. ## Syntax ``` $getTextSplitLength ``` This function takes **no parameters**. ## Return Value - **Type**: `string` (representing a number) - Returns the total number of elements. For example, splitting `"a;b;c"` by `;` yields `3`. - Returns `"0"` if no `$textSplit` has been called yet. ## Usage ``` $textSplit[apple;banana;orange;grape;] $getTextSplitLength → "4" ``` ``` $textSplit[hello world; ] $getTextSplitLength → "2" ``` ## Common Patterns ### Bounds Checking Prevent out-of-bounds access by validating index first: ``` $textSplit[$message; ] $if[$getTextSplitLength>2] $sendMessage[Third argument: $splitText[2]] $else $sendMessage[Please provide at least 3 arguments] $endif ``` ### Conditional Empty Check ``` $textSplit[$getUserVar[list];,] $if[$getTextSplitLength==0] $sendMessage[The list is empty] $else $sendMessage[The list contains $getTextSplitLength items] $endif ``` ### Iteration Count Display Display progress inside a split text loop: ``` Processing element $math[$getTextSplitIndex+1] of $getTextSplitLength... ``` ## Important Notes - **Read-only**: This function reports the count; it does not modify the split text array. - **After each $textSplit**: The length reflects the most recent split. Calling `$textSplit` again resets it. - **No parameter**: This function takes no arguments. --- ### $getTimestampMs # $getTimestampMs The function `$getTimestampMs` returns the current Unix timestamp in **milliseconds**. The Unix timestamp represents the number of milliseconds elapsed since January 1, 1970, at 00:00:00 UTC (epoch). > **Important:** This function uses the special identifier `((getTimestampMs))` which is resolved at **runtime**. ## Difference with $getTimestamp | Function | Unit | Value Example | |----------|-------|-------------------| | `$getTimestampMs` | **Milliseconds** (ms) | `1718697600123` | | `$getTimestamp` | **Seconds** (s) | `1718697600` | - `$getTimestampMs` = `$getTimestamp` × 1000 + additional milliseconds. - Use `$getTimestampMs` for **high-precision** measurements (benchmarks, fine cooldowns, timeouts). - Use `$getTimestamp` for common use cases where precision to the second is sufficient (dates, long durations, storage). ## Syntax ``` $getTimestampMs ``` > **Note:** This function does not take any parameters. ## Parameters No parameters. ## Return Value - **Type**: String (integer) - The current Unix timestamp in milliseconds (13 digits). ## Examples ### Simple timestamp ```bdfd Timestamp (ms): $getTimestampMs ``` ### Performance measurement ```bdfd $let[start;$getTimestampMs] $title[🔍 Performance Test] $description[ Calculation in progress... ] $sendMessage[] $let[end;$getTimestampMs] $let[duration;$sub[$get[end];$get[start]]] $title[📊 Result] $description[ Operation completed in **$get[duration] ms**. ] $color[#5865F2] $sendMessage[] ``` ### Precise cooldown (anti-spam) ```bdfd $let[now;$getTimestampMs] $let[last;$getUserVar[lastCmd]] $let[diff;$sub[$get[now];$get[last]]] $if[$get[diff]<2000] $title[⏳ Too Fast!] $description[ Please wait another **$math[(2000 - $get[diff]) / 1000]** seconds. ] $color[#ED4245] $sendMessage[] $stop[] $endif $setUserVar[lastCmd;$get[now]] Your command has run successfully! ``` ### Conversion to seconds ```bdfd $let[ms;$getTimestampMs] $let[seconds;$math[$get[ms] / 1000]] Timestamp (ms): $get[ms] Timestamp (seconds): $get[seconds] ``` ## Notes - The precision is accurate to the millisecond (1 ms = 0.001 seconds). - To compare with a timestamp in seconds, do not forget to convert: multiply seconds by 1000 or divide milliseconds by 1000. - The returned values are integers, but calculations with `$math[]` can produce decimal numbers during conversion. --- ### $hasRole # $hasRole The function `$hasRole[userID;roleID]` **checks if a user has a specific role** on the server. It is commonly used for permission systems. ## Syntax ``` $hasRole[userID;roleID] ``` Or with a single parameter (checks the author): ``` $hasRole[roleID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | Optional - The ID of the user. Default: author of the command. | | `roleID` | The ID of the role to check. Required. | ## Return Value - **Type**: Boolean - `true` if the user has the role. - `false` if the role is not assigned, does not exist, or if the user is not found. ## Behavior - Checks in the user's role list on the current server. - Works only in a server context. - Case-insensitive for the role name (if `$roleID[Name]` is used). ## Examples ### Admin Portal ```bdfd $if[$hasRole[$authorID;$roleID[Admin]]==true] $title[🔧 Admin Panel] $description[ Available commands: - `!ban ` - Ban a member - `!kick ` - Kick a member - `!warn ` - Warn ] $sendMessage[] $else $sendEphemeral[❌ Access reserved for Administrators.] $endif ``` ### Staff Command ```bdfd $if[$hasRole[$roleID[Staff]]==false] $sendMessage[❌ Permission denied. Staff role required.] $stop $endif ;; Command executed $ban[$mentioned[1];Banned by $userName] $sendMessage[🔨 <@$mentioned[1]> was banned.] ``` ### Multi-Role Check ```bdfd $if[$hasRole[$mentioned[1];$roleID[Modo]]==true] $sendMessage[<@$mentioned[1]> is Moderator.] $elseif[$hasRole[$mentioned[1];$roleID[Admin]]==true] $sendMessage[<@$mentioned[1]> is Administrator.] $else $sendMessage[<@$mentioned[1]> is a standard member.] $endif ``` ### Role Badge ```bdfd $if[$hasRole[$roleID[VIP]]==true] $var[badge;👑 VIP] $elseif[$hasRole[$roleID[Booster]]==true] $var[badge;🚀 Booster] $else $var[badge;👤 Member] $endif $sendMessage[$var[badge] $userName] ``` ## Notes - `$hasRole[userID;roleID]` requires the bot to be able to see the server's roles. - To assign a role, use `$giveRole[]` or `$giveRoles[]`. - To remove a role, use `$takeRole[]` or `$takeRoles[]`. - `$hasRole` is often used as a guard at the beginning of commands with `$stop`. --- ### $isBanned # $isBanned The function `$isBanned[userID]` **checks if a user is currently banned** from the server where the command was executed. The bot must have the `BanMembers` permission. ## Syntax ``` $isBanned[userID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user to check. | ## Return Value - **Type**: Boolean - `true` if the user is banned from the server. - `false` if the user is not banned or does not exist. ## Behavior - The bot needs the `BanMembers` permission to consult the ban list. - Works even if the user has left the server. - Checks only the current server. ## Examples ### Check before commanding ```bdfd $if[$isBanned[$mentioned[1]]==true] $sendMessage[⚠️ <@$mentioned[1]> is already banned from this server.] $else $ban[$mentioned[1];Reason provided by $userName] $sendMessage[🔨 <@$mentioned[1]> was banned.] $endif ``` ### Unban a user ```bdfd $if[$isBanned[$message[1]]==true] $unban[$message[1]] $sendMessage[✅ The user $message[1] was unbanned.] $else $sendMessage[❌ This ID is not banned.] $endif ``` ### Verification log ```bdfd $var[userID;$message[1]] $if[$isBanned[$var[userID]]==true] $var[reason;$getBanReason[$var[userID]]] $sendMessage[📋 **Ban found:** > ID: $var[userID] > Reason: $var[reason]] $else $sendMessage[✅ No ban found for $var[userID].] $endif ``` ## Notes - The bot must have the `BanMembers` permission for this function to return a reliable result. - To get the ban reason, use `$getBanReason[]`. - To ban or unban, use `$ban[]` or `$unban[]`. - Works only within a server context (not in DMs). --- ### $isBoolean # $isBoolean The function `$isBoolean[value]` **checks if a value is a boolean** (`true` or `false`). It returns `true` if the value is strictly a boolean, and `false` in all other cases (number, text, etc.). ## Syntax ``` $isBoolean[value] ``` ## Parameters | Parameter | Description | |---|---| | `value` | The value to test. | ## Return Value - **Type**: Boolean - `true` if `value` is `true` or `false`. - `false` if `value` is a number, a character string, or empty. ## Behavior - Only the literals `true` and `false` are recognized as booleans. - `"true"` (string) is **not** a boolean. - `0` and `1` are **not** booleans (use `$isNumber[]` for those cases). ## Examples ### Validation in a condition ```bdfd $if[$isBoolean[$message[1]]==true] $sendMessage[✅ $message[1] is a valid boolean.] $else $sendMessage[❌ $message[1] is not a boolean. Expected: true or false.] $endif ``` ### Checking a variable ```bdfd $var[actif;true] $if[$isBoolean[$var[actif]]==true] $sendMessage[The variable is a boolean.] $endif ``` ### Advanced type checking ```bdfd $var[val;$message[1]] $if[$isBoolean[$var[val]]==true] $sendMessage[📌 Boolean detected: $var[val]] $elseif[$isInteger[$var[val]]==true] $sendMessage[🔢 Integer detected: $var[val]] $elseif[$isNumber[$var[val]]==true] $sendMessage[🔣 Number detected: $var[val]] $else $sendMessage[📝 Text detected: $var[val]] $endif ``` ## Notes - `$isBoolean[true]` returns `true`. - `$isBoolean[false]` returns `true`. - `$isBoolean[0]` returns `false` (0 is a number). - `$isBoolean[]` (empty) returns `false`. --- ### $isEmojiAnimated # $isEmojiAnimated The function `$isEmojiAnimated[emoji]` **checks if a custom emoji is animated**. Discord animated emojis start with `` or ``). | ## Return Value - **Type**: Boolean - `true` if the emoji is animated. - `false` if the emoji is static, standard (Unicode), or invalid. ## Behavior - Works only with Discord custom emojis. - Standard Unicode emojis (😀, 🎉) return `false`. - The expected format is the full emoji mention. ## Examples ### Emoji Check ```bdfd $var[emoji;$message[1]] $if[$isEmojiAnimated[$var[emoji]]==true] $sendMessage[🎞️ $var[emoji] is an animated emoji!] $else $sendMessage[🖼️ $var[emoji] is a static or standard emoji.] $endif ``` ### Emoji Statistics ```bdfd $title[📊 Emoji Info] $description[ **Emoji:** $message[1] **Animated:** $if[$isEmojiAnimated[$message[1]]==true]Yes$elseNo$endif **Name:** $emojiName[$message[1]] **ID:** $emojiID[$message[1]] ] $sendMessage[] ``` ### Filter Animated Emojis ```bdfd $var[emoji;$message[1]] $if[$isEmojiAnimated[$var[emoji]]==true] $sendMessage[✅ Animated emoji detected!] $sendMessage[$var[emoji]] $else $sendMessage[❌ Only animated emojis are allowed in this command.] $endif ``` ## Notes - Animated format: `` → `true`. - Static format: `<:name:id>` → `false`. - Unicode emoji: `😀` → `false`. - To get the name of an emoji, use `$emojiName[]`. - To get the ID of an emoji, use `$emojiID[]`. --- ### $isInteger # $isInteger The function `$isInteger[value]` **checks if a value is an integer** (without decimals). It accepts positive integers, negative integers and zero. ## Syntax ``` $isInteger[value] ``` ## Parameters | Parameter | Description | |---|---| | `value` | The value to test. | ## Return Value - **Type**: Boolean - `true` if `value` is an integer (e.g. `42`, `-7`, `0`) - `false` if `value` is a decimal, text, or empty. ## Behavior - Decimal numbers (`3.14`, `2.0`) return `false`. - Integers in scientific notation are not recognized. - `0` is a valid integer. - Spaces around the number can invalidate the test. ## Examples ### Parameter Validation ```bdfd $if[$isInteger[$message[1]]==true] $sendMessage[✅ $message[1] is a valid integer.] $else $sendMessage[❌ Please provide an integer.] $endif ``` ### Pagination (Validation) ```bdfd $var[page;$message[1]] $if[$isInteger[$var[page]]==true] $if[$var[page]>=1] $sendMessage[📄 Displaying page $var[page]...] $else $sendMessage[❌ Page must be >= 1.] $endif $else $sendMessage[❌ Invalid parameter. Usage: !page ] $endif ``` ### Custom Counter ```bdfd $var[number;$message[1]] $if[$isInteger[$var[number]]==true] $for[i;1;$var[number];1] Counter: $for[i] $endfor $else $sendMessage[Please enter an integer.] $endif ``` ## Notes - `$isInteger[42]` returns `true`. - `$isInteger[-10]` returns `true`. - `$isInteger[3.14]` returns `false`. - `$isInteger[abc]` returns `false`. - To also accept decimals, use `$isNumber[]`. --- ### $isNSFW # $isNSFW The function `$isNSFW[channelID]` **checks if a Discord channel is marked as NSFW** (Not Safe For Work). ## Syntax ``` $isNSFW[channelID] ``` Or without parameter for the current channel: ``` $isNSFW ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional - The ID of the channel. Default: channel where the command is executed. | ## Return Value - **Type** : Boolean - `true` if the channel is marked NSFW. - `false` if the channel is not NSFW or is not found. ## Behavior - Checks the `nsfw` attribute of the Discord channel. - NSFW channels are restricted to users over 18 years old. - Works only in servers (not in DM). ## Examples ### Restricted command ```bdfd $if[$isNSFW==true] ;; Display NSFW content $sendMessage[🔞 NSFW content...] $else $sendMessage[❌ This command can only be used in an NSFW channel.] $endif ``` ### Channel information ```bdfd $title[📺 Channel information] $description[ **Name:** $channelName **ID:** $channelID **NSFW:** $if[$isNSFW==true]🔞 Yes$else✅ No$endif **Category:** $channelCategory ] $sendMessage[] ``` ### Check another channel ```bdfd $var[channel;$message[1]] $if[$isNSFW[$var[channel]]==true] $sendMessage[🔞 Channel <#$var[channel]> is NSFW.] $else $sendMessage[✅ Channel <#$var[channel]> is not NSFW.] $endif ``` ## Notes - Without parameter, checks the channel where the command is executed. - In DM, the function always returns `false`. - To modify the NSFW status of a channel, use `$modifyChannel[]`. --- ### $isNumber # $isNumber The function `$isNumber[value]` **checks if a value is a number**, whether integer, decimal, positive or negative. More permissive than `$isInteger[]`. ## Syntax ``` $isNumber[value] ``` ## Parameters | Parameter | Description | |---|---| | `value` | The value to test. | ## Return Value - **Type** : Boolean - `true` if `value` is a number (e.g. `42`, `-7`, `3.14`, `0.001`) - `false` if `value` is text, a boolean, or empty. ## Behavior - Accepts integers and decimals. - Accepts negative numbers. - Does not accept scientific notation (`1e5`). - Does not accept thousands separators (`1,000`). ## Examples ### Price validation ```bdfd $var[price;$message[1]] $if[$isNumber[$var[price]]==true] $if[$var[price]>=0] $var[tax;$math[$var[price]*0.2]] $sendMessage[💰 Price: $var[price]€ | VAT: $var[tax]€ | Total: $math[$var[price]+$var[tax]]€] $else $sendMessage[❌ The price must be positive.] $endif $else $sendMessage[❌ Please enter a valid number.] $endif ``` ### Simple calculator ```bdfd $var[a;$message[1]] $var[b;$message[2]] $if[$isNumber[$var[a]]==true&&$isNumber[$var[b]]==true] $sendMessage[📊 $var[a] + $var[b] = $math[$var[a]+$var[b]]] $sendMessage[📊 $var[a] × $var[b] = $math[$var[a]*$var[b]]] $else $sendMessage[❌ Please enter two valid numbers.] $endif ``` ### Complete type detection ```bdfd $var[val;$message[1]] $if[$isInteger[$var[val]]==true] $sendMessage[🔢 Integer] $elseif[$isNumber[$var[val]]==true] $sendMessage[🔣 Decimal number] $elseif[$isBoolean[$var[val]]==true] $sendMessage[📌 Boolean] $else $sendMessage[📝 Text] $endif ``` ## Notes - `$isNumber[42]` returns `true`. - `$isNumber[3.14]` returns `true`. - `$isNumber[-5.5]` returns `true`. - `$isNumber[true]` returns `false`. - To accept only integers, use `$isInteger[]`. --- ### $isSlash # $isSlash The function `$isSlash` **checks if the current command was triggered via a slash command** (application command) rather than a classic prefix command. ## Syntax ``` $isSlash ``` ## Parameters None. ## Return Value - **Type**: Boolean - `true` if the command was invoked via `/command`. - `false` if it was invoked via prefix (`!command`, `?command`, etc.). ## Behavior - Allows adapting behavior based on the invocation mode. - Useful for sending ephemeral responses in slash mode (`$sendEphemeral[]`). - No parameters: current command context only. ## Examples ### Adaptive Response ```bdfd $if[$isSlash==true] $sendEphemeral[✅ Action completed successfully!] $else $sendMessage[✅ Action completed successfully!] $endif ``` ### Diagnostic Log ```bdfd $if[$isSlash==true] $log[Command /$commandName executed by $userName] $else $log[Command $commandTrigger executed by $userName] $endif ``` ### Info Message ```bdfd $var[type;$if[$isSlash==true]Slash$elsePrefix$endif] $title[ℹ️ Command Information] $description[ **Name:** $commandName **Type:** $var[type] **Folder:** $commandFolder ] $color[$if[$isSlash==true]#5865F2$else#57F287$endif] $sendMessage[] ``` ### Hybrid Command ```bdfd ;; This command works in prefix and slash mode $if[$isSlash==true] $var[args;$slashOption[1]] $else $var[args;$message[1]] $endif ;; Common processing $sendMessage[You provided: $var[args]] ``` ## Related functions - [$slashOption](/docs/slashoption/) — read slash command option values - [$sendResponse](/docs/sendresponse/) — direct interaction replies (including `// ephemeral`) ## Notes - `$isSlash` takes no parameters. - To get the precise command type, use `$commandType`. - Ephemeral responses (`$sendEphemeral[]`) only work in slash mode. - `$isSlash` is evaluated in the context of the currently executing command. --- ### $isTicket # $isTicket The function `$isTicket` checks if the current channel is a ticket created via the `$newTicket[]` function in BDFD. Tickets are temporary channels used for support. ## Syntax ``` $isTicket ``` ## Parameters None. ## Return Value - **Type**: Boolean - `true` if the current channel is a BDFD ticket. - `false` if it is not a ticket (normal channel, DM, etc.). ## Behavior - Only recognizes tickets created via `$newTicket[]`. - Useful for restricting or adapting commands to the ticket context. - Tickets are identified by an internal BDFD marker. ## Examples ### Command restricted to tickets ```bdfd $if[$isTicket==false] $sendMessage[❌ This command can only be used in a ticket.] $stop $endif ;; Command logic $sendMessage[📋 Processing the ticket...] ``` ### Contextual close button ```bdfd $if[$isTicket==true] $addButton[close;Close Ticket;danger] $sendMessage[📌 Active ticket - Use the button below to close it.] $else $sendMessage[❌ You are not in a ticket channel.] $endif ``` ### Channel information ```bdfd $title[📋 Channel Info] $description[ **Name:** $channelName **ID:** $channelID **Ticket:** $if[$isTicket==true]✅ Yes$else❌ No$endif **NSFW:** $if[$isNSFW==true]🔞 Yes$else✅ No$endif ] $sendMessage[] ``` ## Notes - Only detects tickets created by `$newTicket[]`. - To close a ticket, use `$closeTicket[]`. - To create a ticket, use `$newTicket[]`. - Only works in a server (not in DMs). --- ### $isUserDmEnabled # $isUserDmEnabled The function `$isUserDmEnabled[userID]` checks if a user accepts private messages (DMs) from members of the same server or from the bot. ## Syntax ``` $isUserDmEnabled[userID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user to check. | ## Return Value - **Type**: Boolean - `true` if the user's DMs are open to the bot. - `false` if the DMs are closed or inaccessible. ## Behavior - Checks if the bot can send a private message to this user. - A user can close their DMs via their Discord privacy settings. - The bot must share at least one server with the user. ## Examples ### Conditional notification ```bdfd $if[$isUserDmEnabled[$mentioned[1]]==true] $sendDM[$mentioned[1];📬 You have received a warning on **$serverName**: $message[2]] $sendMessage[✅ Warning sent in DMs to <@$mentioned[1]>.] $else $sendMessage[⚠️ Cannot send a DM to <@$mentioned[1]>. Public notification instead.] $endif ``` ### Check before sending ```bdfd $var[userID;$mentioned[1]] $var[contenu;$message[2]] $if[$isUserDmEnabled[$var[userID]]==true] $sendDM[$var[userID];$var[contenu]] $sendEphemeral[✅ Message sent privately.] $else $sendEphemeral[❌ This user has disabled their DMs.] $endif ``` ### Notification loop ```bdfd $for[i;1;$mentionedCount;1] $if[$isUserDmEnabled[$mentioned[$for[i]]]==true] $sendDM[$mentioned[$for[i]];Reminder: meeting tomorrow at 14:00] $endif $endfor $sendMessage[✅ Reminders sent to the available members.] ``` ## Notes - DMs can be closed by user privacy settings. - The bot cannot force open a user's DMs. - To send a private message, use `$sendDM[]`. - If DMs are closed, `$sendDM[]` will fail silently. --- ### $isValidHex # $isValidHex The function `$isValidHex[value]` checks if a string is a valid hexadecimal color code in the format `#RRGGBB` (or `RRGGBB` without the hashtag). ## Syntax ``` $isValidHex[value] ``` ## Parameters | Parameter | Description | |---|---| | `value` | The string to test, with or without the `#` prefix. | ## Return Value - **Type**: Boolean - `true` if the string is a valid 6-character hexadecimal code (0-9, A-F). - `false` if the string contains invalid characters, is too short/long, or is empty. ## Behavior - Accepts `#RRGGBB` and `RRGGBB` (6 hexadecimal characters). - Letters are case-insensitive (A-F or a-f). - Does not validate short formats (`#FFF`). - Does not validate formats with alpha (`#RRGGBBAA`). ## Examples ### Validation before use ```bdfd $var[couleur;$message[1]] $if[$isValidHex[$var[couleur]]==true] $embedAddField[Color;$var[couleur];yes] $color[$var[couleur]] $sendMessage[✅ Embed with the color $var[couleur].] $else $sendMessage[❌ Invalid color. Expected format: #RRGGBB] $endif ``` ### Colored role command ```bdfd $var[couleur;$message[1]] $if[$isValidHex[$var[couleur]]==true] $modifyRole[$roleID[Color];color;$var[couleur]] $sendMessage[🎨 The color of the role was changed to $var[couleur]!] $else $sendMessage[❌ Invalid format. Example: !color #FF5733] $endif ``` ### Interactive palette ```bdfd $var[hex;$message[1]] $if[$isValidHex[$var[hex]]==true] $title[🎨 Color Preview] $description[**Hex:** $var[hex]] $color[$var[hex]] $addTimestamp[] $sendMessage[] $else $sendMessage[❌ Invalid hex format. Usage: !color #5865F2] $endif ``` ## Notes - `$isValidHex[#FF0000]` returns `true`. - `$isValidHex[ff0000]` returns `true`. - `$isValidHex[#FFF]` returns `false` (short format not supported). - `$isValidHex[#GG0000]` returns `false` (G is not hex). - `$isValidHex[]` (empty) returns `false`. --- ### $joinSplitText[] # $joinSplitText — Join Split Elements `$joinSplitText` recombines all elements from the current `$textSplit` result into a single string. It's the inverse operation of splitting — useful when you need to transform a split array back into a delimited string, often with a different separator. ## Syntax ``` $joinSplitText[separator] ``` ## Parameters - **separator** *(string, required)* — The string to place between each element. Pass an empty value `$joinSplitText[]` to concatenate with no separation. ## Return Value - **Type**: `string` - Returns the joined string. If `$textSplit` produced `N` elements, the result contains all `N` elements with `(N-1)` separators between them. - Returns an **empty string** if no split has been performed (split array is empty/missing). ## Usage ``` $textSplit[one;two;three;four;] $joinSplitText[-] → "one-two-three-four" $joinSplitText[, ] → "one, two, three, four" $joinSplitText[] → "onetwothreefour" $joinSplitText[ | ] → "one | two | three | four" ``` ## Common Patterns ## Changing Delimiters Transform a semicolon-delimited list into a comma-delimited one: ``` $textSplit[$getUserVar[data];;] $var[csv;$joinSplitText[,]] ``` ### Removing a Separator Concatenate all words without spaces: ``` $textSplit[$message; ] $var[compact;$joinSplitText[]] ``` ### Reordering Elements Modify a few elements, then rejoin: ``` $textSplit[$message; ] $editSplitText[0;Hello] $editSplitText[1;World] $sendMessage[$joinSplitText[ ]] ``` ## Important Notes - **Current split only**: `$joinSplitText` operates on the most recent `$textSplit` result. - **Respects modifications**: If elements were changed via `$editSplitText` or removed via `$removeSplitTextElement`, the joined result reflects those changes. - **Empty separator**: `$joinSplitText[]` with no argument produces a concatenated string with nothing between elements. --- ### $linesCount[] # $linesCount — Count Lines `$linesCount` returns the number of lines in a string. A line is defined as text terminated by a newline character (`\n`). Even a single word with no newline counts as 1 line. ## Syntax ``` $linesCount[text] ``` ## Parameters - **text** *(string, required)* — The text whose lines to count. ## Return Value - **Type**: `string` (representing a number) - Returns the line count. An empty string returns `"0"`. A string without newlines returns `"1"`. ## Usage ``` $linesCount[hello] → "1" $linesCount[line1\nline2] → "2" $linesCount[] → "0" ``` With actual newlines in code: ``` $linesCount[First line Second line Third line] → "3" ``` ## Common Patterns ### Limit Multi-Line Input ``` $if[$linesCount[$message]>10] $sendMessage[Your message has too many lines (max 10).] $stop $endif ``` ### Code Block Validation ``` $if[$linesCount[$getUserVar[code]]>50] $sendMessage[Code too long — max 50 lines.] $endif ``` ### Display Line Count ``` $sendMessage[Your submission: $linesCount[$message] lines, $charCount[$message] characters] ``` ## Important Notes - **Trailing newline**: A trailing `\n` may or may not create an additional empty line depending on the BDFD runtime. Test your specific version. - **Empty string = 0**: Different from a single non-empty line which returns `"1"`. - **Return type**: The return value is a string, compatible with numeric comparisons in `$checkCondition` and `$math`. --- ### $log[] # $log[] The function `$log[]` calculates the **natural logarithm** (denoted as `ln`), which is the logarithm in base `e` (≈ 2.71828). ## Syntax ``` $log[value] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|----------------------------------------------------| | `value` | number | Yes | The number whose logarithm to calculate. Must be > 0. | ## Behavior - Returns the natural logarithm of the value as a decimal number (double precision). - `$log[1]` → `0` (because e^0 = 1). - `$log[e]` → `1` (because e^1 = e). - For `0` or negative numbers, the behavior is undefined (may return `-Infinity`, `NaN` or generate an error). ## Examples **Logarithm of 1:** ``` $log[1] → 0 ``` **Logarithm of e (approx.):** ``` $log[2.718281828] → ~1 ``` **Logarithm of a large number:** ``` $log[1000] → 6.907755... ``` **Logarithm of a fraction:** ``` $log[0.5] → -0.693147... ``` ## Notes - This is the **natural** logarithm (base e), not the base 10 logarithm. - For base 10 logarithm, use inside `$calculate[]`: `$calculate[log10(value)]`. - For a logarithm in an arbitrary base, use the change of base formula: `log_b(a) = ln(a) / ln(b)`, which translates to `$calculate[log(a) / log(b)]`. - The inverse function is exponential: `$calculate[exp(value)]`. - The precision matches that of a Java `double` (~15 significant digits). --- ### $max[] # $max[] The function `$max[]` compares all provided values and returns the largest among them. It is variadic: it accepts an unlimited number of arguments. ## Syntax ``` $max[value1;value2;...] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|----------------------------------------------------------| | `values` | number | Yes | List of numeric values separated by `;`. Variadic. | ## Behavior - Scans all values and returns the largest. - Supports negative and decimal numbers. - With a single argument, returns that argument. - With zero arguments, the behavior is undefined (returns empty or 0). ## Examples **Simple maximum:** ``` $max[10;3] → 10 ``` **Multiple values:** ``` $max[5;12;3;8;1] → 12 ``` **With negative numbers:** ``` $max[-5;10;-2;0] → 10 ``` **High score:** ``` $max[$getVar[scoreP1];$getVar[scoreP2];$getVar[scoreP3]] ``` ## Notes - To find the lowest value, use `$min[]`. - For more complex comparisons, use `$calculate[max(a, b)]`. - The separator is the semicolon `;`. --- ### $min[] # $min[] The function `$min[]` compares all provided values and returns the smallest of them. It is variadic, meaning it accepts an unlimited number of arguments. ## Syntax ``` $min[value1;value2;...] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|----------------------------------------------------------| | `values` | number | Yes | List of numerical values separated by `;`. Variadic. | ## Behavior - Iterates through all values and returns the smallest one. - Supports negative and decimal numbers. - With a single argument, returns that argument. - With zero arguments, the behavior is undefined (returns empty or 0). ## Examples **Simple minimum:** ``` $min[10;3] → 3 ``` **Multiple values:** ``` $min[5;12;3;8;1] → 1 ``` **With negative numbers:** ``` $min[-5;10;-2;0] → -5 ``` **With decimal numbers:** ``` $min[2.5;1.1;3.9] → 1.1 ``` ## Notes - To find the largest value, use `$max[]`. - For more complex comparisons, use `$calculate[min(a, b)]`. - The separator is the semicolon `;`. --- ### $modulo[] # $modulo[] The function `$modulo[]` returns the remainder of the division of `a` by `b` (modulo operation: `a % b`). Like `$divide[]`, it is protected against division by zero. ## Syntax ``` $modulo[a;b] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|--------------------| | `a` | number | Yes | The dividend. | | `b` | number | Yes | The divisor. | ## Behavior - Returns the remainder of `a` divided by `b`. - If `b = 0`, returns `0` (built-in protection). - The result always has the same sign as the dividend `a`. ## Examples **Simple modulo:** ``` $modulo[17;5] → 2 ``` **Even/odd detection:** ``` $modulo[$getVar[number];2] → 0 if even, 1 if odd ``` **With exact multiples:** ``` $modulo[20;5] → 0 ``` **Modulo by zero (protected):** ``` $modulo[42;0] → 0 ``` ## Common Use Cases - Checking if a number is divisible by another. - Alternating behaviors (even/odd). - Cycling through a list (index % size). - Calculating cycles (every N iterations). ## Notes - For negative numbers, the behavior follows standard mathematical definitions: `$modulo[-17;5]` → `-2`. --- ### $multi[] # $multi[] The function `$multi[]` multiplies two values: `a * b`. > **Important Note:** This function is purely mathematical. For conditional branching, use `$if[]`, `$elseif[]`, and `$else[]`. ## Syntax ``` $multi[a;b] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|------------------------| | `a` | number | Yes | The first factor. | | `b` | number | Yes | The second factor. | ## Behavior - Returns the product `a * b`. - Supports decimal numbers. - If either argument is `0`, the result is `0`. ## Examples **Simple multiplication:** ``` $multi[6;7] → 42 ``` **With decimals:** ``` $multi[2.5;4] → 10 ``` **Calculating total price:** ``` $multi[$getVar[unitPrice];$getVar[quantity]] ``` **By zero:** ``` $multi[100;0] → 0 ``` ## Notes - Only supports two arguments. To multiply more values, nest them: `$multi[$multi[a;b];c]` or use `$calculate[a * b * c]`. - The separator is the semicolon `;`. --- ### $numberSeparator[] # $numberSeparator — Format Number with Commas `$numberSeparator` inserts thousands separators (commas) into a number to make it more human-readable. It handles integers and decimal values, leaving the decimal portion untouched. ## Syntax ``` $numberSeparator[number] ``` ## Parameters - **number** *(number or numeric string, required)* — The value to format. ## Return Value - **Type**: `string` - Returns the formatted number with commas. If the input is not a valid number, it may be returned unchanged. ## Usage ``` $numberSeparator[1000] → "1,000" $numberSeparator[50000] → "50,000" $numberSeparator[1234567890] → "1,234,567,890" $numberSeparator[999] → "999" $numberSeparator[1500.75] → "1,500.75" $numberSeparator[0] → "0" ``` ## Common Patterns ### Displaying Currency ``` $sendMessage[Your balance: $numberSeparator[$getUserVar[coins]] coins] ``` Output: `Your balance: 12,500 coins` ### Server Statistics ``` $sendMessage[Members: $numberSeparator[$membersCount]] ``` Output: `Members: 25,342` ### Scoreboards ``` $sendMessage[#$getTextSplitIndex - Score: $numberSeparator[$splitText]] ``` ### Experience Points ``` $sendMessage[Level $getUserVar[level] — XP: $numberSeparator[$getUserVar[xp]]] ``` ## Important Notes - **Decimal handling**: The decimal part (after `.`) is preserved as-is without separators. - **Negative numbers**: Formatting with negative sign is supported: `$numberSeparator[-5000]` → `"-5,000"`. - **Non-numeric input**: If the input cannot be parsed as a number, it is returned unchanged. - **Large numbers**: Handles arbitrarily large integers within BDFD's numeric limits. --- ### $random[] # $random[] The `$random[]` function generates a random integer between `min` and `max`, with both values being **inclusive**. **Important:** This function is evaluated at **compile-time**, meaning the value is determined once when the code is compiled. It will not change if the code is executed multiple times without recompilation. ## Syntax ``` $random[min;max] ``` ## Parameters | Parameter | Description | |-----------|-------------| | `min` | The lower bound of the random range (inclusive). | | `max` | The upper bound of the random range (inclusive). | ## Return Value A random integer as a string, between `min` and `max` (inclusive bounds). ## Behavior - Values are evaluated only once at the time of command compilation. - Both `min` and `max` bounds are inclusive in the possible range. - If `max` is less than `min`, the behavior may be unpredictable. ## Examples ### Random number between 1 and 100 ```bdfd $random[1;100] ``` ### Dice roll ```bdfd 🎲 You rolled a **$random[1;6]**! ``` ### Random selection in an embed ```bdfd $title[Prize draw] $description[The winning number is: **$random[1000;9999]**] $footer[🎉 Congratulations to the winner!] ``` ## Notes - Use `$randomString[]` to generate random alphanumeric strings. - Use `$randomText[]` to randomly choose from a list of text options. --- ### $randomCategoryID # $randomCategoryID The `$randomCategoryID` function returns the **Discord identifier (snowflake)** of a randomly selected category from all categories present on the server where the command is executed. ## Syntax ``` $randomCategoryID ``` > **Note:** This function takes no parameters. ## Parameters No parameters. ## Return Value - **Type**: String (Discord snowflake) - The ID of a random category on the current server. - Returns an empty string if the server has no categories. ## Behavior - The function selects a category **randomly** from all existing categories on the server. - The result changes on each call (non-deterministic). - Only **categories** (GUILD_CATEGORY type) are concerned, not text or voice channels. - If no category-type channel exists on the server, the function may return an empty value. ## Examples ### Mention a random category ```bdfd $title[🎲 Random category] $description[ Selected category: <#$randomCategoryID> **Name:** $channelName[$randomCategoryID] ] $color[#5865F2] $sendMessage[] ``` ### Random assignment ```bdfd $title[📂 Category assignment] $description[ You have been assigned to the **$channelName[$randomCategoryID]** category! ] $footer[ID: $randomCategoryID] $color[#57F287] $sendMessage[] ``` ### Existence check ```bdfd $let[cat;$randomCategoryID] $if[$get[cat]==] $title[⚠️ No categories] $description[This server has no categories.] $color[#ED4245] $else $title[✅ Category found] $description[Category: **$channelName[$get[cat]]** (ID: `$get[cat]`)] $color[#57F287] $endif $sendMessage[] ``` ## Notes - Use `$randomChannelID` to get a random channel ID (all types). - To list all categories, use `$categoryChannels[]`. - Returned IDs are **Discord snowflakes** (17-19 digit numeric strings). - The function is useful for games, random systems, or "roulette" type commands. --- ### $randomChannelID[] # $randomChannelID[] The `$randomChannelID[]` function returns the Discord ID of a random channel present on the server where the command is executed. ## Syntax ``` $randomChannelID ``` > **Note:** This function takes no parameters. ## Return Value The Discord ID (snowflake) of a random channel on the server, as a string. ## Examples ### Get a random channel ID ```bdfd Random channel ID: $randomChannelID ``` ### Mention a random channel ```bdfd Random channel: <#$randomChannelID> ``` ### Use as destination channel ```bdfd $sendMessage[$randomChannelID;Message sent to a random channel!] ``` ## Notes - The channel is chosen from all channels accessible to the bot on the server. - For text channels, you can use the ID with message sending functions. --- ### $randomGuildID[] # $randomGuildID[] The `$randomGuildID[]` function returns the Discord ID of a random server from all servers where the bot is present. ## Syntax ``` $randomGuildID ``` > **Note:** This function takes no parameters. ## Return Value The Discord ID (snowflake) of a random server, as a string. ## Examples ### Get a random server ID ```bdfd Random server ID: $randomGuildID ``` ### Get information about a random server ```bdfd $title[Random server] $description[Name: $serverName[$randomGuildID]] $addField[Members:;$membersCount[$randomGuildID]] ``` ## Notes - The server is chosen from all servers where the bot is present. - Each server has an equal probability of being selected. --- ### $randomMention[] # $randomMention[] The `$randomMention[]` function returns the formatted mention of a random user present on the server. The mention is in `<@id>` format, which creates a ping for the targeted user. ## Syntax ``` $randomMention ``` > **Note:** This function takes no parameters. ## Return Value The formatted mention (`<@id>`) of a random user on the server. ## Difference with similar functions | Function | Returns | |----------|---------| | `$randomMention` | `<@id>` — clickable mention with ping | | `$randomUser` | `id` — raw ID | | `$randomUserID` | `id` — raw ID | ## Examples ### Direct mention ```bdfd $randomMention, you have been chosen randomly! ``` ### Winner announcement ```bdfd $title[🎊 Prize draw] $description[Congratulations $randomMention! You win the giveaway!] $color[#FFD700] $footer[Good luck to everyone for the next draw] ``` ### Random tag ```bdfd Tag, it's your turn $randomMention! ``` ## Notes - The user receives a notification (ping) when mentioned. - Use `$randomUserID[]` if you do not want to ping the user. --- ### $randomRoleID[] # $randomRoleID[] The `$randomRoleID[]` function returns the Discord ID of a random role present on the server. ## Syntax ``` $randomRoleID ``` > **Note:** This function takes no parameters. ## Return Value The Discord ID (snowflake) of a random role on the server, as a string. ## Examples ### Get a random role ID ```bdfd Random role ID: $randomRoleID ``` ### Mention a random role ```bdfd Random role: <@&$randomRoleID> ``` ### Assign a random role ```bdfd $giveRole[$authorID;$randomRoleID] ``` ## Notes - The role is chosen from all roles on the server, including the `@everyone` role. - The bot must have the manage roles permission to use `$giveRole[]`. --- ### $randomString[] # $randomString[] The `$randomString[]` function generates a random alphanumeric character string of a given length. ## Syntax ``` $randomString[length] ``` ## Parameters | Parameter | Description | |-----------|-------------| | `length` | The length of the random string to generate (in number of characters). | ## Return Value A string of random alphanumeric characters containing: - Lowercase letters (a-z) - Uppercase letters (A-Z) - Digits (0-9) ## Examples ### Generate a unique identifier ```bdfd $title[Your session ID] $description[ID: `$randomString[8]`] $footer[Keep this identifier] ``` ### Verification code ```bdfd Your verification code is: **$randomString[6]** ``` ### Access token ```bdfd $randomString[32] ``` ## Use cases - Generating unique identifiers for tickets, sessions, or keys. - Creating verification codes or temporary passwords. - Generating random tokens. --- ### $randomText[] # $randomText[] The `$randomText[]` function randomly chooses an option from a list of provided text options and returns that option. ## Syntax ``` $randomText[option1;option2;...] ``` ## Parameters | Parameter | Description | |-----------|-------------| | `option1;option2;...` | List of text options separated by semicolons (`;`). | ## Return Value A string corresponding to one of the options in the list, chosen randomly. ## Behavior - Each option has an equal probability of being selected. - Options are separated by semicolons (`;`). - All characters are allowed in options, but be careful with the semicolon which acts as a separator. ## Examples ### Heads or Tails ```bdfd 🪙 The coin lands on: **$randomText[Heads;Tails]**! ``` ### Random color choice ```bdfd $title[Color of the day] $description[The color of the day is: **$randomText[Red;Blue;Green;Yellow;Purple;Orange;Pink]**] $color[$randomText[#FF0000;#0000FF;#00FF00;#FFFF00;#800080;#FFA500;#FF69B4]] ``` ### Random welcome message ```bdfd $randomText[ Welcome $username to the server! 🎉; Hey $username, glad to see you! 👋; $username just joined us! 🥳; A new adventurer, $username, has arrived! ⚔️ ] ``` ## Notes - To generate a random number, use `$random[]`. - To generate a random alphanumeric string, use `$randomString[]`. --- ### $randomUser[] # $randomUser[] The `$randomUser[]` function returns the ID of a random user present on the server where the command is executed. ## Syntax ``` $randomUser ``` > **Note:** This function takes no parameters. ## Return Value The Discord ID (snowflake) of a random user on the server, as a string. ## Examples ### Mention a random user ```bdfd Random user: <@$randomUser> ``` ### Announce a winner ```bdfd $title[🎉 Prize draw] $description[Congratulations <@$randomUser>! You won!] $color[#FFD700] ``` ### Get the ID only ```bdfd Random ID: $randomUser ``` ## Notes - The selected user is a member of the server. - The bot must have access to the member list for this function to work correctly. - To get only the ID without formatting, use `$randomUserID[]`. - For a direct mention (with the `<@id>` format), use `$randomMention[]`. --- ### $randomUserID[] # $randomUserID[] The `$randomUserID[]` function returns the Discord ID (snowflake) of a random user present on the server. ## Syntax ``` $randomUserID ``` > **Note:** This function takes no parameters. ## Return Value The Discord ID (snowflake) of a random user on the server, as a string. ## Difference with `$randomUser[]` `$randomUser[]` and `$randomUserID[]` return the same value: the user ID. The distinction is purely semantic. Use `$randomUserID[]` when you explicitly want to manipulate the ID. ## Examples ### Get a random ID ```bdfd Random user ID: $randomUserID ``` ### Store in a variable ```bdfd $let[winner;$randomUserID] The winner is: <@$get[winner]> ``` ## Notes - The user is chosen from the server members. - To directly mention the user, use `$randomMention[]`. --- ### $removeContains # $removeContains The `$removeContains[]` function **removes all occurrences** of a string in the text. It operates on the message text ($message) or the current text context. ## Syntax ``` $removeContains[text] ``` ## Parameters | Parameter | Description | |---|---| | `text` | The string to remove. | ## Return Value - **Type**: String - The text without the occurrences of the target string. ## Behavior - Case-sensitive. - Removes all occurrences, not just the first one. - Works on the user message or the text value in context. ## Examples ### Clean a message ```bdfd $sendMessage[Cleaned message: $removeContains[spam]] ; For a message "this is spam marketing" ; Result: "this is marketing" ``` ### Remove bad words ```bdfd $let[filtered;$removeContains[insult]] $sendMessage[Filtered message: $filtered] ``` ### Multiple cleanup ```bdfd $sendMessage[$removeContains[badword1]] $sendMessage[$removeContains[badword2]] ``` ## Notes - For a replacement (not removal), use `$replaceText[]`. - To remove only links, use `$removeLinks`. - To remove surrounding spaces, use `$trimContent[]`. --- ### $removeLinks # $removeLinks The `$removeLinks` function **removes all URLs** (http://, https://) from the message or current text. ## Syntax ``` $removeLinks ``` ## Parameters None. ## Return Value - **Type**: String - The text without any URLs. ## Behavior - Detects URLs starting with `http://` or `https://`. - Removes the entire URL, not just the protocol. - Works on the current text context (`$message`, `$input`, etc.). ## Examples ### Anti-spam cleanup ```bdfd $sendMessage[Cleaned message: $removeLinks] ; "Visit https://spam.com now" → "Visit now" ``` ### Secure echo command ```bdfd $let[safe;$removeLinks] $sendMessage[$safe] ``` ### Comparison and alert ```bdfd $if[$message!=$removeLinks] $sendMessage[⚠️ Your message contained links which have been removed.] $sendMessage[$removeLinks] $else $sendMessage[$message] $endif ``` ### Logs without links ```bdfd $channelSendMessage[123456789;Message from $username: $removeLinks] ``` ## Notes - To completely block links (not just remove them), use `$ignoreLinks`. - To remove other patterns, use `$removeContains[]`. - Does not remove Discord links (channel mentions, etc.). --- ### $removeSplitTextElement[] # $removeSplitTextElement — Remove Split Text Element `$removeSplitTextElement` deletes a single element from the current split text array. After removal, the array shrinks by one, and all subsequent elements shift down to fill the gap. ## Syntax ``` $removeSplitTextElement[index] ``` ## Parameters - **index** *(integer, required)* — The zero-based position of the element to remove. Negative indices are supported. ## Behavior - **Action-only**: This function modifies the split text array directly and does not return a value. - Elements after the removed one shift left by one position. - The total length decreases by 1. - Removing an out-of-bounds index has no effect. ## Usage ### Before and After ``` $textSplit[A;B;C;D;E;] $removeSplitTextElement[2] // Remove "C" Before: [A, B, C, D, E] (length: 5) After: [A, B, D, E] (length: 4) ``` Now `$splitText[2]` returns `"D"` instead of `"C"`. ### With Negative Index ``` $textSplit[one;two;three;four;] $removeSplitTextElement[-1] // Remove "four" $joinSplitText[ ] → "one two three" ``` ## Common Patterns ### Remove Known Value ``` $textSplit[$getUserVar[tags];,] $removeSplitTextElement[0] // Remove first tag $var[updatedTags;$joinSplitText[,]] ``` ### Clean Up Before Rejoining ``` $textSplit[$message; ] $removeSplitTextElement[0] // Remove command prefix $removeSplitTextElement[0] // Remove another prefix $var[args;$joinSplitText[ ]] ``` ### Filter First/Last ``` $textSplit[$message; ] $removeSplitTextElement[-1] // Drop last word $sendMessage[$joinSplitText[ ]] ``` ## Important Notes - **Index shift**: After removal, all higher indices shift down. If you need to remove multiple elements, work from highest index to lowest to avoid index corruption. - **Out-of-bounds**: Removing an invalid index silently does nothing. - **No return**: Do not use inline; it's an action function. - **Permanent for this execution**: The removal cannot be undone within the same command, but the original text is not permanently lost — it can be re-split from the source. --- ### $repeatMessage[] # $repeatMessage — Repeat a Message `$repeatMessage` sends the same message to the channel a specified number of times. It is an action function — it performs the sends directly without producing an inline return value. ## Syntax ``` $repeatMessage[count;message] ``` ## Parameters - **count** *(integer, required)* — How many times to send. Must be a positive integer. - **message** *(string, required)* — The content to send. Can include embeds, variables, and other functions. ## Behavior - **Action-only**: This function does not return a value. It sends messages to the channel as a side effect. - Each repetition is sent as a separate Discord message. - The function blocks until all messages are sent (subject to Discord rate limits). ## Usage ``` $repeatMessage[3;Hello World!] ``` Sends: ``` Hello World! Hello World! Hello World! ``` ## Common Patterns ### Spam Command (Use with Caution) ``` $repeatMessage[5;$username sent a message!] ``` ### Announcement Emphasis ``` $repeatMessage[3;$sendMessage[🎉 ATTENTION EVERYONE! 🎉]] ``` ### Testing ``` $repeatMessage[10;Test message $getTextSplitIndex] ``` ## Important Notes - **Rate Limits**: Discord enforces rate limits on message sending (typically 5 messages per 5 seconds per channel). Sending too many messages too quickly may cause the bot to be rate-limited or the command to fail. Use `$repeatMessage` sparingly. - **No return value**: Do not use `$repeatMessage` inside expressions or as arguments to other functions expecting a value. - **Best for small counts**: Stick to small `count` values (1–5). For larger counts, consider sending a single message with repeated content using `$joinSplitText` or a loop. - **Discord ToS**: Excessive message spamming may violate Discord's Terms of Service. Use responsibly. - **Channel context**: Messages are sent to the channel where the command was triggered. --- ### $replaceText[] # $replaceText — Replace Text `$replaceText` performs a global find-and-replace on a string. Every occurrence of the `search` substring is replaced with the `replacement` string. It is one of the most commonly used text manipulation functions in BDFD. ## Syntax ``` $replaceText[input;search;replacement] ``` ## Parameters - **input** *(string, required)* — The text to operate on. Can be a literal string, a variable, or any expression resolving to text. - **search** *(string, required)* — The exact substring to find. Case-sensitive. Matches are literal, not regex. - **replacement** *(string, required)* — The string to insert in place of each match. Pass an empty value to remove occurrences. ## Return Value - **Type**: `string` - Returns the modified text with all matches replaced. ## Evaluation Behavior `$replaceText` can be evaluated either at **compile-time** or **runtime**, depending on its arguments: - If all arguments are **static** (no variables or placeholders), replacement happens at compile time. - If any argument contains **placeholders** (e.g., `$message`, `$getUserVar[...]`), it is evaluated at **runtime**. ## Usage ### Basic Replacement ``` $replaceText[I like cats;cats;dogs] → "I like dogs" ``` ### Removal (empty replacement) ``` $replaceText[remove-all-dashes;-;] → "removealldashes" ``` ### Placeholder Cleanup ``` $replaceText[$getUserVar[bio];\n; ] ``` ### Chaining Replacements ``` $replaceText[$replaceText[$message;@;];#;] ``` This first removes all `@` characters, then all `#` characters. ## Common Patterns ### Censoring Words ``` $replaceText[$message;badword;\*\*\*\*] ``` ### Normalizing Input ``` $replaceText[$toLowercase[$message]; ; ] ``` Removes double spaces after lowercasing. ### Formatting for Display ``` $var[clean;$replaceText[$getUserVar[rawText];\n;, ]] ``` ## Important Notes - **Case-sensitive**: `$replaceText[Hello;h;H]` will NOT replace — `h` ≠ `H`. - **Global replacement**: All occurrences are replaced, not just the first. - **Literal only**: No regex support. The search string is matched exactly. - **Order matters in chaining**: Nest `$replaceText` calls carefully when doing multiple replacements, as earlier replacements may affect later ones. --- ### $round[] # $round[] The function `$round[]` rounds a number to the nearest integer according to standard rounding rules. ## Syntax ``` $round[value] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|----------------------------------| | `value` | number | Yes | The number to round. | ## Behavior - If the decimal part is **strictly less than .5**: rounds down. - If the decimal part is **greater than or equal to .5**: rounds up. - For an integer: returns the integer itself. ## Examples **Rounding up:** ``` $round[3.5] → 4 $round[3.6] → 4 $round[3.9] → 4 ``` **Rounding down:** ``` $round[3.4] → 3 $round[3.1] → 3 ``` **Negative number:** ``` $round[-3.4] → -3 $round[-3.6] → -4 ``` ## Comparison: floor / ceil / round | Value | $floor[] | $ceil[] | $round[] | |--------|----------|---------|----------| | `3.2` | `3` | `4` | `3` | | `3.5` | `3` | `4` | `4` | | `3.9` | `3` | `4` | `4` | | `-3.2` | `-4` | `-3` | `-3` | | `-3.5` | `-4` | `-3` | `-3`* | *The exact behavior for values ending in `.5` may depend on the underlying Java implementation (`Math.round`). ## Notes - The result is always an integer (in the form of a string). - Use `$floor[]` to always round down, and `$ceil[]` to always round up. - For finer control (number of decimal places), use `$calculate[]`. --- ### $sort[] # $sort — Sort Elements `$sort` takes a delimited list of values, sorts them, and returns them as a string using the same delimiter. It is primarily designed for numeric sorting but can be used with any comparable values. ## Syntax ``` $sort[separator;(direction)] ``` Wait — note the unusual syntax: `$sort` takes the **separator** as its first argument, not the data! The data is the **current spreads text** or must be set up beforehand. > **Common usage pattern**: Use `$textSplit` first to load the data, then `$sort` to sort it. ``` $textSplit[5;2;8;1;3;] $sort[;;(direction)] ``` Alternatively, `$sort` can operate on a delimited string directly: ``` $sort[5,2,8,1,3;,;(asc)] ``` ## Parameters - **separator** *(string, required)* — The delimiter separating the values. - **direction** *(string, optional)* — `"asc"` or `"ascending"` for ascending; `"desc"` or `"descending"` for descending. Default: **descending (numerical)**. ## Return Value - **Type**: `string` - Returns the sorted elements joined by the same separator. ## Usage ``` $sort[3,1,4,1,5;,;asc] → "1,1,3,4,5" $sort[z,y,x;,] → depends on implementation (default descending) $sort[100 10 1000; ;asc] → "10 100 1000" (numerical sort) ``` ## Common Patterns ### Sorting User-Provided Numbers ``` $textSplit[$message; ] $sendMessage[Sorted: $sort[ ;asc]] ``` ### Ranking Scores ``` $textSplit[$getUserVar[scores];,] $var[topScores;$sort[,;desc]] ``` ### Organizing Data for Display ``` $textSplit[$getUserVar[items];,] $sendMessage[Items (A-Z): $sort[,;asc]] ``` ## Important Notes - **Default is descending**: Unlike many sorting functions, BDFD's `$sort` defaults to descending order. - **Numerical sort**: Numbers are sorted numerically (`2` before `10`), which is the expected behavior. For alphabetical sorting, behavior may differ. - **Separator consistency**: The same separator is used for both input parsing and output joining. - **Works with spreads context**: Can operate on the current `$textSplit` result, using the separator to join the output. --- ### $splitText[] # $splitText — Access Spreads Element `$splitText` retrieves a single element from the array produced by the most recent `$textSplit` call. It is the primary way to access individual pieces of spreads text. ## Syntax ``` $splitText[index] ``` ## Parameters - **index** *(integer, required)* — The zero-based position of the element to retrieve. Negative indices are supported: `-1` returns the last element, `-2` the second-to-last, and so on. ## Return Value - **Type**: `string` - Returns the text content of the element at the specified index. - Returns an **empty string** `""` if the index is out of bounds (too large or too small). - No error or warning is emitted for out-of-bounds access — it silently returns empty. ## Usage `$splitText` only works after `$textSplit` has been called in the same command execution. Without a prior split, `$splitText` returns an empty string. ``` $textSplit[Hello World Foo Bar; ] $splitText[0] → "Hello" $splitText[2] → "Foo" $splitText[-1] → "Bar" $splitText[99] → "" (out of bounds) ``` ## Negative Indices Negative indices count backward from the end: | Spreads result | Index `-1` | Index `-2` | Index `-3` | |-------------|-----------|-----------|-----------| | `[A, B, C, D]` | `D` | `C` | `B` | This is useful for retrieving the last element without knowing the total length: ``` $textSplit[$message; ] $sendMessage[The last word you typed was: $splitText[-1]] ``` ## Common Patterns ### Access by Index ``` $textSplit[$getUserVar[list];,] $var[first;$splitText[0]] $var[last;$splitText[-1]] ``` ### Conditional Element Check ``` $textSplit[$message; ] $if[$splitText[0]==!help] $sendMessage[Help command detected!] $endif ``` ### Building Output from Multiple Elements ``` $textSplit[$message; ] $sendMessage[Args: 1=$splitText[0], 2=$splitText[1], 3=$splitText[2]] ``` ## Important Notes - **Depends on $textSplit**: `$splitText` is meaningless without a prior `$textSplit` call. It reads from the current spreads context. - **Silent out-of-bounds**: Accessing an invalid index returns `""` without error. Always validate with `$getTextSplitLength` if bounds are uncertain. - **No mutation**: `$splitText` is read-only. Use `$editSplitText` to modify elements. --- ### $sqrt[] # $sqrt[] The function `$sqrt[]` calculates the square root of a non-negative number. ## Syntax ``` $sqrt[value] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|------------------------------------------------| | `value` | number | Yes | The number to calculate the square root of. ≥ 0. | ## Behavior - Returns the square root of the value as a decimal number (double precision). - For perfect squares, the result is an integer: `$sqrt[16]` → `4`. - For other values, the result is a decimal number: `$sqrt[2]` → `1.4142135...`. - For `0`, it returns `0`. - For negative numbers, the behavior is undefined (may return `NaN` or an error). ## Examples **Perfect square:** ``` $sqrt[16] → 4 $sqrt[25] → 5 $sqrt[100] → 10 ``` **Non-integer root:** ``` $sqrt[2] → 1.4142135623730951 ``` **Root of zero:** ``` $sqrt[0] → 0 ``` **Hypotenuse calculation (Pythagorean theorem):** ``` $sqrt[$calculate[$getVar[a]^2 + $getVar[b]^2]] ``` ## Notes - Do not use with negative numbers. - For powers (squaring), use `$calculate[value^2]` or `$multi[value;value]`. - For other roots (cube root, etc.), use `$calculate[value^(1/3)]`. - The precision is that of a Java `double` (~15 significant digits). --- ### $sub[] # $sub[] The function `$sub[]` performs a subtraction between two values: `a - b`. ## Syntax ``` $sub[a;b] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|------------------------------------| | `a` | number | Yes | The starting value (minuend). | | `b` | number | Yes | The value to subtract (subtrahend). | ## Behavior - Returns `a - b`. - The result can be negative. - Supports decimal numbers. - If the values are not numerical, the behavior is undefined. ## Examples **Simple subtraction:** ``` $sub[10;3] → 7 ``` **Negative result:** ``` $sub[5;10] → -5 ``` **With decimals:** ``` $sub[10.5;3.2] → 7.3 ``` **Profit calculation:** ``` $sub[$getVar[revenue];$getVar[expense]] ``` ## Notes - Only two arguments are accepted. To subtract several values, nest the calls: `$sub[$sub[a;b];c]` or use `$calculate[a - b - c]`. - The separator is the semicolon `;`. --- ### $sum[] # $sum[] The function `$sum[]` adds up all numerical values passed to it. It is variadic, meaning it accepts an unlimited number of arguments. ## Syntax ``` $sum[value1;value2;...] ``` ## Parameters | Parameter | Type | Required | Description | |-----------|--------|-------------|----------------------------------------------------------| | `values` | number | Yes | List of numerical values separated by `;`. Variadic. | ## Behavior - Adds all values in the order they are provided. - If no value is passed, it returns `0`. - Non-numerical values are ignored or converted to `0` depending on the context. - Supports decimal numbers. ## Examples **Simple sum:** ``` $sum[5;10;15] → 30 ``` **With a single value:** ``` $sum[42] → 42 ``` **Without arguments:** ``` $sum[] → 0 ``` **In a practical context (cart total):** ``` $sum[$getVar[item1];$getVar[item2];$getVar[item3]] ``` ## Notes - The result is always a string of characters representing a number. - For more complex operations, use `$calculate[]`. - Semicolons `;` are required as separators. --- ### $textSplit[] # $textSpreads — Spreads Text into Array `$textSplit` splits a text string into multiple elements using a specified separator. The resulting array is stored internally and can be accessed through `$splitText[]`, iterated over, and manipulated with related text-spreads functions. ## Syntax ``` $textSplit[text;separator] ``` ## Behavior - **Action-only**: `$textSplit` is not an inline function. It performs an action (splitting) and stores the result. It does not produce output by itself. - The spreads result is stored in the **current text-spreads context**. Calling `$textSplit` again overwrites any previous split. - Spreads elements are 0-indexed: the first element is at index `0`. - The separator is case-sensitive and literal. It is not a regex. ## How It Works 1. The `text` parameter is spreads at every occurrence of `separator`. 2. The resulting elements are stored in an internal array. 3. Each element preserves its original content — no trimming or modification occurs. 4. The array persists for the duration of the command execution or until the next `$textSplit` call. ## Accessing Spreads Results After calling `$textSplit`, use the following functions to work with the spreads data: | Function | Description | |----------|------------| | `$splitText[index]` | Get the element at a specific index | | `$getTextSplitLength` | Get the total number of elements | | `$getTextSplitIndex` | Get the current index during iteration | | `$joinSplitText[separator]` | Join all elements with a new separator | | `$editSplitText[index;newValue]` | Modify one element | | `$removeSplitTextElement[index]` | Remove one element | ## Common Use Cases ### Splitting User Input ``` $textSplit[$message; ] $sendMessage[First word: $splitText[0]] ``` ### CSV Parsing ``` $textSplit[$getUserVar[data];,] $sendMessage[Column 3: $splitText[2]] ``` ### Multi-line Processing ``` $textSplit[$message; ] $sendMessage[You sent $getTextSplitLength lines] ``` ## Important Notes - **Overwrite behavior**: Each new `$textSplit` call replaces the previous split. If you need multiple splits, process one completeely before calling the next. - **Empty elements**: If the separator appears consecutively (e.g., `a;;b` with separator `;`), empty string elements are created. Plan your logic accordingly. - **No auto-trim**: Leading/trailing spaces in elements are preserved. Use `$trimSpace` on individual elements if needed. - **Memory**: The spreads array exists only for the current command execution. It is not persisted across commands or sessions. --- ### $toLowercase[] # $toLowercase — Convert to Lowercase `$toLowercase` transforms all uppercase characters in a string to their lowercase equivalents. It's commonly used to normalize user input for case-insensitive comparisons. ## Syntax ``` $toLowercase[text] ``` ## Parameters - **text** *(string, required)* — The string to convert. ## Return Value - **Type**: `string` - Returns the input text with all letters converted to lowercase. - Non-alphabetic characters (numbers, symbols, spaces) remain unchanged. ## Evaluation Behavior - **Static text** (no placeholders): Converted at compile time. - **Contains placeholders** (e.g., `$message`, variables): Evaluated at runtime. ## Usage ``` $toLowercase[HELLO] → "hello" $toLowercase[Hello] → "hello" $toLowercase[123 ABC] → "123 abc" $toLowercase[$message] → user's message in lowercase ``` ## Common Patterns ### Case-Insensitive Command Detection ``` $if[$toLowercase[$splitText[0]]==!ping] $sendMessage[Pong!] $endif ``` This matches `!ping`, `!PING`, `!Ping`, etc. ### Normalizing User Input for Storage ``` $setUserVar[name;$toLowercase[$message]] ``` ### Case-Insensitive Keyword Check ``` $if[$checkContains[$toLowercase[$message];help]==true] $sendMessage[Here's the help menu...] $endif ``` ## Important Notes - **Locale-independent**: Basic ASCII lowercasing is applied. Behavior with non-ASCII characters (accented letters, etc.) may vary. - **Only letters**: Digits, punctuation, and whitespace pass through unchanged. - **Combine with $replaceText**: Use `$toLowercase` before `$replaceText` for consistent matching. --- ### $toTitlecase[] # $toTitlecase — Convert to Title Case `$toTitlecase` capitalizes the first letter of every word and lowercases the rest. Words are delimitd by whitespace. This is useful for formatting names, titles, or display text. ## Syntax ``` $toTitlecase[text] ``` ## Parameters - **text** *(string, required)* — The string to convert to title case. ## Return Value - **Type**: `string` - Returns the text with each word's first character in uppercase and the rest in lowercase. ## Usage ``` $toTitlecase[hello world] → "Hello World" $toTitlecase[jOHN dOE] → "John Doe" $toTitlecase[THE GREAT GATSBY] → "The Great Gatsby" $toTitlecase[$message] → user message in title case ``` ## Common Patterns ### Formatting User Names ``` $setUserVar[displayName;$toTitlecase[$message]] ``` ### Displaying Stored Data Nicely ``` $sendMessage[Welcome, $toTitlecase[$getUserVar[name]]!] ``` ### Normalizing Database Entries ``` $var[city;$toTitlecase[$getUserVar[city]]] ``` Transforms `"new york"` → `"New York"`, `"LOS ANGELES"` → `"Los Angeles"`. ## Important Notes - **Word boundaries**: Words are separated by whitespace. Punctuation attached to words may affect capitalization. - **All subsequent letters are lowered**: `"mCDONALD"` → `"Mcdonald"`. For proper name casing, additional logic may be needed. - **ASCII only**: Non-ASCII character behavior depends on the BDFD runtime. --- ### $toUppercase[] # $toUppercase — Convert to Uppercase `$toUppercase` transforms all lowercase characters in a string to their uppercase equivalents. It's commonly used for emphasis, formatting codes, or case-insensitive comparisons. ## Syntax ``` $toUppercase[text] ``` ## Parameters - **text** *(string, required)* — The string to convert. ## Return Value - **Type**: `string` - Returns the input text with all letters converted to uppercase. - Non-alphabetic characters (numbers, symbols, spaces) remain unchanged. ## Evaluation Behavior - **Static text** (no placeholders): Converted at compile time. - **Contains placeholders** (e.g., `$message`, variables): Evaluated at runtime. ## Usage ``` $toUppercase[hello] → "HELLO" $toUppercase[Hello] → "HELLO" $toUppercase[123 abc] → "123 ABC" $toUppercase[$message] → user's message in uppercase ``` ## Common Patterns ### Code Formatting ``` $toUppercase[$getUserVar[promoCode]] ``` Ensures promo codes are stored and compared in uppercase. ### Emphasis ``` $sendMessage[$toUppercase[Warning: $message]] ``` ### Case-Insensitive Comparisons (Alternative) ``` $if[$toUppercase[$getUserVar[role]]==ADMIN] $sendMessage[Welcome, admin!] $endif ``` ## Important Notes - **Locale-independent**: Basic ASCII uppercasing is applied. Behavior with non-ASCII characters may vary. - **Only letters**: Digits, punctuation, and whitespace pass through unchanged. - **Often paired with $toLowercase**: Choose one convention and stick with it for comparisons. --- ### $trimContent # $trimContent The function `$trimContent[]` **removes leading and trailing spaces** from a string (trim). ## Syntax ``` $trimContent[text] ``` ## Parameters | Parameter | Description | |---|---| | `text` | The text to clean (leading/trailing spaces will be removed). | ## Return Value - **Type**: String - The text without leading or trailing spaces. ## Behavior - Does NOT affect spaces between words. - Removes spaces, tabs, and newlines at the beginning/end. - Very useful after extraction or concatenation. ## Examples ### Simple Cleaning ```bdfd $sendMessage[Result: "$trimContent[ Hello World ]"] ; Displays: Result: "Hello World" ``` ### Cleaning User Input ```bdfd $let[input;$trimContent[$message[2]]] $sendMessage[Cleaned argument: "$input"] ``` ### Comparison Without Spaces ```bdfd $if[$trimContent[$message[1]]==admin] $sendMessage[Mode admin enabled.] $endif ``` ### Cleaning After Extraction ```bdfd $let[extracted;$subString[$message;0;10]] $let[clean;$trimContent[$extracted]] $sendMessage[$clean] ``` ## Notes - More efficient than `$replaceText[text; ;]` because it only modifies the ends. - To remove all spaces (including internal ones), use `$replaceText[text; ;]`. - To preserve all spaces, use `$disableInnerSpaceRemoval`. --- ### $trimSpace[] # $trimSpace — Trim Whitespace `$trimSpace` strips leading and trailing whitespace characters from a string. Internal whitespace (between words) is preserved. This is essential for cleaning user input and normalizing data. ## Syntax ``` $trimSpace[text] ``` ## Parameters - **text** *(string, required)* — The string to trim. ## Return Value - **Type**: `string` - Returns the text with all leading and trailing whitespace removed. - Whitespace includes: spaces, tabs (`\t`), newlines (`\n`), and carriage returns (`\r`). ## Usage ``` $trimSpace[ hello ] → "hello" $trimSpace[ foo bar ] → "foo bar" $trimSpace[\n text\n] → "text" $trimSpace[ ] → "" (empty string) $trimSpace[$message] → user input with no accidental spacing ``` ## Common Patterns ### Sanitizing User Input ``` $var[clean;$trimSpace[$message]] $if[$var[clean]==] $sendMessage[Please type something!] $endif ``` ### Cleaning Variable Values ``` $setUserVar[name;$trimSpace[$message]] ``` Prevents storing `" John "` when the user types extra spaces. ### Before Validation ``` $var[input;$trimSpace[$toLowercase[$message]]] $if[$var[input]==!help] ...show help... $endif ``` ## Important Notes - **Preserves internal spaces**: Only leading and trailing whitespace is removed. `"hello world"` stays `"hello world"`. - **Empty result**: If the text is all whitespace, returns an empty string. - **Often combined**: Use `$trimSpace` with `$toLowercase` for robust input normalization. --- ### $unEscape # $unEscape The function `$unEscape[]` **converts escape sequences** (`\n`, `\t`, `\\`, etc.) into their real characters. ## Syntax ``` $unEscape[text] ``` ## Parameters | Parameter | Description | |---|---| | `text` | String containing escape sequences to resolve. | ## Return Value - **Type**: String - The text with escape sequences resolved. ## Supported Sequences | Sequence | Result | |---|---| | `\n` | Line break | | `\t` | Tab | | `\\` | Backslash | | `\"` | Double quote | | `\'` | Single quote | ## Examples ### Multi-line Text ```bdfd $sendMessage[$unEscape[Line 1\nLine 2\nLine 3]] ``` ### Message Formatted from a Variable ```bdfd $let[data;Name: John\nAge: 25\nCity: Paris] $sendMessage[$unEscape[$var[data]]] ``` ### Code with Quotes ```bdfd $sendMessage[$unEscape[He said: \"Hello!\" ]] ``` ### Embed with Formatted Description ```bdfd $title[Information] $description[$unEscape[**User:** $username\n**ID:** $authorID\n**Role:** $getRole[$authorID;1]]] $sendMessage[] ``` ## Notes - Do not confuse with `$disableSpecialEscaping` which disables BDFD interpretation. - Useful for formatting text stored in variables or databases. - To encode text for URLs, use `$urlEncode[]`. --- ## Meta ### Deployment & Hosting Bot Creator supports two deployment models: **managed hosting from the app** and **self-hosted Docker runners**. ## App hosting (recommended) Most teams should start here. 1. Download the [mobile or desktop app](/download/). 2. Create a bot token — [token setup guide](/getting-started/2025/05/18/how-to-create-a-bot-token-bot-creator/). 3. Design commands in the visual editor or JavaScript blocks. 4. Host directly from the app dashboard. The app handles uptime, reconnects, and monitoring without server administration. ## Docker runner (self-hosted) Use the Docker runner when you need: - A browser-based control panel on your own Linux server or Raspberry Pi - Persistent logs and state in mounted volumes - Long-lived remote runtime separate from mobile/desktop editing ### Quick start ```bash docker pull ghcr.io/ketsuna-org/bot-creator-runner:latest docker volume create bot-creator-data docker run -d --name bot-creator-runner \ -p 3000:3000 \ -v bot-creator-data:/data \ ghcr.io/ketsuna-org/bot-creator-runner:latest ``` Copy commands and version-specific flags from the [Download page](/download/#runner). ### Full runner guide The complete API and configuration reference is in the [Docker Runner (API only)](/guides/runner-docker-api-only/) guide, including: - Environment variables - Volume layout - HTTP API endpoints - Pairing with the mobile/desktop app ## Choosing a model | Need | Recommendation | |------|----------------| | Fast setup, mobile editing | App hosting | | Team on the go | App hosting | | Server you already manage | Docker runner | | Raspberry Pi / homelab | Docker runner | | Maximum uptime on your infra | Docker runner | ## Related documentation - [Getting started](/docs/getting-started/) — zero-to-first-command path - [Download](/download/) — app stores and runner setup - [Docker Runner guide](/guides/runner-docker-api-only/) — full self-host reference --- ### Events & Placeholders Bot Creator bots react to Discord events (messages, joins, button clicks) and resolve dynamic values through the `((...))` template system. ## Event-driven workflows Commands are not the only entry point. You can attach logic to Discord events such as: | Event family | Typical use | |--------------|-------------| | `messageCreate` | Auto-moderation, keyword triggers | | `guildMemberAdd` | Welcome messages, auto-roles | | `interactionCreate` | Buttons, select menus, modals, slash commands | | `voiceStateUpdate` | Voice channel logging | Configure events in the Bot Creator app under **Events**. Each event workflow runs in its own context with event-specific placeholders available. ## Placeholders `((...))` Placeholders insert runtime values into messages, embeds, and action parameters. They are resolved when the bot executes — not at design time. ```bdfd $sendMessage[Welcome ((user.username))! You joined ((guild.name)).] ``` ### Core placeholder families | Prefix | Examples | |--------|----------| | `((user.*))` | `((user.id))`, `((user.username))`, `((user.avatar))` | | `((member.*))` | `((member.nick))`, `((member.joinedAt))`, `((member.roles))` | | `((guild.*))` | `((guild.name))`, `((guild.memberCount))` | | `((channel.*))` | `((channel.id))`, `((channel.name))` | | `((message.*))` | `((message.content))`, `((message.id))` | | `((interaction.*))` | `((interaction.customId))`, `((interaction.kind))` | ## Interaction placeholders When a user clicks a button or submits a modal, interaction placeholders are populated automatically: ```bdfd $if[((interaction.kind))==button] $sendResponse[Clicked: ((interaction.customId)) // ephemeral] $endif ``` See [Interactions overview](/docs/interactions-overview/) for component-specific patterns. ## Full reference | Resource | Scope | |----------|-------| | [Template system](/docs/template-system/) | Complete `((...))` syntax, fallbacks, JSONPath, inline functions | | [Exhaustive event variables guide](/reference-deployment/2026/05/22/available-variables-per-event-exhaustive/) | Every variable per event type | | [JavaScript placeholders](/docs/javascript/placeholders/) | BDJS usage of `((...))` patterns | ## BDScript vs JavaScript - **BDScript:** placeholders work directly in `$sendMessage`, embed fields, and component payloads. - **JavaScript:** use template strings or read resolved values from the `variables` object. See [variables](/docs/javascript/variables/). ## Next steps 1. Register persistent variables in the app panel before using `$getUserVar` — see the [Database variables guide](/advanced-topics/2026/05/30/mastering-persistent-database-variables-in-bdfd/). 2. Build your first event workflow with [Create Your First Command](/getting-started/2026/03/12/how-to-create-a-command-in-bot-creator-step-by-step/). --- ### Getting Started Welcome to Bot Creator documentation. This page links the fastest path from zero to a running command. ## 1. Install Bot Creator Download the app for [mobile or desktop](/download/). Create a Discord application and bot token — see the [Create a Discord Bot Token](/getting-started/2025/05/18/how-to-create-a-bot-token-bot-creator/) guide. ## 2. Choose your scripting mode | Mode | When to use | Documentation | |------|-------------|---------------| | **Visual + BDScript** | Block editor, `$functions` | [BDFD Function Reference](/docs/) | | **BDJS (JavaScript)** | Full scripting power | [JavaScript API](/docs/javascript/) | Use [$scriptLanguage](/docs/scriptlanguage/) in BDScript to detect which mode is active. ## 3. Build your first command - **BDScript:** [Create a Command step-by-step](/getting-started/2026/03/12/how-to-create-a-command-in-bot-creator-step-by-step/) → [Perfect ping command](/getting-started/2026/05/30/how-to-create-a-perfect-ping-command-in-bdfd/) - **JavaScript:** Add a JavaScript block and use `interaction.reply('pong')` or `message.reply('pong')` ## 4. Persistent data - **BDScript:** `$getUserVar` / `$setUserVar` — see [Variables](/docs/#variables) and the [Database variables guide](/advanced-topics/2026/05/30/mastering-persistent-database-variables-in-bdfd/) - **JavaScript:** `await db.user.get()` / `await db.user.set()` — see [db.user](/docs/javascript/db-user/) ## 5. Deploy and monitor Host your bot from the app dashboard. For self-hosted runners, see [Deployment & hosting](/docs/deployment/) and the [Docker Runner API](/guides/runner-docker-api-only/) guide. ## Popular references - [Events & placeholders](/docs/events-and-placeholders/) — event-driven bots and `((...))` variables - [Interactions overview](/docs/interactions-overview/) — buttons, select menus, modals - [Handling rich interactions](/building-commands/2026/05/23/handling-rich-interactions-in-bot-creator-buttons-select-menus-modals/) — full walkthrough - [MCP server](/docs/mcp/) — AI tool integration for this documentation --- ### Interactions Overview Rich interactions let users tap buttons, pick from dropdowns, or fill modals instead of typing long command arguments. Bot Creator resolves these through the `interactionCreate` event. ## Interaction types | `((interaction.kind))` | Trigger | |------------------------|---------| | `command` | Slash command or context menu | | `button` | Button click | | `select` | Select menu choice | | `modal` | Modal form submission | | `autocomplete` | Slash option autocomplete | ## Core variables Every interaction exposes: | Variable | Description | |----------|-------------| | `((interaction.customId))` | Developer-defined ID on the component | | `((interaction.userId))` | User who triggered the interaction | | `((interaction.channelId))` | Channel ID | | `((interaction.guildId))` | Server ID (empty in DMs) | | `((interaction.messageId))` | Message holding the component | ## BDScript workflow ### 1. Build the UI Use component builders to attach elements to a message: - [$addButton](/docs/addbutton/) / [$addButtonCV2](/docs/addbuttoncv2/) - [$addStringSelect](/docs/addstringselect/) - [$newModal](/docs/newmodal/) ### 2. Handle the callback Route by `((interaction.customId))` in an event workflow: ```bdfd $if[((interaction.customId))==btn_verify] $sendResponse[Verified! // ephemeral] $endif ``` See [$sendResponse](/docs/sendresponse/) for direct interaction replies. ### 3. Read select values | Select type | Getter | |-------------|--------| | String select | [$getStringSelectValue](/docs/getstringselectvalue/) | | User select | [$getUserSelectUserId](/docs/getuserselectuserid/) | | Role select | [$getRoleSelectRoleId](/docs/getroleselectroleid/) | | Channel select | [$getChannelSelectChannelId](/docs/getchannelselectchannelid/) | ## JavaScript workflow In BDJS scripts, use the global `interaction` object: ```javascript if (interaction.isButton()) { await interaction.reply({ content: 'Clicked!', ephemeral: true }); } ``` See [Components](/docs/javascript/components/) and [interaction](/docs/javascript/interaction/). ## Slash commands Slash commands are interactions too. Read options with [$slashOption](/docs/slashoption/) in BDScript or `interaction.options.getString()` in JavaScript. For slow commands, call [$defer](/docs/defer/) first to avoid Discord's 3-second timeout. ## Guides | Guide | Topics | |-------|--------| | [Handling rich interactions](/building-commands/2026/05/23/handling-rich-interactions-in-bot-creator-buttons-select-menus-modals/) | Buttons, selects, modals, autocomplete | | [Building interactive buttons and select menus](/building-commands/2026/05/30/building-interactive-buttons-and-select-menus-in-bdfd/) | Role assignment patterns | ## Function reference Browse the [Components & Interactions](/docs/#components-interactions) category for all builder and getter functions. --- ### Mcp # MCP Server Bot Creator exposes its documentation and blog posts through a **Model Context Protocol (MCP)** server. Any MCP-compatible client (opencode, Claude Desktop, Cursor, custom tooling) can connect to query function docs and posts programmatically. ## Endpoint ``` https://bot-creator.fr/api/mcp ``` - **Protocol:** [MCP 2025-11-25](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports) - **Transport:** Streamable HTTP, stateless mode - **Auth:** None (read-only public content) ## Available tools | Tool | Description | |------|-------------| | `search_docs` | Search function docs by name, slug, or category. Returns matches with their slugs. | | `get_doc` | Fetch the raw markdown of a function doc by slug (e.g. `sendmessage`). | | `list_posts` | List blog posts, optionally filtered by `locale` (`en` / `fr`). | | `search_posts` | Search blog posts by title or description. | | `get_post` | Fetch the raw markdown of a blog post by slug (e.g. `image-creation-canvas-functions-in-bdfd`). | ## Quick example (curl) ```bash # 1. Initialize the session curl -X POST https://bot-creator.fr/api/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"demo","version":"0"}}}' # 2. Search docs curl -X POST https://bot-creator.fr/api/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_docs","arguments":{"query":"canvas"}}}' # 3. Read a doc curl -X POST https://bot-creator.fr/api/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_doc","arguments":{"slug":"sendmessage"}}}' ``` ## Connect from opencode Add this to your project's `opencode.json` (or `~/.config/opencode/opencode.json`): ```json { "$schema": "https://opencode.ai/config.json", "mcp": { "vitrine": { "type": "remote", "url": "https://bot-creator.fr/api/mcp", "enabled": true } } } ``` Restart opencode and the `vitrine` server will appear with its five tools. ## Discovery A discovery manifest is published at [`/.well-known/mcp.json`](/.well-known/mcp.json). Note: a ratified standard for MCP server discovery does not exist yet (the [Server Card Working Group](https://modelcontextprotocol.io/community/working-groups/server-card.md) is still chartered), so this file is currently informational. --- ### Template System — ((...)) Placeholders & Functions # Template System — `((...))` Placeholders Placeholders let you insert dynamic values into messages, embeds, and action parameters. They are resolved at runtime — when your bot actually runs the command or workflow. ## Basic syntax ``` ((variableName)) ``` Anything wrapped in `((` `))` is treated as a placeholder and replaced with the actual value at execution time. **Examples:** ```text Hello ((userName)), welcome to ((guild.name))! ``` If `userName` is "Alice" and `guild.name` is "My Server", the message becomes: ```text Hello Alice, welcome to My Server! ``` ## Where placeholders work Placeholders are resolved in: - Message content (`$sendMessage`, `$reply`, `$dm`) - Embed fields (title, description, footer, author, fields) - Button labels and select menu options - Modal titles and text inputs - Action parameters that accept dynamic values ## Available variables Bot Creator provides a rich set of runtime variables. Here are the most commonly used: ### Context | Variable | Description | |----------|-------------| | `((userId))` | ID of the user who triggered the command | | `((userName))` | Username of the triggering user | | `((guildId))` | ID of the current server | | `((guild.name))` | Name of the current server | | `((channelId))` | ID of the current channel | | `((channel.name))` | Name of the current channel | | `((messageId))` | ID of the triggering message | ### Bot | Variable | Description | |----------|-------------| | `((bot.id))` | Bot's user ID | | `((bot.username))` | Bot's username | | `((bot.guildCount))` | Number of servers the bot is in | | `((bot.ping))` | Bot's latency in milliseconds | | `((bot.uptime))` | Time since the bot started (formatted HH:MM:SS) | ### Time | Variable | Description | |----------|-------------| | `((getTimestamp))` | Current Unix timestamp (seconds) | | `((getTimestampMs))` | Current Unix timestamp (milliseconds) | | `((date))` | Current date as `YYYY-MM-DD` | | `((time))` | Current time as `HH:MM:SS` | | `((day))` | Current day of month | | `((month))` | Current month | | `((year))` | Current year | | `((hour))` | Current hour (UTC) | | `((minute))` | Current minute (UTC) | | `((second))` | Current second (UTC) | ### Scoped variables When you use `$setUserVar`, `$setServerVar`, etc., the stored values are accessible as placeholders: ```text ((global.myKey)) — global variable ((guild.bc_mySetting)) — server-scoped variable ((user.bc_myScore)) — user-scoped variable ((channel.bc_config)) — channel-scoped variable ``` --- ## Fallback values with `|` Use `|` to provide a fallback when a variable is not set: ```text ((target.user.username | userName)) ((channel.topic | "No topic set")) ((guild.description | "No description")) ``` The engine tries each value from left to right. The first one that exists is used. If nothing matches, the result is an empty string. --- ## JSONPath access When a variable contains JSON (e.g. from `$httpGet`), use `.$` followed by a path to extract nested values: ```text ((httpRequest.body.$.data)) ((query.items.$[0].name)) ((global.settings.$.channels.logs)) ``` **Path segments:** - `.field` — access an object property - `[0]` — access an array index - `$` — the root of the JSON document **Examples:** ```text # From an HTTP response containing {"items":[{"name":"Alice"},{"name":"Bob"}]} ((search.body.$.items[0].name)) → Alice ((search.body.$.items[1].name)) → Bob ``` --- ## Template functions — parentheses syntax Template functions use `functionName(arg1, arg2, ...)` with comma-separated arguments. ### Text functions | Function | Description | Example | |----------|-------------|---------| | `lowercase(text)` | Converts to lowercase | `((lowercase(userName)))` | | `uppercase(text)` | Converts to UPPERCASE | `((uppercase(userName)))` | | `titlecase(text)` | Converts to Title Case | `((titlecase(channelName)))` | | `trim(text)` | Removes leading/trailing spaces | `((trim(userInput)))` | | `replace(text, old, new)` | Replaces all occurrences | `((replace(title, "_", " ")))` | | `contains(text, needle)` | Returns `"true"` if found (case-insensitive) | `((contains(role, "admin")))` | | `charcount(text)` | Number of characters (alias: `length`) | `((charcount(userName)))` | | `linescount(text)` | Number of lines | `((linescount(description)))` | | `split(text, sep, index?)` | Splits and optionally gets one part | `((split(tags, ",", 0)))` | | `croptext(text, max, suffix?)` | Truncates text, adds suffix | `((croptext(bio, 100, "...")))` | | `numberseparator(num, sep?)` | Formats number with thousands separator | `((numberseparator(memberCount, " ")))` | | `url(mode, text)` | URL-encodes or decodes text | `((url("encode", rawText)))` | | `bytecount(text)` | Number of UTF-8 bytes | `((bytecount(message)))` | **Aliases:** - `lower` = `lowercase`, `tolowercase` (bracket: `[tolowercase]`) - `upper` = `uppercase`, `touppercase` (bracket: `[touppercase]`) - `title` = `titlecase`, `totitlecase` (bracket: `[totitlecase]`) - `charcounts` = `charcount` (bracket: `[charcount]`) ### Array / list functions These work on JSON arrays (e.g. HTTP responses, stored lists). | Function | Description | Example | |----------|-------------|---------| | `length(array)` | Number of elements | `((length(query.items.$)))` | | `at(array, index)` | Element at position | `((at(query.items.$, 0)))` | | `first(array)` | First element | `((first(query.items.$)))` | | `last(array)` | Last element | `((last(query.items.$)))` | | `slice(array, start, end?)` | Sub-array | `((slice(tags.$, 1, 3)))` | | `join(array, separator)` | Joins elements into a string | `((join(tags.$, ", ")))` | | `sum(array)` | Sum of numeric elements | `((sum(scores.$)))` | **Note:** `slice()` also works on strings: `((slice("hello", 1, 4)))` → `"ell"`. `sum()` also accepts multiple arguments: `((sum(10, 20, 30)))` → `60`. ### Formatting functions | Function | Description | |----------|-------------| | `formatEach(array, template, separator)` | Formats each item with a template | | `embedFields(array, nameTemplate, valueTemplate, inline?)` | Generates embed field JSON | **formatEach example:** ```text ((formatEach(search.body.$.items, "{name} ({score})", "\n"))) ``` If items is `[{"name":"Alice","score":12}, {"name":"Bob","score":7}]`, this produces: ```text Alice (12) Bob (7) ``` Item placeholders within the template: - `{value}` — the item itself (for scalar arrays) - `{field}` — a top-level property - `{field.subField}` — a nested property ### Media functions | Function | Description | Example | |----------|-------------|---------| | `avatar(url, format?, size?)` | Reformats a Discord avatar URL | `((avatar(userAvatar, "png", 256)))` | | `banner(url, format?, size?)` | Reformats a Discord banner URL | `((banner(userBanner, "webp", 1024)))` | **Parameters:** - `format` — `"webp"` (default), `"png"`, `"jpg"`, or `"gif"` (animated only) - `size` — power of 2 from 16 to 4096 (default 1024) ### Random functions | Function | Description | Example | |----------|-------------|---------| | `coin()` | Random `"true"` or `""` | `((coin()))` | | `random()` | Alias for `coin()` | `((random()))` | | `randomchoice(a, b, ...)` | Picks one argument at random | `((randomchoice("Yes", "No", "Maybe")))` | | `randomint(min, max)` | Random integer in `[min, max]` | `((randomint(1, 100)))` | | `randomtext(a, b, c)` | Picks one at random (bracket variant) | `[randomtext;Heads;Tails]` | **Notes:** - Use `coin()` when you need a true/false condition (returns `"true"` or empty). - Use `randomchoice()` to pick from a list of options inline. - Use `randomint()` for numeric random values. - If you need to **store** a random result and reuse it across multiple actions, use the `$calculate[random...]` action instead. --- ## Template functions — bracket syntax Bracket-syntax functions use `functionName[arg1;arg2;...]` with semicolon-separated arguments. These are typically used for math, logic, and system queries. ### Math functions | Function | Description | Example | |----------|-------------|---------| | `calculate[expr]` | Evaluates a math expression | `[calculate;5 * (2 + 3)]` → `25` | | `ceil[num]` | Rounds up to nearest integer | `[ceil;3.2]` → `4` | | `floor[num]` | Rounds down to nearest integer | `[floor;3.8]` → `3` | | `round[num]` | Rounds to nearest integer | `[round;3.5]` → `4` | | `sqrt[num]` | Square root | `[sqrt;16]` → `4` | | `max[a;b]` | Larger of two numbers | `[max;42;17]` → `42` | | `min[a;b]` | Smaller of two numbers | `[min;42;17]` → `17` | | `modulo[a;b]` | Remainder after division | `[modulo;10;3]` → `1` | | `multi[a;b]` | Multiplication | `[multi;6;7]` → `42` | | `divide[a;b]` | Division | `[divide;10;2]` → `5` | | `sub[a;b]` | Subtraction | `[sub;10;3]` → `7` | | `sum[a;b;c]` | Sum of multiple numbers | `[sum;1;2;3;4]` → `10` | | `random[min;max]` | Random integer in `[min, max]` | `[random;1;100]` | **Note:** Use `calculate[]` for complex expressions with variables: `[calculate;((userVarBalance)) * 1.2]`. ### Logic functions | Function | Description | Example | |----------|-------------|---------| | `checkcondition[expr]` | Evaluates a comparison expression | `[checkcondition;((age))>=18]` → `"true"` or `"false"` | | `and[cond1;cond2;...]` | True if ALL conditions are true | `[and;((a))>=10;((b))>=5]` | | `or[cond1;cond2;...]` | True if ANY condition is true | `[or;((role))==admin;((role))==mod]` | **checkcondition operators:** | Operator | Meaning | |----------|---------| | `>=` | Greater or equal | | `<=` | Less or equal | | `==` | Equals | | `!=` | Not equals | | `>` | Greater than | | `<` | Less than | | `contains` | String contains (case-insensitive) | | `notContains` | String does not contain | | `startsWith` | String starts with | | `endsWith` | String ends with | **Examples:** ```text # Numeric comparison [checkcondition;((hour))>=12] → "true" if it's PM, "false" if AM # String comparison [checkcondition;((userName))==Alice] → "true" if the user is Alice # Combined with and/or [and;[checkcondition;((score))>=50];[checkcondition;((level))>=10]] → "true" if both conditions pass ``` ### Utility functions | Function | Description | Example | |----------|-------------|---------| | `date[]` | Current date as `YYYY-MM-DD` | `[date]` → `2026-06-19` | | `trimcontent[text]` | Removes spaces (alias: `trimspace`) | `[trimcontent; hello ]` → `hello` | | `charcount[text]` | Character count (bracket variant) | `[charcount;hello]` → `5` | | `linescount[text]` | Line count (bracket variant) | `[linescount;((description))]` | | `croptext[text;max;suffix?]` | Truncates text with suffix | `[croptext;((bio));50;...]` | | `bytecount[text]` | UTF-8 byte count | `[bytecount;((message))]` | | `url[mode;text]` | URL encode/decode | `[url;encode;hello world]` → `hello%20world` | | `tolowercase[text]` | Lowercase (bracket variant) | `[tolowercase;HELLO]` → `hello` | | `touppercase[text]` | Uppercase (bracket variant) | `[touppercase;hello]` → `HELLO` | | `totitlecase[text]` | Title case (bracket variant) | `[totitlecase;hello world]` → `Hello World` | | `randomtext[choice1;choice2;...]` | Picks one at random | `[randomtext;Yes;No;Maybe]` | | `listvar[separator?]` | Lists all variable names | `[listvar;, ]` | | `userperms[userId?;amount?;sep?]` | Lists user's permissions | `[userperms;((author.id));5;, ]` | | `servernames[amount?;sep?]` | Lists server names | `[servernames;10;, ]` | | `variablescount[type]` | Counts variables by scope | `[variablescount;global]` | **`variablescount` scope values:** `global`, `user`, `guild` (or `server`), `channel`. --- ## Complete examples ### Welcome message ```text Welcome ((userName)) to ((guild.name))! We now have ((bot.guildCount)) members. ``` ### User info with fallbacks ```text **Author:** ((author.username | userName)) **ID:** ((author.id | userId)) **Avatar:** ((avatar(author.avatar, "png", 256))) ``` ### HTTP response formatting ```text **First result:** ((search.body.$.items[0].name)) **All results:** ((formatEach(search.body.$.items, "- {name}", "\n"))) ``` ### Embed with dynamic fields ```json { "title": "Leaderboard", "fieldsTemplate": "((embedFields(scores.$, \"{name}\", \"{score}\", true)))" } ``` ### Title case with bracket syntax ```text ((titlecase(channel.name))) — parentheses syntax [totitlecase;((channel.name))] — bracket syntax equivalent ``` ### Conditional with coin ```text $if[$checkCondition[((coin()))==true]] You won the coin flip! $else Better luck next time! $endif ``` ### Math with variables ```text Your balance with 20% bonus: [calculate;((userVarBalance)) * 1.2] ``` ### Combined logic check ```text [and;[checkcondition;((score))>=50];[checkcondition;((level))>=10]] ``` ### URL encoding ```text Search URL: https://google.com/search?q=[url;encode;((searchTerm))] ``` ### Count variables ```text You have [variablescount;user] user variables set. ``` --- ## Important behaviors | Situation | Result | |-----------|--------| | Variable exists | Resolved value | | Unknown variable | `""` (empty string) | | Fallback with a match | First matching value | | JSONPath not found | `""` | | Invalid JSON | `""` | | Unknown function | `""` | | Array/object as final value | JSON-serialized string | | Embed URL without scheme | Field silently ignored | --- ## Best practices - Use `formatEach()` to turn JSON arrays into readable text - Use `embedFields()` to dynamically build embed fields from data - Use `|` only for fallback, not for data transformation - Use `coin()` for true/false conditions (not `random()`) - When you need to **store and reuse** a random value, use the `$calculate` action with `random`, `randomFloat`, or `randomString` operations - For complex math, use `calculate[]` — it evaluates full expressions with support for parentheses and all standard operators - For HTTP responses that return arrays of objects, prefer `formatEach()` over manual indices: ```text # Good ((formatEach(items.$, "{name}", ", "))) # Avoid ((items.$[0].name)), ((items.$[1].name)), ((items.$[2].name)) ``` - Use bracket syntax (`[func;arg1;arg2]`) for math, logic, and system functions; use parentheses syntax (`func(arg1, arg2)`) for text and array manipulation --- ## Misc ### Endloop # $endLoop Marks the end of a `$loop` block. ## Syntax ``` $endLoop ``` ## Parameters This function has no parameters. ## Description `$endLoop` is the closing tag for a loop block opened with `$loop[iterations]`. Everything between `$loop[...]` and `$endLoop` is the loop body and will be repeated the specified number of times. Every `$loop` **must** be paired with exactly one `$endLoop`. Forgetting to close a loop results in a parse error. ## Examples ### Basic Loop ``` $loop[3] This message repeats 3 times. $endLoop ``` ### Loop with Inner Logic ``` $var[total;0] $loop[5] $var[total;$sum[$total;10]] $endLoop Total: $total ``` **Output:** `Total: 50` ### Nested Loops ``` $loop[2] Row: $loop[3] - Item $endLoop $endLoop ``` **Output:** ``` Row: - Item - Item - Item Row: - Item - Item - Item ``` ## Notes - `$endLoop` takes no parameters — adding any will cause a parse error. - This closes only the legacy `$loop` block, **not** the `$for` loop (which uses `$endFor`). - The parser treats `$loop` / `$endLoop` as structural tokens, similar to `$if` / `$endif`. - When nesting loops, ensure each `$loop` has its corresponding `$endLoop` in the correct order (LIFO: Last In, First Out). --- ### Error # $error Generates a custom error that stops the command execution with the provided message. ## Syntax ``` $error[message] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `message` | The error message to display | Yes | ## Description `$error` stops the execution of the current command immediately and displays a custom error message to the user. This is useful when you want to interrupt a command under certain conditions with a clear, descriptive message. Unlike `$stop` which silently stops execution, `$error` explicitly signals that something went wrong and provides feedback. ## Examples ### Missing parameter ``` $if[$message==] $error[❌ Please provide a message.] $endif $sendMessage[$message] ``` ### Invalid value ``` $if[$isNumber[$message]!=true] $error[❌ The provided value must be a number.] $endif $sendMessage[Valid number: $message] ``` ### Permission check ``` $if[$checkContains[$userPerms;BanMembers]!=true] $error[❌ You need the Ban Members permission to use this command.] $endif $ban[$mentioned[1]] $sendMessage[User banned.] ``` ### Conditional validation ``` $var[age;$message] $if[$var[age]<18] $error[❌ You must be at least 18 years old.] $endif $sendMessage[Access granted.] ``` ## Notes - `$error` immediately stops command execution; no code after it will run. - For silent stops without a message, use `$stop`. - The error message can contain emojis, mentions, and formatting. - Useful for input validation and permission checks. --- ### Func # $func Defines a reusable user-defined function that can be called later with `$funcCall`. Functions must be closed with `$funcEnd`. ## Syntax ``` $func[name;param1;param2;...] ...body... $funcEnd ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `name` | Unique name for the function | Yes | | `param1`, `param2`, ... | Parameter names accessible via `$funcArg[name]` inside the body | No | ## Description The `$func` system lets you define **reusable blocks of code** — similar to functions in programming. Define a function once with `$func[name;params...]...$funcEnd`, then call it anywhere in your command with `$funcCall[name;args...]`. Inside the function body: - Access parameters with `$funcArg[paramName]` - Return a value early with `$funcReturn[value]` - If no `$funcReturn` is used, the accumulated text content of the body is returned - Functions are **compile-time**: the body is expanded inline at each call site - Recursion is blocked (max depth: 10) ## Examples ### Simple function with $funcReturn ``` $func[greet;name] $funcReturn[Hello $funcArg[name]!] $funcEnd $sendMessage[$funcCall[greet;World]] ``` Output: `Hello World!` ### Function without $funcReturn (text body) ``` $func[wave;who] Waving at $funcArg[who]... $funcEnd $sendMessage[$funcCall[wave;Alice]] ``` Output: `Waving at Alice...` ### Multiple parameters ``` $func[add;a;b] $funcReturn[$funcArg[a] + $funcArg[b]] $funcEnd $sendMessage[Result: $funcCall[add;10;20]] ``` Output: `Result: 10 + 20` ### Multiple calls ``` $func[tag;val] $funcReturn[<$funcArg[val]>] $funcEnd $sendMessage[$funcCall[tag;a] $funcCall[tag;b] $funcCall[tag;c]] ``` Output: ` ` ## Notes - Functions must be defined **before** they are called - Function names are case-insensitive - Nested `$func` definitions are supported - Max recursion depth is 10 calls — exceeding this triggers a warning and returns empty string - Parameter names become local variables inside the function body - `$funcArg` is only valid inside a function call context --- ### Funcarg # $funcArg Retrieves the value of a parameter passed to a user-defined function. Only valid inside a `$func[...]...$funcEnd` block. ## Syntax ``` $funcArg[paramName] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `paramName` | Name of the parameter (as declared in `$func[name;p1;p2;...]`) | Yes | ## Description `$funcArg` gives you access to the arguments passed when a user-defined function is called via `$funcCall`. Each parameter name must match one of the names declared in the function's `$func[...]` header. The value is resolved from the caller's scope, so it can contain BDFD variables, inline functions, or runtime placeholders. ## Examples ### Access by name ``` $func[welcome;user] $funcReturn[Welcome, $funcArg[user]!] $funcEnd $sendMessage[$funcCall[welcome;$username]] ``` ### Multiple parameters ``` $func[format;label;value] **$funcArg[label]:** $funcArg[value] $funcEnd $sendMessage[$funcCall[format;Score;100]] ``` Output: `**Score:** 100` ### With calculations ``` $func[double;x] $funcReturn[$calculate[$funcArg[x] * 2]] $funcEnd $sendMessage[$funcCall[double;21]] ``` Output: `42` ## Notes - Only valid inside a `$func` body called via `$funcCall` - Outside a function context, `$funcArg` returns an empty string - Parameter names are case-insensitive --- ### Funccall # $funcCall Calls a user-defined function previously declared with `$func[name;...]`. The call is expanded inline at compile-time. ## Syntax ``` $funcCall[funcName;arg1;arg2;...] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `funcName` | Name of the function to call (must match a `$func` definition) | Yes | | `arg1`, `arg2`, ... | Arguments passed to the function's parameters | No | ## Description `$funcCall` invokes a user-defined function. The function body is expanded **at compile-time** — all text, inline functions, and `$funcArg` references are resolved and inserted at the call site. If the function uses `$funcReturn`, that value becomes the result. Otherwise, the accumulated text content of the function body is used. ## Examples ### Basic call with return ``` $func[greet;name] $funcReturn[Hello $funcArg[name]!] $funcEnd $sendMessage[$funcCall[greet;World]] ``` ### Call with runtime placeholders ``` $func[say;msg] $funcReturn[You said: $funcArg[msg]] $funcEnd $sendMessage[$funcCall[say;$username]] ``` At runtime: `You said: ` ### Chaining calls ``` $func[wrap;x] $funcReturn[[$funcArg[x]]] $funcEnd $func[bracket;v] $funcReturn[{$funcArg[v]}] $funcEnd $sendMessage[$funcCall[wrap;$funcCall[bracket;hello]]] ``` Output: `[{hello}]` ### Calling an undefined function ``` $sendMessage[$funcCall[notfound;test]] ``` Returns empty string with a diagnostic warning. ## Notes - The function must be defined **before** the call - Calls are resolved at compile-time — not at runtime - Max recursion depth: 10 calls - If the function is not found, returns an empty string and emits a diagnostic --- ### Funcend # $funcEnd Marks the end of a user-defined function block started with `$func[...]`. ## Syntax ``` $funcEnd ``` ## Parameters None. ## Description `$funcEnd` closes a function definition. Every `$func[name;params...]` must be paired with a matching `$funcEnd`. The parser treats everything between `$func[...]` and `$funcEnd` as the function body. Nested `$func` definitions are supported — each inner `$func` must have its own `$funcEnd`. ## Examples ### Basic definition ``` $func[greet;name] $funcReturn[Hello $funcArg[name]!] $funcEnd ``` ### Multiple functions ``` $func[one] One $funcEnd $func[two] Two $funcEnd $sendMessage[$funcCall[one] $funcCall[two]] ``` Output: `One Two` ### Nested functions ``` $func[outer] $func[inner;x] $funcReturn[<$funcArg[x]>] $funcEnd $funcCall[inner;nested] $funcEnd $sendMessage[$funcCall[outer]] ``` Output: `` ## Notes - Forgetting `$funcEnd` causes a parse error - `$funcEnd` outside a function block triggers a diagnostic warning - Functions defined without a closing `$funcEnd` are still registered, but may produce unexpected results --- ### Funcreturn # $funcReturn Returns a value from a user-defined function. The function call resolves to this value instead of the body's text content. ## Syntax ``` $funcReturn[value] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `value` | The value to return (can contain inline functions, variables, etc.) | Yes | ## Description `$funcReturn` sets the return value of a user-defined function. When a function call is expanded, if `$funcReturn` was used anywhere in the body, its value becomes the result. If `$funcReturn` is not used, the accumulated text content of the body is returned instead. Only the **last** `$funcReturn` executed matters — if multiple `$funcReturn` calls appear (e.g., inside conditionals), the last one wins. ## Examples ### Simple return ``` $func[greet;name] $funcReturn[Hello $funcArg[name]!] $funcEnd $sendMessage[$funcCall[greet;World]] ``` Output: `Hello World!` ### Without return — uses body text ``` $func[wave;who] Waving at $funcArg[who]... $funcEnd $sendMessage[$funcCall[wave;Alice]] ``` Output: `Waving at Alice...` ### Return with inline functions ``` $func[double;x] $funcReturn[$calculate[$funcArg[x] * 2]] $funcEnd $sendMessage[$funcCall[double;21]] ``` Output: `42` ### Conditional return ``` $func[status;score] $if[$checkCondition[$funcArg[score] >= 50]] $funcReturn[Pass] $else $funcReturn[Fail] $endif $funcEnd $sendMessage[Result: $funcCall[status;75]] ``` Output: `Result: Pass` ## Notes - `$funcReturn` is optional — functions work without it - Only valid inside a `$func` body — outside, it has no effect - The returned value is resolved in the function's scope, then inserted at the call site --- ### Loop # $loop Repeats a block of code a fixed number of times. The loop block must be closed with `$endLoop`. ## Syntax ``` $loop[iterations] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `iterations` | Number of times to repeat the loop block | Yes | ## Description The legacy `$loop` function executes the block of code between `$loop[iterations]` and `$endLoop` exactly N times, where N is the specified number of iterations. This is one of the oldest loop constructs in BDFD. For iterating over a list of values, consider using the newer `$for` / `$endFor` loop instead, which provides loop metadata variables like `$loopIndex` and `$loopCount`. ## Opening & Closing - **Open**: `$loop[iterations]` - **Close**: `$endLoop` Every `$loop` **must** be closed with `$endLoop`. Missing `$endLoop` causes a parse error. ## Examples ### Simple Repetition ``` $loop[3] Hello! This is iteration #... $endLoop ``` **Output:** ``` Hello! This is iteration #... Hello! This is iteration #... Hello! This is iteration #... ``` ### Sending Multiple Messages ``` $loop[5] $sendMessage[Spam protection reminder!] $endLoop ``` ### With Conditional Logic ``` $loop[10] $if[$random[0;1]==0] Heads! $else Tails! $endif $endLoop ``` ### Using with Variables ``` $var[counter;0] $loop[5] $var[counter;$sum[$counter;1]] Count: $counter $endLoop ``` **Output:** ``` Count: 1 Count: 2 Count: 3 Count: 4 Count: 5 ``` ## Notes - `$loop` is a legacy construct. For new code, prefer `$for` / `$endFor` which provides `$loopIndex`, `$loopCount`, and iterator variables. - `$loop` does **not** provide an automatic loop index — you must manage counters manually with variables. - Nested loops are supported but can impact performance significantly. - Keep iteration counts reasonable (under 100 for responsive commands). Large iteration counts may cause timeouts. - Use `$stop` inside the loop to break out early if needed. --- ### $ping[] # $ping[] The `$ping[]` function returns the bot's current WebSocket latency, expressed in milliseconds (ms). This value represents the communication time between the bot and Discord's servers. ## Syntax ``` $ping ``` > **Note:** This function takes no parameters. ## Return Value A number representing the WebSocket latency in milliseconds. ## Interpretation | Latency | Status | |---------|--------| | < 100 ms | Excellent | | 100-200 ms | Good | | 200-400 ms | Average | | > 400 ms | High | ## Examples ### Simple ping command ```bdfd 🏓 Pong! Latency: $ping ms ``` ### Detailed embed ```bdfd $title[🏓 Pong!] $description[WebSocket latency: **$ping ms**] $color[$if[$ping<100]#00FF00$elseif[$ping<200]#FFFF00$else#FF0000$endif] $footer[🤖 $username] ``` ### Visual indicator ```bdfd $if[$ping<100] 🟢 | $ping ms $elseif[$ping<200] 🟡 | $ping ms $else 🔴 | $ping ms $endif ``` ## Notes - This is the **WebSocket** latency (real-time connection), not the HTTP response time. - Latency may vary depending on Discord server load and the location of the server hosting the bot. - To check the bot's uptime, use `$uptime[]`. --- ### Serververificationlvl # $serverVerificationLvl Returns the server's verification level as an integer (0 to 4). Alias of `$serverVerificationLevel`. ## Syntax ``` $serverVerificationLvl ``` ## Parameters This function takes no parameters. ## Description `$serverVerificationLvl` is a **shorter alias** of `$serverVerificationLevel`. It returns the verification level of the server as an integer, which determines the criteria a member must meet before being able to send messages. ## Return Value - **Type**: Integer (0 to 4) | Value | Level | Description | |-------|-------|-------------| | 0 | None | No restrictions | | 1 | Low | Accounts with a verified email | | 2 | Medium | Accounts registered for more than 5 minutes | | 3 | High | Members of the server for more than 10 minutes | | 4 | Very High | Accounts with a verified phone number | ## Examples ### Simple display ``` $sendMessage[🔒 Verification level: $serverVerificationLvl] ``` ### Interpreted message ``` $var[vl;$serverVerificationLvl] $if[$var[vl]==0] $sendMessage[🔒 No restrictions] $elseIf[$var[vl]==1] $sendMessage[🔒 Verified email required] $elseIf[$var[vl]==2] $sendMessage[🔒 Account older than 5 minutes] $elseIf[$var[vl]==3] $sendMessage[🔒 Member for over 10 minutes] $else $sendMessage[🔒 Verified phone number required] $endif ``` ### Server info embed ``` $title[Server Configuration] $addField[Verification level;$serverVerificationLvl;yes] $addField[Server name;$serverName;yes] $color[#5865F2] $sendEmbedMessage ``` ## Notes - `$serverVerificationLvl` and `$serverVerificationLevel` are identical and interchangeable. - A higher verification level offers better protection against spam and raids. - Level 4 (phone verification) is the most restrictive. - Use this value in moderation commands or contextual welcome messages. --- ### $uptime[] # $uptime[] The function `$uptime[]` returns the elapsed time since the last start (or restart) of the bot. ## Syntax ``` $uptime ``` > **Note:** This function takes no parameters. ## Return Value A formatted string indicating the uptime duration, for example: - `2 hours, 15 minutes, 30 seconds` - `3 days, 5 hours, 42 minutes` - `45 seconds` The exact format may vary according to the duration. ## Examples ### Simple uptime ```bdfd The bot has been online for $uptime. ``` ### Status embed ```bdfd $title[📊 Bot Status] $addField[⏱️ Uptime;$uptime] $addField[🏓 Ping;$ping ms] $color[#5865F2] ``` ### Complete info command ```bdfd $title[🤖 Information] $description[ **Uptime:** $uptime **Ping:** $ping ms **Servers:** $guildCount **Users:** $allMembersCount ] ``` ## Notes - The uptime is reset on each bot restart. - The output format is automatically adapted to the duration (seconds, minutes, hours, days). - For bot latency, use `$ping[]`. --- ## Moderation ### $addCmdReactions # $addCmdReactions The `$addCmdReactions[]` function **adds reactions directly to the user's message** that triggered the command. ## Syntax ``` $addCmdReactions[emoji1;emoji2;...] ``` ## Parameters | Parameter | Description | |---|---| | `emoji1;emoji2;...` | List of emojis separated by `;`. Supports Unicode and custom emojis. | ## Return value This function does not return a value. The reactions are added to the command message. ## Behavior - Unlike `$addReactions[]`, this function targets the **trigger** message (the user's message). - Useful for giving quick visual feedback without sending a message. - The bot must have the permission `ADD_REACTIONS` in the channel. ## Examples ### Simple feedback ```bdfd $addCmdReactions[✅] $suppressErrors[Action completed.] ``` ### Conditional feedback ```bdfd $if[$checkContains[$userPerms;Administrator]==true] $addCmdReactions[✅] $ban[$mentioned[1]] $else $addCmdReactions[❌] $ephemeral[You do not have permission.] $endif ``` ### Progress indicator ```bdfd $addCmdReactions[⏳] $wait[2] $removeReaction[$channelID;$messageID;⏳] $addCmdReactions[✅] ``` ## Notes - `$addCmdReactions[]` only works if the trigger message still exists. - Does not require sending a response message. - Ideal for quick commands where a simple emoji is enough for confirmation. --- ### $addEmoji # $addEmoji The `$addEmoji[]` function **adds a new custom emoji** to the server from an image URL. The emoji can be public or restricted to a specific role. ## Syntax ``` $addEmoji[name;url;(roleID)] ``` ## Parameters | Parameter | Description | |---|---| | `name` | The emoji name (2 to 32 characters, alphanumeric + underscores). | | `url` | The URL of the image (PNG, JPEG, GIF). The image must be publicly accessible. | | `roleID` | Optional - ID of the role allowed to use the emoji. If omitted, the emoji is public. | ## Return value - **Type**: String - The markup of the created emoji in the format `<:name:ID>` on success. - An error message if the URL is invalid, the name is already taken, or permissions are insufficient. ## Behavior - The bot must have the permission `MANAGE_EMOJIS_AND_STICKERS`. - The name must be unique among the server's emojis. - Limit of 50 standard emojis (more for boosted servers). - Animated GIFs are accepted and create an animated emoji. ## Examples ### Simple addition ```bdfd $if[$checkContains[$userPerms;ManageEmojisAndStickers]==true] $let[emoji;$addEmoji[cool;https://example.com/cool.png]] $sendMessage[✅ Emoji added : $emoji] $else $sendMessage[❌ Permission denied.] $endif ``` ### Emoji with attachment ```bdfd $let[url;$getAttachments[$noMentionMessage]] $if[$url!=] $let[firstUrl;$splitText[$url;, ;1]] $let[emojiName;$noMentionMessage] $let[emoji;$addEmoji[$emojiName;$firstUrl]] $sendMessage[✅ Emoji created : $emoji] $else $sendMessage[❌ No image found. Please attach an image to your message.] $endif ``` ### Staff-restricted emoji ```bdfd $let[staffRole;$roleID[Staff]] $let[emoji;$addEmoji[confidential;https://example.com/lock.png;$staffRole]] $if[$emoji!=] $sendMessage[✅ Emoji **$emoji** created and restricted to the role <@&$staffRole>.] $else $sendMessage[❌ Error during emoji creation.] $endif ``` ### Validation of the name ```bdfd $let[name;$message] $if[$length[$name]<2] $sendMessage[❌ The name must be at least 2 characters.] $elseif[$length[$name]>32] $sendMessage[❌ The name must not exceed 32 characters.] $elseif[$emojiExists[$name]==true] $sendMessage[❌ An emoji named **$name** already exists.] $else $let[emoji;$addEmoji[$name;$getAttachments[$noMentionMessage]]] $sendMessage[✅ Emoji **$emoji** created !] $endif ``` ## Notes - The URL must point directly to an image (with extension .png, .jpg, .gif). - The server has an emoji limit according to its boost level. - Animated emojis count toward a separate limit. - The name must only contain letters, numbers, and underscores. --- ### $addMessageReactions # $addMessageReactions The `$addMessageReactions[]` function **adds reactions to any message** on the server, identified by its channel and message ID. ## Syntax ``` $addMessageReactions[channelID;messageID;emoji1;emoji2;...] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the channel containing the target message. | | `messageID` | The ID of the message to add the reactions to. | | `emoji1;emoji2;...` | List of emojis to add, separated by `;`. | ## Return value This function does not return a value. ## Behavior - Allows reacting to old messages or messages in other channels. - The bot must have access to the channel and the `ADD_REACTIONS` permission. - The message must exist and not have been deleted. ## Examples ### Reacting to a rules message ```bdfd $addMessageReactions[$rulesChannelID;123456789012345678;✅] ``` ### Reaction to a stored message ```bdfd $let[msgID;$getUserVar[lastMessageID]] $let[chanID;$getUserVar[lastChannelID]] $addMessageReactions[$chanID;$msgID;👍;👎] ``` ### Reacting to a giveaway message ```bdfd $addMessageReactions[$giveawayChannel;123456789;🎉] $sendMessage[React with 🎉 to participate!] ``` ## Notes - `$addMessageReactions[]` is the most flexible function for reactions because it can target any message. - For the bot's own response message, prefer `$addReactions[]`. - For the trigger message, use `$addCmdReactions[]`. --- ### $addReactions # $addReactions The `$addReactions[]` function **adds reactions** to the response message sent by the bot in the current command. ## Syntax ``` $addReactions[emoji1;emoji2;...] ``` ## Parameters | Parameter | Description | |---|---| | `emoji1;emoji2;...` | List of emojis separated by `;`. Supports Unicode and custom emojis. | ## Return value This function does not return a value. The reactions are added to the bot's response message. ## Behavior - Reactions are added in the specified order. - The bot must have the permission `ADD_REACTIONS` in the channel. - Custom emojis must be accessible to the bot (present on a shared server). - If an emoji is invalid, subsequent reactions may not be added. ## Examples ### Reactions to a poll ```bdfd $title[Poll] $description[$message] $addReactions[👍;👎;🤷] $sendMessage[] ``` ### Confirmation reactions ```bdfd $if[$checkContains[$message;!delete]==true] $title[Confirmation] $description[Are you sure you want to delete?] $addReactions[✅;❌] $sendMessage[] $endif ``` ### Reactions to an announcement ```bdfd $title[📢 Announcement] $description[$noMentionMessage] $addReactions[📢;👀] $sendMessage[] ``` ## Notes - `$addReactions[]` applies to the response message of the bot (the one sent by `$sendMessage[]`). - To add reactions to the user's command message, use `$addCmdReactions[]`. - For specific messages, use `$addMessageReactions[]`. --- ### $authorPerms # $authorPerms The `$authorPerms` function **retrieves the list of permissions** that the author of the command has on the current server. ## Syntax ``` $authorPerms ``` ## Parameters No parameters. ## Return value - **Type**: String - List of permissions of the author, separated by `, `. - Example: `SendMessages, ReadMessageHistory, AddReactions,...` ## Behavior - Returns the effective permissions of the user (taking into account roles and channel permissions). - Equivalent to `$userPerms[$authorID]`. - Permission names are in English (Discord API format). ## Examples ### Permission verification ```bdfd $if[$checkContains[$authorPerms;BanMembers]==true] $sendMessage[✅ You have permission to ban.] $else $sendMessage[❌ Permission "Ban Members" is missing.] $endif ``` ### Debugging permissions ```bdfd $title[🔑 Your Permissions] $description[ $textSplit[$authorPerms;, ] $index. $splitText[$index] $endTextSplit ] $sendMessage[] ``` ### Admin-only command ```bdfd $if[$checkContains[$authorPerms;Administrator]==true] // Sensitive code executed $sendMessage[✅ Admin action performed.] $elseif[$checkContains[$authorPerms;ManageGuild]==true] // Management permissions $sendMessage[✅ Management action performed.] $else $sendMessage[❌ Insufficient permissions.] $endif ``` ### Multi-verification ```bdfd $if[$checkContains[$authorPerms;KickMembers]==true] $if[$checkContains[$authorPerms;BanMembers]==true] $sendMessage[✅ You can kick AND ban.] $else $sendMessage[⚠️ You can kick but not ban.] $endif $else $sendMessage[❌ No moderation permissions.] $endif ``` ## Notes - Use `$checkContains[$authorPerms;Permission]` to test a specific permission. - Permissions are returned in English (Discord API names). - `$authorPerms` is a shortcut for `$userPerms[$authorID]`. --- ### $ban # $ban The `$ban` function **bans a user** from the Discord server. The bot must have the `BanMembers` permission. ## Syntax ``` $ban[userID;(reason);(deleteMessagesDays)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user to ban. Required. | | `reason` | Optional. The ban reason. | | `deleteMessagesDays` | Optional. Number of days (0-7) of messages to delete. Default `0`. | ## Return value None. The function bans the user and deletes their messages if requested. ## Examples ### Simple ban with mention ```bdfd $ban[$mentioned[1];Spam] $sendMessage[<@$mentioned[1]> has been banned for spam.] ``` ### Ban with message deletion ```bdfd $ban[$findUser[JohnDoe];Harassment;7] $sendMessage[JohnDoe banned — 7 days of messages deleted.] ``` ### Ban command with confirmation ```bdfd $if[$argsCount<1] $sendMessage[Usage: !ban <@mention> ] $stop $endif $ban[$mentioned[1];$replaceText[$message;-;$mentioned[1];]] $sendMessage[✅ <@$mentioned[1]> banned.] ``` ## Notes - The bot must have the `BanMembers` permission. - `deleteMessagesDays` accepts a value between `0` and `7`. - The bot cannot ban a user with a role higher than its own. - To ban by ID without mention, use `$banID`. --- ### $banID # $banID The `$banID` function **bans a user by their Discord ID**, even if they are not present on the server. The bot must have the `BanMembers` permission. ## Syntax ``` $banID[userID;(reason)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The Discord ID of the user to ban. Required. | | `reason` | Optional. The ban reason. | ## Return value None. The user is banned from the server. ## Examples ### Ban by ID simple ```bdfd $banID[123456789012345678;Raid] $sendMessage[User 123456789012345678 banned for raiding.] ``` ### Preventive ban ```bdfd $banID[$message[1]] $sendMessage[User $message[1] preventively banned.] ``` ## Notes - Allows banning a user who is no longer on the server. - Useful for preventive bans. - The bot must have the `BanMembers` permission. - Unlike `$ban`, this does not delete messages. --- ### $blacklistIDs # $blacklistIDs The guard function `$blacklistIDs` blocks the execution of the command for users whose ID is in the list. Unlike `$onlyForIDs` which whitelists, `$blacklistIDs` acts as a **blacklist**. ## Syntax ``` $blacklistIDs[userID1;userID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `userID1;userID2;...` | Snowflake[] | IDs of users to blacklist, separated by `;`. | | `errorMessage` | String (optional) | Message sent to the blacklisted user. If omitted, it remains silent. | ## Behavior - Compares the ID of the triggering user with the blacklist. - If the ID matches, the command is interrupted. - If an error message is provided, it is sent before the interruption. - Without an error message, the guard is silent. ## Examples ### Simple blacklist ```bdfd $blacklistIDs[123456789012345678;❌ You have been blacklisted from this command.] $sendMessage[Processing completed.] ``` ### Multiple blacklist with external list ```bdfd $blacklistIDs[$getGlobalUserVar[blacklist];❌ Access revoked.] $sendMessage[Welcome.] ``` ### Without message (silent) ```bdfd $blacklistIDs[111111111111111111;222222222222222222] $sendMessage[OK.] ``` ## Notes - `$blacklistIDs` and `$blacklistUsers` are interchangeable. - For a persistent blacklist, combine it with `$getGlobalUserVar` or `$getServerUserVar`. - To blacklist an entire role, use `$blacklistRoles` or `$blacklistRoleIDs`. - The opposite of this function is `$onlyForIDs` (whitelist). --- ### $blacklistRoleIDs # $blacklistRoleIDs The guard function `$blacklistRoleIDs` blocks the execution of the command if the user has any of the blacklisted roles. This is a direct alias of `$blacklistRoles`. ## Syntax ``` $blacklistRoleIDs[roleID1;roleID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `roleID1;roleID2;...` | Snowflake[] | IDs of blacklisted roles. | | `errorMessage` | String (optional) | Message sent if the user has a blacklisted role. | ## Behavior - Checks the user's roles. - Checked using an **OR** condition: a single blacklisted role is enough. - Exact alias of `$blacklistRoles`. ## Examples ### Muted Role ```bdfd $blacklistRoleIDs[123456789012345678;❌ You are muted.] $sendMessage[Processing completed.] ``` ### Multi-roles ```bdfd $blacklistRoleIDs[111;222;333;❌ Access denied.] $sendMessage[OK.] ``` ## Notes - `$blacklistRoleIDs` and `$blacklistRoles` are interchangeable. - To whitelist roles, use `$onlyForRoleIDs`. - For large servers, store the IDs in a variable (`$getServerVar`) for easier maintenance. --- ### $blacklistRoles # $blacklistRoles The guard function `$blacklistRoles` blocks the execution of the command if the user has **at least one** of the blacklisted roles. ## Syntax ``` $blacklistRoles[roleID1;roleID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `roleID1;roleID2;...` | Snowflake[] | IDs of roles to blacklist, separated by `;`. | | `errorMessage` | String (optional) | Message sent if the user has a blacklisted role. | ## Behavior - Checks if the user has any of the roles in the list. - If **at least one** role matches, the command is interrupted. - Checked using an **OR** condition (a single blacklisted role is enough to block). - If an error message is provided, it is sent; otherwise, it remains silent. ## Examples ### Block muted users ```bdfd $blacklistRoles[123456789012345678;❌ You are currently muted. Contact a moderator.] $sendMessage[Your message has been processed.] ``` ### Multiple blacklisted roles ```bdfd $blacklistRoles[111111111111111111;222222222222222222;❌ Access forbidden for your role.] $clear[10] $sendMessage[10 messages deleted.] ``` ### Silent blacklist ```bdfd $blacklistRoles[123456789012345678] $sendMessage[Command executed.] ``` ## Notes - `$blacklistRoles` and `$blacklistRoleIDs` are interchangeable. - To whitelist roles, use `$onlyForRoles`. - Very useful to prevent muted or restricted users from using commands. - Combine it with `$blacklistUsers` for complete protection (specific roles + users). --- ### Blacklistrolesids # $blacklistRolesIDs Adds role IDs to the command's blacklist. Users with any of the specified roles will not be able to execute the command. ## Syntax ``` $blacklistRolesIDs[roleIds;(errorMessage)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `roleIds` | IDs of the roles to blacklist, separated by `;` | Yes | | `errorMessage` | Custom error message sent when a user has a blacklisted role | No | ## Description `$blacklistRolesIDs` is a **guard function** that blocks command execution if the user has at least one of the specified roles. The check is performed with an **OR** condition: a single match among the listed roles is enough to block the user. If no custom error message is provided, a default message is sent. ## Examples ### Default error ``` $blacklistRolesIDs[123456789012345678] $sendMessage[Command executed successfully.] ``` ### Multiple roles with custom message ``` $blacklistRolesIDs[111111111111111111;222222222222222222;333333333333333333;❌ You are not allowed to use this command.] $sendMessage[Processing...] ``` ### Variable-based blacklist ``` $blacklistRolesIDs[$getServerVar[blacklistedRoles];⛔ Access denied.] $sendMessage[Done.] ``` ## Notes - Uses an **OR** logic: the user is blocked if they have **any** of the listed roles. - Role IDs must be valid Discord snowflakes (18-19 digits). - To whitelist roles, use `$onlyForRoleIDs`. - For easier maintenance, store blacklisted role IDs in server variables. --- ### $blacklistServers # $blacklistServers The guard function `$blacklistServers` blocks the execution of the command on the listed servers. If the command is executed on a blacklisted server, it is interrupted. ## Syntax ``` $blacklistServers[guildID1;guildID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `guildID1;guildID2;...` | Snowflake[] | IDs of servers to blacklist. | | `errorMessage` | String (optional) | Message sent if the server is blacklisted. | ## Behavior - Compares the ID of the current server (`$guildID`/`$serverID`) with the list. - If the server is in the list, the command is interrupted. - If an error message is provided, it is sent; otherwise, it remains silent. ## Examples ### Block a server ```bdfd $blacklistServers[123456789012345678;❌ Command disabled on this server.] $sendMessage[Command executed.] ``` ### Multi-server blacklist ```bdfd $blacklistServers[111111111111111111;222222222222222222] $sendMessage[OK.] ``` ### Dynamic blacklist via variable ```bdfd $blacklistServers[$getGlobalVar[blacklistedServers];❌ Server blacklisted.] $sendMessage[Welcome.] ``` ## Notes - To whitelist servers (only allow certain servers), use `$onlyForServers`. - Server blacklisting is useful for public bots to disable commands on problematic servers. - Combine it with global variables to manage the blacklist dynamically without modifying the code. --- ### $blacklistUsers # $blacklistUsers The guard function `$blacklistUsers` blocks the execution of the command for the listed users. This is a direct alias of `$blacklistIDs`. ## Syntax ``` $blacklistUsers[userID1;userID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `userID1;userID2;...` | Snowflake[] | IDs of users to blacklist. | | `errorMessage` | String (optional) | Message sent to the blacklisted user. | ## Behavior - If the user is in the list, the command is interrupted. - If an error message is provided, it is sent before the interruption. - Exact alias of `$blacklistIDs`. ## Examples ### Blacklist with message ```bdfd $blacklistUsers[111111111111111111;222222222222222222;❌ You are blacklisted.] $sendMessage[Access allowed.] ``` ### Silent blacklist ```bdfd $blacklistUsers[123456789012345678] $sendMessage[OK.] ``` ## Notes - `$blacklistUsers` and `$blacklistIDs` are interchangeable. - To blacklist roles, use `$blacklistRoles`. - To whitelist (only allow certain users), use `$onlyForUsers`. --- ### $botLeave # $botLeave The `$botLeave[]` function **makes the bot leave a server**. This is an irreversible action that removes the bot from the target server. ## Syntax ``` $botLeave[(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `guildID` | Optional - The ID of the server to leave. By default, the current server. | ## Return value This function does not return a value. ## Behavior - The bot immediately leaves the specified server. - **Irreversible action**: All bot data on this server will be lost. - If executed without `guildID`, the bot leaves the server where the command was run. ## Examples ### Leave the current server ```bdfd $if[$checkContains[$userPerms;Administrator]==true] $sendMessage[Goodbye! The bot is leaving this server.] $botLeave $else $sendMessage[Only administrators can use this command.] $endif ``` ### Leave a specific server (owner only) ```bdfd $if[$authorID==OWNER_ID] $let[targetGuild;$message[1]] $if[$targetGuild!=] $botLeave[$targetGuild] $sendMessage[Bot removed from the server $targetGuild.] $else $sendMessage[Usage: !leave ] $endif $else $sendMessage[Reserved for the bot owner.] $endif ``` ### Automatic Cleanup ```bdfd $if[$membersCount<5] $channelSendMessage[$channelID;This server has fewer than 5 members. The bot will leave.] $botLeave $endif ``` ## Notes - **Irreversible action**: Use with extreme caution. - Protect this command with strict permission checks. - All user data linked to this server will become inaccessible. - The bot cannot rejoin a server via command (requires an invite link). --- ### $botTyping # $botTyping The `$botTyping[]` function **triggers the typing indicator** ("Bot is typing...") in the channel where the command is executed. ## Syntax ``` $botTyping ``` ## Parameters This function does not take any parameters. ## Return value This function does not return a value. ## Behavior - The typing indicator lasts about 10 seconds or until a message is sent. - Useful to simulate a processing delay or to provide visual feedback. - The indicator stops automatically if a message is sent. ## Examples ### Processing with feedback ```bdfd $botTyping $wait[3] $sendMessage[Processing completed! Here are the results...] ``` ### Search simulation ```bdfd $botTyping $wait[2] $sendMessage[🔍 Searching the database...] $botTyping $wait[2] $sendMessage[✅ Results found!] ``` ### Long action execution ```bdfd $botTyping $let[result;$httpGet[https://api.example.com/data]] $if[$result!=] $sendMessage[Data retrieved successfully.] $else $sendMessage[Error during retrieval.] $endif ``` ## Notes - The indicator is purely cosmetic and has no effect on actual processing. - Particularly useful for commands with `$wait[]` or API calls. - Only works in text channels. --- ### $changeUsername # $changeUsername The `$changeUsername` function **modifies the global username** of the bot on Discord. Unlike `$setNickname`, which changes the nickname per server, `$changeUsername` changes the bot's name globally. ## Syntax ``` $changeUsername[newName] ``` ## Parameters | Parameter | Description | |---|---| | `newName` | The new username for the bot. Required. | ## Return value None. The bot's username is updated globally. ## Examples ### Simple change ```bdfd $changeUsername[My Awesome Bot] $sendMessage[✅ The bot is now named "My Awesome Bot".] ``` ### Conditional change ```bdfd $if[$isAdmin==true] $changeUsername[$message[1]] $sendMessage[Bot username updated.] $else $sendMessage[Permission denied.] $endif ``` ### Programmatic change ```bdfd $changeUsername[Bot of $serverName] $sendMessage[Bot name adapted to the server.] ``` ## Notes - **Discord rate limit**: Maximum of 2 username changes per hour. - The global name is visible on all servers. - To change the nickname on a specific server, use `$setNickname`. - To change the name of another user, use `$changeUsernameWithID` (requires special permissions). - The bot must have a token with the necessary permissions. --- ### $changeUsernameWithID # $changeUsernameWithID The `$changeUsernameWithID` function **modifies the global username** of a specific Discord user. This function requires elevated permissions (generally reserved for bots with a user token or special permissions). ## Syntax ``` $changeUsernameWithID[userID;newName] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the target user. Required. | | `newName` | The new username. Required. | ## Return value None. The username is updated globally. ## Examples ### Change for a mentioned user ```bdfd $changeUsernameWithID[$mentioned[1];Corrected Name] $sendMessage[✅ Username of <@$mentioned[1]> changed to "Corrected Name".] ``` ### Administrative command ```bdfd $if[$isAdmin==true] $changeUsernameWithID[$findUser[$message[1]];$message[2]] $sendMessage[Username of user $message[1] changed.] $else $sendMessage[Permission denied.] $endif ``` ### Change for the author ```bdfd $changeUsernameWithID[$authorID;$message[1]] $sendMessage[$userName, your username has been changed.] ``` ## Notes - **Special permissions required**: This function may not work with a standard bot token. - **Discord rate limit**: Maximum of 2 name changes per hour per account. - To change the name of the bot itself, use `$changeUsername`. - To change the nickname on the server only, use `$setNickname` instead. - The change is global and visible across all Discord servers. --- ### $channelSendMessage # $channelSendMessage The `$channelSendMessage[]` function **sends a message to a specific channel**, which can be different from the channel where the command was executed. ## Syntax ``` $channelSendMessage[channelID;content] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the target channel. | | `content` | The content of the message (markdown, mentions, and emojis are supported). Max 2000 characters. | ## Return value - **Type**: Snowflake (string) - The ID of the sent message. - Empty string on failure (inaccessible channel, missing permissions). ## Behavior - The bot must have access to the target channel and the `SEND_MESSAGES` permission. - The message is sent like a normal message from the bot. - Embed functions (`$title`, `$description`, etc.) placed before `$channelSendMessage[]` will be applied. ## Examples ### Moderation logs ```bdfd $let[logChannel;123456789012345678] $title[⚠️ Moderation Action] $description[ **Moderator:** $username **Action:** Ban **User:** $userName[$mentioned[1]] **Reason:** $noMentionMessage ] $color[#ED4245] $channelSendMessage[$logChannel;] $sendMessage[User banned.] ``` ### Welcome notification ```bdfd $let[welcomeChannel;123456789] $title[👋 Welcome!] $description[Welcome to **$serverName**, $username! You are member #$membersCount!] $thumbnail[$authorAvatar] $color[#57F287] $channelSendMessage[$welcomeChannel;] ``` ### Send to a mentioned channel ```bdfd $if[$mentionedChannels[1]!=] $channelSendMessage[$mentionedChannels[1];Message forwarded by $username: >>> $noMentionMessage] $sendMessage[Message sent to <#$mentionedChannels[1]>] $else $sendMessage[No channel mentioned.] $endif ``` ## Notes - `$channelSendMessage[]` does not respond to the user — combine it with `$sendMessage[]` to provide feedback. - Maximum of 2000 characters per message. - To retrieve a message, use `$getMessage[]`. --- ### $checkUserPerms # $checkUserPerms The `$checkUserPerms` function checks if a user has all the specified Discord permissions. This is a **direct alias** of `$hasPerms` — the two functions are strictly identical. ## Syntax ``` $checkUserPerms[userID;permission1;permission2;...] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `userID` | Snowflake | The ID of the user to check. | | `permission1;permission2;...` | String[] | Required permissions (checks with **AND**). | ## Return value - **Type**: String `"true"` or `"false"` - `"true"`: The user has all permissions. - `"false"`: At least one permission is missing. ## Behavior - **Inline** check: Does not interrupt the command. - **AND** check: All listed permissions are required. - `Administrator` covers all permissions. ## Examples ### Inline verification ```bdfd $if[$checkUserPerms[$authorID;KickMembers]==true] $kick[$mentioned[1]] $else $sendMessage[❌ KickMembers permission required.] $endif ``` ### Checking another user's permissions ```bdfd $if[$checkUserPerms[$mentioned[1];Administrator]==true] $sendMessage[⚠️ You cannot perform this action on an administrator.] $stop $endif $ban[$mentioned[1]] ``` ### Multi-permissions ```bdfd $if[$checkUserPerms[$authorID;ManageMessages;ReadMessageHistory]==true] $clear[50] $else $sendMessage[❌ Insufficient permissions.] $endif ``` ## Notes - `$checkUserPerms` and `$hasPerms` are **interchangeable**. Use whichever syntax is most explicit for your context. - For the bot itself, pass `$botID` as the `userID`. - For a check with automatic interruption (guard), use `$onlyPerms`. - Permissions are in **PascalCase**: `BanMembers`, `ManageMessages`, `Administrator`, etc. --- ### $clear # $clear The `$clear` function **deletes a specified number of messages** in the current channel. This function is dedicated to bulk-deleting messages (moderation), not to be confused with the variable function `$clear` of the same name. The bot must have the `ManageMessages` permission. ## Syntax ``` $clear[amount;(userID);(removePinned)] ``` ## Parameters | Parameter | Description | |---|---| | `amount` | Number of messages to delete (1-100). Required. | | `userID` | Optional. Filter: only deletes messages from this user. | | `removePinned` | Optional. `"yes"` to include pinned messages. Default is `"no"`. | ## Return value None. The messages are deleted. ## Examples ### Simple deletion ```bdfd $clear[50] $sendMessage[🧹 50 messages have been cleared.] ``` ### Targeted deletion by user ```bdfd $clear[100;$mentioned[1]] $sendMessage[🧹 Messages from <@$mentioned[1]> deleted.] ``` ### Clear command with verification ```bdfd $if[$argsCount<1] $sendMessage[Usage: !clear ] $stop $endif $if[$isAdmin==true] $clear[$message[1]] $sendMessage[🧹 $message[1] messages deleted.] $else $sendMessage[Permission denied.] $endif ``` ### Deletion including pinned messages ```bdfd $clear[10;;yes] $sendMessage[10 messages deleted (pinned included).] ``` ## Notes - The bot must have the `ManageMessages` permission. - Maximum 100 messages per call (Discord API limitation). - Messages older than 14 days cannot be deleted by the Discord API. - `removePinned` defaults to `"no"`: pinned messages are ignored. - If `userID` is omitted, leave the semicolon field empty (e.g., `$clear[10;;yes]`). - This `$clear` function is dedicated to moderation. To clear a variable, see `$clear` in the Variables category. --- ### $clearReactions # $clearReactions The `$clearReactions[]` function **removes all reactions** from a message in a single operation. ## Syntax ``` $clearReactions[messageID] ``` ## Parameters | Parameter | Description | |---|---| | `messageID` | The ID of the message from which you want to remove all reactions. | ## Return value This function does not return a value. ## Behavior - Removes ALL reactions from the message, including those of other users if the bot has the `MANAGE_MESSAGES` permission. - If the bot does not have `MANAGE_MESSAGES`, only the bot's own reactions can be deleted. - Useful for resetting a reaction system (poll, giveaway, etc.). ## Examples ### Resetting a poll ```bdfd $clearReactions[$messageID] $addMessageReactions[$channelID;$messageID;👍;👎;🤷] $sendMessage[The votes have been reset.] ``` ### Automatic cleanup ```bdfd $clearReactions[$messageID] $addReactions[✅] $editMessage[Finished!] ``` ### Removal after closing ```bdfd $clearReactions[$messageID] $sendMessage[This poll is now closed.] ``` ## Notes - `$clearReactions[]` removes all reactions, not just the bot's. - Requires the `MANAGE_MESSAGES` permission to delete other users' reactions. - To delete a specific reaction, use `$removeReaction[]`. --- ### $closeTicket # $closeTicket The `$closeTicket[]` function **closes and deletes a ticket** (the current channel). It is equivalent to `$deleteChannels[$channelID]` with check validation. ## Syntax ``` $closeTicket[(errorMessage)] ``` ## Parameters | Parameter | Description | |---|---| | `errorMessage` | Optional - Message sent if the command is not executed in a ticket channel. Default: "This channel is not a ticket." | ## Return value This function does not return a value. ## Behavior - Deletes the channel in which the command is executed. - Designed for use in channels created by `$newTicket[]`. - If the channel is not a recognized ticket, displays the error message. - The bot must have `MANAGE_CHANNELS` permission. ## Examples ### Simple closure ```bdfd $closeTicket ``` ### Closure with confirmation ```bdfd $sendMessage[Closing the ticket in 5 seconds...] $wait[5] $closeTicket ``` ### Closure with logs ```bdfd $let[logChannel;123456789] $channelSendMessage[$logChannel;Ticket closed by $username.] $closeTicket ``` ### Conditional closure ```bdfd $if[$checkContains[$userPerms;Administrator]==true] $closeTicket $else $closeTicket[Only administrators and moderators can close this ticket.] $endif ``` ### Closure with backup ```bdfd $let[transcript;$getChannelMessages[$channelID;100]] $setUserVar[lastTicketTranscript;$transcript] $channelSendMessage[$logChannel;Transcript saved. Ticket closed by $username.] $closeTicket ``` ## Notes - `$closeTicket[]` deletes the channel — this action is irreversible. - Save important information before closing (transcripts, logs). - Custom error messages help prevent accidental closures. - For a closure without deletion, archive the channel using `$modifyChannel[]` instead. --- ### $createChannel # $createChannel The `$createChannel[]` function **creates a new channel** on the Discord server. ## Syntax ``` $createChannel[name;(type);(categoryID);(topic);(nsfw);(slowmode)] ``` ## Parameters | Parameter | Description | |---|---| | `name` | Name of the channel (1 to 100 characters). | | `type` | Optional - Type: `0`=text, `2`=voice, `4`=category, `5`=announcement, `13`=stage. Default: `0`. | | `categoryID` | Optional - ID of the parent category. | | `topic` | Optional - Topic/description of the channel (max 1024). | | `nsfw` | Optional - `true`/`false` for NSFW marking. | | `slowmode` | Optional - Delay in seconds (0-21600). | ## Return value - **Type**: Snowflake (string) - The ID of the created channel. - Empty string if failed (insufficient permissions). ## Behavior - The bot must have the `MANAGE_CHANNELS` permission. - Announcement channels (type 5) require a community server. - Stage channels (type 13) are special voice channels. ## Examples ### Log channel ```bdfd $let[logChan;$createChannel[logs-bot;0;123456789;;false;0]] $if[$logChan!=] $channelSendMessage[$logChan;Log system enabled.] $sendMessage[Log channel created: <#$logChan>] $else $sendMessage[Error: MANAGE_CHANNELS permission required.] $endif ``` ### Dynamic ticket channel ```bdfd $let[ticketChan;$createChannel[ticket-$username;0;123456789;Ticket for $username;false;0]] $if[$ticketChan!=] $channelSendMessage[$ticketChan;Welcome $username! Describe your issue.] $sendMessage[Ticket created: <#$ticketChan>] $endif ``` ### Category + channels ```bdfd $let[cat;$createChannel[New Project;4;0]] $let[chat;$createChannel[discussion;0;$cat]] $let[voice;$createChannel[Voice;2;$cat]] $sendMessage[Category and channels created!] ``` ## Notes - Channel names are converted to lowercase and spaces are replaced by hyphens. - Maximum 500 channels per server. - To delete, use `$deleteChannels[]`. --- ### $createRole # $createRole The `$createRole` function **creates a new role** on the Discord server and returns its ID. The bot must have the `ManageRoles` permission. ## Syntax ``` $createRole[name;(color);(hoist);(mentionable)] ``` ## Parameters | Parameter | Description | |---|---| | `name` | The name of the role to create. Required. | | `color` | Optional. Hex color (e.g., `"#FF0000"`, `"#3498DB"`). | | `hoist` | Optional. `"yes"` to display separately in the member list. Default `"no"`. | | `mentionable` | Optional. `"yes"` to make the role mentionable. Default `"no"`. | ## Return value - **Type**: ID of the created role - The ID can be stored in a variable for future use. ## Examples ### Simple creation ```bdfd $createRole[Member VIP] $sendMessage[✅ Role "Member VIP" created!] ``` ### Creation with all options ```bdfd $var[newRole;$createRole[Staff;#E74C3C;yes;yes]] $giveRole[$authorID;$var[newRole]] $sendMessage[Staff role created and assigned!] ``` ### Creation with conditions ```bdfd $if[$isAdmin==true] $var[role;$createRole[$message[1];$message[2];no;no]] $sendMessage[Role created with the ID: $var[role]] $else $sendMessage[Permission denied.] $endif ``` ### Create a colored role ```bdfd $createRole[Custom Color;#9B59B6;no;no] $sendMessage[Colored role created!] ``` ## Notes - The bot must have the `ManageRoles` permission. - The name of the role is required; the other parameters are optional. - The color must be in the hexadecimal format `#RRGGBB`. - `hoist`: displays the members of the role in a separate section of the member list. - `mentionable`: allows mentioning the role with `@role`. - Use the returned value (ID of the role) with `$giveRole` to assign the new role immediately. --- ### $customEmoji # $customEmoji The `$customEmoji[]` function **generates the markup of a custom emoji** usable in a message or an embed. It returns the format `<:name:ID>` which will be rendered as an emoji by Discord. ## Syntax ``` $customEmoji[name;(id)] ``` ## Parameters | Parameter | Description | |---|---| | `name` | The custom emoji name. | | `id` | Optional - The ID of the emoji. If omitted, it is searched for on the server by name. | ## Return value - **Type**: String - The markup `<:name:ID>` (or `` for animated ones) displayable in Discord. - Empty string or text name if the emoji is not found. ## Behavior - Without an ID, the function searches for the emoji by name on the current server. - With an ID, it directly generates the markup. - Animated emojis are automatically detected and formatted with ``. ## Examples ## Simple display ```bdfd $title[Welcome!] $description[ $customEmoji[wave] Welcome to the server $customEmoji[party]! ] $sendMessage[] ``` ### With explicit ID ```bdfd $let[emoji;$customEmoji[boost;123456789012345678]] $title[🚀 Boost detected $emoji] $description[Thank you for your boost!] $color[#F47FFF] $sendMessage[] ``` ### Menu with emojis ```bdfd $title[📋 Menu] $description[ $customEmoji[rules] Rules $customEmoji[announce] Announcements $customEmoji[chat] General Discussion ] $color[#5865F2] $sendMessage[] ``` ### Conditional emoji ```bdfd $if[$emojiExists[verified]==true] $customEmoji[verified] $else ✅ $endif Verified User ``` ## Notes - If the emoji does not exist on the server and no ID is provided, the markup will not display correctly. - For emojis from other servers, the ID is required. - The bot must have access to the server hosting the emoji to resolve it by name. --- ### $deleteChannels # $deleteChannels The `$deleteChannels[]` function **deletes one or multiple channels** by their ID. An alias `$deleteChannelsByName[]` exists for deleting channels by name. ## Syntax ``` $deleteChannels[channelID1;channelID2;...] ``` ## Parameters | Parameter | Description | |---|---| | `channelID1;channelID2;...` | Channel IDs to delete, separated by `;`. | ## Return value This function does not return a value. ## Behavior - The bot must have the `MANAGE_CHANNELS` permission. - Deletion is **irreversible**. - If an ID is invalid, the other valid channels are still deleted. ## Examples ### Simple deletion ```bdfd $deleteChannels[$channelID] $sendMessage[Channel deleted.] ``` ### Ticket cleanup ```bdfd $deleteChannels[$ticketID] $sendMessage[Ticket closed and channel deleted.] ``` ### Conditional deletion ```bdfd $if[$checkContains[$userPerms;Administrator]==true] $deleteChannels[$mentionedChannels[1]] $sendMessage[Channels deleted.] $else $sendMessage[Permission denied.] $endif ``` ### Deletion by name (alias) ```bdfd $deleteChannelsByName[ticket-*] $sendMessage[All ticket channels deleted.] ``` ## Notes - **Irreversible action**: use with caution. - Deleted channels cannot be restored via the API. - For categories, deletion also deletes all child channels. - The alias `$deleteChannelsByName[]` accepts wildcards (`*`). --- ### $deleteCommand # $deleteCommand The `$deleteCommand` function **deletes the command message** of the user who triggered the command. ## Syntax ``` $deleteCommand ``` ## Parameters None. ## Return value This function does not return a value. ## Behavior - Immediately deletes the user's message that triggered the command. - The bot must have the `MANAGE_MESSAGES` permission in the channel. - If the message has already been deleted, nothing happens. ## Examples ### Clean command ```bdfd $deleteCommand $sendMessage[Result of your command...] ``` ### Silent feedback ```bdfd $deleteCommand $addReactions[✅] $ephemeral[Command executed successfully.] ``` ### Anti-spam protection ```bdfd $deleteCommand $if[$checkContains[$userPerms;Administrator]==false] $sendMessage[This command is reserved for administrators.] $suppressErrors[] $else $sendMessage[Admin command executed.] $endif ``` ### ModMail / confession ```bdfd $deleteCommand $channelSendMessage[$modChannel;Anonymous message: >>> $noMentionMessage] $ephemeral[Your message has been sent to the moderation team.] ``` ## Notes - Only works if the bot has the `MANAGE_MESSAGES` permission. - Ideal for moderation commands, confession systems, or modmails. - The message is deleted before the bot sends its response. - If combined with `$addCmdReactions[]`, place `$deleteCommand` before or after depending on the desired behavior. --- ### $deleteRole # $deleteRole The `$deleteRole` function **permanently deletes a role** from the Discord server. This action is irreversible. The bot must have the `ManageRoles` permission. ## Syntax ``` $deleteRole[roleID] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the role to delete. Required. | ## Return value None. The role is deleted from the server. ## Examples ### Simple deletion ```bdfd $deleteRole[$roleID[Old Staff]] $sendMessage[🗑️ Role "Old Staff" deleted.] ``` ### Deletion with existence check ```bdfd $if[$roleExists[$roleID[VIP]]==true] $deleteRole[$roleID[VIP]] $sendMessage[Role VIP deleted.] $else $sendMessage[The role VIP does not exist.] $endif ``` ### Secure deletion command ```bdfd $if[$isAdmin==true] $if[$roleExists[$roleID[$message[1]]]==true] $deleteRole[$roleID[$message[1]]] $sendMessage[✅ Role deleted successfully.] $else $sendMessage[Role not found.] $endif $else $sendMessage[Permission denied. Admin required.] $endif ``` ## Notes - The bot must have the `ManageRoles` permission. - **Irreversible action**: the role is permanently deleted. - The bot cannot delete a role higher than its own. - Use `$roleExists` to check the existence before deletion. - To modify a role without deleting it, use `$modifyRole`. --- ### $editChannelPerms # $editChannelPerms The `$editChannelPerms[]` function **modifies the permissions of a role or user** on a channel using numerical values (bitfields). ## Syntax ``` $editChannelPerms[channelID;roleOrUserID;allow;deny] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the target channel. | | `roleOrUserID` | The ID of the role or the user. | | `allow` | Bitfield of permissions to allow (integer). | | `deny` | Bitfield of permissions to deny (integer). | ## Return value This function does not return a value. ## Behavior - The bot must have `MANAGE_ROLES` or `MANAGE_CHANNELS` permission. - Permissions are defined by numerical values: - `1024` = View channel - `2048` = Send messages - `4096` = Send TTS messages - `8192` = Manage messages - `16384` = Embed links - etc. ## Examples ### Locking a channel ```bdfd $editChannelPerms[$channelID;$guildID;0;2048] $sendMessage[Channel locked: messages disabled for @everyone.] ``` ### Unlocking a channel ```bdfd $editChannelPerms[$channelID;$guildID;2048;0] $sendMessage[Channel unlocked.] ``` ### Private channel by role ```bdfd $editChannelPerms[$channelID;$guildID;0;1024] $editChannelPerms[$channelID;$vipRoleID;1024;0] $sendMessage[Channel made private for the VIP role.] ``` ## Notes - The `allow` and `deny` permissions are sums of flags. Add the values together to combine permissions. - `$guildID` represents the @everyone role. - For a more readable approach, use `$modifyChannelPerms[]`. --- ### $editThread # $editThread The `$editThread[]` function **modifies the properties of an existing thread**: name, archiving, locking, and archive duration. ## Syntax ``` $editThread[threadID;name;(archived);(locked);(autoArchiveDuration)] ``` ## Parameters | Parameter | Description | |---|---| | `threadID` | The ID of the thread to modify. | | `name` | New name of the thread (1 to 100 characters). | | `archived` | Optional - `true` to archive, `false` to unarchive. | | `locked` | Optional - `true` to lock, `false` to unlock. | | `autoArchiveDuration` | Optional - New duration: 60, 1440, 4320 or 10080 minutes. | ## Return value This function does not return a value. ## Behavior - The bot must have the `MANAGE_THREADS` permission. - Archiving hides the thread from the active thread list. - Locking prevents new messages in the thread. ## Examples ### Close a support thread ```bdfd $editThread[$threadID;[$resolved] Support;true;true] $channelSendMessage[$threadID;This thread has been marked as resolved and locked.] $sendMessage[Thread closed.] ``` ### Unarchive a thread ```bdfd $editThread[$threadID;Active support;false;false;10080] $channelSendMessage[$threadID;Thread reopened for discussion.] ``` ### Rename based on subject ```bdfd $let[newName;[FAQ] $noMentionMessage] $editThread[$threadID;$newName] $sendMessage[Thread renamed to: $newName] ``` ## Notes - An archived thread cannot receive new messages until it is unarchived. - Locked threads can be unlocked with `locked=false`. - The archive duration is ignored if the thread is already manually archived. --- ### $emojiExists # $emojiExists The `$emojiExists` function **checks if a custom emoji exists** on the current server. ## Syntax ``` $emojiExists[name] ``` ## Parameters | Parameter | Description | |---|---| | `name` | The emoji name to check (without colons, e.g. `:name:`). | ## Return value - **Type**: String (boolean) - `true` if an emoji with this name exists on the server. - `false` if no emoji with this name is found. ## Behavior - The search is case-sensitive. - Checks only the emojis of the current server. - Useful as a check/guard before using emoji actions. ## Examples ### Before deletion ```bdfd $if[$emojiExists[$noMentionMessage]==true] $removeEmoji[$noMentionMessage] $sendMessage[✅ Emoji **$noMentionMessage** deleted.] $else $sendMessage[❌ The emoji **$noMentionMessage** does not exist.] $endif ``` ### Before creation ```bdfd $let[name;$noMentionMessage] $if[$emojiExists[$name]==true] $sendMessage[❌ An emoji named **$name** already exists.] $else $let[url;$getAttachments[$noMentionMessage]] $if[$url!=] $addEmoji[$name;$url] $sendMessage[✅ Emoji **$name** created !] $else $sendMessage[❌ Please attach an image.] $endif $endif ``` ### Verification in a message ```bdfd $if[$emojiExists[$message]==true] ✅ The emoji **$message** is available. $customEmoji[$message] $else ❌ The emoji **$message** does not exist. Import it with `!addemoji $message`. $endif ``` ## Notes - The name is case-sensitive: `Cool` ≠ `cool`. - Only checks emojis of the current server. - For external emojis, use `$emojiName[]` which returns empty if inaccessible. --- ### $emojiName # $emojiName The `$emojiName[]` function **retrieves the name of a custom emoji** from its Discord ID. ## Syntax ``` $emojiName[emojiID] ``` ## Parameters | Parameter | Description | |---|---| | `emojiID` | The Discord ID of the emoji (the digits in `<:name:ID>`). | ## Return value - **Type**: String - The name of the custom emoji. - An empty string if the emoji does not exist or is not accessible. ## Behavior - Extracts the name from the emoji's ID. - Works for emojis from any server that the bot has access to. - The ID can be extracted from a message containing the emoji. ## Examples ### Identification of emoji ```bdfd $let[emojiID;$message[1]] $let[name;$emojiName[$emojiID]] $if[$name!=] Emoji detected: **$name** (ID: $emojiID) $else Emoji not found. $endif ``` ### Log of emojis used ```bdfd $let[id;$message[1]] $if[$id!=] $sendMessage[$channelID[logs];📊 Emoji **$emojiName[$id]** used by $userName in $channelName.] $endif ``` ### List of emojis ```bdfd $title[📋 Server Emojis] $description[ $textSplit[$serverEmojis[,];, ] $index. $splitText[$index] — $emojiName[$splitText[$index]] $endTextSplit ] $sendMessage[] ``` ## Notes - Only works with custom emojis, not Unicode emojis. - The emoji must be on a server that the bot has access to. - Useful for logs and emoji usage statistics. --- ### $emojiCount / $emoteCount # $emojiCount / $emoteCount The `$emojiCount` function (alias `$emoteCount`) allows you to **retrieve the total number of custom emojis** present on the current server. ## Syntax ``` $emojiCount ``` or ``` $emoteCount ``` ## Parameters No parameters. ## Return value - **Type**: String (number) - The total number of custom emojis on the server. - Includes both static and animated emojis. ## Behavior - `$emoteCount` is an exact alias of `$emojiCount` (same behavior). - Counts all custom emojis of the server. - Useful for checking the usage slots of available emojis. ## Examples ### Emoji Statistics ```bdfd $title[🎨 Server Emojis] $description[ **Total number:** $emojiCount **Limit:** 50 emojis (more for boosted servers) **Remaining slots:** $math[50-$emojiCount] ] $color[#5865F2] $sendMessage[] ``` ### Limit alert ```bdfd $if[$emojiCount>=50] $sendMessage[⚠️ The emoji limit has been reached ($emojiCount/50). Delete some unused emojis.] $else $sendMessage[✅ $math[50-$emojiCount] emoji slots available.] $endif ``` ### Display using alias ```bdfd $title[📊 Server Info] $description[ **Members:** $membersCount **Channels:** $channelCount **Roles:** $roleCount **Emojis:** $emoteCount ] $sendMessage[] ``` ## Notes - The two names (`$emojiCount` and `$emoteCount`) are interchangeable. - The base limit is 50 emojis, which increases with server boosts. - Animated and static emojis share separate limits. --- ### $getBanReason # $getBanReason The `$getBanReason[]` function allows you to **retrieve the ban reason** of a banned user on the current server. ## Syntax ``` $getBanReason[userID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the banned user. | ## Return Value - **Type**: String - The ban reason as registered by Discord. - An empty string if the user is not banned or if no reason was specified. ## Behavior - The bot must have the `BAN_MEMBERS` permission to view ban reasons. - The reason returned is the one provided during the ban (via `$ban[userID;reason]`). - If the user is not banned, it returns an empty string. ## Examples ### Ban verification ```bdfd $let[reason;$getBanReason[$mentioned[1]]] $if[$reason!=] $title[🔨 Banned User] $description[ **User:** $userName[$mentioned[1]] **ID:** $mentioned[1] **Reason:** $reason ] $color[#ED4245] $sendMessage[] $else $sendMessage[This user is not banned.] $endif ``` ### Ban log ```bdfd $let[reason;$getBanReason[$userID]] $title[📋 Ban Details] $description[ **User:** $userName[$userID] ($userID) **Ban Reason:** $reason **Checked on:** $date[$day]/$date[$month]/$date[$year] ] $color[#5865F2] $sendMessage[] ``` ### Verification command ```bdfd $if[$checkContains[$userPerms;BanMembers]==true] $let[target;$findUser[$message]] $if[$target!=] $let[reason;$getBanReason[$target]] $if[$reason!=] $sendMessage[**$userName[$target]** is banned. Reason: $reason] $else $sendMessage[**$userName[$target]** is not banned.] $endif $else $sendMessage[User not found.] $endif $else $sendMessage[Permission denied.] $endif ``` ## Notes - The reason is stored by Discord and is persistent. - Useful for moderation logs and transparency. - Only users with `BAN_MEMBERS` can view the reasons. - Only works on the current server. --- ### $getBotInvite # $getBotInvite The `$getBotInvite[]` function allows you to **generate the invite link of the bot** with the permissions necessary for its functioning. ## Syntax ``` $getBotInvite[(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `guildID` | Optional - ID of the server to pre-select the server in the invite interface. | ## Return Value - **Type**: String (URL) - The complete invite URL of the bot. - Format: `https://discord.com/oauth2/authorize?client_id=ID&permissions=...&scope=bot` ## Behavior - The permissions included in the link correspond to those configured for the bot. - If a guildID is provided, the server selector is pre-filled. - The link includes the `bot` and `applications.commands` scopes automatically. ## Examples ### Invite command ```bdfd $title[📨 Invite the bot] $description[ Click on the link below to invite the bot to your server: [$getBotInvite] **Required permissions:** - Manage messages - Send messages - Embed links - Read message history ] $color[#5865F2] $sendMessage[] ``` ### Link for this server ```bdfd $title[🔗 Invite Link] $description[ Share this link to invite the bot to **$serverName**: ``` $getBotInvite[$guildID] ``` ] $sendMessage[] ``` ### Info + Invite command ```bdfd $title[🤖 Bot Info] $description[ **Name:** $botName **Servers:** $guildCount **Users:** $membersCount [🔗 Invite the bot]($getBotInvite) ] $thumbnail[$botAvatar] $color[#57F287] $sendMessage[] ``` ## Notes - The permissions in the link are defined in the Discord application configuration. - The link only works if the bot is public or if the user has access to the server. - For a server invite (not the bot's invite), use `$getServerInvite[]`. --- ### $getInviteInfo # $getInviteInfo The function `$getInviteInfo[]` allows **retrieving information** about a Discord invite from its code. ## Syntax ``` $getInviteInfo[code] ``` ## Parameters | Parameter | Description | |---|---| | `code` | The invite code (e.g. `abc123` for `discord.gg/abc123`). | ## Return Value - **Type** : String - Information about the invite: server name, description, number of members, etc. - Empty string if the invite is invalid or expired. ## Behavior - Works with any valid Discord invite code. - Does not require the bot to be on the target server. - Returns public information only. ## Examples ### Check an invite ```bdfd $let[info;$getInviteInfo[$message[1]]] $if[$info!=] $sendMessage[Invite information: >>> $info] $else $sendMessage[❌ Invalid or expired invite.] $endif ``` ### Invite spam detection ```bdfd $if[$checkContains[$message;discord.gg]==true] $deleteCommand $let[code;$replaceText[$message;https://discord.gg/;]] $let[info;$getInviteInfo[$code]] $if[$info!=] $sendMessage[⚠️ $username, external invites are not allowed. \ (Invite to: $info)] $else $sendMessage[⚠️ $username, invites are not allowed.] $endif $endif ``` ## Notes - The invite must be valid and not expired. - Useful for anti-spam invite moderation. - The returned information depends on what the server makes public. --- ### $getMessage # $getMessage The function `$getMessage[]` retrieves the **text content** of a message from its channel and message ID. ## Syntax ``` $getMessage[channelID;messageID] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the channel containing the message. | | `messageID` | The ID of the message to retrieve. | ## Return Value - **Type**: String - The text content of the message. - An empty string if the message does not exist, was deleted, or is inaccessible. ## Behavior - Returns only the text content (not embeds, attachments, etc.). - The bot must have access to the channel and the `READ_MESSAGE_HISTORY` permission. - The message must be less than 14 days old (Discord API limitation for unpinned messages). ## Examples ### Quoting a message ```bdfd $let[msgContent;$getMessage[$channelID;$noMentionMessage]] $if[$msgContent!=] $title[Quoted Message] $description[>>> $msgContent] $footer[Message ID: $noMentionMessage] $color[#5865F2] $sendMessage[] $else $sendMessage[Message not found.] $endif ``` ### Log of deleted message ```bdfd $let[msgContent;$getMessage[$channelID;$messageID]] $if[$msgContent!=] $title[🗑️ Retrieved Message] $description[ **Author:** $username **Content:** >>> $msgContent ] $color[#ED4245] $channelSendMessage[$logChannel;] $endif ``` ### Content verification ```bdfd $let[target;$getMessage[$channelID;$message[1]]] $if[$checkContains[$target;http]==true] $sendMessage[⚠️ This message contains a link.] $else $sendMessage[✅ No links detected.] $endif ``` ## Notes - Limited to the last 14 days for unpinned messages (Discord API restriction). - Does not retrieve embeds, only raw text. - Useful for citation systems, logs, and moderation. --- ### $getReactions # $getReactions The function `$getReactions[]` retrieves the **number of reactions** for a specific emoji on a given message. ## Syntax ``` $getReactions[channelID;messageID;emoji] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the channel containing the message. | | `messageID` | The ID of the target message. | | `emoji` | The emoji to count. Unicode (`👍`) or custom (`<:name:ID>`). | ## Return Value - **Type**: Integer - The number of times the emoji was used as a reaction on the message. - Returns `0` if the emoji is not present. ## Behavior - Counts ONLY the number of reactions, not specific users. - A single person can count for 1 even if they reacted several times (only one reaction per emoji per user). - The bot must have access to the channel to read the reactions. ## Examples ### Poll results ```bdfd $let[yes;$getReactions[$channelID;$messageID;👍]] $let[no;$getReactions[$channelID;$messageID;👎]] $title[Results of the poll] $description[ **Yes:** $yes vote(s) **No:** $no vote(s) **Total:** $sum[$yes;$no] votes ] $color[#5865F2] $sendMessage[] ``` ### Threshold verification ```bdfd $let[votes;$getReactions[$channelID;$messageID;✅]] $if[$votes>=5] $sendMessage[Threshold of 5 votes reached! Action executed.] $else $sendMessage[Still $sub[5;$votes] vote(s) needed.] $endif ``` ### Giveaway ```bdfd $let[participants;$getReactions[$channelID;$giveawayMsg;🎉]] $if[$participants>0] $sendMessage[**$participants** participant(s) in the giveaway!] $else $sendMessage[No participants at the moment.] $endif ``` ## Notes - The count includes the bot itself if it has reacted. - Useful for voting systems, polls, and giveaways. - Alternative methods are required to retrieve the list of users who reacted. --- ### $getRoleColor # $getRoleColor The function `$getRoleColor[]` retrieves the **hexadecimal color** of a Discord role. ## Syntax ``` $getRoleColor[roleID] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The Discord ID of the role. | ## Return Value - **Type**: String - The color in hexadecimal `#RRGGBB` format. - `#000000` (black) if the role has no defined color (default color). ## Behavior - Extracts the color configured for the role. - Returns `#000000` for roles without a color (default transparent). - The color is usable directly in `$color[]` or any other context requiring a color. ## Examples ### Simple display ```bdfd $let[roleID;$roleID[Admin]] Color of the role **$roleName[$roleID]**: $getRoleColor[$roleID] ``` ### Embed colored according to the role ```bdfd $let[roleID;$highestRole[$authorID]] $title[👤 Profile of $userName] $description[ **Main role:** $roleName[$roleID] **Color:** $getRoleColor[$roleID] ] $color[$getRoleColor[$roleID]] $thumbnail[$userAvatar[$authorID]] $sendMessage[] ``` ### Role palette ```bdfd $title[🎨 Role Colors] $description[ $textSplit[$serverRoles[,];, ] $index. $roleName[$splitText[$index]] — $getRoleColor[$splitText[$index]] $endTextSplit ] $sendMessage[] ``` ### Dynamic embed ```bdfd $let[color;$getRoleColor[$highestRole[$authorID]]] $if[$color==#000000] $let[color;#5865F2] $endif $title[Title] $description[Description] $color[$color] $sendMessage[] ``` ## Notes - If the role has a default color (no color), `$getRoleColor` returns `#000000`. - Tip: use `$if[$getRoleColor[$roleID]==#000000]` to detect roles without a color. - The color is compatible with the embed `$color[]` function. --- ### $getServerInvite # $getServerInvite The function `$getServerInvite[]` generates or retrieves a Discord server invite. ## Syntax ``` $getServerInvite[(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `guildID` | Optional - The ID of the server. Default: the server where the command is executed. | ## Return Value - **Type**: String (URL) - The server invite URL (format `https://discord.gg/CODE`). - An empty string if the bot does not have the `CREATE_INSTANT_INVITE` permission. ## Behavior - The bot must have the `CREATE_INSTANT_INVITE` permission on the target server. - The created invite is generally permanent (without expiration). - If an invite already exists, it may be reused. ## Examples ### Server invite link ```bdfd $title[🌐 Server Invite] $description[ Here is the invite link for **$serverName**: ``` $getServerInvite ``` Share it with your friends! ] $thumbnail[$serverIcon] $color[#5865F2] $sendMessage[] ``` ### Display in a welcome message ```bdfd $title[👋 Welcome to $serverName!] $description[ **Invite your friends:** $getServerInvite We are now **$membersCount** members! ] $color[#57F287] $sendMessage[] ``` ### Complete server information ```bdfd $title[📊 Server Information] $description[ **Name:** $serverName **Members:** $membersCount **Boosts:** Level $boostLevel **Invite:** $getServerInvite ] $thumbnail[$serverIcon] $color[#5865F2] $sendMessage[] ``` ## Notes - The created invite uses the channel where the command is executed (or the system channel). - To invite the bot itself, use `$getBotInvite[]`. - To get information about an invite, use `$getInviteInfo[]`. --- ### $giveRole # $giveRole The function `$giveRole` assigns a role to a user on the Discord server. The bot must have the `ManageRoles` permission. ## Syntax ``` $giveRole[userID;roleID] ``` Or with a single parameter (targeting the mentioned user): ``` $giveRole[roleID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the target user. If omitted, targets the mentioned user. | | `roleID` | The ID of the role to assign. Required. | ## Return Value None. The role is assigned. ## Examples ### Simple assignment ```bdfd $giveRole[$mentioned[1];$roleID[Confirmed]] $sendMessage[<@$mentioned[1]> has received the Confirmed role!] ``` ### Auto-assignment for the author ```bdfd $giveRole[$roleID[Member]] $sendMessage[$userName, you now have the Member role.] ``` ### Assignment command with verification ```bdfd $if[$roleExists[$roleID[$message[2]]]==true] $giveRole[$mentioned[1];$roleID[$message[2]]] $sendMessage[Role assigned successfully.] $else $sendMessage[This role does not exist.] $endif ``` ### Assignment after hierarchy check ```bdfd $if[$rolePosition[$getRole[$authorID;1]]>$rolePosition[$roleID[Staff]]] $giveRole[$mentioned[1];$roleID[Staff]] $sendMessage[<@$mentioned[1]> is now Staff!] $else $sendMessage[You do not have permission to promote members.] $endif ``` ## Notes - The bot must have the `ManageRoles` permission. - The bot cannot assign a role higher than its own highest role. - To assign multiple roles at once, use `$giveRoles`. - To replace all roles of a user, use `$setUserRoles`. - Functional equivalent to `$roleGrant`. --- ### $giveRoles # $giveRoles The function `$giveRoles` assigns multiple roles at once to a user. It is the multi-role version of `$giveRole`. The bot must have the `ManageRoles` permission. ## Syntax ``` $giveRoles[userID;role1;role2;...] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the target user. Required. | | `role1;role2;...` | The IDs of the roles to assign, separated by `;`. Required. | ## Return Value None. All specified roles are assigned. ## Examples ### Simple multiple assignment ```bdfd $giveRoles[$mentioned[1];$roleID[Member];$roleID[Notifications]] $sendMessage[<@$mentioned[1]> has received the Member and Notifications roles.] ``` ### Grouped assignment with a condition ```bdfd $if[$isAdmin==true] $giveRoles[$mentioned[1];$roleID[Modo];$roleID[Staff];$roleID[VIP]] $sendMessage[All staff roles assigned to <@$mentioned[1]>.] $else $sendMessage[Permission denied.] $endif ``` ### Welcome command ```bdfd $giveRoles[$authorID;$roleID[Member];$roleID[New];$roleID[Auto]] $sendMessage[Welcome $userName! Default roles assigned.] ``` ## Notes - The bot must have the `ManageRoles` permission. - The roles are separated by `;` in the syntax. - To assign a single role, `$giveRole` is simpler. - To replace all existing roles, use `$setUserRoles`. - Roles already possessed by the user are ignored. --- ### $hasPerms # $hasPerms The function `$hasPerms` is an **inline permission check**. Unlike guards (`$onlyPerms`, `$onlyBotPerms`), it does not interrupt the command but returns `"true"` or `"false"`, allowing fine-grained conditional management. ## Syntax ``` $hasPerms[userID;permission1;permission2;...] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `userID` | Snowflake | The ID of the user whose permissions to check. | | `permission1;permission2;...` | String[] | List of permissions to verify. **All** permissions must be present. | ## Return Value - **Type**: String `"true"` or `"false"` - `"true"`: the user has **all** listed permissions - `"false"`: at least one permission is missing ## Behavior - Checks the global permissions of the user on the server. - The check is of type **AND**: all listed permissions are required. - The `Administrator` permission implicitly satisfies all others. - **Does not interrupt** the command (unlike `$onlyPerms`). ## Examples ### Simple Conditional Check ```bdfd $if[$hasPerms[$authorID;BanMembers]==true] $ban[$mentioned[1];$noMentionMessage] $sendMessage[Member banned.] $else $sendMessage[❌ You do not have permission to ban.] $endif ``` ### Multi-Permission Check ```bdfd $if[$hasPerms[$authorID;ManageMessages;ManageChannels]==true] $clear[$message[1]] $sendMessage[$message[1] messages deleted.] $else $sendMessage[❌ Insufficient permissions.] $endif ``` ### Check Bot Permissions ```bdfd $if[$hasPerms[$botID;KickMembers]==false] $sendMessage[⚠️ I do not have permission to kick. Please check my permissions.] $stop $endif $kick[$mentioned[1]] ``` ### Conditional Log ```bdfd $if[$hasPerms[$authorID;Administrator]==true] $log[Admin action: $userName used the command.] $endif ``` ## Notes - `$hasPerms` is an **inline** function: it does not block the command. Use it with `$if` to create conditional behaviors. - For the bot, use `$botID` as the `userID`. - Permission names are in **PascalCase** (`BanMembers`, `KickMembers`, `ManageMessages`, etc.). - For a check with automatic interruption, use `$onlyPerms` (user) or `$onlyBotPerms` (bot). - `$checkUserPerms` is an alias of `$hasPerms`. --- ### $ignoreChannels # $ignoreChannels The function guard `$ignoreChannels` **silently** interrupts the execution of the command if it is used in one of the specified channels. Unlike `$onlyForChannels` which acts as a whitelist, `$ignoreChannels` acts as a **blacklist** of channels. ## Syntax ``` $ignoreChannels[channelID1;channelID2;...] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `channelID1;channelID2;...` | Snowflake[] | Channel IDs to ignore, separated by `;`. | ## Behavior - If the current channel is in the list, the command execution is stopped **without any message** (total silence). - If the channel is not in the list, the command continues normally. - No error message is supported — the guard is strictly silent. ## Examples ### Restricting commands in general discussion channels ```bdfd $ignoreChannels[123456789012345678] $sendMessage[Moderation command executed.] ``` ### Multiple blacklisted channels ```bdfd $ignoreChannels[111111111111111111;222222222222222222;333333333333333333] $ban[$mentioned[1]] ``` ### Ignore announcement channels ```bdfd $ignoreChannels[123456789012345678;987654321098765432] $sendMessage[Action completed.] ``` ## Notes - `$ignoreChannels` is a silent **blacklist**. For a **whitelist** with an error message, use `$onlyForChannels`. - No error message is sent to the user. If you want to notify the user, use `$onlyForChannels` with an error message. - Place this at the beginning of the command, before any other logic. - Convenient for disabling commands in specific channels without spamming users. --- ### $ignoreLinks # $ignoreLinks The function guard `$ignoreLinks` detects the presence of **HTTP/HTTPS links** in the triggering message. If a link is found, command execution is silently interrupted. ## Syntax ``` $ignoreLinks ``` ## Parameters No parameters. `$ignoreLinks` is used on its own. ## Behavior - Analyzes the content of the message searching for `http://` or `https://`. - If a link is found, the command is immediately interrupted **without a message**. - If no link is found, the command continues normally. - Detects all standard links (HTTP and HTTPS), but not links like `discord.gg`, `ftp://`, etc. ## Examples ### Anti-link spam command ```bdfd $ignoreLinks $sendMessage[Your message was processed (no link detected).] ``` ### With custom error message ```bdfd $if[$messageContains[https://;http://]==true] $sendMessage[❌ Links are forbidden in this command.] $stop $endif $sendMessage[Processing OK.] ``` ### Log attempts with links ```bdfd $if[$messageContains[https://;http://]==true] $log[Link blocked: $message — Author: $userName ($authorID)] $stop $endif $sendMessage[Message processed.] ``` ## Notes - `$ignoreLinks` is **silent**: the user receives no notification. To inform the user, use manual checking with `$messageContains`. - It does not detect links in the format `discord.gg/invite` or hidden Markdown links `[text](https://...)`. To cover these cases, use `$messageContains`. - `$ignoreLinks` only checks the triggering message, not embeds or attachments. - Ideal for channels where links are forbidden (spam/phishing prevention). --- ### $kick # $kick The function `$kick` **kicks a user** from the Discord server. Unlike a ban, the user can rejoin with a new invite. The bot must have the `Kick Members` permission. ## Syntax ``` $kick[userID;(reason)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user to kick. Required. | | `reason` | Optional. The reason for the kick. | ## Return Value None. The user is kicked from the server. ## Examples ### Simple kick ```bdfd $kick[$mentioned[1];Rules violation] $sendMessage[<@$mentioned[1]> has been kicked.] ``` ### Kick command with confirmation ```bdfd $if[$argsCount<1] $sendMessage[Usage: !kick <@mention> ] $stop $endif $kick[$mentioned[1];$replaceText[$message;-;$mentioned[1];]] $sendMessage[✅ Kick completed successfully.] ``` ### Check before kick ```bdfd $if[$isAdmin==true] $kick[$mentioned[1];Abuse] $sendMessage[Member kicked.] $else $sendMessage[Permission denied. Admin required.] $endif ``` ## Notes - The bot must have the `Kick Members` permission. - The kicked user can be re-invited. - Use `$ban` for a permanent ban. - To kick the mentioned user without specifying the ID, use `$kickMention`. --- ### $kickMention # $kickMention The function `$kickMention` **automatically kicks the user mentioned** in the triggering message. This is a convenient shortcut that avoids the need to specify an ID. The bot must have the `Kick Members` permission. ## Syntax ``` $kickMention ``` ## Parameters No parameters. The function automatically detects the mentioned user. ## Return Value None. The mentioned user is kicked. ## Examples ### Simple kick ```bdfd $kickMention $sendMessage[Member kicked successfully!] ``` ### Kick with default reason ```bdfd $kickMention $sendMessage[<@$mentioned[1]> has been kicked for violating the rules.] ``` ## Notes - The triggering message must contain a user mention. - The bot must have the `Kick Members` permission. - To kick a specific user by ID, use `$kick`. - If no mention is present, the behavior may be undefined. --- ### $modifyChannel # $modifyChannel The function `$modifyChannel` allows you to modify the properties of an existing channel. ## Syntax ``` $modifyChannel[channelID;name;(topic);(categoryID);(nsfw);(slowmode)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the channel to modify. | | `name` | The new name of the channel. | | `topic` | Optional - The new topic (max 1024 characters). | | `categoryID` | Optional - The ID of the new category, `0` for none. | | `nsfw` | Optional - `true`/`false` for NSFW status. | | `slowmode` | Optional - The slowmode delay in seconds (0-21600). | ## Return Value This function does not return any value. ## Behavior - The bot must have the `MANAGE_CHANNELS` permission. - Optional parameters can be left empty to keep their current value. - The parameter order is important — use empty semicolons `;` to skip parameters. ## Examples ### Renaming a channel ```bdfd $modifyChannel[$channelID;archives-$date] $sendMessage[Channel renamed.] ``` ### Changing the slowmode ```bdfd $modifyChannel[$channelID;$channelName;;;false;5] $sendMessage[Slowmode set to 5 seconds.] ``` ### Moving to a category ```bdfd $modifyChannel[$channelID;$channelName;;123456789] $sendMessage[Channel moved.] ``` ### Modifying all properties ```bdfd $modifyChannel[$channelID;rules;Server Rules - updated on $date;123456789;false;0] $sendMessage[Channel updated successfully.] ``` ## Notes - Use empty parameters (`;`) to skip options you do not want to modify. - Channel names must follow the same rules as in `$createChannel[]`. - To modify channel permissions, use `$modifyChannelPerms[]`. --- ### $modifyChannelPerms # $modifyChannelPerms The function `$modifyChannelPerms` allows you to modify the permissions of a role or user in a channel using a readable syntax. ## Syntax ``` $modifyChannelPerms[channelID;roleOrUserID;permissions] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the target channel. | | `roleOrUserID` | The ID of the role or the user. | | `permissions` | Permissions prefixed with `+` (allow) or `-` (deny). Example: `+sendmessages -attachfiles`. | ## Return Value This function does not return any value. ## Behavior - More readable than `$editChannelPerms[]` thanks to permission names. - Available permissions: `viewchannel`, `sendmessages`, `managemessages`, `embedlinks`, `attachfiles`, `readmessagehistory`, `mentioneveryone`, `useexternalemojis`, `connect`, `speak`, `mute`, `deafen`, `move`, `usevad`, `priorityspeaker`, `stream`, etc. - The bot must have `MANAGE_CHANNELS` or `MANAGE_ROLES` permissions. ## Examples ### VIP Private Channel ```bdfd $modifyChannelPerms[$channelID;$guildID;-viewchannel] $modifyChannelPerms[$channelID;$vipRoleID;+viewchannel +sendmessages] $sendMessage[VIP Channel configured.] ``` ### Fast Lockdown ```bdfd $modifyChannelPerms[$channelID;$guildID;-sendmessages] $sendMessage[🔒 Channel locked.] ``` ### Unlocking ```bdfd $modifyChannelPerms[$channelID;$guildID;+sendmessages] $sendMessage[🔓 Channel unlocked.] ``` ### Mixed Permissions ```bdfd $modifyChannelPerms[$channelID;$mutedRoleID;-sendmessages -speak -connect] $sendMessage[Permissions of the muted role applied.] ``` ## Notes - `$modifyChannelPerms` is recommended because it is more readable than `$editChannelPerms[]`. - `$guildID` represents `@everyone`. - Permissions that are not mentioned remain unchanged. --- ### $modifyRole # $modifyRole The function `$modifyRole` **modifies the properties of an existing role** (name, color, display, mentionability). The bot must have the `ManageRoles` permission. ## Syntax ``` $modifyRole[roleID;name;(color);(hoist);(mentionable)] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the role to modify. Required. | | `name` | The new name of the role. Required. | | `color` | Optional. New hex color code. | | `hoist` | Optional. `"yes"` or `"no"` to display role members separately from online members. | | `mentionable` | Optional. `"yes"` or `"no"` to make the role mentionable. | ## Return Value None. The properties of the role are updated. ## Examples ### Renaming a role ```bdfd $modifyRole[$roleID[VIP];Super VIP] $sendMessage[✅ Role renamed to "Super VIP".] ``` ### Changing the color ```bdfd $modifyRole[$roleID[Staff];Staff;#FFD700] $sendMessage[✅ Color of the Staff role changed to gold.] ``` ### Modifying all properties ```bdfd $modifyRole[$roleID[Moderator];Moderator;#E74C3C;yes;yes] $sendMessage[✅ Moderator role fully updated.] ``` ### Modification command ```bdfd $if[$isAdmin==true] $modifyRole[$roleID[$message[1]];$message[2];$message[3]] $sendMessage[Role modified.] $else $sendMessage[Permission denied.] $endif ``` ## Notes - The bot must have the `ManageRoles` permission. - The `name` parameter is required even if you are not changing the name. - To modify only the permissions, use `$modifyRolePerms`. - To create a new role, use `$createRole`. - To delete a role, use `$deleteRole`. --- ### $modifyRolePerms # $modifyRolePerms The function `$modifyRolePerms` **modifies the permissions** of an existing role on the Discord server. The bot must have the `ManageRoles` permission. ## Syntax ``` $modifyRolePerms[roleID;permissions] ``` ## Parameters | Parameter | Description | |---|---| | `roleID` | The ID of the role to modify. Required. | | `permissions` | List of permissions in the format `permission=value`, separated by `;`. Required. | ## Return Value None. The permissions of the role are updated. ## Examples ### Disabling sending of messages ```bdfd $modifyRolePerms[$roleID[Muted];sendmessages=no;sendmessagesinthreads=no] $sendMessage[✅ The Muted role can no longer send messages.] ``` ### Enabling moderation permissions ```bdfd $modifyRolePerms[$roleID[Mod];banmembers=yes;kickmembers=yes;managemessages=yes] $sendMessage[✅ Moderation permissions enabled for the Mod role.] ``` ### Restricting a role ```bdfd $modifyRolePerms[$roleID[Restricted];sendmessages=no;connect=no;speak=no] $sendMessage[✅ Restricted role configured.] ``` ### Permission management command ```bdfd $if[$isAdmin==true] $modifyRolePerms[$roleID[$message[1]];$message[2]] $sendMessage[Permissions updated.] $else $sendMessage[Permission denied.] $endif ``` ## Notes - The bot must have the `ManageRoles` permission. - Permission format: `permission=yes` or `permission=no`. - Permissions are separated by `;`. - To modify role properties (name, color), use `$modifyRole`. - To view the current permissions of a role, use `$rolePerms`. - Permissions that are not specified remain unchanged. --- ### $mute # $mute The function `$mute` **mutes a user** on the Discord server. This prevents them from speaking in voice channels. The bot must have the `MuteMembers` permission. ## Syntax ``` $mute[userID;(reason)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user to mute. Required. | | `reason` | Optional. The reason for the mute. | ## Return Value None. The user is muted. ## Examples ### Simple Mute ```bdfd $mute[$mentioned[1];Spam vocal] $sendMessage[<@$mentioned[1]> was muted for voice spam.] ``` ### Mute with moderation command ```bdfd $if[$argsCount<1] $sendMessage[Usage: !mute <@mention> ] $stop $endif $mute[$mentioned[1];$replaceText[$message;-;$mentioned[1];]] $sendMessage[🔇 <@$mentioned[1]> is now muted.] ``` ### Verification before mute ```bdfd $if[$isAdmin==true] $mute[$mentioned[1];Violation of voice rules] $sendMessage[Member muted.] $else $sendMessage[Permission denied.] $endif ``` ## Notes - The bot must have the `MuteMembers` permission. - The mute prevents users from speaking in voice channels, not from writing in text channels. - To prevent sending messages, create a role without write permissions and use `$giveRole`. - To unmute the user, use `$unmute`. - For a temporary timeout, use `$timeout`. --- ### $newTicket # $newTicket The function `$newTicket` allows you to **create a ticket** as a dedicated text channel in a specific category. ## Syntax ``` $newTicket[categoryID;(name);(message)] ``` ## Parameters | Parameter | Description | |---|---| | `categoryID` | The ID of the category where the ticket channel should be created. | | `name` | Optional - The name of the channel. Default: `ticket-{username}`. | | `message` | Optional - An automatic welcome message inside the ticket. | ## Return Value - **Type** : Snowflake (string) - The ID of the created ticket channel. - An empty string if it fails (due to permissions, invalid category, etc.). ## Behavior - The bot must have the `MANAGE_CHANNELS` permission to create the channel. - The ticket creator (the user who ran the command) automatically receives access to the channel. - Other members cannot see the ticket by default. ## Examples ### Simple support ticket ```bdfd $let[ticket;$newTicket[123456789;support-$username;Welcome $username! \ A staff member will assist you shortly. \ Please describe your issue in detail.]] $if[$ticket!=] $sendMessage[✅ Ticket created: <#$ticket>] $else $sendMessage[❌ Error during the creation of the ticket.] $endif ``` ### Ticket with staff notification ```bdfd $let[ticket;$newTicket[123456789;ticket-$username]] $if[$ticket!=] $channelSendMessage[$staffChannel;📩 New ticket by $username: <#$ticket>] $sendMessage[Your ticket has been created: <#$ticket>] $endif ``` ### Ticket with limit ```bdfd $let[userTickets;$getUserVar[ticketCount]] $if[$userTickets>=3] $sendMessage[❌ You already have 3 open tickets. Please close one before creating a new one.] $else $let[ticket;$newTicket[123456789;ticket-$username]] $if[$ticket!=] $setUserVar[ticketCount;$sum[$userTickets;1]] $sendMessage[✅ Ticket #$sum[$userTickets;1] created: <#$ticket>] $endif $endif ``` ## Notes - Tickets are regular text channels, not threads. - Permissions are automatically configured for the creator. - To close a ticket, use `$closeTicket[]`. - Ideal for support systems, appeals, and modmails. --- ### $onlyAdmin # $onlyAdmin The guard function `$onlyAdmin` immediately stops the execution of the command if the user who triggered it does not have the **Administrator** permission on the server. ## Syntax ``` $onlyAdmin ``` ## Parameters No parameters. `$onlyAdmin` is used alone, without arguments. ## Behavior - If the user is an administrator, the command continues normally. - If the user is **not** an administrator, the command is immediately interrupted (implicit `$stop`). - No error message is sent by default — the bot remains silent. - Functional equivalent to `$onlyPerms[administrator]` but more readable and concise. ## Examples ### Restricting a command to administrators ```bdfd $onlyAdmin $ban[$mentioned[1]] $sendMessage[<@$mentioned[1]> was banned.] ``` ### Administration Panel ```bdfd $onlyAdmin $title[⚙️ Admin Panel] $description[ **Available Commands:** `!ban`, `!kick`, `!mute`, `!config` ] $color[#ED4245] $sendMessage[] ``` ### Hybrid Command (Admin or Moderator role) ```bdfd $if[$isAdmin==false] $onlyForRoles[123456789012345678] $endif $sendMessage[Moderation action allowed.] ``` ## Notes - `$onlyAdmin` only checks the `Administrator` permission. To check other permissions, use `$onlyPerms`. - The owner of the server is implicitly an administrator and passes this guard. - To add a custom error message, use `$onlyPerms[administrator;Error message]` instead. - Place this function at the **very top** of the command, before any other logic. --- ### $onlyBotChannelPerms # $onlyBotChannelPerms The guard function `$onlyBotChannelPerms` checks if the **bot** has the specified permissions **in the current channel**. Unlike `$onlyBotPerms` which checks server-wide permissions, this function respects channel permission overwrites. ## Syntax ``` $onlyBotChannelPerms[permission1;permission2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `permission1;permission2;...` | String[] | Channel permissions that the bot must have in this channel. Separator `;`. | | `errorMessage` | String (optional) | The message sent if the bot lacks any of the permissions. | ## Behavior - Checks the effective permissions of the bot in the **channel where the command is executed**. - Takes channel overwrites into account (specific channel permissions modifying role inheritance). - If any permission is missing, the command execution is halted. - Works even if the bot has the permission server-wide, but the channel has a deny overwrite. ## Examples ### Checking embed creation capability ```bdfd $onlyBotChannelPerms[SendMessages;EmbedLinks;❌ I cannot post embeds in this channel.] $title[Announcement] $description[This is an important announcement.] $color[#5865F2] $sendMessage[] ``` ### Checking voice permissions ```bdfd $onlyBotChannelPerms[Connect;Speak;❌ I do not have access to this voice channel.] $joinVC[$voiceChannelID] $sendMessage[Connecting to the voice channel...] ``` ### File uploads ```bdfd $onlyBotChannelPerms[AttachFiles;❌ I cannot send files here.] $attachment[./report.pdf] $sendMessage[Here is the report.] ``` ## Notes - `$onlyBotChannelPerms` checks **channel** permissions, while `$onlyBotPerms` checks **server** permissions. - Channel permissions include: `SendMessages`, `EmbedLinks`, `AttachFiles`, `AddReactions`, `UseExternalEmojis`, `Connect`, `Speak`, `Stream`, `UseVAD`, `PrioritySpeaker`, `MuteMembers`, `DeafenMembers`, `MoveMembers`, `ViewChannel`, `ReadMessageHistory`, `SendTTSMessages`, `UseApplicationCommands`, `ManageMessages`, `ManageChannels`, `CreateInstantInvite`, `UseEmbeddedActivities`. - Combine with `$onlyBotPerms` for a complete check (server + channel). --- ### $onlyBotPerms # $onlyBotPerms The guard function `$onlyBotPerms` checks if the **bot itself** has all the specified Discord permissions on the server. If the bot lacks any of these permissions, the command execution is halted. ## Syntax ``` $onlyBotPerms[permission1;permission2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `permission1;permission2;...` | String[] | List of Discord permissions separated by `;`. The bot must possess **all** of these permissions. | | `errorMessage` | String (optional) | The message sent if the bot does not have the required permissions. If omitted, the bot remains silent. | ## Behavior - Checks the global permissions of the bot on the server (not just in the current channel). - The `Administrator` permission implicitly covers all other permissions. - If the bot lacks the permissions, the command execution stops immediately. - Difference from `$onlyPerms`: `$onlyPerms` checks the **user**, while `$onlyBotPerms` checks the **bot**. ## Examples ### Check before banning ```bdfd $onlyBotPerms[BanMembers;❌ I do not have the **BanMembers** permission. Please contact an admin.] $ban[$mentioned[1]] ``` ### Multi-permission check ```bdfd $onlyBotPerms[ManageMessages;ReadMessageHistory;❌ I need permissions to manage messages.] $clear[50] $sendMessage[Clean up completed.] ``` ### Role creation command ```bdfd $onlyBotPerms[ManageRoles;❌ I cannot create roles without the **ManageRoles** permission.] $createRole[New Role;#5865F2] $sendMessage[Role created successfully.] ``` ## Notes - Use this systematically before any action requiring specific bot permissions (banning, kicking, managing roles, deleting messages, etc.). - For permissions specific to the **channel** (e.g. `SendMessages`, `ViewChannel`), use `$onlyBotChannelPerms`. - Permission names must be in PascalCase (`ManageMessages`, `BanMembers`, etc.). - Equivalent to `$onlyIf[$hasPerms[$botID;Permission]==true]` but more concise. --- ### $onlyForCategories # $onlyForCategories The guard function `$onlyForCategories` checks if the channel where the command is executed belongs to one of the specified Discord categories. If the channel is not part of the allowed categories, the command execution is halted. ## Syntax ``` $onlyForCategories[categoryID1;categoryID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `categoryID1;categoryID2;...` | Snowflake[] | The IDs of the allowed categories. | | `errorMessage` | String (optional) | The message sent if the channel does not belong to the allowed categories. | ## Behavior - Gets the ID of the parent category of the current channel via `$channelCategoryID`. - Compares this category ID with the provided list. - If the category matches, the command continues; otherwise, execution is halted. - If the channel does not have a parent category, the command is always halted. ## Examples ### Tickets Category ```bdfd $onlyForCategories[123456789012345678;❌ Only available in ticket channels.] $closeTicket ``` ### Moderation + Staff Categories ```bdfd $onlyForCategories[111111111111111111;222222222222222222;❌ Out of bounds.] $clear[50] ``` ### Without error message ```bdfd $onlyForCategories[123456789012345678] $sendMessage[Function allowed in this category.] ``` ## Notes - A Discord category is a container of channels. Enable Developer Mode to copy its ID. - `$onlyForCategories` is broader than `$onlyForChannels` because it allows all channels inside an entire category. - For channels with no parent category, the command will always be blocked. - Combine with `$onlyForChannels` for more granular rules (category + specific channels). --- ### $onlyForChannels # $onlyForChannels The guard function `$onlyForChannels` limits the execution of a command to one or several specific Discord channels. If the command is executed elsewhere, execution is halted. ## Syntax ``` $onlyForChannels[channelID1;channelID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `channelID1;channelID2;...` | Snowflake[] | The IDs of the allowed channels, separated by `;`. | | `errorMessage` | String (optional) | The message sent if the channel is not allowed. | ## Behavior - Compares the ID of the current channel with the provided list. - If the channel is in the list, the command continues normally. - If the channel is **not** in the list, the command execution is halted. - Useful for creating dedicated channels (e.g., `#commands` or `#bots`). ## Examples ### Dedicated command channel ```bdfd $onlyForChannels[123456789012345678;❌ Please use this command in <#123456789012345678>.] $sendMessage[Processing...] ``` ### Multiple allowed channels ```bdfd $onlyForChannels[111111111111111111;222222222222222222;333333333333333333;❌ Channel not allowed.] $clear[50] ``` ### Without error message ```bdfd $onlyForChannels[123456789012345678] $ban[$mentioned[1]] ``` ## Notes - Enable Discord **Developer Mode** to easily copy channel IDs. - `$onlyForChannels` acts as a **whitelist** (allows specific channels). For a **blacklist** (blocking specific channels), use `$ignoreChannels`. - To restrict a command to an entire category, use `$onlyForCategories`. - Combine with `$onlyForServers` to restrict commands to certain servers and specific channels. --- ### $onlyForIDs # $onlyForIDs The guard function `$onlyForIDs` restricts the execution of a command to a specific list of user IDs. It is a direct alias of `$onlyForUsers` — both functions are interchangeable. ## Syntax ``` $onlyForIDs[userID1;userID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `userID1;userID2;...` | Snowflake[] | Discord IDs of allowed users. | | `errorMessage` | String (optional) | The message sent to users who are not allowed. | ## Behavior - Compares the ID of the triggering user (`$authorID`) with the list. - If the ID matches, the command execution continues. - If the ID does not match, the command execution is halted. - Functionally identical to `$onlyForUsers`. ## Examples ### Owner-only command ```bdfd $onlyForIDs[$botOwnerID;❌ Only the owner can use this command.] $eval[$message] ``` ### Multiple allowed IDs ```bdfd $onlyForIDs[111111111111111111;222222222222222222;333333333333333333] $sendMessage[Access allowed.] ``` ### Informative error message ```bdfd $onlyForIDs[123456789012345678;❌ This command is undergoing maintenance. Only the developer can use it.] ``` ## Notes - `$onlyForIDs` and `$onlyForUsers` are **strictly identical**. Use whichever is more readable in your context. - Enable **Developer Mode** in Discord (User Settings → Advanced) to copy IDs. - For blacklisting IDs, use `$blacklistIDs`. - If you want to allow an entire role rather than specific users, use `$onlyForRoles`. --- ### $onlyForRoleIDs # $onlyForRoleIDs The guard function `$onlyForRoleIDs` checks if the user has **at least one** of the specified roles by their ID. It is a direct alias of `$onlyForRoles`. ## Syntax ``` $onlyForRoleIDs[roleID1;roleID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `roleID1;roleID2;...` | Snowflake[] | The IDs of the allowed roles. | | `errorMessage` | String (optional) | The message sent if no matching role is found. | ## Behavior - Checks if the user possesses at least one of the listed roles. - This is an **OR** check: having a single matching role is sufficient. - Exact alias of `$onlyForRoles`. ## Examples ### Staff command ```bdfd $onlyForRoleIDs[123456789012345678;❌ Reserved for staff.] $ban[$mentioned[1]] ``` ### Multi-roles ```bdfd $onlyForRoleIDs[111111111111111111;222222222222222222;❌ Access denied.] $clear[100] ``` ## Notes - `$onlyForRoleIDs` and `$onlyForRoles` are interchangeable. - To blacklist roles by ID, use `$blacklistRoleIDs`. - To allow specific users instead of roles, use `$onlyForIDs`. --- ### $onlyForRoles # $onlyForRoles The guard function `$onlyForRoles` checks if the user has **at least one** of the specified Discord roles. If the user does not have any of these roles, the command execution is halted. ## Syntax ``` $onlyForRoles[roleID1;roleID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `roleID1;roleID2;...` | Snowflake[] | The IDs of the allowed roles, separated by `;`. | | `errorMessage` | String (optional) | The message sent if the user has none of the roles. | ## Behavior - Checks the roles of the triggering user. - The check is an **OR** operation: the user only needs to have at least one of the listed roles. - If the user has at least one role from the list, the command continues. - If the user has **none** of the listed roles, the command execution is halted. ## Examples ### Command reserved for moderators ```bdfd $onlyForRoles[123456789012345678;❌ Only moderators can use this command.] $mute[$mentioned[1];Reason] $sendMessage[$mentioned[1] was muted.] ``` ### Multiple allowed roles (Mod or Admin) ```bdfd $onlyForRoles[111111111111111111;222222222222222222;❌ Insufficient permissions.] $clear[100] ``` ### Staff command with redirect message ```bdfd $onlyForRoles[123456789012345678;❌ Command reserved for staff. Please open a ticket for any inquiries.] $sendMessage[Welcome to the staff panel.] ``` ## Notes - The check is an **OR** check (a single role is enough), unlike `$onlyPerms` which performs an **AND** operation on permissions. - To check by role name dynamically, use `$hasRole[$authorID;Role Name]`. - `$onlyForRoleIDs` is an alias of `$onlyForRoles`. - To blacklist roles, use `$blacklistRoles` or `$blacklistRoleIDs`. - Combine with `$onlyForChannels` to restrict a command by both role and channel. --- ### $onlyForServers # $onlyForServers The guard function `$onlyForServers` restricts command execution to one or more specific Discord servers. If the command is used on another server, it is interrupted. ## Syntax ``` $onlyForServers[guildID1;guildID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `guildID1;guildID2;...` | Snowflake[] | IDs of the authorized servers. | | `errorMessage` | String (optional) | Message sent if the server is not authorized. | ## Behavior - Compares the current server ID (`$guildID` / `$serverID`) with the list. - If the server is in the list, the command continues. - If the server is **not** in the list, the command is interrupted. - Alias: `$onlyForGuilds` (both syntaxes are equivalent). ## Examples ### Single server ```bdfd $onlyForServers[123456789012345678;❌ This command is exclusive to our main server.] $sendMessage[Welcome!] ``` ### Multiple servers ```bdfd $onlyForServers[111111111111111111;222222222222222222;❌ Command not available here.] $restart ``` ### Without error message ```bdfd $onlyForServers[123456789012345678] $sendMessage[Private server feature enabled.] ``` ## Notes - `$onlyForServers` and `$onlyForGuilds` are interchangeable. Use the clearest syntax for your team. - Very useful for private bots or features exclusive to a partner server. - To blacklist servers, use `$blacklistServers`. - Combine with `$onlyForChannels` for fine-grained control (server + channel). --- ### $onlyForUsers # $onlyForUsers The guard function `$onlyForUsers` restricts command execution to a specific list of users, identified by their Discord ID. If the user who triggers the command is not in the list, the command is interrupted. ## Syntax ``` $onlyForUsers[userID1;userID2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `userID1;userID2;...` | Snowflake[] | List of Discord IDs of authorized users. Separator `;`. | | `errorMessage` | String (optional) | Message sent to unauthorized users. | ## Behavior - Compares the triggering user's ID with the provided list. - If the ID matches one of the IDs in the list, the command continues. - If the ID matches **no** ID in the list, the command is interrupted. - The error message, if provided, is sent before the interruption. ## Examples ### Owner-only command ```bdfd $onlyForUsers[$botOwnerID;❌ Command reserved for the bot owner.] $restart ``` ### Multiple trusted users ```bdfd $onlyForUsers[111111111111111111;222222222222222222;333333333333333333;❌ Access denied.] $sendMessage[Welcome to the control panel.] ``` ### Without error message ```bdfd $onlyForUsers[123456789012345678] $eval[$message] ``` ## Notes - Discord IDs are 17 to 19 digit numbers (snowflakes). Enable **Developer Mode** in Discord to obtain them (right-click → Copy ID). - `$onlyForUsers` checks the user ID, not the name or tag. Use `$onlyForRoles` for a role-based check. - `$onlyForIDs` is an alias of `$onlyForUsers` — the two functions are interchangeable. - To blacklist users instead of whitelisting them, use `$blacklistUsers` or `$blacklistIDs`. --- ### $onlyNSFW # $onlyNSFW The guard function `$onlyNSFW` checks that the channel where the command is executed is marked as **NSFW** (Not Safe For Work) on Discord. If the channel is not NSFW, the command is silently interrupted. ## Syntax ``` $onlyNSFW ``` ## Parameters No parameters. `$onlyNSFW` is used alone, without arguments. ## Behavior - If the channel is NSFW, the command continues normally. - If the channel is **not** NSFW, the command is interrupted (implicit `$stop`), without an error message by default. - Equivalent to `$onlyIf[$channelNSFW==true]` but more concise. ## Examples ### NSFW-only command ```bdfd $onlyNSFW $sendMessage[This content is visible only in NSFW channels.] ``` ### With custom error message ```bdfd $if[$channelNSFW==false] $sendMessage[❌ Switch to an NSFW channel to use this command.] $stop $endif $sendMessage[NSFW content.] ``` ### Content filtering ```bdfd $if[$channelNSFW==true] $sendMessage[🔞 Search result...] $else $sendMessage[Filtered search (SFW mode)...] $endif ``` ## Notes - `$onlyNSFW` is silent: no error message is sent by default. To inform the user, use the manual condition with `$channelNSFW`. - NSFW marking is configured in the Discord channel settings (Channel Settings → Overview → NSFW Channel). - Use `$channelNSFW` for an inline check without interrupting the command. - Compatible with text channels only. Threads inherit the NSFW status of their parent channel. --- ### $onlyPerms # $onlyPerms The guard function `$onlyPerms` checks that the user has **all** the listed Discord permissions. If any permission is missing, the command is interrupted. ## Syntax ``` $onlyPerms[permission1;permission2;...;(errorMessage)] ``` ## Parameters | Parameter | Type | Description | |-----------|------|-------------| | `permission1;permission2;...` | String[] | List of Discord permissions separated by `;`. The user must have **all** of these permissions. | | `errorMessage` | String (optional) | Message sent to the user if permissions are insufficient. If omitted, the bot remains silent. | **Common Discord permissions:** `Administrator`, `BanMembers`, `KickMembers`, `ManageMessages`, `ManageChannels`, `ManageRoles`, `ManageGuild`, `ModerateMembers`, `MuteMembers`, `DeafenMembers`, `MoveMembers`, `ManageNicknames`, `ManageWebhooks`, `ManageGuildExpressions`, `ViewAuditLog`, `ViewGuildInsights`. ## Behavior - Checks the user's permissions **in the server**, not in the channel. - If the user has the `Administrator` permission, **all** other permissions are implicitly granted. - The check is an **AND** type: all listed permissions are required. ## Examples ### Single permission ```bdfd $onlyPerms[BanMembers;❌ Ban permission required.] $ban[$mentioned[1];Reason provided by staff] $sendMessage[$mentioned[1] has been banned.] ``` ### Multiple permissions ```bdfd $onlyPerms[ManageMessages;ManageChannels;❌ You need Messages + Channels perms.] $clear[50] $sendMessage[50 messages deleted.] ``` ### Without error message (silent) ```bdfd $onlyPerms[KickMembers] $kick[$mentioned[1]] ``` ## Notes - Permission names are case-sensitive. Use Discord's exact PascalCase notation (`BanMembers`, not `banmembers`). - To check the **bot's** permissions, use `$onlyBotPerms`. - For an inline check (without interrupting the command), use `$hasPerms`. - Place `$onlyPerms` at the beginning of the command to avoid any partial execution. --- ### $pinMessage # $pinMessage The `$pinMessage[]` function allows **pinning a message** in its channel. Pinned messages appear in the dedicated section of the channel. ## Syntax ``` $pinMessage[messageID] ``` ## Parameters | Parameter | Description | |---|---| | `messageID` | The ID of the message to pin. | ## Return Value This function does not return a value. ## Behavior - The bot must have the `MANAGE_MESSAGES` permission. - Maximum 50 pinned messages per channel. - Pinning works in the channel where the message is located. ## Examples ### Pin an announcement ```bdfd $title[📢 Important announcement] $description[$noMentionMessage] $color[#FEE75C] $sendMessage[] $pinMessage[$messageID] ``` ### Pin a specific message ```bdfd $pinMessage[$mentionedMessage] $sendMessage[Message pinned!] ``` ### Conditional pinning ```bdfd $if[$checkContains[$userPerms;Administrator]==true] $pinMessage[$noMentionMessage] $addCmdReactions[📌] $else $sendMessage[Only administrators can pin.] $endif ``` ## Notes - Discord notifies the concerned users when a message is pinned. - To unpin, use `$unpinMessage[]`. - Pinned messages remain visible even after years. --- ### $publishMessage # $publishMessage The `$publishMessage[]` function allows **publishing a message** from an announcement channel to all subscribed servers. ## Syntax ``` $publishMessage[messageID] ``` ## Parameters | Parameter | Description | |---|---| | `messageID` | The ID of the message to publish (must be in an announcement channel). | ## Return Value This function does not return a value. ## Behavior - Requires a channel of type **announcement** (type 5). - The bot must have the `MANAGE_MESSAGES` or `SEND_MESSAGES` permission in the announcement channel. - The message is broadcast to all servers that follow this announcement channel. - Publishing may take a few seconds. ## Examples ### Publish an announcement ```bdfd $title[📢 Bot update] $description[ **New version:** 2.0.0 **Changes:** - New !help command - Bug fixes - Improved performance ] $color[#5865F2] $channelSendMessage[$announcementChannel;] $publishMessage[$messageID] $sendMessage[Announcement published!] ``` ### Conditional publication ```bdfd $if[$checkContains[$userPerms;Administrator]==true] $title[Announcement from $username] $description[$noMentionMessage] $footer[Published by $username] $channelSendMessage[$announcementChannel;] $publishMessage[$messageID] $sendMessage[✅ Announcement published successfully.] $else $sendMessage[❌ Permission denied.] $endif ``` ## Notes - Only messages in announcement channels can be published. - Subscribed servers see the message in their dedicated announcement channel. - Publishing is irreversible: the message cannot be "unpublished". - Ideal for bot updates, changelogs, and community announcements. --- ### $registerGuildCommands # $registerGuildCommands The `$registerGuildCommands[]` function allows **registering the bot's slash commands** on a specific server. ## Syntax ``` $registerGuildCommands[guildID] ``` ## Parameters | Parameter | Description | |---|---| | `guildID` | The ID of the server where to register the slash commands. | ## Return Value This function does not return a value. ## Behavior - The slash commands defined in the bot are registered on the target server. - Guild commands are available immediately (unlike global commands which can take up to 1 hour). - The bot must have the `applications.commands` permission on the server. ## Examples ### Manual registration ```bdfd $if[$checkContains[$userPerms;Administrator]==true] $registerGuildCommands[$guildID] $sendMessage[✅ Slash commands registered on this server!] $else $sendMessage[❌ Permission denied.] $endif ``` ### Automatic registration ```bdfd $registerGuildCommands[$guildID] $sendMessage[Slash commands synced.] ``` ### Multi-server registration (owner) ```bdfd $if[$authorID==OWNER_ID] $registerGuildCommands[$message[1]] $sendMessage[Commands registered on server $message[1].] $endif ``` ## Notes - Guild commands are faster to update than global commands. - Useful for testing new commands before global deployment. - To remove commands, use `$unregisterGuildCommands[]`. - Maximum 100 slash commands per server. --- ### $removeEmoji # $removeEmoji The `$removeEmoji[]` function allows **removing a custom emoji** from the server using its name. ## Syntax ``` $removeEmoji[name] ``` ## Parameters | Parameter | Description | |---|---| | `name` | The name of the emoji to remove (without the colons `:`). | ## Return Value - **Type**: String (empty on success) - Empty string if the removal succeeds. - Error message if the emoji doesn't exist or if the bot lacks permissions. ## Behavior - The bot must have the `MANAGE_EMOJIS_AND_STICKERS` permission. - The emoji is permanently removed from the server. - All messages using this emoji will display the text name instead of the image. ## Examples ### Simple removal ```bdfd $if[$checkContains[$userPerms;ManageEmojisAndStickers]==true] $if[$emojiExists[$noMentionMessage]==true] $removeEmoji[$noMentionMessage] $sendMessage[✅ Emoji **$noMentionMessage** removed.] $else $sendMessage[❌ The emoji **$noMentionMessage** does not exist.] $endif $else $sendMessage[❌ Permission denied.] $endif ``` ### Secure removal with confirmation ```bdfd $let[name;$noMentionMessage] $if[$emojiExists[$name]==true] $removeEmoji[$name] $title[🗑️ Emoji removed] $description[ **Name:** $name **Removed by:** $userName[$authorID] ] $color[#ED4245] $sendMessage[] $else $sendMessage[❌ No emoji named **$name** found.] $endif ``` ## Notes - The emoji name is case-sensitive. - Removal is irreversible. - Always check the emoji's existence with `$emojiExists[]` before removing. --- ### $removeReaction # $removeReaction The `$removeReaction[]` function allows **removing a specific reaction** from a message. ## Syntax ``` $removeReaction[channelID;messageID;emoji] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the channel containing the message. | | `messageID` | The ID of the target message. | | `emoji` | The emoji to remove (Unicode or custom `<:name:ID>`). | ## Return Value This function does not return a value. ## Behavior - Removes ONLY the bot's reaction. - To remove other users' reactions, the `MANAGE_MESSAGES` permission is required. - If the emoji is not present as a reaction, nothing happens. ## Examples ### Progress indicator ```bdfd $addCmdReactions[⏳] $wait[3] $removeReaction[$channelID;$messageID;⏳] $addCmdReactions[✅] ``` ### Selective cleanup ```bdfd $removeReaction[$channelID;$messageID;❌] $addMessageReactions[$channelID;$messageID;✅] $editMessage[Action confirmed.] ``` ### Confirmation system ```bdfd $if[$checkContains[$userPerms;Administrator]==true] $removeReaction[$channelID;$messageID;⏳] $addMessageReactions[$channelID;$messageID;✅] $else $removeReaction[$channelID;$messageID;⏳] $addMessageReactions[$channelID;$messageID;❌] $endif ``` ## Notes - To remove all reactions at once, use `$clearReactions[]`. - The emoji must be exactly the same as the one used for the reaction. - Custom emojis must be in the format `<:name:ID>`. --- ### $roleGrant # $roleGrant The function `$roleGrant` **assigns a role** to a member of the Discord server. The bot must have the `ManageRoles` permission to perform this action. ## Syntax ``` $roleGrant[userID;roleID;(guildID)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the target member. Required. | | `roleID` | The ID of the role to assign. Required. | | `guildID` | Optional. The ID of the target server. | ## Return Value None. The function performs the assignment action. ## Examples ### Simple assignment ```bdfd $roleGrant[$authorID;$roleID[Member]] $sendMessage[You now have the Member role!] ``` ### Verification before assignment ```bdfd $if[$roleExists[$roleID[VIP]]==true] $roleGrant[$authorID;$roleID[VIP]] $sendMessage[VIP role successfully assigned!] $else $sendMessage[The VIP role does not exist.] $endif ``` ### Assigning to another member ```bdfd $roleGrant[$mentioned[1];$roleID[Muted]] $sendMessage[<@$mentioned[1]> has been muted.] ``` ### With hierarchy check ```bdfd $if[$rolePosition[$getRole[$authorID;1]]>$rolePosition[$roleID[Mod]]] $roleGrant[$mentioned[1];$roleID[Mod]] $sendMessage[<@$mentioned[1]> is now a Moderator!] $else $sendMessage[You do not have permission to promote moderators.] $endif ``` ## Notes - The bot must have the `ManageRoles` permission. - The bot cannot assign a role higher than its own highest role. - If the member already has the role, nothing happens. - To remove a role, use `$roleRemove`. --- ### $setNickname # $setNickname The function `$setNickname` **modifies the nickname** of a user on the Discord server. The nickname is specific to each server and does not affect the global username. The bot must have the `Manage Nicknames` permission. ## Syntax ``` $setNickname[nickname;(userID)] ``` ## Parameters | Parameter | Description | |---|---| | `nickname` | The new nickname to apply. Required. Leave empty to reset the nickname. | | `userID` | Optional. The ID of the target user. If omitted, the mentioned user is targeted. | ## Return Value None. The nickname is modified. ## Examples ### Simple change ```bdfd $setNickname[Gentil Member;$mentioned[1]] $sendMessage[Nickname of <@$mentioned[1]> changed to "Gentil Member".] ``` ### Resetting the nickname ```bdfd $setNickname[;$mentioned[1]] $sendMessage[Nickname of <@$mentioned[1]> reset.] ``` ### Moderation command ```bdfd $if[$argsCount<1] $sendMessage[Usage: !nick <@mention> ] $stop $endif $setNickname[$replaceText[$message;-;$mentioned[1];];$mentioned[1]] $sendMessage[✅ Nickname modified.] ``` ### Applying a nickname with a prefix ```bdfd $setNickname[[Member] $username;$mentioned[1]] $sendMessage[Formatted nickname applied.] ``` ## Notes - The bot must have the `Manage Nicknames` permission. - The bot cannot modify the nickname of a user with a higher role than its own. - To change the global username of the bot, use `$changeUsername`. - Leaving `nickname` empty resets the nickname to the default username. --- ### $setUserRoles # $setUserRoles The function `$setUserRoles` **replaces all roles of a user** with a new list. Unlike `$giveRoles` which adds roles, `$setUserRoles` first removes all existing roles before assigning the specified ones. The bot must have the `Manage Roles` permission. ## Syntax ``` $setUserRoles[userID;role1;role2;...] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the target user. Required. | | `role1;role2;...` | List of role IDs to set, separated by `;`. | ## Return Value None. The user's roles are replaced. ## Examples ### Resetting roles ```bdfd $setUserRoles[$mentioned[1];$roleID[Member]] $sendMessage[<@$mentioned[1]> now only has the Member role.] ``` ### Setting a specific set of roles ```bdfd $setUserRoles[$mentioned[1];$roleID[Member];$roleID[VIP];$roleID[Active]] $sendMessage[Roles of <@$mentioned[1]> updated.] ``` ### Promoting a member ```bdfd $if[$isAdmin==true] $setUserRoles[$mentioned[1];$roleID[Moderator];$roleID[Staff]] $sendMessage[<@$mentioned[1]> is now a Moderator!] $else $sendMessage[Permission denied.] $endif ``` ### Clearing all roles ```bdfd $setUserRoles[$mentioned[1]] $sendMessage[All roles of <@$mentioned[1]> have been removed.] ``` ## Notes - The bot must have the `Manage Roles` permission. - **All existing roles are removed** before applying the new ones. - To simply add roles, use `$giveRoles` instead. - To remove specific roles, use `$takeRoles` instead. - Leaving the role list empty removes all roles (except the @everyone role). - The @everyone role cannot be removed. --- ### $startThread # $startThread The function `$startThread[]` allows **creating a discussion thread** in a channel. Threads are organized sub-conversations. ## Syntax ``` $startThread[name;(autoArchiveDuration);(messageID)] ``` ## Parameters | Parameter | Description | |---|---| | `name` | Name of the thread (1 to 100 characters). | | `autoArchiveDuration` | Optional - Duration of inactivity before archiving: 60, 1440 (24h), 4320 (3d), 10080 (7d). Default: 1440. | | `messageID` | Optional - ID of the source message. By default, the triggering message. | ## Return Value - **Type**: Snowflake (string) - The ID of the newly created thread. - An empty string in case of failure (insufficient permissions or incompatible channel). ## Behavior - Threads can only be created in text channels (not in voice or announcement channels). - The bot must have the `CREATE_PUBLIC_THREADS` or `CREATE_PRIVATE_THREADS` permission. - The thread is created as a public thread by default (visible to all). ## Examples ### Support thread ```bdfd $let[thread;$startThread[Support - $username;10080]] $if[$thread!=] $channelSendMessage[$thread;Welcome to your support thread, $username! A moderator will answer you soon.] $sendMessage[Support thread created: <#$thread>] $else $sendMessage[Impossible to create the thread. Missing permissions.] $endif ``` ### Automatic thread ```bdfd $if[$checkContains[$message;!discussion]==true] $let[topic;$message[1]] $let[thread;$startThread[$topic;4320]] $if[$thread!=] $threadAddMember[$thread;$authorID] $sendMessage[Discussion created: <#$thread>] $endif $endif ``` ## Notes - Archived threads can be unarchived with `$editThread[]`. - Private threads require `CREATE_PRIVATE_THREADS` permission. - The name of the thread can be modified later with `$editThread[]`. --- ### $takeRole # $takeRole The `$takeRole` function **removes a role** from a user on the Discord server. The bot must have the `ManageRoles` permission. ## Syntax ``` $takeRole[userID;roleID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the target user. Required. | | `roleID` | The ID of the role to remove. Required. | ## Return Value None. The role is removed. ## Examples ### Simple Removal ```bdfd $takeRole[$mentioned[1];$roleID[Muted]] $sendMessage[🔊 <@$mentioned[1]> is no longer muted!] ``` ### Removal After Verification ```bdfd $if[$checkContains[$userRoles[$mentioned[1]];$roleID[Muted]]==true] $takeRole[$mentioned[1];$roleID[Muted]] $sendMessage[Muted role removed.] $else $sendMessage[This user does not have the Muted role.] $endif ``` ### Removal Command with Confirmation ```bdfd $takeRole[$mentioned[1];$roleID[$message[2]]] $sendMessage[✅ Role removed from <@$mentioned[1]>.] ``` ## Notes - The bot must have the `ManageRoles` permission. - The bot cannot remove a role higher than or equal to its own highest role. - If the user does not have the role, nothing happens. - To remove multiple roles, use `$takeRoles`. - Functionally equivalent to `$roleRemove`. --- ### $takeRoles # $takeRoles The `$takeRoles` function **removes multiple roles at once** from a user on the Discord server. The bot must have the `ManageRoles` permission. ## Syntax ``` $takeRoles[userID;role1;role2;...] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the target user. Required. | | `role1;role2;...` | The IDs of the roles to remove, separated by `;`. Required. | ## Return Value None. All specified roles are removed. ## Examples ### Simple Multiple Removal ```bdfd $takeRoles[$mentioned[1];$roleID[Muted];$roleID[Warned];$roleID[Monitored]] $sendMessage[All sanctions for <@$mentioned[1]> have been lifted.] ``` ### Role Cleanup ```bdfd $if[$isAdmin==true] $takeRoles[$mentioned[1];$roleID[VIP];$roleID[Staff];$roleID[Mod]] $sendMessage[All special roles removed from <@$mentioned[1]>.] $endif ``` ### Conditional Removal ```bdfd $takeRoles[$authorID;$roleID[Old];$roleID[Inactive]] $giveRole[$authorID;$roleID[Active]] $sendMessage[Roles updated!] ``` ## Notes - The bot must have the `ManageRoles` permission. - The role IDs are separated by `;`. - To remove a single role, `$takeRole` is simpler. - Roles not possessed by the user are silently ignored. - To completely redefine a user's roles, use `$setUserRoles`. --- ### $threadAddMember # $threadAddMember The function `$threadAddMember[]` allows you to **add a user to a thread**. It is particularly useful for private threads. ## Syntax ``` $threadAddMember[threadID;userID] ``` ## Parameters | Parameter | Description | |---|---| | `threadID` | The ID of the target thread. | | `userID` | The ID of the user to add. | ## Return Value This function does not return any value. ## Behavior - For public threads, users can join freely; this function is rarely needed. - For private threads, only added members can view and participate in the thread. - The bot must have the `MANAGE_THREADS` permission or be the creator of the private thread. ## Examples ### Adding the Creator ```bdfd $let[thread;$startThread[Support - $username;1440]] $threadAddMember[$thread;$authorID] $channelSendMessage[$thread;Your support thread is ready, $username!] ``` ### Adding Moderators ```bdfd $threadAddMember[$threadID;$mentioned[1]] $sendMessage[<@$mentioned[1]> has been added to the thread.] ``` ### Automatic Staff Addition ```bdfd $let[thread;$startThread[Ticket #$random[1000;9999];1440]] $threadAddMember[$thread;$authorID] $threadAddMember[$thread;MODERATOR_ROLE_ID_1] $threadAddMember[$thread;MODERATOR_ROLE_ID_2] $channelSendMessage[$thread;Welcome! A member of the staff will assist you.] ``` ## Notes - In public threads, members can join without an invitation. - `$threadAddMember[]` does not send a notification to the added user. - To remove a member, use `$threadRemoveMember[]`. --- ### $threadMessageCount # $threadMessageCount The function `$threadMessageCount[]` returns the **total number of messages** in a thread. ## Syntax ``` $threadMessageCount[threadID] ``` ## Parameters | Parameter | Description | |---|---| | `threadID` | The ID of the thread to analyze. | ## Return Value - **Type**: Integer - The total number of messages in the thread. - `0` if the thread is empty or inaccessible. ## Behavior - Counts only messages within the thread, not those in the parent channel. - Includes system messages (thread creation, added members, etc.). - The bot must have access to the thread to count these messages. ## Examples ### Thread Statistics ```bdfd $title[Thread Statistics] $description[ **Messages:** $threadMessageCount[$threadID] **Members:** $threadUserCount[$threadID] ] $color[#5865F2] $sendMessage[] ``` ### Activity Check ```bdfd $let[msgCount;$threadMessageCount[$threadID]] $if[$msgCount<=1] $channelSendMessage[$threadID;This thread seems inactive. Feel free to ask your questions!] $endif ``` ### Auto Archiving ```bdfd $let[msgCount;$threadMessageCount[$threadID]] $if[$msgCount>=100] $editThread[$threadID;[$threadName];true;true] $sendMessage[Thread archived automatically (100 messages reached).] $endif ``` ## Notes - Useful for statistics and automatic thread management. - Deleted messages are not counted. - To get the number of members, use `$threadUserCount[]`. --- ### $threadRemoveMember # $threadRemoveMember The function `$threadRemoveMember[]` allows you to **remove a user from a thread**. The user will no longer be able to access the private thread. ## Syntax ``` $threadRemoveMember[threadID;userID] ``` ## Parameters | Parameter | Description | |---|---| | `threadID` | The ID of the target thread. | | `userID` | The ID of the user to remove. | ## Return Value This function does not return any value. ## Behavior - Works primarily for private threads. - In a public thread, users cannot be removed (they can always view it). - The bot must have the `MANAGE_THREADS` permission or be the creator of the private thread. ## Examples ### Closing a Ticket ```bdfd $threadRemoveMember[$threadID;$authorID] $editThread[$threadID;[Closed] Ticket;true;true] $sendMessage[Ticket closed and user removed.] ``` ### Removal After Resolution ```bdfd $threadRemoveMember[$threadID;$mentioned[1]] $channelSendMessage[$threadID;<@$mentioned[1]> has been removed from the thread.] ``` ## Notes - In public threads, `$threadRemoveMember[]` may not have any visible effect. - The removed user does not receive a notification. - For private threads, this is the appropriate method to manage access. --- ### $threadUserCount # $threadUserCount The function `$threadUserCount[]` returns the **number of members** present in a thread. ## Syntax ``` $threadUserCount[threadID] ``` ## Parameters | Parameter | Description | |---|---| | `threadID` | The ID of the thread to analyze. | ## Return Value - **Type**: Integer - The number of members in the thread. - `0` if the thread is empty or inaccessible. ## Behavior - Counts all users who have joined the thread (public) or have been added to it (private). - Includes the bot itself if it has joined the thread. - The bot must have access to the thread. ## Examples ### Thread Summary ```bdfd $title[Thread Activity] $description[ **Members:** $threadUserCount[$threadID] participants **Messages:** $threadMessageCount[$threadID] messages ] $color[#57F287] $sendMessage[] ``` ### Popularity Alert ```bdfd $let[userCount;$threadUserCount[$threadID]] $if[$userCount>=10] $sendMessage[This thread has attracted $userCount participants! 🔥] $endif ``` ### Participation Monitoring ```bdfd $let[members;$threadUserCount[$threadID]] $let[messages;$threadMessageCount[$threadID]] $let[ratio;$round[$divide[$messages;$members]]] $sendMessage[Average of $ratio messages per participant.] ``` ## Notes - In public threads, the count includes all users who have opened the thread. - Useful alongside `$threadMessageCount[]` to evaluate engagement. - Members who leave a public thread are no longer counted. --- ### $timeout # $timeout The function `$timeout` times out a user on Discord. During the specified duration, the user cannot send messages, speak in voice channels, or react. The bot must have the `ModerateMembers` permission. ## Syntax ``` $timeout[userID;duration;(reason)] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user. Required. | | `duration` | Duration of the timeout. Required. Accepted formats: `s` (seconds), `m` (minutes), `h` (hours), `d` (days). Examples: `"60s"`, `"5m"`, `"1h"`, `"7d"`. | | `reason` | Optional. The reason for the timeout. | ## Return Value None. The user is timed out for the specified duration. ## Examples ### Timeout of 5 Minutes ```bdfd $timeout[$mentioned[1];5m;Spam in the chat] $sendMessage[⏳ <@$mentioned[1]> has been timed out for 5 minutes.] ``` ### Timeout of One Hour ```bdfd $timeout[$mentioned[1];1h;Toxic behavior] $sendMessage[⏳ 1-hour timeout applied.] ``` ### Timeout of 7 Days ```bdfd $timeout[$mentioned[1];7d;Repeatedly breaking the rules] $sendMessage[⏳ 7-day timeout applied. Next infraction will result in a ban.] ``` ### Customizable Timeout Command ```bdfd $if[$argsCount<2] $sendMessage[Usage: !timeout <@mention> ] $stop $endif $timeout[$mentioned[1];$message[2];$message[3]] $sendMessage[Timeout applied.] ``` ## Notes - The bot must have the `ModerateMembers` permission. - The maximum duration is 28 days (Discord limit). - Duration formats: `s` (seconds), `m` (minutes), `h` (hours), `d` (days). - To remove a timeout early, use `$unTimeout`. - Unlike a mute, a timeout also prevents sending text messages. --- ### $unBan # $unBan The function `$unBan[]` allows you to **unban a user** from the server using their Discord ID. Once unbanned, the user will be able to rejoin the server with a new invite. ## Syntax ``` $unBan[userID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The Discord ID of the user to unban. | ## Return Value - **Type**: String (empty on success) - An empty string if the unban is successful. - An error message if the user is not banned or if the bot lacks permissions. ## Behavior - The bot must have the `BAN_MEMBERS` permission. - The user must be in the server's ban list. - The ID can be retrieved via `$mentioned[]`, `$findUser[]`, or any other method. - The user does not receive an unban notification. ## Examples ### Simple Unban ```bdfd $if[$checkContains[$userPerms;BanMembers]==true] $unBan[$mentioned[1]] $sendMessage[✅ **$userName[$mentioned[1]]** was unbanned.] $else $sendMessage[❌ Permission denied.] $endif ``` ### Unban with Confirmation ```bdfd $let[target;$mentioned[1]] $if[$isBanned[$target]==true] $unBan[$target] $title[🔓 Unban] $description[ **User:** $userName[$target] ($target) **Previous Reason:** $getBanReason[$target] **Unbanned by:** $userName[$authorID] ] $color[#57F287] $sendMessage[] $else $sendMessage[❌ This user is not banned.] $endif ``` ### Command with Manual ID ```bdfd $if[$message!=] $let[exists;$userExists[$message]] $if[$exists==true] $unBan[$message] $sendMessage[✅ User **$message** unbanned.] $elseif[$isBanned[$message]==true] $unBan[$message] $sendMessage[✅ User **$message** unbanned.] $else $sendMessage[❌ Invalid ID or user not banned.] $endif $else $sendMessage[Please provide a user ID.] $endif ``` ## Notes - The unbanned user does not automatically rejoin the server; they must use an invite. - Works only if the user is in the ban list. - The ID is the only reliable method, because a banned user is no longer in the server. --- ### $unBanID # $unBanID The function `$unBanID[]` allows **unbanning a user by their ID**. Similar to `$unBan[]`, it is optimized for cases where only the raw ID is available. ## Syntax ``` $unBanID[userID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The Discord ID of the user to unban. | ## Return Value - **Type** : String (empty on success) - Empty string if the unban succeeds. - Error message on failure (user not banned, insufficient permissions, etc.). ## Behavior - Works identically to `$unBan[]`. - The bot must have the `BAN_MEMBERS` permission. - Accepts only a raw ID (not a mention). ## Examples ### Unban from a list ```bdfd $let[bans;$getBanList[, ]] $textSplit[$bans;, ] $let[userID;$splitText[$index]] $if[$checkCondition[$userID==$mentioned[1]]==true] $unBanID[$userID] ✅ **$userName[$userID]** was unbanned. $break $endif $endTextSplit ``` ### Scheduled unban ```bdfd $let[target;$noMentionMessage] $if[$isBanned[$target]==true] $unBanID[$target] $title[🔓 Automatic unban] $description[ User **$target** was unbanned (end of ban duration). ] $color[#57F287] $sendMessage[$channelID[mod-logs]] $endif ``` ## Notes - `$unBanID[]` is interchangeable with `$unBan[]` for raw IDs. - The difference is minimal; prefer `$unBan[]` which also handles mentions. - Useful for internal scripts where only the ID is known. --- ### $unmute # $unmute The function `$unmute` **removes the mute** of a user on the Discord server, allowing them to speak again in voice channels. The bot must have the `MuteMembers` permission. ## Syntax ``` $unmute[userID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user to unmute. Required. | ## Return Value None. The user can speak again in voice. ## Examples ### Simple unmute ```bdfd $unmute[$mentioned[1]] $sendMessage[🔊 <@$mentioned[1]> can speak again!] ``` ### Conditional unmute ```bdfd $if[$isAdmin==true] $unmute[$mentioned[1]] $sendMessage[Member re-enabled in voice.] $else $sendMessage[Permission denied.] $endif ``` ## Notes - The bot must have the `MuteMembers` permission. - Only has effect if the user is currently muted. - To remove a timeout (temporary text and voice silence), use `$unTimeout`. --- ### $unpinMessage # $unpinMessage The function `$unpinMessage[]` allows **removing a message from the pinned messages list** of a channel. ## Syntax ``` $unpinMessage[messageID] ``` ## Parameters | Parameter | Description | |---|---| | `messageID` | The ID of the message to unpin. | ## Return Value This function does not return a value. ## Behavior - The bot must have the `MANAGE_MESSAGES` permission. - The message is not deleted, only unpinned. - If the message is not pinned, nothing happens. ## Examples ### Unpin After Action ```bdfd $unpinMessage[$noMentionMessage] $sendMessage[Message unpinned.] ``` ### Automatic Cleanup ```bdfd $unpinMessage[$messageID] $editMessage[This message is no longer relevant.] ``` ### Announcement Rotation ```bdfd $unpinMessage[$oldAnnouncementID] $title[New Announcement] $description[$noMentionMessage] $sendMessage[] $pinMessage[$messageID] ``` ## Notes - Users are not notified when a message is unpinned. - A message can be re-pinned after having been unpinned. - Combine with `$pinMessage[]` to manage rotating announcements. --- ### $unregisterGuildCommands # $unregisterGuildCommands The function `$unregisterGuildCommands[]` allows **deleting all slash commands** of the bot on a specific server. ## Syntax ``` $unregisterGuildCommands[guildID] ``` ## Parameters | Parameter | Description | |---|---| | `guildID` | The ID of the server from which to delete the slash commands. | ## Return Value This function does not return a value. ## Behavior - Deletes ONLY guild commands, not global commands. - Commands disappear immediately from the slash menu. - The bot must have the `applications.commands` permission. ## Examples ### Manual Cleanup ```bdfd $if[$checkContains[$userPerms;Administrator]==true] $unregisterGuildCommands[$guildID] $sendMessage[✅ Slash commands deleted from this server.] $else $sendMessage[❌ Permission denied.] $endif ``` ### Reset ```bdfd $unregisterGuildCommands[$guildID] $wait[2] $registerGuildCommands[$guildID] $sendMessage[Slash commands reset successfully.] ``` ### Cleanup Before Leaving ```bdfd $if[$authorID==OWNER_ID] $unregisterGuildCommands[$message[1]] $botLeave[$message[1]] $sendMessage[Commands deleted and bot removed from server $message[1].] $endif ``` ## Notes - Global commands are NOT affected by this function. - To re-register, use `$registerGuildCommands[]`. - Useful before leaving a server or to clean up old commands. --- ### $unTimeout # $unTimeout The function `$unTimeout` **removes the timeout** of a user before its expiration, restoring their ability to send messages and speak in voice. The bot must have the `ModerateMembers` permission. ## Syntax ``` $unTimeout[userID] ``` ## Parameters | Parameter | Description | |---|---| | `userID` | The ID of the user to free from timeout. Required. | ## Return Value None. The user is freed from timeout. ## Examples ### Simple removal ```bdfd $unTimeout[$mentioned[1]] $sendMessage[✅ <@$mentioned[1]> is no longer in timeout.] ``` ### Conditional removal ```bdfd $if[$isTimedOut[$mentioned[1]]==true] $unTimeout[$mentioned[1]] $sendMessage[Timeout removed.] $else $sendMessage[This user is not in timeout.] $endif ``` ### Pardon command ```bdfd $unTimeout[$mentioned[1]] $sendMessage[🙏 Pardon granted. <@$mentioned[1]> can participate again.] ``` ## Notes - The bot must have the `ModerateMembers` permission. - Use `$isTimedOut` to check if a user is in timeout before calling `$unTimeout`. - Only has effect if the user is currently in timeout. --- ### $voiceUserLimit # $voiceUserLimit The `$voiceUserLimit` function allows you to **retrieve the user limit** configured on a Discord voice channel. ## Syntax ``` $voiceUserLimit[(channelID)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | Optional - The ID of the voice channel. By default, the channel where the author is located. | ## Return Value - **Type**: String (number) - The maximum number of users allowed in the channel. - `0` means unlimited (no limit). ## Behavior - If no channelID is provided and the author is not in a voice channel, it returns `0` or an error. - The limit is set during creation/modification of the channel. - Useful for checking capacity before joining or inviting. ## Examples ### Checking capacity ```bdfd $let[limit;$voiceUserLimit] $let[users;$voiceMembersCount] $if[$limit==0] Unlimited channel — **$users** user(s) connected. $else Channel: **$users / $limit** users. $if[$users>=$limit] ⚠️ Channel full! $else ✅ $math[$limit-$users] spot(s) available. $endif $endif ``` ### Voice channel info ```bdfd $title[🔊 $channelName[$voiceChannelID]] $description[ **Connected:** $voiceMembersCount **Limit:** $if[$voiceUserLimit==0]Unlimited$else$voiceUserLimit$endif **Bitrate:** $voiceBitrate kbps ] $color[#5865F2] $sendMessage[] ``` ### Checking for a specific channel ```bdfd $let[target;$channelID[Gaming Channel]] $let[limit;$voiceUserLimit[$target]] $let[users;$voiceMembersCount[$target]] $if[$users<$limit] $sendMessage[✅ You can join <#$target>.] $else $sendMessage[❌ <#$target> is full ($users/$limit).] $endif ``` ## Notes - `0` = no limit (unlimited), which is the default value for voice channels. - The maximum limit is 99 users. - Works only with channels of type voice (`$channelType` = 2). --- ## Music ### $joinVoice[] Joins a Discord voice channel. If no channel ID is provided, the bot automatically joins the voice channel that the command user is currently connected to. If the user is not in a voice channel, the join will fail. This is called automatically by $playMusic if the bot is not already connected. --- ### $lavalinkAuthor[] Returns the author or artist name of the currently playing track. For YouTube tracks, this typically returns the channel name. If no track is playing, returns an empty string. --- ### $lavalinkDuration[] Returns the total duration of the currently playing track in milliseconds. To display a human-readable format (minutes:seconds), divide by 60000 for minutes and use modulo for seconds. Returns 0 if no track is playing. --- ### $lavalinkIsLooping[] Returns "true" if the music player has looping enabled (either track loop or queue loop). Returns "false" if loop mode is off. Use $setMusicLoop to change the loop mode. --- ### $lavalinkIsPaused[] Returns "true" if the music player is currently paused, and "false" if it is actively playing or stopped. Useful for building toggle commands and status displays. --- ### $lavalinkPlaying[] Returns the title of the currently playing track from the Lavalink music player. If no track is playing, this returns an empty string. Use this in combination with other Lavalink info functions to build a "now playing" display. --- ### $lavalinkPosition[] Returns the current playback position of the currently playing track in milliseconds. Combined with $lavalinkDuration, you can build progress bars and time displays. Returns 0 if no track is playing. --- ### $lavalinkQueueSize[] Returns the number of tracks currently waiting in the music queue. This count does not include the track that is currently playing. Use this to display queue status or check if the queue is empty before adding more tracks. --- ### $lavalinkVolume[] Returns the current playback volume level as an integer between 0 (silent) and 100 (maximum). Use $setMusicVolume to change the volume. --- ### $leaveVoice[] Leaves the current voice channel and disconnects from voice. Any currently playing music stops immediately. This does not clear the queue — use $stopMusic first if you want to clear the queue before disconnecting. --- ### $pauseMusic[] Pauses the currently playing track. The track can be resumed later with $resumeMusic. If no track is playing, this function has no effect. Use $lavalinkIsPaused to check the current pause state. --- ### $playMusic[] Searches for a track by query or plays directly from a supported URL (YouTube, SoundCloud, etc.). If the bot is not already in a voice channel, it automatically joins the user's voice channel (or the specified channel). If a track is already playing, the new track is added to the queue. --- ### $resumeMusic[] Resumes the currently paused track. If no track is paused or playing, this function has no effect. Use $lavalinkIsPaused to check whether playback is currently paused before calling resume. --- ### $seekMusic[] Seeks to a specific position in the currently playing track. The position parameter is specified in seconds (not milliseconds). Use $lavalinkPosition (which returns milliseconds) to read the current position. Seeking to 0 restarts the track from the beginning. --- ### $setMusicLoop[] Sets the looping behavior of the music player. Three modes are available: "off" disables looping entirely; "track" repeats only the currently playing track indefinitely; "queue" repeats the entire queue once all tracks finish. Use $lavalinkIsLooping to check if looping is currently active. --- ### $setMusicVolume[] Sets the playback volume for the music player. The volume parameter must be an integer between 0 (completely silent) and 100 (maximum volume). Use $lavalinkVolume to read the current volume level. Volume changes take effect immediately on the currently playing track. --- ### $skipMusic[] Skips the currently playing track. If there are tracks in the queue, the next one begins playing automatically. If the queue is empty, playback stops. Use $lavalinkQueueSize to check how many tracks remain after skipping. --- ### $stopMusic[] Stops the music player immediately and clears all tracks from the queue. After calling $stopMusic, the player is idle — no tracks are playing and the queue is empty. The bot remains in the voice channel unless you also call $leaveVoice. --- ## Permission ### Checkusersperms # $checkUsersPerms Checks if one or multiple users have all the specified permissions. Returns `true` or `false`. ## Syntax ``` $checkUsersPerms[userIds;permissions;(separator);(amount)] ``` ## Parameters | Parameter | Description | Required | |-----------|-------------|:-----------:| | `userIds` | IDs of users to check, separated by the chosen separator | Yes | | `permissions` | Permissions to check, separated by `;` | Yes | | `separator` | Separator used in `userIds` (default: `;`) | No | | `amount` | Minimum number of users who must have the permissions for the result to be `true` (default: 1) | No | ## Description `$checkUsersPerms` is the **multi-user version** of `$checkUserPerms`. It checks whether one or more users possess all the specified permissions and allows defining a minimum threshold of users who must satisfy the condition. This function performs an **inline** check — it does not interrupt the command and simply returns `true` or `false`. The permissions check is done with an **AND** logic: all listed permissions must be present for a user to be counted as having them. ## Examples ### Checking multiple users ``` $if[$checkUsersPerms[$authorID;$mentioned[1];KickMembers]==true] $kick[$mentioned[2]] $sendMessage[User kicked.] $else $sendMessage[❌ Insufficient permissions.] $endif ``` ### At least 2 users must have Administrator ``` $if[$checkUsersPerms[$authorID;$mentioned[1];$mentioned[2];Administrator;;2]==true] $sendMessage[At least 2 users are administrators.] $else $sendMessage[Less than 2 users have Administrator permission.] $endif ``` ### Custom separator ``` $var[ids;$authorID,$mentioned[1],$mentioned[2]] $if[$checkUsersPerms[$var[ids];ManageMessages;,]==true] $clear[50] $sendMessage[Messages cleared.] $endif ``` ## Notes - Uses an **AND** logic for permissions: all listed permissions are required for a user. - The `amount` parameter lets you define how many users must satisfy the condition. - Use `$checkUserPerms` for a single-user check (simpler syntax). - Permissions are in **PascalCase**: `KickMembers`, `BanMembers`, `Administrator`, `ManageMessages`, etc. - `Administrator` covers all permissions. --- ## Variables ### $argCount[] $argCount tells you exactly how many arguments were supplied by the user. It is a simple but essential function for input validation — almost every command that accepts arguments should check `$argCount` before proceeding. ## Return Value Always a string representation of a non-negative integer. Even if no arguments are provided, the return value is `"0"`, never an empty string. ## Use in Conditionals Since the return value is a string, numeric comparisons work naturally: ``` $if[$argCount>=2] $if[$argCount<1] $if[$argCount!=0] ``` ## Relationship with $args - `$argCount` tells you _how many_ arguments exist. - `$args` / `$args[index]` lets you _retrieve_ them. - Valid indices for `$args[index]` range from `0` to `$argCount - 1`. ## Common Pattern Pair `$argCount` with `$argsCheck` for comprehensive validation: ``` $argsCheck[>=;1;Error: at least 1 argument required] $if[$argCount>3] Too many arguments (max 3). $stop $endif ``` --- ### $args[] $args is the primary mechanism for accessing user-provided input in text commands. Arguments are the words that follow the command name, separated by whitespace. ## Indexing Arguments are **0-indexed**: the first word after the command name is at index `0`. If the user types `!command hello world`: - `$args[0]` → `"hello"` - `$args[1]` → `"world"` - `$args` (without index) → `"hello world"` Requesting an index beyond the available arguments returns an empty string — no error is raised. ## Slash Command Fallback When used in hybrid commands (supporting both text and slash invocation), `$args[index;option]` provides a graceful fallback: 1. If a text argument exists at the given index, it is returned. 2. If no text argument exists, the slash command option named `option` is returned instead. 3. If neither exists, an empty string is returned. This allows the same command code to handthe both invocation methods seamlessly. ## Comparison with Other Functions | Function | Purpose | |----------|---------| | `$args` / `$args[index]` | Access individual arguments | | `$argCount` | Count how many arguments were provided | | `$argsCheck` | Validate argument count and block if insufficient | --- ### $argsCheck[] $argsCheck is a guard function that enforces argument count constraints at the beginning of a command. It is the recommended way to validate user input before processing — cleaner and more concise than manual `$if`/`$stop` combinations. ## How It Works 1. The current argument count (`$argCount`) is compared to the specified `count` using the given `operator`. 2. If the condition is **true**, execution continues to the next line. 3. If the condition is **false**, the `errorMessage` is sent to the user and the command **stops executing immediately** — no further code in the command runs. ## Operators | Operator | Meaning | Condition passes when.. | |----------|---------|--------------------------| | `>=` | Greater or equal | `$argCount >= count` | | `>` | Strictly greater | `$argCount > count` | | `<=` | Less or equal | `$argCount <= count` | | `<` | Strictly less | `$argCount < count` | ## Best Practices - Place `$argsCheck` at the very top of your command, before any other logic. - Write clear, actionable error messages that tell the user what they did wrong and how to fix it. - Use `$argsCheck[>=;N;...]` for minimum argument requirements — the most common use case. - Use `$argsCheck[<=;N;...]` to enforce maximums. - Combine two checks for exact count requirements (as shown in the examples). ## Comparison with Manual Validation Without `$argsCheck`: ``` $if[$argCount<2] Error: at least 2 arguments required. $stop $endif ``` With `$argsCheck` (equivalent, cleaner): ``` $argsCheck[>=;2;Error: at least 2 arguments required.] ``` --- ### $enabled # $enabled The `$enabled[]` function **enables or disables** the command in which it is placed. ## Syntax ``` $enabled[yes/no] ``` ## Parameters | Parameter | Description | |---|---| | `yes/no` | `yes` to enable the command, `no` to disable it. | ## Return value None. ## Behavior - `$enabled[no]` makes the command invisible and inexecutable. - `$enabled[yes]` reactivates it. - Can be combined with conditions for conditional activation. ## Examples ### Disable temporarily ```bdfd $enabled[no] ``` ### Conditional activation by role ```bdfd $if[$hasRole[$authorID;Admin]==true] $enabled[yes] $else $enabled[no] $endif ``` ### Maintenance mode command ```bdfd $var[maintenance;$getVar[maintenance]] $if[$var[maintenance]==true] $if[$hasRole[$authorID;Staff]==true] $enabled[yes] $else $enabled[no] $endif $else $enabled[yes] $endif ``` ## Notes - A disabled command does not appear in command suggestions. - Unlike `$onlyIf[]` which keeps the command visible but blocks execution, `$enabled[no]` hides it completely. - Useful for commands in maintenance or seasonal commands. --- ### $getChannelVar[] $getChannelVar reads a variable scoped to a Discord channel. The variable value is specific to that channel context within a server. When called with only a `name`, it reads from the channel where the command is being executed (`((channel.id))`). When a Channel ID is provided, the variable is read from the specified channel. Variables are defined and configured in the Bot Creator Variables UI, where you can set default values per variable. If a variable has not been set via $setChannelVar but a default exists in the definitions, $getChannelVar returns that default. If neither a stored value nor a default exists, an empty string is returned. > **JavaScript (BDJS) equivalent:** `await db.channel.get('name')` — see [db.channel](/docs/javascript/db-channel/). --- ### $getGuildMemberVar[] $getGuildMemberVar reads a variable scoped to a guild member — a specific user within a specific server. The context key is composed as `guildId:userId`, making the variable value unique per user per server. $getMemberVar is an exact alias and can be used interchangeably. When called with only a `name`, it reads the variable of the current command author in the current guild (`((guild.id)):((author.id))`). When a User ID is provided, the current guild is still used. When both User ID and Guild ID are provided, the variable is read from the exact guild-member combination. Variables are defined and configured in the Bot Creator Variables UI, where you can set default values. If a variable has not been set via $setGuildMemberVar but a default exists in the definitions, $getGuildMemberVar returns that default. If neither exists, an empty string is returned. --- ### $getGuildVar[] $getGuildVar reads a variable scoped to a Discord guild (server). The variable value is shared by all members within that server context. $getServerVar is an exact alias and can be used interchangeably. When called with only a `name`, it reads from the guild where the command is being executed (`((guild.id))`). When a Guild ID is provided as the second argument, the variable is read from the specified guild. Variables are defined and configured in the Bot Creator Variables UI, where you can set default values per variable. If a variable has not been set via $setGuildVar but a default exists in the definitions, $getGuildVar returns that default. If neither a stored value nor a default exists, an empty string is returned. > **JavaScript (BDJS) equivalent:** `await db.guild.get('name')` — see [db.guild](/docs/javascript/db-guild/). --- ### $getLeaderboardPosition[] # $getLeaderboardPosition The function `$getLeaderboardPosition` allows retrieving the position (rank) of the current user in the active leaderboard. This function only makes sense **in the context of iterating through a leaderboard** — that is, after calling `$globalUserLeaderboard`, `$serverLeaderboard` or `$userLeaderboard` and while iterating through their results. ## How It Works When you use a leaderboard, the system iterates through each entry one by one. During this iteration, `$getLeaderboardPosition` exposes the current rank (1 for the first, 2 for the second, etc.). The returned value corresponds to the internal variable `((leaderboard.position))` which is resolved at runtime by the dedicated leaderboard action. ## Use Cases Typically, you use `$getLeaderboardPosition` with `$textSplit` to split the leaderboard result line by line, then display the positions: - Display a formatted ranking with ranks - Compare the current user's position with others - Build custom messages based on rank (podium, top 10, etc.) ## Important - `$getLeaderboardPosition` **returns nothing** outside the context of an active leaderboard. - The function takes **no parameters**. - It is typically paired with `$getLeaderboardValue` which gives the value associated with that position. - The leaderboard itself is generated by a dedicated action at code execution time. ## See Also - [`$getLeaderboardValue`](/docs/getleaderboardvalue) — Get the value associated with the current position - [`$globalUserLeaderboard`](/docs/globaluserleaderboard) — Global user leaderboard - [`$serverLeaderboard`](/docs/serverleaderboard) — Server-level leaderboard - [`$userLeaderboard`](/docs/userleaderboard) — Personal leaderboard - [`$textSplit`](/docs/textsplit) — Split the result of a leaderboard --- ### $getLeaderboardValue[] # $getLeaderboardValue The function `$getLeaderboardValue` returns the value associated with the current position in the active leaderboard. This can be a score, a number of coins, XP points, or any other variable the ranking is based on. This function only makes sense **in the context of iterating through a leaderboard** — that is, after calling `$globalUserLeaderboard`, `$serverLeaderboard` or `$userLeaderboard` and while iterating through their results with `$textSplit`. ## How It Works When iterating through a leaderboard, each entry contains an identifier (user) and a value (the score). `$getLeaderboardValue` exposes this value for the entry currently being processed. The returned value corresponds to the internal variable `((leaderboard.value))` which is resolved at runtime by the dedicated leaderboard action. ## Use Cases - Display each player's score in a ranking - Compare values between different positions - Trigger rewards based on the score reached - Format congratulation messages with the score ## Important - `$getLeaderboardValue` **returns nothing** outside the context of an active leaderboard. - The function takes **no parameters**. - It is almost always used with `$getLeaderboardPosition` for a complete display (rank + value). - The returned value depends on the variable the leaderboard was built on (for example, if the leaderboard is based on `coins`, the value will be the number of coins). ## See Also - [`$getLeaderboardPosition`](/docs/getleaderboardposition) — Get the rank in the leaderboard - [`$globalUserLeaderboard`](/docs/globaluserleaderboard) — Global user leaderboard - [`$serverLeaderboard`](/docs/serverleaderboard) — Server-level leaderboard - [`$userLeaderboard`](/docs/userleaderboard) — Personal leaderboard - [`$textSplit`](/docs/textsplit) — Split the result of a leaderboard --- ### $getMemberVar[] $getMemberVar reads a variable scoped to a guild member — a specific user within a specific server. The context key is composed as `guildId:userId`, making the variable value unique per user per server. $getGuildMemberVar is an exact alias and can be used interchangeably. When called with only a `name`, it reads the variable of the current command author in the current guild (`((guild.id)):((author.id))`). When a User ID is provided, the current guild is still used. When both User ID and Guild ID are provided, the variable is read from the exact guild-member combination. Variables are defined and configured in the Bot Creator Variables UI, where you can set default values. If a variable has not been set via $setMemberVar but a default exists in the definitions, $getMemberVar returns that default. If neither exists, an empty string is returned. > **JavaScript (BDJS) equivalent:** `await db.guildMember.get('name')` — see [db.guildMember](/docs/javascript/db-guild-member/). --- ### $getMessageVar[] $getMessageVar reads a variable scoped to a specific Discord message. The variable value is tied directly to a singthe message. When called with only a `name`, it reads from the message that triggered the current command or event. When a Message ID is provided, the variable is read from the specified message. This is particularly useful for message-tracking features, reaction roles, polls, or any scenario where you need to attach persistent metadata to a specific message. Variables are defined and configured in the Bot Creator Variables UI, where you can set default values. If a variable has not been set via $setMessageVar but a default exists in the definitions, $getMessageVar returns that default. If neither exists, an empty string is returned. > **JavaScript (BDJS) equivalent:** `await db.message.get('name')` — see [db.message](/docs/javascript/db-message/). --- ### $getServerVar[] $getServerVar reads a variable scoped to a Discord guild (server). The variable value is shared by all members within that server context. $getGuildVar is an exact alias and can be used interchangeably. When called with only a `name`, it reads from the guild where the command is being executed (`((guild.id))`). When a Guild ID is provided as the second argument, the variable is read from the specified guild. Variables are defined and configured in the Bot Creator Variables UI, where you can set default values per variable. If a variable has not been set via $setServerVar but a default exists in the definitions, $getServerVar returns that default. If neither a stored value nor a default exists, an empty string is returned. --- ### $getUserVar[] $getUserVar reads a scoped variable stored persistently in the BDFD database. The variable is scoped to the user level, meaning its value is tied to a specific Discord user. When called with only a `name`, it reads the variable of the user who triggered the current command (`((author.id))`). If a second argument (User ID) is provided, the variable is read for that specific user. When a third argument (Guild ID) is also provided, the scope shifts to `guildMember`, using the composite key `guildId:userId` for the context. This is useful when the same user may have different variable values across different servers. Variables are defined and configured in the Bot Creator Variables UI, where you can set default values. If a variable has not been set via $setUserVar but a default value exists in the definitions, $getUserVar returns that default. If neither a stored value nor a default exists, an empty string is returned. > **JavaScript (BDJS) equivalent:** `await db.user.get('name')` — see [db.user](/docs/javascript/db-user/). --- ### $getVar[] $getVar retrieves values from the bot's persistent storage. Unlike temporary variables (`$var`), global and user-scoped variables survive across command executions and bot restarts. They are stored in the bot's database. ## Global vs User-Scoped Variables The second parameter determines the scope: - **Omitted**: the variable is treated as **global** — accessible from any command, any user, any server. - **User ID provided**: the variable is **user-scoped** — each user has their own independent value for the same variable name. Use `$authorID` to reference the current user. ## Storage Details - All values are stored as strings. When reading back, you receive the exact string that was stored. - Variable names are case-insensitive. - Returns an empty string if the variable has never been set. ## Comparison with $var | Aspect | $var | $getVar | |--------|------|---------| | Persistence | Execution only | Persistent (DB) | | Scope | Local | Global or user | | Performance | Fast (in-memory) | DB read | | Use case | Temporary calculations | Long-term storage | --- ### $globalUserLeaderboard[] # $globalUserLeaderboard The function `$globalUserLeaderboard` generates a global ranking of all users of the bot, based on the values of a user variable. It is the primary tool to create cross-server leaderboards and motivate competition between users. ## Syntax ``` $globalUserLeaderboard[variable] $globalUserLeaderboard[variable;sort] ``` | Parameter | Required | Description | |-----------|-------------|-------------| | `variable` | Yes | The name of the global user variable to rank | | `sort` | No | `desc` (descending, default) or `asc` (ascending) | ## How It Works 1. `$globalUserLeaderboard` is a **placeholder**: it is replaced at runtime by the dedicated leaderboard action. 2. The system scans the global variables of **all users** of the bot. 3. The entries are sorted according to the specified direction. 4. The result is a multiline string where each line represents an entry of the leaderboard. The format of each line is typically: ``` username ``` Or potentially a combined format depending on the bot configuration. ## Typical Usage The classic pattern to use a leaderboard: ``` $textSplit[$globalUserLeaderboard[score;desc];\n] ``` Then iterate through the elements with `$splitText[index]`, `$getLeaderboardPosition` and `$getLeaderboardValue`. ## Data Persistence For the ranking to be meaningful, user variables must be populated beforehand via: - [`$setUserVar`](/docs/setuservar) — Set a variable for a user - [`$getUserVar`](/docs/getuservar) — Read a user variable Example of score update: ``` $setUserVar[score;$sum[$getUserVar[score];10];$authorID] ``` ## Sorting - **`desc`** (default): highest values first — ideal for scores, XP, coins. - **`asc`**: lowest values first — useful for time, penalties, or reversed rankings. ## Important Notes - Users who do not have the specified variable are ignored in the ranking. - The number of entries returned depends on the bot configuration and the leaderboard action. - For a ranking limited to a specific server, use [`$serverLeaderboard`](/docs/serverleaderboard). - To see only the current user's position, use [`$userLeaderboard`](/docs/userleaderboard). ## See Also - [`$getLeaderboardPosition`](/docs/getleaderboardposition) — Rank in the active leaderboard - [`$getLeaderboardValue`](/docs/getleaderboardvalue) — Value in the active leaderboard - [`$serverLeaderboard`](/docs/serverleaderboard) — Ranking limited to the server - [`$userLeaderboard`](/docs/userleaderboard) — Current user's position - [`$textSplit`](/docs/textsplit) — Parse the result - [`$setUserVar`](/docs/setuservar) — Set a user variable --- ### $input # $input The function `$input` returns the **text entered after the command name**. For a command `!say Hello World`, `$input` evaluates to `Hello World`. ## Syntax ``` $input ``` ## Parameters None. ## Return Value - **Type**: String - The full text entered after the command name. - An empty string if no arguments were provided. ## Difference with $message | Function | Example with `!say hello` | |---|---| | `$message` | `!say hello` (complete command) | | `$input` | `hello` (arguments only) | ## Examples ### Echo command ```bdfd $sendMessage[$input] ``` ### Say command with embed ```bdfd $if[$input!=] $title[Message of $username] $description[$input] $color[#5865F2] $sendMessage[] $else $sendMessage[Usage: !say ] $endif ``` ### Extracting the first word ```bdfd $let[firstWord;$splitText[1; ;$input]] $sendMessage[First word: $firstWord] ``` ## Notes - `$input` is affected by `$noMentionMessage` (mentions are converted). - To avoid mention conversion, use `$messageSlice[>1]`. - `$input` does not contain the prefix or the command name. --- ### $listVar[] $listVar is a diagnostic and debugging function that provides visibility into all currently active temporary variables. Each entry in the output includes both the variable name and its current value. ## Output Format Variables are listed with their names and values in the format `name: "value"`. The default separator is a comma followed by a space: `, `. To customize this, provide a separator string: - `$listVar[\n]` — one variable per line. - `$listVar[ | ]` — pipe-separated list. - `$listVar[; ]` — semicolon-separated list. Use `\n` for a literal newline character in the separator. ## Scope Only **temporary** variables (`$var`) are listed. Global and user-scoped variables (`$getVar`/`$setVar`) are **not** included. There is no built-in equivalent for listing persistent variables. ## When to Use - **Debugging**: verify that variables are set to expected values at various points in a complex command. - **Logging / error messages**: include the variable state in error output to help users diagnose issues. - **Dynamic inspection**: check which variables exist before branching logic. --- ### $noMentionMessage # $noMentionMessage The function `$noMentionMessage` returns the **message content** by replacing all mentions with their plain text equivalents. ## Syntax ``` $noMentionMessage ``` ## Parameters None. ## Return Value - **Type** : String - The message with mentions converted. ## Behavior - `<@userID>` → `@username` - `<#channelID>` → `#channel-name` - `<@&roleID>` → `@role-name` - Prevents unwanted pings in logs or relayed messages. ## Examples ### Logging without pinging ```bdfd $let[logChannel;123456789] $title[📋 New Message] $description[ **Author:** $username **Content:** $noMentionMessage ] $channelSendMessage[$logChannel;] ``` ### Secure say command ```bdfd $sendMessage[$noMentionMessage] ``` ### Relaying a message ```bdfd $title[Relayed message from $username] $description[$noMentionMessage] $footer[From <#$channelID>] $channelSendMessage[123456789;] ``` ## Notes - `$noMentionMessage` prevents the bot from accidentally pinging users. - Unlike `$message`, mentions are resolved to names. - To completely disable mentions, combine with `$suppressMentions`. --- ### $resetChannelVar[] $resetChannelVar restores a channel-scoped variable to its default value defined in the Bot Creator Variables UI. If no default is defined, the stored value is removed entirely. When called with only a `name`, it resets the variable for the current channel. When a Channel ID is provided, it resets the variable for the specified channel. Use this function to clear channel-specific settings, reset counters, or restore channel defaults. After resetting, $getChannelVar returns the default value (if defined) or an empty string. This function does not return any output. --- ### $resetGuildMemberVar[] $resetGuildMemberVar restores a guild-member-scoped variable to its default value defined in the Bot Creator Variables UI. If no default is defined, the stored value is removed. $resetMemberVar is an exact alias. When called with only a `name`, it resets the variable for the current command author in the current guild. When a User ID is provided, it resets for that user in the current guild. When both User ID and Guild ID are provided, it resets for the exact guild-member combination. Use this function to clear warnings, reset XP after a season, remove moderation flags, or restore member defaults after an unban/unmute. After resetting, $getGuildMemberVar returns the default value (if defined) or an empty string. This function does not return any output. --- ### $resetGuildVar[] $resetGuildVar restores a guild-scoped variable to its default value defined in the Bot Creator Variables UI. If no default is defined, the stored value is removed. $resetServerVar is an exact alias and can be used interchangeably. When called with only a `name`, it resets the variable for the current guild. When a Guild ID is provided, it resets the variable for the specified server. Use this function to revert server settings to their defaults, clear maintenance mode, or perform bulk resets. After resetting, $getGuildVar returns the default value (if defined) or an empty string. This function does not return any output. --- ### $resetMemberVar[] $resetMemberVar restores a guild-member-scoped variable to its default value defined in the Bot Creator Variables UI. If no default is defined, the stored value is removed. $resetGuildMemberVar is an exact alias. When called with only a `name`, it resets the variable for the current command author in the current guild. When a User ID is provided, it resets for that user in the current guild. When both User ID and Guild ID are provided, it resets for the exact guild-member combination. Use this function to clear warnings, reset XP after a season, remove moderation flags, or restore member defaults after an unban/unmute. After resetting, $getMemberVar returns the default value (if defined) or an empty string. This function does not return any output. --- ### $resetServerVar[] $resetServerVar restores a guild-scoped variable to its default value defined in the Bot Creator Variables UI. If no default is defined, the stored value is removed. $resetGuildVar is an exact alias and can be used interchangeably. When called with only a `name`, it resets the variable for the current guild. When a Guild ID is provided, it resets the variable for the specified server. Use this function to revert server settings to their defaults, clear maintenance mode, or perform bulk resets. After resetting, $getServerVar returns the default value (if defined) or an empty string. This function does not return any output. --- ### $resetUserVar[] $resetUserVar restores a user-scoped variable to its default value, or removes the stored value entirely if no default is defined in the Bot Creator Variables UI. It performs a `resetScopedVariable` action with scope `user`. When called with only a `name`, it resets the variable for the current command author. When a User ID is provided, it resets the variable for that specific user. This function is useful for seasonal resets, clearing temporary data, or reverting a user's settings to their defaults. After resetting, subsequent calls to $getUserVar will return the default value (if defined) or an empty string. This function does not return any output. --- ### $serverLeaderboard[] # $serverLeaderboard The function `$serverLeaderboard` generates a leaderboard of users **limited to the current Discord server** (guild). Unlike `$globalUserLeaderboard` which covers all users of the bot across all servers, this function restricts the scope to the members of the server where the command was executed. ## Syntax ``` $serverLeaderboard[variable] $serverLeaderboard[variable;sort] ``` | Parameter | Required | Description | |-----------|-------------|-------------| | `variable` | Yes | The name of the variable to rank (user-scoped or guild-scoped) | | `sort` | No | `desc` (descending, default) or `asc` (ascending) | ## How It Works 1. `$serverLeaderboard` acts as a **placeholder**: it is replaced at runtime by the dedicated leaderboard action. 2. The system only considers user variables for **members of the current server**. 3. The entries are sorted according to the specified direction. 4. The result is a multi-line string where each line represents an entry in the leaderboard. The format of each line is typically the user's name, which can be parsed using `$textSplit`. ## Typical Usage ``` $textSplit[$serverLeaderboard[xp;desc];\n] ``` Then iterate through the list using `$splitText`, `$getLeaderboardPosition`, and `$getLeaderboardValue`. ## Data Persistence The variables can be of two types: - **User-scoped**: specific to each user, defined with [`$setUserVar`](/docs/setuservar). Example: XP earned on the server. - **Guild-scoped**: specific to the server, defined using server variable functions. Example of updating server XP: ``` $setUserVar[xp;$sum[$getUserVar[xp];$random[10;50]];$authorID] ``` ## Sorting - **`desc`** (default): Highest values first (XP, messages, coins). - **`asc`**: Lowest values first (warns, times, penalties). ## Common Use Cases - 🎮 **XP Leaderboard**: Motivate activity on the server. - 💬 **Top Messages**: Reward the most active members. - 🛡️ **Moderation**: Monitor members with the most warns. - 🎯 **Events**: Temporary leaderboards for contests. ## Important Notes - Only **current** members of the server are included in the leaderboard. - Users who do not have the specified variable set are ignored. - For a cross-server leaderboard, use [`$globalUserLeaderboard`](/docs/globaluserleaderboard). - To check the rank of a specific user, use [`$userLeaderboard`](/docs/userleaderboard). ## See Also - [`$getLeaderboardPosition`](/docs/getleaderboardposition) — Rank in the active leaderboard - [`$getLeaderboardValue`](/docs/getleaderboardvalue) — Value in the active leaderboard - [`$globalUserLeaderboard`](/docs/globaluserleaderboard) — Cross-server global leaderboard - [`$userLeaderboard`](/docs/userleaderboard) — Rank of the current user - [`$textSplit`](/docs/textsplit) — Parse the result - [`$setUserVar`](/docs/setuservar) — Set a user variable --- ### $setChannelVar[] $setChannelVar stores a value persistently in the BDFD database under a channel-scoped variable. The variable value is specific to a Discord channel within a server. When called with two arguments (`name` and `value`), it sets the variable for the current channel (`((channel.id))`). When a Channel ID is provided, the variable is set for the specified channel. The scope is `channel`, making it ideal for per-channel settings like locks, slowmode, topic tracking, message counters, or channel-specific configurations. This function does not return any output — use $getChannelVar to read the value. To reset, use $resetChannelVar. --- ### $setGuildMemberVar[] $setGuildMemberVar stores a value persistently in the BDFD database under a guild-member-scoped variable. The context key is composed as `guildId:userId`, making the value unique per user per server. $setMemberVar is an exact alias. When called with two arguments, it sets the variable for the current command author in the current guild. When a User ID is provided, it sets for that user in the current guild. When both User ID and Guild ID are provided, it sets for the exact guild-member combination. The scope is `guildMember`, ideal for per-user-per-server data like XP, warnings, ranks, inventory, economy balances (server-specific), and moderation records. This function does not return any output — use $getGuildMemberVar to read. To reset, use $resetGuildMemberVar. --- ### $setGuildVar[] $setGuildVar stores a value persistently in the BDFD database under a guild-scoped variable. The variable value is shared by all members within that server context. $setServerVar is an exact alias and can be used interchangeably. When called with two arguments (`name` and `value`), it sets the variable for the current guild (`((guild.id))`). When a Guild ID is provided, the variable is set for the specified server. The scope is `guild`, meaning the value is shared server-wide. This is ideal for server settings such as prefixes, welcome channels, auto-roles, logging channels, and similar configuration values. This function does not return any output — use $getGuildVar to read the value. To reset, use $resetGuildVar. --- ### $setMemberVar[] $setMemberVar stores a value persistently in the BDFD database under a guild-member-scoped variable. The context key is composed as `guildId:userId`, making the value unique per user per server. $setGuildMemberVar is an exact alias. When called with two arguments, it sets the variable for the current command author in the current guild. When a User ID is provided, it sets for that user in the current guild. When both User ID and Guild ID are provided, it sets for the exact guild-member combination. The scope is `guildMember`, ideal for per-user-per-server data like XP, warnings, ranks, inventory, economy balances (server-specific), and moderation records. This function does not return any output — use $getMemberVar to read. To reset, use $resetMemberVar. --- ### $setMessageVar[] $setMessageVar stores a value persistently in the BDFD database under a message-scoped variable. The variable value is tied directly to a specific Discord message. When called with two arguments (`name` and `value`), it sets the variable for the message that triggered the current command or event. When a Message ID is provided, the variable is set for the specified message. The scope is `message`, making it ideal for tracking message status, reaction roles, polls, click counters, and any metadata that should be attached to a particular message. This function does not return any output — use $getMessageVar to read the value. There is currently no dedicated resetter for message-scoped variables; use $setMessageVar with an empty value to clear it. --- ### $setServerVar[] $setServerVar stores a value persistently in the BDFD database under a guild-scoped variable. The variable value is shared by all members within that server context. $setGuildVar is an exact alias and can be used interchangeably. When called with two arguments (`name` and `value`), it sets the variable for the current guild (`((guild.id))`). When a Guild ID is provided, the variable is set for the specified server. The scope is `guild`, meaning the value is shared server-wide. This is ideal for server settings such as prefixes, welcome channels, auto-roles, logging channels, and similar configuration values. This function does not return any output — use $getServerVar to read the value. To reset, use $resetServerVar. --- ### $setUserVar[] $setUserVar stores a value persistently in the BDFD database under a user-scoped variable. When called with two arguments (`name` and `value`), it sets the variable for the user who triggered the current command. When a third argument (User ID) is provided, the variable is set for that specific user. The scope is `user`, meaning the context ID is `((author.id))` by default. This function does not return any output — it performs a silent write operation. Use $getUserVar to read the value back. Variables must first be defined in the Bot Creator Variables UI. The value stored can be any string, including numbers, booleans, JSON, or the output of other BDFD functions. To reset a variable to its default value, use $resetUserVar. > **JavaScript (BDJS) equivalent:** `await db.user.set('name', value)` — see [db.user](/docs/javascript/db-user/). --- ### $setVar[] $setVar writes values to the bot's persistent database. This is the counterpart to `$getVar` and is used for any data that needs to survive beyond the current command execution. ## Global vs User-Scoped Variables The third parameter determines the scope: - **Omitted**: the variable is stored as **global** — accessible from any command, any user, any server. Use sparingly for configuration or shared data. - **User ID provided**: the variable is **user-scoped** — each user gets their own independent copy. Perfect for coins, XP, settings, and any per-user data. ## Important Considerations - **All values are strings**. If you need numeric operations, use `$add`, `$sub`, `$mul`, `$div` to convert and calculate. - **Overwrite behavior**: calling `$setVar` on an existing variable replaces its value — there is no append mode. - **Case insensitivity**: `$setVar[Score;100]` and `$setVar[score;200]` target the same variable. - **No return value**: this function performs a write action and returns void. It cannot be used inline in a string — use it as a standalone statement. --- ### $url # $url The function `$url` returns the **URL of the current web context** in which the bot is running. ## Syntax ``` $url ``` ## Parameters None. ## Return Value - **Type** : String - The URL of the current context (web page, dashboard, etc.). ## Behavior - Returns the page URL if the bot is executed in a web context. - May return an empty string outside a web context. ## Examples ### Display the current URL ```bdfd $sendMessage[Current URL: $url] ``` ### Check a specific page ```bdfd $if[$checkContains[$url;/dashboard]==true] $sendMessage[You are on the dashboard.] $else $sendMessage[You are on: $url] $endif ``` ## Notes - Context-dependent: returns nothing in classic Discord commands. - Useful for web-based applications and BDFD dashboards. --- ### $useChannel # $useChannel The function `$useChannel[]` **changes the channel context** for the rest of the command execution. All functions that interact with "the current channel" (like `$sendMessage`) will then use the specified channel. ## Syntax ``` $useChannel[channelID] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the target channel. | ## Return Value None. The context is modified. ## Behavior - Changes the current channel for **the entire remainder** of the command. - Affects `$sendMessage`, `$title`, `$description`, etc. - The change is local to the current command execution. ## Examples ### Redirect Logs ```bdfd $let[logChannel;123456789012345678] $useChannel[$logChannel] $title[📋 Command Log] $description[ **User:** $username **Command:** $message **Channel:** <#$channelID> **Date:** $day/$month/$year ] $color[#5865F2] $sendMessage[] ``` ### Send a Cross Notification ```bdfd $useChannel[$dmChannelID[$authorID]] $sendMessage[Your ticket has been created! A staff member will contact you soon.] ``` ### Response in an Announcement Channel ```bdfd $if[$hasPerms[$authorID;Administrator]==true] $useChannel[123456789] $sendMessage[@everyone Important announcement: $noMentionMessage] $else $sendMessage[Permission denied.] $endif ``` ## Notes - `$channelSendMessage[]` is often safer for one-off sends without changing the entire context. - Use `$useChannel[]` when several functions need to execute in the same target channel. - The original channel is "forgotten" for the rest of the command. --- ### $userLeaderboard[] # $userLeaderboard The `$userLeaderboard` function displays the position of the **current user** in a leaderboard, surrounded by the users who immediately precede and follow them. Unlike `$globalUserLeaderboard` or `$serverLeaderboard` which return the full leaderboard, this function focuses on the user's immediate context. ## Syntax ``` $userLeaderboard[variable] $userLeaderboard[variable;sort] ``` | Parameter | Required | Description | |-----------|-------------|-------------| | `variable` | Yes | The name of the variable to rank | | `sort` | No | `desc` (descending, default) or `asc` (ascending) | ## How It Works 1. `$userLeaderboard` is a **placeholder** resolved at runtime by the leaderboard action. 2. The system identifies the position of the current user in the leaderboard. 3. It returns a neighborhood around that position (the user + a few neighbors above and below). 4. The current user is identifiable by their username or ID in the returned lines. ## Typical Usage ``` $textSplit[$userLeaderboard[score;desc];\n] ``` Then loop through the entries with `$splitText`, `$getLeaderboardPosition`, and `$getLeaderboardValue`. ## Use Cases - 📊 **Personal dashboard**: show the user where they stand. - 🎯 **Motivation**: display direct neighbors to encourage competition. - 🏆 **Congratulation messages**: detect if the user is on the podium. - 📈 **Progression tracking**: see the gap with players ahead of you. ## Comparison with other leaderboards | Function | Scope | Returns | |----------|-----------|----------| | `$userLeaderboard` | Current user | Neighborhood around the user | | `$serverLeaderboard` | Current server | Complete leaderboard of the server | | `$globalUserLeaderboard` | All users | Complete global leaderboard | ## Important Notes - The user must have a value set for the specified variable, otherwise they will not appear in the leaderboard. - The number of entries returned around the user depends on the bot's configuration. - `$getLeaderboardPosition` and `$getLeaderboardValue` work normally during iteration. - For a complete leaderboard, prefer `$globalUserLeaderboard` or `$serverLeaderboard`. ## See Also - [`$getLeaderboardPosition`](/docs/getleaderboardposition) — Rank in the active leaderboard - [`$getLeaderboardValue`](/docs/getleaderboardvalue) — Value in the active leaderboard - [`$globalUserLeaderboard`](/docs/globaluserleaderboard) — Complete global leaderboard - [`$serverLeaderboard`](/docs/serverleaderboard) — Complete server leaderboard - [`$textSplit`](/docs/textsplit) — Parse the result - [`$getUserVar`](/docs/getuservar) — Read a user variable - [`$setUserVar`](/docs/setuservar) — Set a user variable --- ### $var[] $var is the primary function for working with temporary variables in BDFD. Temporary variables exist only during the current command execution and are not persisted between commands. They are ideal for intermediate calculations, formatting results, or passing data between functions within the same command block. ## Read vs Write Mode The function's behavior depends on the number of parameters: - **1 parameter** (`$var[name]`): read mode. Returns the current value of the variable, or an empty string if it doesn't exist. - **2+ parameters** (`$var[name;value]`): write mode. Any additional parameters beyond the first are part of the value (joined with `;` if the value itself contains semicolons). Note: only the first semicolon acts as the name/value separator. If your value contains semicolons, they are preserved as part of the stored string. ## Scope and Lifetime Temporary variables are scoped to the current execution context. They are not shared with other commands, scheduled tasks, or concurrent invocations. When the command finishes execution, all temporary variables are discarded. ## Case Insensitivity Variable names are case-insensitive. `$var[Name]`, `$var[NAME]`, and `$var[name]` all refer to the same variable. ## Silent Failure When reading a variable that does not exist, `$var` returns an empty string rather than throwing an error. This means you should always validate if a variable exists before relying on its value, for example using `$varExists[]`. --- ### $varExistsError[] $varExistsError is a **no-op stub** included solely for backward compatibility with scripts originally written for the classic BDFD (Bot Designer For Discord) application. In the original BDFD, this function would halt execution with an error if the variable did not exist. In this implementation, it does nothing — it always returns an empty string and never interrupts execution. ## Why This Exists When migrating BDFD scripts to Bot Creator, existing code may call `$varExistsError` to check that required variables are present before proceeding. Instead of removing these calls manually from every script, this stub silently accepts them, allowing the script to run without modification. ## Behavior - Accepts one parameter (the variable name). - Always returns an empty string. - Never raises an error, regardless of whether the variable exists. - Has no side effects on variables or the execution state. ## Recommendation Do not use `$varExistsError` in new code. Use `$varExists` combined with your own conditional logic to handle missing variables gracefully: ``` $if[$varExists[required]==false] Error: required variable missing. $stop $endif ``` --- ### $varExists[] $varExists is used to safely check whether a temporary variable has been set before attempting to read it. Since `$var` returns an empty string for missing variables (silent failure), `$varExists` is the only reliable way to distinguish between "variable exists with an empty value" and "variable does not exist." ## Return Value The return value is always the string `"true"` or `"false"` — not a boolean. Use string comparison in conditionals: ``` $if[$varExists[name]==true] $if[$varExists[name]!=false] ``` Both forms work. `$if[$varExists[name]]` alone will always be truthy (non-empty string), so always compare explicitly. ## Scope This function only checks **temporary** variables created with `$var`. It does not check global or user-scoped variables — those would need to be checked by attempting `$getVar` and comparing the result. ## Use Cases - **Lazy initialization**: set a variable only if it hasn't been set yet. - **Guard clauses**: skip logic that depends on a variable being present. - **Debugging**: verify that expected intermediate values are available. --- ### $variablesCount[] $variablesCount provides a quick way to check how many variables are active in the current execution context. This is useful for validation, debugging, and conditional logic. ## Return Value The count is always returned as a string representation of an integer (e.g., `"3"`, `"0"`, `"15"`). When used in numeric comparisons, BDFD will automatically coerce the string to a number. ## Type Filtering When a Type parameter is provided, only variables of that type are counted: - `$variablesCount` — count all active variables (all types). - `$variablesCount[temp]` — count only temporary variables. ## Comparison with $listVar While `$listVar` gives the names and values of temporary variables, `$variablesCount` gives only the count. Use `$variablesCount` when you need a numeric check (e.g., "are there at least 3 variables?") without the overhead of formatting a full list. --- ## Webhooks & Integrations ### $webhookAvatarURL # $webhookAvatarURL The `$webhookAvatarURL` function allows you to **set the avatar** that will be used during the next delivery via `$webhookSend`. ## Syntax ``` $webhookAvatarURL[url] ``` ## Parameters | Parameter | Description | |---|---| | `url` | The URL of the image to use as an avatar. Supported formats: PNG, JPG, GIF, WEBP. | ## Return Value This function does not return a value. It only sets the avatar for the next call to `$webhookSend`. ## Behavior - The URL must be publicly accessible. - The image is downloaded by Discord at the time of sending. - The avatar is reset after each `$webhookSend`. - If the URL is invalid, the default avatar of the webhook is used. ## Examples ### Custom avatar ```bdfd $webhookAvatarURL[https://cdn.example.com/avatars/notif.png] $webhookUsername[System] $webhookContent[New notification!] $webhookSend[$webhookURL;] ``` ### Dynamic avatar ```bdfd $webhookAvatarURL[$authorAvatar] $webhookUsername[$username] $webhookContent[$message] $webhookSend[$webhookURL;] ``` ### Server avatar ```bdfd $webhookAvatarURL[$serverIcon] $webhookUsername[$serverName] $webhookTitle[Welcome!] $webhookDescription[Welcome to $serverName, $username!] $webhookSend[$welcomeHook;] ``` ## Notes - The defined avatar only applies to the **next** `$webhookSend`. - For repeated sendings with the same avatar, include `$webhookAvatarURL[]` before each `$webhookSend[]`. - The maximum image size is 8 MB. --- ### $webhookColor # $webhookColor The `$webhookColor` function allows you to **set the color of the embed** (left sidebar) for the next webhook message. ## Syntax ``` $webhookColor[hexColor] ``` ## Parameters | Parameter | Description | |---|---| | `hexColor` | Hexadecimal color code, with or without the `#` prefix. Examples: `#FF0000`, `5865F2`, `00FF00`. | ## Return Value This function does not return a value. It only sets the color of the next embed. ## Behavior - The color applies to the left sidebar of the embed. - If no embed is defined (no `$webhookTitle` or `$webhookDescription`), the color is ignored. - The color is reset after each `$webhookSend`. ## Examples ### Colored embed ```bdfd $webhookTitle[Success] $webhookDescription[The operation was completed successfully.] $webhookColor[#57F287] $webhookFooter[✅ Operation successful] $webhookSend[$webhookURL;] ``` ### Conditional colors ```bdfd $if[$checkContains[$message;error]==true] $webhookColor[#ED4245] $webhookTitle[Error Detected] $else $webhookColor[#5865F2] $webhookTitle[Information] $endif $webhookDescription[$message] $webhookSend[$logHook;] ``` ## Notes - Use consistent colors for readability: red for errors, green for success, blue for info. - The default Discord color is `#000000` (no colored sidebar). - Very light colors may be hard to see in light theme. --- ### $webhookContent # $webhookContent The `$webhookContent` function allows you to **set the text content** of a webhook message, as an alternative to the second parameter of `$webhookSend`. ## Syntax ``` $webhookContent[text] ``` ## Parameters | Parameter | Description | |---|---| | `text` | The text of the message. Supports markdown, emojis, and mentions. Maximum 2000 characters. | ## Return Value This function does not return a value. It only sets the content for the next `$webhookSend`. ## Behavior - The defined content replaces the second parameter of `$webhookSend`. - Supports all Discord markdown formatting. - If both `$webhookContent` and `$webhookSend[url;text]` are used, the content of `$webhookContent` takes priority. ## Examples ### Simple content ```bdfd $webhookContent[This is a message sent via webhook!] $webhookSend[$webhookURL;] ``` ### Formatted content ```bdfd $webhookUsername[Announcements] $webhookAvatarURL[$serverIcon] $webhookContent[📢 **New announcement** from $username! >>> $message] $webhookSend[$webhookURL;] ``` ### With embed and content ```bdfd $webhookContent[Here are the details below:] $webhookTitle[Important Details] $webhookDescription[The detailed information can be found here.] $webhookColor[#FEE75C] $webhookSend[$webhookURL;] ``` ## Notes - The limit is 2000 characters for the text content. - The text content appears above the embed if there is one. - Use `>>> ` to create a block quote in the content. --- ### $webhookCreate # $webhookCreate The `$webhookCreate` function allows you to **create a new webhook** in a Discord channel and returns its complete URL. ## Syntax ``` $webhookCreate[channelID;name;(avatarURL)] ``` ## Parameters | Parameter | Description | |---|---| | `channelID` | The ID of the channel where the webhook will be created. | | `name` | The name of the webhook (2 to 80 characters). | | `avatarURL` | Optional - URL of the avatar image of the webhook. | ## Return Value - **Type**: String (URL) - The complete URL of the webhook in the format `https://discord.com/api/webhooks/ID/TOKEN` - Empty string or error if the bot does not have the `MANAGE_WEBHOOKS` permission. ## Behavior - Requires the `MANAGE_WEBHOOKS` permission in the target channel. - The name must be between 2 and 80 characters. - The avatar must be a valid URL pointing to an image (PNG, JPG, GIF, WEBP). - A channel can have up to 10 webhooks (or 100 for community-enabled servers). ## Examples ### Simple creation ```bdfd $let[hook;$webhookCreate[$channelID;Server Logger]] $if[$hook!=] $webhookSend[$hook;Webhook for logs created successfully!] $else $sendMessage[Failure: MANAGE_WEBHOOKS permission required.] $endif ``` ### Creation with storage ```bdfd $let[logHook;$webhookCreate[$channelID;Logs;$serverIcon]] $setUserVar[logWebhook;$logHook] $sendMessage[Webhook of logs configured!] ``` ## Notes - Webhooks created by the bot are linked to the bot. - A webhook cannot be moved to another channel after creation. - Delete unused webhooks with `$webhookDelete[]`. --- ### $webhookDelete # $webhookDelete The `$webhookDelete` function allows you to **delete an existing Discord webhook** using its ID and token. ## Syntax ``` $webhookDelete[webhookID;webhookToken] ``` ## Parameters | Parameter | Description | |---|---| | `webhookID` | The ID of the webhook (first part of the URL after `/webhooks/`). | | `webhookToken` | The token of the webhook (second part after the ID). | ## Return Value This function does not return a value. The deletion is performed silently. ## Behavior - The bot must have the `MANAGE_WEBHOOKS` permission or be the creator of the webhook. - Once deleted, the webhook can no longer be used. - Remaining URLs pointing to this webhook will become invalid. ## Examples ### Deletion of a webhook ```bdfd $let[hookID;123456789] $let[hookToken;abcdefghijklmnop] $webhookDelete[$hookID;$hookToken] $sendMessage[Webhook deleted.] ``` ### Extraction from a stored URL ```bdfd $let[url;$getUserVar[tempHook]] $let[parts;$splitText[$url;/]] $let[hookID;$getTextSplitIndex[$parts;5]] $let[hookToken;$getTextSplitIndex[$parts;6]] $webhookDelete[$hookID;$hookToken] $sendMessage[Webhook cleaned up.] ``` ## Notes - Webhooks created via the Discord interface can only be deleted by an administrator. - Webhooks created by the bot can be deleted by it. - Delete temporary webhooks after use to avoid accumulation. --- ### $webhookDescription # $webhookDescription The `$webhookDescription` function allows you to **set the description** (main body) of the embed for the next webhook message. ## Syntax ``` $webhookDescription[text] ``` ## Parameters | Parameter | Description | |---|---| | `text` | The content of the embed description. Supports markdown, mentions, and emojis. Max 4096 characters. | ## Return Value This function does not return a value. It only sets the description of the next embed. ## Behavior - The description appears below the title of the embed. - Supports full markdown: bold, italics, links, lists, code blocks, etc. - Line breaks are preserved. - The description is reset after each `$webhookSend`. ## Examples ### Simple description ```bdfd $webhookTitle[Server Statistics] $webhookDescription[ **Members:** $membersCount **Online:** $onlineMembers **Bots:** $botCount **Boost:** Level $boostLevel ] $webhookColor[#5865F2] $webhookSend[$webhookURL;] ``` ### Formatted description ```bdfd $webhookTitle[Moderation Report] $webhookDescription[ **Moderator:** $username **Action:** Ban **User:** $userName[$mentioned[1]] **Reason:** $message[2] *Action performed on $date[$day]/$date[$month]/$date[$year]* ] $webhookColor[#ED4245] $webhookSend[$logHook;] ``` ### Conditional description ```bdfd $if[$checkContains[$message;!report]==true] $webhookTitle[New Report] $webhookDescription[ **Reported by:** $username **Reported user:** $userName[$mentioned[1]] **Reason:** $noMentionMessage ] $webhookColor[#FEE75C] $webhookSend[$reportHook;] $endif ``` ## Notes - Maximum 4096 characters for the description. - The description is the main body of the embed. - Combine title + description + color for a visually complete embed. --- ### $webhookFooter # $webhookFooter The `$webhookFooter` function allows you to **set the footer** of the embed for the next webhook message. ## Syntax ``` $webhookFooter[text] ``` ## Parameters | Parameter | Description | |---|---| | `text` | The text of the footer. Maximum 2048 characters. Supports BDFD variables. | ## Return Value This function does not return a value. It only sets the footer of the next embed. ## Behavior - The footer appears at the bottom of the embed, in smaller, grayed-out text. - Ideal for timestamp information, signatures, or sources. - The footer is reset after each `$webhookSend`. ## Examples ### Informative footer ```bdfd $webhookTitle[Command Log] $webhookDescription[ **Command:** $commandName **User:** $username ($authorID) **Channel:** $channelName ] $webhookFooter[Logger • $date[$day]/$date[$month]/$date[$year] at $date[$hour]:$date[$minute]] $webhookColor[#5865F2] $webhookSend[$logHook;] ``` ### Signature footer ```bdfd $webhookTitle[Welcome!] $webhookDescription[Welcome to **$serverName**, $username! We are now $membersCount members!] $webhookFooter[Please read the rules in $channelName[$rulesChannelID]] $webhookColor[#57F287] $webhookSend[$welcomeHook;] ``` ## Notes - The footer is displayed in smaller, gray text by Discord. - Maximum 2048 characters. - Unlike the title and description, the footer does not support markdown. --- ### $webhookSend # $webhookSend The `$webhookSend` function allows you to **send a message via a Discord webhook**. This is the main entry point for using webhooks with BDFD. ## Syntax ``` $webhookSend[webhookURL;content] ``` ## Parameters | Parameter | Description | |---|---| | `webhookURL` | The complete URL of the Discord webhook (`https://discord.com/api/webhooks/ID/TOKEN`). | | `content` | The text content of the message to send. Supports markdown and emojis. | ## Return Value This function does not return a value directly. The message is sent via the Discord webhook API. ## Behavior - If the webhook is invalid or expired, the sending fails silently. - The content can include line breaks, markdown, and mentions. - Webhook embed functions (`$webhookTitle`, `$webhookDescription`, etc.) must be placed **before** `$webhookSend` in the code. - `$webhookSend` must be the **last** webhook function called, because it triggers the actual delivery. ## Examples ### Simple sending ```bdfd $webhookSend[https://discord.com/api/webhooks/123456/abcdef;Hello World!] ``` ### Sending with embed ```bdfd $webhookTitle[Title of the embed] $webhookDescription[Detailed description here] $webhookColor[#5865F2] $webhookFooter[Footer text] $webhookSend[https://discord.com/api/webhooks/123456/abcdef;] ``` ### Conditional sending ```bdfd $if[$checkContains[$message;!annonce]==true] $webhookTitle[New announcement] $webhookDescription[$message] $webhookSend[$webhookURL;] $endif ``` ## Notes - Webhook URLs are sensitive: never expose them in public code. - Store webhook URLs in environment variables or constants. - A webhook can send up to 10 embeds per message. - The limit of characters per message is 2000 for the text content. --- ### $webhookTitle # $webhookTitle The `$webhookTitle` function allows you to **set the title** of the embed for the next webhook message. ## Syntax ``` $webhookTitle[text] ``` ## Parameters | Parameter | Description | |---|---| | `text` | The title of the embed. Maximum 256 characters. Supports emojis and variables. | ## Return Value This function does not return a value. It only sets the title of the next embed. ## Behavior - The title appears at the top of the embed, in larger, bold text. - If no title is defined but a description is, the embed will be created without a title. - The title is reset after each `$webhookSend`. ## Examples ### Dynamic title ```bdfd $webhookTitle[🔨 Moderation Action] $webhookDescription[ **Action:** $message[1] **User:** $userName[$mentioned[1]] **Reason:** $noMentionMessage ] $webhookColor[#ED4245] $webhookFooter[Moderation • $username] $webhookSend[$modHook;] ``` ### Title with emoji ```bdfd $webhookTitle[✅ Task Completed] $webhookDescription[The automatic data backup was completed successfully.] $webhookColor[#57F287] $webhookSend[$webhookURL;] ``` ### Multiple embeds (conceptual) ```bdfd $webhookTitle[First embed] $webhookDescription[Content of the first embed.] $webhookSend[$webhookURL;] $webhookTitle[Second embed] $webhookDescription[Content of the second embed.] $webhookColor[#FEE75C] $webhookSend[$webhookURL;] ``` ## Notes - Maximum 256 characters for the title. - The title is bold and larger than the description. - An embed can exist without a title (description only), but a title alone (without description) also works. --- ### $webhookUsername # $webhookUsername The `$webhookUsername` function allows you to **set the username** that will be displayed for the next message sent via `$webhookSend`. ## Syntax ``` $webhookUsername[name] ``` ## Parameters | Parameter | Description | |---|---| | `name` | The name to display. Maximum 80 characters. Supports emojis and variables. | ## Return Value This function does not return a value. It only sets the name for the next `$webhookSend`. ## Behavior - The name replaces the default name of the webhook for this sending. - The name is reset after each `$webhookSend`. - If no name is defined, the original name of the webhook is used. ## Examples ### Fixed name ```bdfd $webhookUsername[📢 Server Announcements] $webhookContent[New update available!] $webhookSend[$webhookURL;] ``` ### Dynamic name ```bdfd $webhookUsername[$username (via webhook)] $webhookAvatarURL[$authorAvatar] $webhookContent[$message] $webhookSend[$webhookURL;] ``` ### Anonymization ```bdfd $webhookUsername[Anonymous Message] $webhookAvatarURL[https://cdn.example.com/anonymous.png] $webhookContent[$noMentionMessage] $webhookSend[$confessionHook;] ``` ## Notes - The name cannot exceed 80 characters. - Webhooks with names impersonating official roles (Admin, Moderator) can be misleading — use them ethically. - Combine with `$webhookAvatarURL[]` for a complete customization. ---