diff --git a/README.md b/README.md index d437763..16d4b2c 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ ## Overview -[Twitter](https://about.twitter.com/) is a widely-used social networking service provided by Twitter, Inc., enabling users to post and interact with messages known as "tweets". +[Twitter(X)](https://about.twitter.com/) is a widely-used social networking service provided by X Corp., enabling users to post and interact with messages known as "tweets". -The `ballerinax/twitter` package offers APIs to connect and interact with [Twitter API](https://developer.twitter.com/en/docs/twitter-api) endpoints, specifically based on [Twitter API v2](https://developer.x.com/en/docs/twitter-api/migrate/whats-new). +The `ballerinax/twitter` package offers APIs to connect and interact with [Twitter(X) API](https://developer.twitter.com/en/docs/twitter-api) endpoints, specifically based on [Twitter(X) API v2](https://developer.x.com/en/docs/twitter-api/migrate/whats-new). ## Setup guide @@ -52,7 +52,14 @@ Before proceeding with the Quickstart, ensure you have obtained the Access Token Replace ``, ``, and `` with your specific values. Make sure to include the necessary scopes depending on your use case. - Example: + **Note:** The "code verifier" is a randomly generated string used to verify the authorization code, and the "code challenge" is derived from the code verifier. These methods enhance security during the authorization process. + In OAuth 2.0 PKCE, there are two methods for creating a "code challenge": + + 1. **S256**: The code challenge is a base64 URL-encoded SHA256 hash of a randomly generated string called the "code verifier". + + 2. **plain**: The code challenge is the plain code verifier string itself. + + Example authorization URL: ``` https://twitter.com/i/oauth2/authorize?response_type=code&client_id=asdasASDas21Y0OGR4bnUxSzA4c0k6MTpjaQ&redirect_uri=http://example&scope=tweet.read%20tweet.write%20users.read%20follows.read&state=state&code_challenge=D601XXCSK57UineGq62gUnsoasdas1GfKUY8QWhOF9hiN_k&code_challenge_method=plain @@ -76,6 +83,20 @@ Before proceeding with the Quickstart, ensure you have obtained the Access Token 4. Use the obtained authorization code to run the following curl command, replacing ``, ``, ``, and `` with your specific values: + - Linux/MacOS: + + ```bash + curl --location "https://api.twitter.com/2/oauth2/token" \ + --header "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "code=" \ + --data-urlencode "grant_type=authorization_code" \ + --data-urlencode "client_id=" \ + --data-urlencode "redirect_uri=" \ + --data-urlencode "code_verifier=" + ``` + + - Windows: + ```bash curl --location "https://api.twitter.com/2/oauth2/token" ^ --header "Content-Type: application/x-www-form-urlencoded" ^ @@ -99,7 +120,7 @@ Before proceeding with the Quickstart, ensure you have obtained the Access Token 5. Store the access token securely for use in your application. -**Note**: We recommend using the OAuth 2.0 Authorization Code with PKCE method as used here, but there is another way using OAuth 2.0 App Only. If you want, you can go through this link: [OAuth 2.0 App Only](https://developer.twitter.com/en/docs/authentication/oauth-2-0/application-only). Refer to this document to check which operations in Twitter API v2 are done using which method: [API reference](https://developer.twitter.com/en/docs/authentication/guides/v2-authentication-mapping). +**Note**: We recommend using the OAuth 2.0 Authorization Code with PKCE method as used here, but there is another way using OAuth 2.0 App Only [OAuth 2.0 App Only](https://developer.twitter.com/en/docs/authentication/oauth-2-0/application-only). Refer to this document to check which operations in Twitter API v2 are done using which method: [API reference](https://developer.twitter.com/en/docs/authentication/guides/v2-authentication-mapping). ## Quickstart @@ -116,15 +137,21 @@ import ballerinax/twitter; ### Step 2: Instantiate a new connector -Create a `twitter:ConnectionConfig` with the obtained **Access Token** and initialize the connector with it. +1. Create a `Config.toml` file and, configure the obtained credentials in the above steps as follows: + +```bash +token = "" +``` + +2. Create a `twitter:ConnectionConfig` with the obtained access token and initialize the connector with it. ```ballerina configurable string token = ?; -twitter:Client twitter = check new({ - auth: { - token - } +final twitter:Client twitter = check new({ + auth: { + token + } }); ``` @@ -135,9 +162,13 @@ Now, utilize the available connector operations. #### Post a tweet ```ballerina -twitter:TweetCreateResponse postTweet = check twitter->/tweets.post( payload = { - text: "This is a sample tweet" -}); +public function main() returns error? { + twitter:TweetCreateResponse postTweet = check twitter->/tweets.post( + payload = { + text: "This is a sample tweet" + } + ); +} ``` ### Step 4: Run the Ballerina application diff --git a/ballerina/Module.md b/ballerina/Module.md index ae6e19b..6e2dc9c 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -1,8 +1,8 @@ ## Overview -[Twitter](https://about.twitter.com/) is a widely-used social networking service provided by Twitter, Inc., enabling users to post and interact with messages known as "tweets". +[Twitter(X)](https://about.twitter.com/) is a widely-used social networking service provided by X Corp., enabling users to post and interact with messages known as "tweets". -The `ballerinax/twitter` package offers APIs to connect and interact with [Twitter API](https://developer.twitter.com/en/docs/twitter-api) endpoints, specifically based on [Twitter API v2](https://developer.x.com/en/docs/twitter-api/migrate/whats-new). +The `ballerinax/twitter` package offers APIs to connect and interact with [Twitter(X) API](https://developer.twitter.com/en/docs/twitter-api) endpoints, specifically based on [Twitter(X) API v2](https://developer.x.com/en/docs/twitter-api/migrate/whats-new). ## Setup guide @@ -42,7 +42,14 @@ Before proceeding with the Quickstart, ensure you have obtained the Access Token Replace ``, ``, and `` with your specific values. Make sure to include the necessary scopes depending on your use case. - Example: + **Note:** The "code verifier" is a randomly generated string used to verify the authorization code, and the "code challenge" is derived from the code verifier. These methods enhance security during the authorization process. + In OAuth 2.0 PKCE, there are two methods for creating a "code challenge": + + 1. **S256**: The code challenge is a base64 URL-encoded SHA256 hash of a randomly generated string called the "code verifier". + + 2. **plain**: The code challenge is the plain code verifier string itself. + + Example authorization URL: ``` https://twitter.com/i/oauth2/authorize?response_type=code&client_id=asdasASDas21Y0OGR4bnUxSzA4c0k6MTpjaQ&redirect_uri=http://example&scope=tweet.read%20tweet.write%20users.read%20follows.read&state=state&code_challenge=D601XXCSK57UineGq62gUnsoasdas1GfKUY8QWhOF9hiN_k&code_challenge_method=plain @@ -66,6 +73,20 @@ Before proceeding with the Quickstart, ensure you have obtained the Access Token 4. Use the obtained authorization code to run the following curl command, replacing ``, ``, ``, and `` with your specific values: + - Linux/MacOS: + + ```bash + curl --location "https://api.twitter.com/2/oauth2/token" \ + --header "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "code=" \ + --data-urlencode "grant_type=authorization_code" \ + --data-urlencode "client_id=" \ + --data-urlencode "redirect_uri=" \ + --data-urlencode "code_verifier=" + ``` + + - Windows: + ```bash curl --location "https://api.twitter.com/2/oauth2/token" ^ --header "Content-Type: application/x-www-form-urlencoded" ^ @@ -89,7 +110,7 @@ Before proceeding with the Quickstart, ensure you have obtained the Access Token 5. Store the access token securely for use in your application. -**Note**: We recommend using the OAuth 2.0 Authorization Code with PKCE method as used here, but there is another way using OAuth 2.0 App Only. If you want, you can go through this link: [OAuth 2.0 App Only](https://developer.twitter.com/en/docs/authentication/oauth-2-0/application-only). Refer to this document to check which operations in Twitter API v2 are done using which method: [API reference](https://developer.twitter.com/en/docs/authentication/guides/v2-authentication-mapping). +**Note**: We recommend using the OAuth 2.0 Authorization Code with PKCE method as used here, but there is another way using OAuth 2.0 App Only [OAuth 2.0 App Only](https://developer.twitter.com/en/docs/authentication/oauth-2-0/application-only). Refer to this document to check which operations in Twitter API v2 are done using which method: [API reference](https://developer.twitter.com/en/docs/authentication/guides/v2-authentication-mapping). ## Quickstart @@ -106,15 +127,21 @@ import ballerinax/twitter; ### Step 2: Instantiate a new connector -Create a `twitter:ConnectionConfig` with the obtained **Access Token** and initialize the connector with it. +1. Create a `Config.toml` file and, configure the obtained credentials in the above steps as follows: + +```bash +token = "" +``` + +2. Create a `twitter:ConnectionConfig` with the obtained access token and initialize the connector with it. ```ballerina configurable string token = ?; -twitter:Client twitter = check new({ - auth: { - token - } +final twitter:Client twitter = check new({ + auth: { + token + } }); ``` @@ -125,9 +152,13 @@ Now, utilize the available connector operations. #### Post a tweet ```ballerina -twitter:TweetCreateResponse postTweet = check twitter->/tweets.post( payload = { - text: "This is a sample tweet" -}); +public function main() returns error? { + twitter:TweetCreateResponse postTweet = check twitter->/tweets.post( + payload = { + text: "This is a sample tweet" + } + ); +} ``` ### Step 4: Run the Ballerina application diff --git a/ballerina/Package.md b/ballerina/Package.md index ae6e19b..6e2dc9c 100644 --- a/ballerina/Package.md +++ b/ballerina/Package.md @@ -1,8 +1,8 @@ ## Overview -[Twitter](https://about.twitter.com/) is a widely-used social networking service provided by Twitter, Inc., enabling users to post and interact with messages known as "tweets". +[Twitter(X)](https://about.twitter.com/) is a widely-used social networking service provided by X Corp., enabling users to post and interact with messages known as "tweets". -The `ballerinax/twitter` package offers APIs to connect and interact with [Twitter API](https://developer.twitter.com/en/docs/twitter-api) endpoints, specifically based on [Twitter API v2](https://developer.x.com/en/docs/twitter-api/migrate/whats-new). +The `ballerinax/twitter` package offers APIs to connect and interact with [Twitter(X) API](https://developer.twitter.com/en/docs/twitter-api) endpoints, specifically based on [Twitter(X) API v2](https://developer.x.com/en/docs/twitter-api/migrate/whats-new). ## Setup guide @@ -42,7 +42,14 @@ Before proceeding with the Quickstart, ensure you have obtained the Access Token Replace ``, ``, and `` with your specific values. Make sure to include the necessary scopes depending on your use case. - Example: + **Note:** The "code verifier" is a randomly generated string used to verify the authorization code, and the "code challenge" is derived from the code verifier. These methods enhance security during the authorization process. + In OAuth 2.0 PKCE, there are two methods for creating a "code challenge": + + 1. **S256**: The code challenge is a base64 URL-encoded SHA256 hash of a randomly generated string called the "code verifier". + + 2. **plain**: The code challenge is the plain code verifier string itself. + + Example authorization URL: ``` https://twitter.com/i/oauth2/authorize?response_type=code&client_id=asdasASDas21Y0OGR4bnUxSzA4c0k6MTpjaQ&redirect_uri=http://example&scope=tweet.read%20tweet.write%20users.read%20follows.read&state=state&code_challenge=D601XXCSK57UineGq62gUnsoasdas1GfKUY8QWhOF9hiN_k&code_challenge_method=plain @@ -66,6 +73,20 @@ Before proceeding with the Quickstart, ensure you have obtained the Access Token 4. Use the obtained authorization code to run the following curl command, replacing ``, ``, ``, and `` with your specific values: + - Linux/MacOS: + + ```bash + curl --location "https://api.twitter.com/2/oauth2/token" \ + --header "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "code=" \ + --data-urlencode "grant_type=authorization_code" \ + --data-urlencode "client_id=" \ + --data-urlencode "redirect_uri=" \ + --data-urlencode "code_verifier=" + ``` + + - Windows: + ```bash curl --location "https://api.twitter.com/2/oauth2/token" ^ --header "Content-Type: application/x-www-form-urlencoded" ^ @@ -89,7 +110,7 @@ Before proceeding with the Quickstart, ensure you have obtained the Access Token 5. Store the access token securely for use in your application. -**Note**: We recommend using the OAuth 2.0 Authorization Code with PKCE method as used here, but there is another way using OAuth 2.0 App Only. If you want, you can go through this link: [OAuth 2.0 App Only](https://developer.twitter.com/en/docs/authentication/oauth-2-0/application-only). Refer to this document to check which operations in Twitter API v2 are done using which method: [API reference](https://developer.twitter.com/en/docs/authentication/guides/v2-authentication-mapping). +**Note**: We recommend using the OAuth 2.0 Authorization Code with PKCE method as used here, but there is another way using OAuth 2.0 App Only [OAuth 2.0 App Only](https://developer.twitter.com/en/docs/authentication/oauth-2-0/application-only). Refer to this document to check which operations in Twitter API v2 are done using which method: [API reference](https://developer.twitter.com/en/docs/authentication/guides/v2-authentication-mapping). ## Quickstart @@ -106,15 +127,21 @@ import ballerinax/twitter; ### Step 2: Instantiate a new connector -Create a `twitter:ConnectionConfig` with the obtained **Access Token** and initialize the connector with it. +1. Create a `Config.toml` file and, configure the obtained credentials in the above steps as follows: + +```bash +token = "" +``` + +2. Create a `twitter:ConnectionConfig` with the obtained access token and initialize the connector with it. ```ballerina configurable string token = ?; -twitter:Client twitter = check new({ - auth: { - token - } +final twitter:Client twitter = check new({ + auth: { + token + } }); ``` @@ -125,9 +152,13 @@ Now, utilize the available connector operations. #### Post a tweet ```ballerina -twitter:TweetCreateResponse postTweet = check twitter->/tweets.post( payload = { - text: "This is a sample tweet" -}); +public function main() returns error? { + twitter:TweetCreateResponse postTweet = check twitter->/tweets.post( + payload = { + text: "This is a sample tweet" + } + ); +} ``` ### Step 4: Run the Ballerina application diff --git a/ballerina/tests/README.md b/ballerina/tests/README.md index 39fe177..a8cc5b6 100644 --- a/ballerina/tests/README.md +++ b/ballerina/tests/README.md @@ -42,7 +42,7 @@ If you are using linux or mac, you can use following method: ``` If you are using Windows you can use following method: ```bash - set IS_LIVE_SERVER=false + setx IS_LIVE_SERVER false ``` Then, run the following command to run the tests: diff --git a/docs/setup/resources/set-up.png b/docs/setup/resources/set-up.png index fbaffb6..3ab8605 100644 Binary files a/docs/setup/resources/set-up.png and b/docs/setup/resources/set-up.png differ diff --git a/docs/setup/resources/twitter-developer-portal.png b/docs/setup/resources/twitter-developer-portal.png index e162ef8..a01ff59 100644 Binary files a/docs/setup/resources/twitter-developer-portal.png and b/docs/setup/resources/twitter-developer-portal.png differ diff --git a/examples/DM-mentions/Config.toml b/examples/DM-mentions/Config.toml deleted file mode 100644 index 80ca941..0000000 --- a/examples/DM-mentions/Config.toml +++ /dev/null @@ -1 +0,0 @@ -accessToken = "" diff --git a/examples/DM-mentions/Direct message company mentions.md b/examples/DM-mentions/Direct message company mentions.md index a6f88a4..4d32530 100644 --- a/examples/DM-mentions/Direct message company mentions.md +++ b/examples/DM-mentions/Direct message company mentions.md @@ -6,14 +6,14 @@ This use case demonstrates how the Twitter API v2 can be utilized to enhance cus ### 1. Setup Twitter developer account -Refer to the [Setup guide](https://central.ballerina.io/ballerinax/twitter/latest#setup-guide) to obtain necessary credentials (client ID, secret, tokens). +Refer to the [Setup guide](https://central.ballerina.io/ballerinax/twitter/latest#setup-guide) to obtain necessary credentials (client Id, client secret, tokens). ### 2. Configuration -Configure Twitter API v2 credentials in the `Config.toml` file in the example directory. +Create a `Config.toml` file in the example's root directory and, provide your Twitter account related configurations as follows: ```bash -accessToken = "" +token = "" ``` ## Run the example diff --git a/examples/DM-mentions/main.bal b/examples/DM-mentions/main.bal index 8fa4dbd..c2945c5 100644 --- a/examples/DM-mentions/main.bal +++ b/examples/DM-mentions/main.bal @@ -17,15 +17,14 @@ import ballerina/io; import ballerinax/twitter; -configurable string accessToken = ?; +configurable string token = ?; +final twitter:Client twitter = check new ({ + auth: { + token + } +}); public function main() returns error? { - twitter:Client twitter = check new ({ - auth: { - token: accessToken - } - }); - twitter:Get2TweetsSearchRecentResponse supportTweets = check twitter->/tweets/search/recent( query = "#ballerinaSupport", max_results = 10 diff --git a/examples/README.md b/examples/README.md index 7a02baf..5597731 100644 --- a/examples/README.md +++ b/examples/README.md @@ -14,7 +14,7 @@ The `twitter` connector provides practical examples illustrating usage in variou 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 - accessToken="" + token = "" ``` ## Running an Example diff --git a/examples/build.gradle b/examples/build.gradle new file mode 100644 index 0000000..880dff4 --- /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(":twitter-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 ":twitter-ballerina:build" +testExamples.dependsOn ":twitter-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/tweet-performance-tracker/Ballerina.toml b/examples/tweet-performance-tracker/Ballerina.toml new file mode 100644 index 0000000..18fdcfe --- /dev/null +++ b/examples/tweet-performance-tracker/Ballerina.toml @@ -0,0 +1,5 @@ +[package] +org = "wso2" +name = "tweet_performance_tracker" +version = "0.1.0" +distribution = "2201.9.0" diff --git a/examples/tweet-performance-tracker/Config.toml b/examples/tweet-performance-tracker/Config.toml deleted file mode 100644 index 80ca941..0000000 --- a/examples/tweet-performance-tracker/Config.toml +++ /dev/null @@ -1 +0,0 @@ -accessToken = "" diff --git a/examples/tweet-performance-tracker/Tweet performance tracker.md b/examples/tweet-performance-tracker/Tweet performance tracker.md index 3808531..72f219d 100644 --- a/examples/tweet-performance-tracker/Tweet performance tracker.md +++ b/examples/tweet-performance-tracker/Tweet performance tracker.md @@ -6,14 +6,14 @@ This use case demonstrates how the Twitter API v2 can be utilized to analyze the ### 1. Setup Twitter developer account -Refer to the [Setup guide](https://central.ballerina.io/ballerinax/twitter/latest#setup-guide) to obtain necessary credentials (client ID, secret, tokens). +Refer to the [Setup guide](https://central.ballerina.io/ballerinax/twitter/latest#setup-guide) to obtain necessary credentials (client Id, client secret, tokens). ### 2. Configuration -Configure Twitter API v2 credentials in the `Config.toml` file in the example directory. +Create a `Config.toml` file in the example's root directory and, provide your Twitter account related configurations as follows: ```bash -accessToken = "" +token = "" ``` ## Run the example diff --git a/examples/tweet-performance-tracker/main.bal b/examples/tweet-performance-tracker/main.bal index 4bff707..4e379b9 100644 --- a/examples/tweet-performance-tracker/main.bal +++ b/examples/tweet-performance-tracker/main.bal @@ -18,16 +18,15 @@ import ballerina/io; import ballerina/lang.array; import ballerinax/twitter; -configurable string accessToken = ?; +configurable string token = ?; +final string username = ""; +final twitter:Client twitter = check new ({ + auth: { + token + } +}); public function main() returns error? { - twitter:Client twitter = check new ({ - auth: { - token: accessToken - } - }); - - string username = "ballerinalang"; twitter:Get2UsersByUsernameUsernameResponse userResponse = check twitter->/users/'by/username/[username](); twitter:User? user = userResponse.data; if user is () { @@ -64,9 +63,12 @@ public function main() returns error? { } } - twitter:Tweet[] sortedPerformingTweets = performingTweets.sort(array:DESCENDING, isolated function(twitter:Tweet t) returns int? => t.public_metrics?.like_count); + twitter:Tweet[] sortedPerformingTweets = performingTweets.sort( + array:DESCENDING, + isolated function(twitter:Tweet t) returns int? => t.public_metrics?.like_count + ); io:println("Top Tweets by ", username, " in the last month: "); - foreach var tweet in sortedPerformingTweets { + foreach twitter:Tweet tweet in sortedPerformingTweets { io:println("Tweet: ", tweet.text); io:println("Likes: ", tweet.public_metrics?.like_count); io:println("Retweet Count: ", tweet.public_metrics?.retweet_count);