From f24dddbc238a1142171d88eae0bbcbb7ae26f006 Mon Sep 17 00:00:00 2001 From: Nipuna Ranasinghe Date: Tue, 2 Jul 2024 15:32:48 +0530 Subject: [PATCH 1/7] Add README and build files --- examples/README.md | 52 +++++++++++++++++++++++++++++ examples/build.gradle | 78 +++++++++++++++++++++++++++++++++++++++++++ examples/build.sh | 63 ++++++++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 examples/README.md create mode 100644 examples/build.gradle create mode 100755 examples/build.sh diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..55b5c8a --- /dev/null +++ b/examples/README.md @@ -0,0 +1,52 @@ +# Examples + +The `ballerinax/discord` connector provides practical examples illustrating usage in various scenarios. Explore the below examples, covering use cases like automated event announcements and automated role assignment based on reactions. + +1. [Automated Event Announcements] +2. [Automated Role Assignment Based on Reactions] + +## Prerequisites + +1. Generate Discord credentials to authenticate the connector as described in the [Setup guide](https://central.ballerina.io/ballerinax/discord/latest#setup-guide). + +2. For each example, create a `Config.toml` file the related configuration. Here's an example of how your `Config.toml` file should look: + + ```toml + clientId="" + clientSecret="" + scopes=["", ""] + ``` + +## Running an Example + +Execute the following commands to build an example from the source: + +* To build an example: + + ```bash + bal build + ``` + +* To run an example: + + ```bash + bal run + ``` + +## Building the Examples with the Local Module + +**Warning**: Due to the absence of support for reading local repositories for single Ballerina files, the Bala of the module is manually written to the central repository as a workaround. Consequently, the bash script may modify your local Ballerina repositories. + +Execute the following commands to build all the examples against the changes you have made to the module locally: + +* To build all the examples: + + ```bash + ./build.sh build + ``` + +* To run all the examples: + + ```bash + ./build.sh run + ``` diff --git a/examples/build.gradle b/examples/build.gradle new file mode 100644 index 0000000..b8f7186 --- /dev/null +++ b/examples/build.gradle @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.tools.ant.taskdefs.condition.Os + +apply plugin: 'java' + +def graalvmFlag = "" + +task testExamples { + if (project.hasProperty("balGraalVMTest")) { + graalvmFlag = "--graalvm" + } + doLast { + try { + exec { + workingDir project.projectDir + println("Working dir: ${workingDir}") + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine 'cmd', "/c", "chmod +x ./build.sh && ./build.sh run && exit %%ERRORLEVEL%%" + } else { + commandLine 'sh', "-c", "chmod +x ./build.sh && ./build.sh run" + } + } + } catch (Exception e) { + println("Example Build failed: " + e.message) + throw e + } + } +} + +task buildExamples { + gradle.taskGraph.whenReady { graph -> + if (graph.hasTask(":discord-examples:test")) { + buildExamples.enabled = false + } else { + testExamples.enabled = false + } + } + doLast { + try { + exec { + workingDir project.projectDir + println("Working dir: ${workingDir}") + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine 'cmd', "/c", "chmod +x ./build.sh && ./build.sh build && exit %%ERRORLEVEL%%" + } else { + commandLine 'sh', "-c", "chmod +x ./build.sh && ./build.sh build" + } + } + } catch (Exception e) { + println("Example Build failed: " + e.message) + throw e + } + } +} + +buildExamples.dependsOn ":discord-ballerina:build" +testExamples.dependsOn ":discord-ballerina:build" + +// TODO: Enable the examples build once https://github.com/ballerina-platform/ballerina-library/issues/6135 is fixed +// test.dependsOn testExamples +// build.dependsOn buildExamples diff --git a/examples/build.sh b/examples/build.sh new file mode 100755 index 0000000..10fe84c --- /dev/null +++ b/examples/build.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +BAL_EXAMPLES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BAL_CENTRAL_DIR="$HOME/.ballerina/repositories/central.ballerina.io" +BAL_HOME_DIR="$BAL_EXAMPLES_DIR/../ballerina" + +set -e + +case "$1" in +build) + BAL_CMD="build" + ;; +run) + BAL_CMD="run" + ;; +*) + echo "Invalid command provided: '$1'. Please provide 'build' or 'run' as the command." + exit 1 + ;; +esac + +# Read Ballerina package name +BAL_PACKAGE_NAME=$(awk -F'"' '/^name/ {print $2}' "$BAL_HOME_DIR/Ballerina.toml") + +# Push the package to the local repository +cd "$BAL_HOME_DIR" && + bal pack && + bal push --repository=local + +# Remove the cache directories in the repositories +cacheDirs=$(ls -d $BAL_CENTRAL_DIR/cache-* 2>/dev/null) || true +for dir in "${cacheDirs[@]}"; do + [ -d "$dir" ] && rm -r "$dir" +done +echo "Successfully cleaned the cache directories" + +# Create the package directory in the central repository, this will not be present if no modules are pulled +mkdir -p "$BAL_CENTRAL_DIR/bala/ballerinax/$BAL_PACKAGE_NAME" + +# Update the central repository +BAL_DESTINATION_DIR="$HOME/.ballerina/repositories/central.ballerina.io/bala/ballerinax/$BAL_PACKAGE_NAME" +BAL_SOURCE_DIR="$HOME/.ballerina/repositories/local/bala/ballerinax/$BAL_PACKAGE_NAME" +[ -d "$BAL_DESTINATION_DIR" ] && rm -r "$BAL_DESTINATION_DIR" +[ -d "$BAL_SOURCE_DIR" ] && cp -r "$BAL_SOURCE_DIR" "$BAL_DESTINATION_DIR" +echo "Successfully updated the local central repositories" + +echo "$BAL_DESTINATION_DIR" +echo "$BAL_SOURCE_DIR" + +# Loop through examples in the examples directory +cd "$BAL_EXAMPLES_DIR" +for dir in $(find "$BAL_EXAMPLES_DIR" -type d -maxdepth 1 -mindepth 1); do + # Skip the build directory + if [[ "$dir" == *build ]]; then + continue + fi + (cd "$dir" && bal "$BAL_CMD" --offline && cd ..); +done + +# Remove generated JAR files +find "$BAL_HOME_DIR" -maxdepth 1 -type f -name "*.jar" | while read -r JAR_FILE; do + rm "$JAR_FILE" +done From d6f4e20dfc04104b3d8b95684cc51294694003cd Mon Sep 17 00:00:00 2001 From: Nipuna Ranasinghe Date: Fri, 5 Jul 2024 01:20:30 +0530 Subject: [PATCH 2/7] Add the example --- .../Ballerina.toml | 5 + .../automated-event-announcements/main.bal | 114 ++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 examples/automated-event-announcements/Ballerina.toml create mode 100644 examples/automated-event-announcements/main.bal diff --git a/examples/automated-event-announcements/Ballerina.toml b/examples/automated-event-announcements/Ballerina.toml new file mode 100644 index 0000000..44325b3 --- /dev/null +++ b/examples/automated-event-announcements/Ballerina.toml @@ -0,0 +1,5 @@ +[package] +org = "wso2" +name = "discord_automated_event_announcements" +version = "0.1.0" +distribution = "2201.9.1" diff --git a/examples/automated-event-announcements/main.bal b/examples/automated-event-announcements/main.bal new file mode 100644 index 0000000..4452616 --- /dev/null +++ b/examples/automated-event-announcements/main.bal @@ -0,0 +1,114 @@ +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import ballerina/log; +import ballerina/task; +import ballerinax/discord; + +configurable string clientId = ?; +configurable string clientSecret = ?; +configurable string[] scopes = ?; + +string guildId = "YOUR_GUILD_ID"; + +# Represents a Discord Channel. +public type Channel record { + # ID of the channel + string id; +}; + +# Represents a Discord Event. +public type Event record { + # ID of the event + string id; + # Name of the event + string name; +}; + +discord:ConnectionConfig discordConfig = { + auth: { + clientId, + clientSecret, + scopes + } +}; + +discord:Client discord = check new (discordConfig); + +public function main() returns error? { + + // Registers the scheduled event. + discord:guild_id_scheduledevents_body payload = { + name: "Community Meeting", + description: "Join us for our monthly community meeting!", + scheduled_start_time: "2024-12-31T23:59:59Z", + scheduled_end_time: "2024-12-31T23:59:59Z", + privacy_level: 2, + entity_type: 1, + entity_metadata: { + location: "Virtual" + } + }; + + Event|error eventResponse = discord->/guilds/[guildId]/scheduled\-events.post(payload); + if (eventResponse is error) { + log:printError("Error creating the scheduled event: ", eventResponse); + return; + } + + // Schedules the daily recurring task to send the event reminders to all the related channels. + task:JobId _ = check task:scheduleJobRecurByFrequency(new EventReminderJob(eventResponse.id), 60 * 60 * 24); +} + +# A Ballerina scheduled job that sends a given event reminder message to a list of Discord channels. +class EventReminderJob { + + *task:Job; + + string eventName; + + public function init(string eventName) { + self.eventName = eventName; + } + + public function execute() { + anydata[]|error channelsResponse = discord->/guilds/[guildId]/channels(); + if channelsResponse is error { + log:printError("Error getting the channels: ", channelsResponse); + return; + } + + Channel[]|error channelsResult = channelsResponse; + if channelsResult is error { + log:printError("Error getting the channels: ", channelsResult); + return; + } + + foreach Channel channel in channelsResult { + any|error reminderResponse = discord->/channels/[channel.id]/messages.post({ + Content\-Type: "application/x-www-form-urlencoded" + }, + { + content: string `⏰ Reminder: Our community meeting '${self.eventName}' is coming up soon! Don't forget to join us.` + } + ); + if reminderResponse is error { + log:printError("Error sending the reminder message: ", reminderResponse); + return; + } + } + } +} From e28ca53b4aeaf8976228cf68558949b147bc2e56 Mon Sep 17 00:00:00 2001 From: Nipuna Ranasinghe Date: Fri, 5 Jul 2024 01:22:28 +0530 Subject: [PATCH 3/7] Add README.md --- .../.github/README.md | 1 + .../Discord automated event reminders.md | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 120000 examples/automated-event-announcements/.github/README.md create mode 100644 examples/automated-event-announcements/Discord automated event reminders.md diff --git a/examples/automated-event-announcements/.github/README.md b/examples/automated-event-announcements/.github/README.md new file mode 120000 index 0000000..3153cf1 --- /dev/null +++ b/examples/automated-event-announcements/.github/README.md @@ -0,0 +1 @@ +../Discord automated event reminders.md \ No newline at end of file diff --git a/examples/automated-event-announcements/Discord automated event reminders.md b/examples/automated-event-announcements/Discord automated event reminders.md new file mode 100644 index 0000000..359b30e --- /dev/null +++ b/examples/automated-event-announcements/Discord automated event reminders.md @@ -0,0 +1,27 @@ +# Discord automated event reminders + +This example demonstrates how to automate event announcements and reminders in a Discord server using the Ballerina Discord connector. + +## Prerequisites + +### 1. Setup Discord account + +Refer to the [Setup guide](https://central.ballerina.io/ballerinax/discord/latest#setup-guide) to set up your Discord account, if you do not have one. + +### 2. Configuration + +Create a `Config.toml` file in the example root directory and update your Discord account related configurations as follows: + +```toml +clientId = "" +clientSecret = "" +scopes = ["", "", ""] +``` + +## Run the example + +Execute the following command to run the example: + +```ballerina +bal run +``` From 130e343d44209e0c3e1dcbafa0244a0284337477 Mon Sep 17 00:00:00 2001 From: Nipuna Ranasinghe Date: Fri, 5 Jul 2024 01:25:39 +0530 Subject: [PATCH 4/7] Fix outdated content --- examples/README.md | 3 +-- examples/automated-event-announcements/Ballerina.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/README.md b/examples/README.md index 55b5c8a..cfe50f8 100644 --- a/examples/README.md +++ b/examples/README.md @@ -2,8 +2,7 @@ The `ballerinax/discord` connector provides practical examples illustrating usage in various scenarios. Explore the below examples, covering use cases like automated event announcements and automated role assignment based on reactions. -1. [Automated Event Announcements] -2. [Automated Role Assignment Based on Reactions] +1. [Automated Event Reminders](/examples/automated-event-announcements/Discord%20automated%20event%20reminders.md) ## Prerequisites diff --git a/examples/automated-event-announcements/Ballerina.toml b/examples/automated-event-announcements/Ballerina.toml index 44325b3..c2a3e69 100644 --- a/examples/automated-event-announcements/Ballerina.toml +++ b/examples/automated-event-announcements/Ballerina.toml @@ -1,5 +1,5 @@ [package] org = "wso2" -name = "discord_automated_event_announcements" +name = "discord_automated_event_reminders" version = "0.1.0" distribution = "2201.9.1" From df2da60ccb8c35f9b8d85eb11fe2068ba74760d3 Mon Sep 17 00:00:00 2001 From: Nipuna Ranasinghe Date: Fri, 5 Jul 2024 01:28:50 +0530 Subject: [PATCH 5/7] Update documentation --- README.md | 8 ++++ ballerina/Module.md | 6 +++ ballerina/Package.md | 94 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) diff --git a/README.md b/README.md index 5db13de..3e92f17 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,14 @@ Now, utilize the available connector operations. ```bash bal run ``` + +## Examples + +The `Discord` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/), covering the following use cases: + +1. [Automated Event Reminders](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/automated-event-announcements) + + ## Build from the source ### Prerequisites diff --git a/ballerina/Module.md b/ballerina/Module.md index 6722000..cd8a963 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -86,3 +86,9 @@ Now, utilize the available connector operations. ```bash bal run ``` + +## Examples + +The `Discord` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/), covering the following use cases: + +1. [Automated Event Reminders](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/automated-event-announcements) diff --git a/ballerina/Package.md b/ballerina/Package.md index e69de29..cb59cd5 100644 --- a/ballerina/Package.md +++ b/ballerina/Package.md @@ -0,0 +1,94 @@ +## Overview + +[Discord](https://support.discord.com/hc/en-us/articles/360045138571-Beginner-s-Guide-to-Discord) is a popular communication platform designed for creating communities and facilitating real-time messaging, voice, and video interactions over the internet. + +The Ballerina Discord connector offers APIs to connect and interact with the [Discord REST API v10](https://discord.com/developers/docs/reference). + +## Setup guide + +Follow these steps to create a Discord developer account. + +### Step 1: Login to Discord developer page + + + +Visit [Discord developer portal](https://discord.com/login?redirect_to=%2Fdevelopers) by logging into your Discord account. + +If you do not have a Discord account already, [create a new discord account](https://discord.com/login) by clicking on the `Register` hyperlink below the `Log In` button when opening the Discord developer page. + + + +Complete the account creation process by including the relavant information in the given fields. + +### Step 2: Make a new Discord application + + + +Once in the Discord developer portal is open, click on the `New Application` button as displayed above to start the process. + +### Step 3: Name the Discord Application + + + +1. Proceed by giving the Discord Application a name and click on the terms of service. + +2. Finally complete the naming process by clicking on the `next` button. + +### Step 4: Obtain the Client ID and Client Secret + + + +Under the `OAuth2` section found on the left-sided list, locate the Client's Information as shown on the screen. To implement the functionalities provided by Discord's API, you will need the Client ID and Client Secret. + +## Quickstart + +To use the `discord` connector in your Ballerina application, modify the `.bal` file as follows: + +### Step 1: Import the module + +Import the `discord` module. + +```ballerina +import ballerinax/discord; +``` + +### Step 2: Instantiate a new connector + +Create a `discord:ConnectionConfig` with the obtained OAuth2.0 Client Credentials and initialize the connector with it. + +Apps must receive approval from users installing them to perform actions within Discord. To enable these functions, specific scopes must be defined. These scopes are outlined in the [OAuth2 Scopes documentation](https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes). + +```ballerina +configurable string clientId = ?; +configurable string clientSecret = ?; +configurable string[] scopes = ?; + +discord:Client discord = check new({ + auth: { + clientId, + clientSecret, + scopes + } +}); +``` + +### Step 3: Invoke the connector operation +Now, utilize the available connector operations. + +### Return linked third-party accounts of the user + +```ballerina + ConnectedAccountResponse[] connectedAccounts = check cl->/users/\@me/connections(); +```` + +### Step 4: Run the Ballerina application + +```bash +bal run +``` + +## Examples + +The `Discord` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/), covering the following use cases: + +1. [Automated Event Reminders](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/automated-event-announcements) From 0aceaca7c880474a1e488ca35ada217fa1089ce6 Mon Sep 17 00:00:00 2001 From: Nipuna Ranasinghe Date: Fri, 5 Jul 2024 01:32:06 +0530 Subject: [PATCH 6/7] Fix broken links --- README.md | 2 +- ballerina/Module.md | 2 +- ballerina/Package.md | 2 +- examples/README.md | 2 +- .../.github/README.md | 0 .../Ballerina.toml | 0 .../Discord automated event reminders.md | 0 .../main.bal | 0 8 files changed, 4 insertions(+), 4 deletions(-) rename examples/{automated-event-announcements => automated-event-reminders}/.github/README.md (100%) rename examples/{automated-event-announcements => automated-event-reminders}/Ballerina.toml (100%) rename examples/{automated-event-announcements => automated-event-reminders}/Discord automated event reminders.md (100%) rename examples/{automated-event-announcements => automated-event-reminders}/main.bal (100%) diff --git a/README.md b/README.md index 3e92f17..03008dd 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ bal run The `Discord` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/), covering the following use cases: -1. [Automated Event Reminders](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/automated-event-announcements) +1. [Automated Event Reminders](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/automated-event-reminders) ## Build from the source diff --git a/ballerina/Module.md b/ballerina/Module.md index cd8a963..7156182 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -91,4 +91,4 @@ bal run The `Discord` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/), covering the following use cases: -1. [Automated Event Reminders](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/automated-event-announcements) +1. [Automated Event Reminders](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/automated-event-reminders) diff --git a/ballerina/Package.md b/ballerina/Package.md index cb59cd5..354e208 100644 --- a/ballerina/Package.md +++ b/ballerina/Package.md @@ -91,4 +91,4 @@ bal run The `Discord` connector provides practical examples illustrating usage in various scenarios. Explore these [examples](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/), covering the following use cases: -1. [Automated Event Reminders](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/automated-event-announcements) +1. [Automated Event Reminders](https://github.com/ballerina-platform/module-ballerinax-discord/tree/main/examples/automated-event-reminders) diff --git a/examples/README.md b/examples/README.md index cfe50f8..c74c83d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -2,7 +2,7 @@ The `ballerinax/discord` connector provides practical examples illustrating usage in various scenarios. Explore the below examples, covering use cases like automated event announcements and automated role assignment based on reactions. -1. [Automated Event Reminders](/examples/automated-event-announcements/Discord%20automated%20event%20reminders.md) +1. [Automated Event Reminders](/examples/automated-event-reminders/Discord%20automated%20event%20reminders.md) ## Prerequisites diff --git a/examples/automated-event-announcements/.github/README.md b/examples/automated-event-reminders/.github/README.md similarity index 100% rename from examples/automated-event-announcements/.github/README.md rename to examples/automated-event-reminders/.github/README.md diff --git a/examples/automated-event-announcements/Ballerina.toml b/examples/automated-event-reminders/Ballerina.toml similarity index 100% rename from examples/automated-event-announcements/Ballerina.toml rename to examples/automated-event-reminders/Ballerina.toml diff --git a/examples/automated-event-announcements/Discord automated event reminders.md b/examples/automated-event-reminders/Discord automated event reminders.md similarity index 100% rename from examples/automated-event-announcements/Discord automated event reminders.md rename to examples/automated-event-reminders/Discord automated event reminders.md diff --git a/examples/automated-event-announcements/main.bal b/examples/automated-event-reminders/main.bal similarity index 100% rename from examples/automated-event-announcements/main.bal rename to examples/automated-event-reminders/main.bal From 95ae9269d6779d6e1c3d46bcec4b5ea8a2748716 Mon Sep 17 00:00:00 2001 From: Nipuna Ransinghe Date: Fri, 5 Jul 2024 08:18:53 +0530 Subject: [PATCH 7/7] Apply suggestions from code review Co-authored-by: Ayesh Almeida <77491511+ayeshLK@users.noreply.github.com> --- examples/automated-event-reminders/main.bal | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/automated-event-reminders/main.bal b/examples/automated-event-reminders/main.bal index 4452616..964ca8e 100644 --- a/examples/automated-event-reminders/main.bal +++ b/examples/automated-event-reminders/main.bal @@ -49,7 +49,6 @@ discord:ConnectionConfig discordConfig = { discord:Client discord = check new (discordConfig); public function main() returns error? { - // Registers the scheduled event. discord:guild_id_scheduledevents_body payload = { name: "Community Meeting", @@ -64,7 +63,7 @@ public function main() returns error? { }; Event|error eventResponse = discord->/guilds/[guildId]/scheduled\-events.post(payload); - if (eventResponse is error) { + if eventResponse is error { log:printError("Error creating the scheduled event: ", eventResponse); return; } @@ -75,10 +74,9 @@ public function main() returns error? { # A Ballerina scheduled job that sends a given event reminder message to a list of Discord channels. class EventReminderJob { - *task:Job; - string eventName; + private final string eventName; public function init(string eventName) { self.eventName = eventName; @@ -91,7 +89,7 @@ class EventReminderJob { return; } - Channel[]|error channelsResult = channelsResponse; + Channel[]|error channelsResult = channelsResponse.ensureType(); if channelsResult is error { log:printError("Error getting the channels: ", channelsResult); return;