I created the Twitter plugin for Corona SDK to give Corona developers an easy way to access the full range of Twitter’s REST APIs from inside their apps, making it simple to get data from or post information to a Twitter user’s account with as little as a single line of code. The plugin automatically handles oAuth authentication, and persistently saves a logged-in user’s token data, so they’ll only need to log in and authorize your app once, even across multiple sessions, until they are manually logged out or revoke your app’s access to their Twitter account. The plugin also comes with a set of “convenience functions” that return Lua tables and/or Corona display objects, for easier access to common-use applications without the need for developers to wade through the raw JSON data that Twitter’s REST APIs return.
This page contains the documentation for the plugin, as well as a sample project you can download and run to see the plugin in action for yourself. Please check back, as I will continue to update this page whenever bug fixes or new features are added.
Table of Contents
- Change Log
- Adding the Plugin to Your App
- Twitter App Registration
- Initializing the Plugin
- Core Plugin Functions
- Convenience Functions
- Error Handling
- Other Plugin Features
- “Gotchas”
- Demo Project
Change Log
- 7/15/2015 :
- Initial public release.
- 7/19/2015 :
- Modified twitter.login() to accept a second “onFail” argument, allowing developers to respond to cancelled or failed login attempts.
- 7/20/2015 :
- Modified twitter.login() to accept a third “windowsSimulatorToken” string argument, to allow the plugin to run in the Corona Simulator for Windows, working around the Windows simulator’s lack of support for native webViews.
- 8/14/2015 :
- Deprecated old “windowsSimulatorToken” argument to twitter.login(), which required you to modify your code and relaunch the Simulator to use the plugin in the Windows Simulator. Instead, calling twitter.login() in the Windows simulator now presents you with a native text field where you can simply paste in your oAuth token string. NOTE: You now must be using SDK build # 2015.2695 or later to use the plugin in the Windows Simulator. This is because native text fields were only introduced for the Windows simulator starting with daily build 2015.2695. Calling twitter.login() in earlier SDK builds will pop up a system alert asking you to update your SDK.
- 8/24/2015 :
- Added improved support for image uploads, including automatic conversion of image files to multipart/form-data. Specifically, the “statuses/update_with_media” endpoint now works if you add a key/value pair to your parameters table with the key “media” and a value that uses Corona’s system.pathForFile() API to return an absolute path to the image file you want to upload. Also modified the twitter.tweet() convenience function to accept an optional string argument representing an image that gets attached to the tweet. Updated sample project to upload an image when trying out the twitter.tweet() function.
- 10/27/2015 :
- Fixed a bug that was preventing twitter.tweet() from posting tweets with an attached image in the Windows Simulator and on Android devices. For more details on this bug and details on the fix, please see this Corona Labs forum post.
- 2/17/2016 :
- Fixed a bug that caused the login webview to be placed incorrectly on the screen if default anchorX and anchorY values are adjusted globally using display.setDefault().
- Added support for error handling in callback functions. Callback functions previously only supported a single argument. They now accept up to 3 arguments: the response from Twitter (same as before), an “isError” boolean and a Corona networkRequest event table (only if there was an error). See the new Error Handling section below for details. Note that this change is backwards-compatible with previous versions of the plugin – you don’t need to change your code if you are happy with the way it was.
- 3/23/2016 :
- Fixed issue where a (non-used) global variable “tempTable” was set to nil.
- Fixed issue with twitter.getFollowers() that could result in a Runtime error if Twitter’s returned JSON data contained no ‘users’ subtable.
- 1/16/2017 :
- Added support for Windows Simulator webviews – this means no more windowsSimulatorToken workaround required! NOTE: You must be using Corona Simulator daily build 2016.3011 or later to take advantage of this.
- The twitter login webview will now clear its cache (on-device) every time it loads. Previously, it was stubbornly retaining the last logged-in user’s credentials.
- Added the new optional logoutSimulator argument to twitter.logout.
- 4/14/2017 :
- Fixed a bug that could potentially cause the login webview to be placed off-center (and hence only cover part of the screen) depending on certain values in config.lua. The webview will now be centered and fullscreen in all circumstances.
- 12/4/2017 :
- Fixed issue with sample project where main.lua was missing line breaks.
- Update sample project to newer style of iOS icon & launchscreen (removing old icon & “Default” PNGs).
Adding the Plugin to Your App
Before you can require the plugin for use in your app, you’ll need to do two things:
- Activate the plugin for your Corona developer account at store.coronalabs.com
- Add an entry into a plugins table of your build.settings. The following is an example of a minimal build.settings file with the required entry for the Twitter plugin:
settings = { plugins = { -- @schroederapps' Twitter plugin: ["plugin.twitter"] = { publisherId = "com.jasonschroeder", }, }, }
After you’ve taken the above steps, you can require the plugin in your app with just one line of code:
local twitter = require("plugin.twitter")
Twitter App Registration
The Twitter plugin must be initialized with an “API Key” and “API Secret,” which are string values that identify a Twitter app you set up at apps.twitter.com (it’s free). Here’s a quick primer on setting up a new Twitter app and obtaining your app’s API Key and API Secret:
- Go to apps.twitter.com and click the “Create New App” button.
- Fill in all the fields with your app’s name, description, website and a callback URL. Note that while it doesn’t matter what your callback URL is, you MUST include one for the plugin to work correctly, even though Twitter does not consider it a required field.
- On your new app’s developer page, click the “Keys and Access Tokens” button. The API Key and API Secret will be shown, for easy copying and pasting into your Corona app. It’ll look something like this:
Initializing the Plugin
Now that you have your Twitter app’s API Key and API Secret, call twitter.init() in your Corona app, preferably just after requiring the plugin. It should look something like this:
local twitter = require("plugin.twitter") twitter.init("API_KEY", "API_SECRET") -- replace API_KEY & API_SECRET with your Twitter app's API Key & API Secret
Core Plugin Functions
The three functions detailed below are all you need to access the full range of Twitter’s REST API. Unlike the “convenience functions,” these functions do not process any of the raw JSON data Twitter’s APIs return for you. These functions – and in particular, twitter.request() – take more effort on your part to integrate into your Lua code, but they also offer you the greatest flexibility and control over the data Twitter gives you access to.
twitter.login( [onSuccess], [onFail], [windowsSimulatorToken] )
Before you can make any Twitter API requests, your user must sign in and authorize your app to access their Twitter account. You do this by calling twitter.login(). You only have to do this once – a logged in user will remain logged in until you manually log them out or they revoke your app’s access to their Twitter account, even if they quit your app. While the plugin will automatically prompt your user to log in if you make an API request before doing so, by using twitter.login(), you have the option of logging them in without making a subsequent API request. twitter.login() accepts two optional arguments:
- onSuccess : a function that is run when a user successfully logs in
- onFail : a function that is run when a login attempt fails (either because the user entered an invalid user/password combination, or because the user cancelled the attempt on purpose)
- (DEPRECATED ON 8/14/2015)
windowsSimulatorToken: this is a string value that is required if you want to use the plugin in the Windows simulator. This argument is not required and will be ignored on all device builds and in the OS X Simulator, but it is the only way to work around the Windows simulator’s lack of support for native webViews. When you call twitter.login() in the Windows simulator, the Twitter authorization webpage will open in a separate browser window. Click “authorize app” and you will be redirected to a webpage that displays a valid windowsSimulatorToken string in red. Copy and paste that string as an argument to twitter.login() and relaunch the Simulator. This time, when your app calls twitter.login() the plugin will log in successfully, and keep you logged in even if you relaunch the Simulator, so long as you don’t call twitter.logout(). Note that a windowsSimulatorToken is single-use, so calling twitter.logout() will require you to obtain another valid windowsSimulatorToken string. The plugin will automatically detect if you have an expired windowsSimulatorToken and prompt you to obtain a new one if necessary.
Sample Code:
local function onSuccess() print("Twitter user " .. twitter.user.screenName .. " successfully logged in!") end local function onFail() print("Twitter login attempt failed or was cancelled by user.") end twitter.login(onSuccess, onFail)
twitter.logout( [callbackFunction], [logoutSimulator] )
twitter.logout() logs out the currently logged-in Twitter user. twitter.logout() accepts two optional arguments:
- callbackFunction: a callback function that will be run on a successful logout
- logoutSimulator: a boolean that when set to “true” will prompt the user to log out of Twitter in a webview when you call twitter.logout() in the Corona Simulator. This is only applicable in the simulator, where Corona webviews stubbornly retain the last logged-in user. If you need to be able to switch users in your app in the simulator, set this value to “true” and confirm that you want to log out in the resulting simulator.
Sample Code:
local function callback() print("Logout successful.") end twitter.logout(callback, true)
twitter.request( requestTable )
twitter.request() is the backbone of the Twitter plugin. It allows you to easily make an API call against any of Twitter’s public REST API endpoints, and pass the resulting JSON data into a callback function. All the “convenience functions” built into the plugin like twitter.tweet() and twitter.search() use twitter.request() behind the scenes, and then they convert the returned JSON data to a more manageable Lua table. You can easily recreate those functions, then tweak them to your liking, by using twitter.request().
twitter.request() requires a single Lua table as an argument, containing the following key/value pairs:
- endpoint: a string representing the API endpoint you want to use (e.g. “statuses/retweets_of_me” or “direct_messages”). A full list of available endpoints can be found at http://dev.twitter.com/rest/public.
- method: a string representing the HTTP method employed by the endpoint you are using. As of July 2015, the only valid methods for Twitter’s API are “GET” and “POST” (and that’s unlikely to change).
- parameters: a Lua table containing key/value pairs for the required and/or optional parameters for the endpoint you are using. Check Twitter’s API docs for details on each API’s accepted parameters.
- callback: a Lua callback function that accepts a single argument, representing the JSON data string returned by Twitter.
As an example, below is an simple twitter.request() call that would search Twitter for the phrase “@schroederapps” and pass the resulting JSON string into a function called “myCallback” that prints that string to the terminal. Note that there are optional parameters for the “search/tweets” API that are not being used in this example, but they could be by adding key/value pairs to the “parameters” table:
Sample Code:
local function myCallback(response) print("Twitter JSON response: " .. response) end twitter.request({ endpoint = "search/tweets", method = "GET", parameters = { q = "@schroederapps", }, callback = myCallback, })
Convenience Functions
The core plugin functions are all you need to access the full range of Twitter’s public APIs, but properly handling the returned data requires you to decode the JSON string and pull out the relevant data for your needs, which can sometimes be complicated. To make this easier, I have created a handful of “convenience functions” that offer a simpler way to make certain API requests, automatically interpret the raw JSON data returned by Twitter, and pass on either a Lua table or a Corona display object into a callback function.
twitter.tweet( status, [imageFile], [callbackFunction] )
twitter.tweet() posts a status update to the logged-in user’s timeline. It accepts up to three arguments: a required string representing the text of the status update, an optional string representing an image file to upload and attach to the tweet, and an optional callback function that accepts a single Lua table as an argument.
The imageFile argument is designed to be very accommodating: you can use Corona’s system.pathForFile() API to pass in an absolute path to the file, but you can also just pass in a file name like you would when calling display.newImage() and the plugin will automatically convert that file name into an absolute path. It will also look in the system.DocumentsDirectory and system.TemporaryDirectory (in that order) if it cannot first find the file in the system.ResourceDirectory. Here are three examples of valid imageFile arguments that would result in a successful upload (assuming that these image files existed in the app sandbox):
- system.pathForFile(“display-save-screenshot.jpg”, system.DocumentsDirectory)
- “images/twitterImage.png”
- “Default.png”
The Lua table that is passed into the callback function has two key/value pairs:
- text: the text of the status update
- id: the tweet’s ID string, which can be used to reference the tweet later on (should you want to delete it, for example).
Sample Code:
local function tweetCallback(response) print("TWEET TEXT: " .. response.text) print("TWEET ID: " .. response.id) end twitter.tweet("I love the Twitter plugin for #CoronaSDK!", "images/twitterImage.png", tweetCallback)
twitter.search( searchTerm, callbackFunction, [parameters] )
twitter.search() searches Twitter for tweets that contain your specified search term. It accepts up to three arguments: a required string representing your search term, a callback function that accepts a single Lua table as an argument, and an optional table that contains additional search parameters.
The optional parameters table can contain any of the following key/value pairs:
- resultType: a string indicating which types of results you want Twitter to return. Valid options are “mixed”, “recent”, or “popular”. Defaults to “mixed”.
- count: A number representing the number of tweets to return, up to a maximum of 100. Defaults to 15.
- retweets: A boolean indicating whether or not to include retweets in search results. Defaults to true.
The Lua table that is passed into the callback function contains a numeric array of tables, one for each returned tweet. Each of these “tweet tables” contains four key/value pairs:
- text: the text of the tweet
- id: the tweet’s ID.
- timeStamp: a string indicating when the tweet was posted.
- screenName: the screen name of the Twitter user who composed the tweet.
The Lua table that is passed into the callback function also contains two additional key/value pairs that are useful for searches with more results than can be collected at once (Twitter limits search results to 100 per API call):
- isMore: a boolean indicating whether or not there are still more tweets in your search results
- getMore: a function that will automatically get the next set of search results, if any more tweets exist.
Sample Code:
local function searchCallback(results) for i = 1, #results do local tweet = results[i] print("TEXT: " .. tweet.text) print("TWEET ID: " .. tweet.id) print("TIME STAMP: " .. tweet. timeStamp) print("SCREEN NAME: " .. tweet.screenName) end if results.isMore then results.getMore() else print("END OF SEARCH RESULTS") end end twitter.search("#CoronaSDK", searchCallback, {resultType = "recent", count = 100, retweets = false})
twitter.follow( screenName, [callbackFunction] )
twitter.follow() makes the logged-in user a follower of any Twitter account you specify. It accepts up to two arguments: a required string representing the Twitter account to follow and an optional callback function that accepts a single Lua table as an argument.
The Lua table that is passed into the callback function contains ten key/value pairs of data from the followed user’s Twitter profile:
- screenName: the user’s screen name – this will always be the same as the screen name you specified when calling twitter.follow()
- name: the user’s display name
- userID: the user’s numeric user ID
- location: the user’s location
- followersCount: the number of followers the user has
- friendsCount: then number of accounts the user follows
- tweetsCount: the number of tweets the user has posted
- favoritesCount: the number of tweets the user has “favorited”
- verified: a boolean indicating if the user has a “verified” profile (for celebrities, etc.)
- following: a boolean indicating whether or not the logged-in user is following this account – this will always be true
Sample Code:
local function followCallback(results) print ("SCREEN NAME: " .. results.screenName) print ("DISPLAY NAME: " .. results.name) print ("USER ID: " .. results.userID) print ("LOCATION: " .. results.location) print ("# FOLLOWERS: " .. results.followersCount) print ("# FOLLOWING: " .. results.friendsCount) print ("# TWEETS: " .. results.tweetsCount) print ("# FAVORITES: " .. results.favoritesCount) print ("VERIFIED: " .. tostring(results.verified)) print ("I AM FOLLOWING: " .. tostring(results.following)) end twitter.follow("@schroederapps", followCallback)
twitter.getUser( [screenName], callbackFunction )
twitter.getUser() looks up a Twitter user and returns an array of data from his or her Twitter profile. It accepts up to two arguments: an optional string (“screenName”) representing a Twitter user name to look up (if screenName is nil, the logged-in user will be looked up) and a required callback function that accepts a single Lua table as an argument.
The Lua table that is passed into the callback function contains ten key/value pairs of data from the followed user’s Twitter profile:
- screenName: the looked-up user’s screen name
- name: the looked-up user’s display name
- userID: the looked-up user’s numeric user ID
- location: the looked-up user’s location
- followersCount: the number of followers the looked-up user has
- friendsCount: then number of accounts the looked-up user follows
- tweetsCount: the number of tweets the looked-up user has posted
- favoritesCount: the number of tweets the looked-up user has “favorited”
- verified: a boolean indicating if the looked-up user has a “verified” profile (for celebrities, etc.)
- following: a boolean indicating whether or not the logged-in user is following the looked-up user
Sample Code:
local function getUserCallback(results) print ("SCREEN NAME: " .. results.screenName) print ("DISPLAY NAME: " .. results.name) print ("USER ID: " .. results.userID) print ("LOCATION: " .. results.location) print ("# FOLLOWERS: " .. results.followersCount) print ("# FOLLOWING: " .. results.friendsCount) print ("# TWEETS: " .. results.tweetsCount) print ("# FAVORITES: " .. results.favoritesCount) print ("VERIFIED: " .. tostring(results.verified)) print ("I AM FOLLOWING: " .. tostring(results.following)) end twitter.getUser("@coronalabs", getUserCallback)
twitter.getFollowers( [screenName], callbackFunction )
twitter.getFollowers() returns an array of data on a Twitter user’s followers. It accepts up to two arguments: an optional string (“screenName”) representing a Twitter user name to look up (if screenName is nil, it will default to the logged-in user’s screen name) and a required callback function that accepts a single Lua table as an argument.
The Lua table that is passed into the callback function contains a numeric array of tables, one for each returned follower. Each of these “follower tables” contains four key/value pairs:
- screenName: the follower’s screen name
- name: the follower’s display name
- userID: the follower’s numeric user ID
- isFriend: a boolean indicating whether or not the follower is a “friend” of the looked-up user (i.e. does this person follow the follower back?)
The Lua table that is passed into the callback function also contains two additional key/value pairs that are useful for searches with more results than can be collected at once (Twitter limits follower lookups to 200 per API call):
- isMore: a boolean indicating whether or not there are still more followers
- getMore: a function that will automatically get the next set of up to 200 followers, if there are any
Sample Code:
local function followerCallback(results) for i = 1, #results do local follower = results[i] print("FOLLOWER # " .. i) print("SCREEN NAME: " .. follower.screenName) print("DISPLAY NAME: " .. follower.name) print("USER ID: " .. follower.userID) print("IS A FRIEND: " .. tostring(follower.isFriend)) print("*****************") end if results.isMore then results.getMore() else print("NO MORE FOLLOWERS") end end twitter.getFollowers("coronageek", followerCallback)
twitter.getFriends( [screenName], callbackFunction )
twitter.getFriends() returns an array of data on a Twitter user’s friends (the Twitter accounts that he or she follows). It accepts up to two arguments: an optional string (“screenName”) representing a Twitter user name to look up (if screenName is nil, it will default to the logged-in user’s screen name) and a required callback function that accepts a single Lua table as an argument.
The Lua table that is passed into the callback function contains a numeric array of tables, one for each returned friend. Each of these “friend tables” contains three key/value pairs:
- screenName: the friend’s screen name
- name: the friend’s display name
- userID: the friend’s numeric user ID
The Lua table that is passed into the callback function also contains two additional key/value pairs that are useful for searches with more results than can be collected at once (Twitter limits friend lookups to 200 per API call):
- isMore: a boolean indicating whether or not there are still more friends
- getMore: a function that will automatically get the next set of up to 200 friends, if there are any
Sample Code:
local function friendCallback(results) for i = 1, #results do local friend = results[i] print("FRIEND # " .. i) print("SCREEN NAME: " .. friend.screenName) print("DISPLAY NAME: " .. friend.name) print("USER ID: " .. friend.userID) print("*****************") end if results.isMore then results.getMore() else print("NO MORE FRIENDS") end end twitter.getFriends(friendCallback)
twitter.getProfileImage( [screenName], callbackFunction, [size] )
twitter.getProfileImage() is a modified version of Corona’s built-in display.loadRemoteImage() API that creates a display object consisting of a Twitter user’s profile image. It accepts up to three arguments: an optional string (“screenName”) representing a Twitter user (if screenName is nil, the logged-in user will be looked up), a required callback function that accepts a single Lua table as an argument, and an optional string (“size”) indicating what size image you want to load. The “size” argument has only four acceptable values:
- “original” : this returns the original image that the user uploaded to their profile, which is the highest-quality version available, but may also be larger than you need. (This is the default value.)
- “normal” : this returns an image sized 48×48>
- “bigger” : this returns an image sized 73×73>
- “mini” : this returns an image sized 24×24>
The Lua table that is passed into the callback function is identical to the “event” table that gets passed into Corona’s built-in display.loadRemoteImage() API. The table has a “target” parameter (“event.target”) that points to the returned display object (so you can assign it to a variable, insert it into a display group, etc.)
Sample Code:
local function imageCallback(event) local image = event.target sceneGroup:insert(image) image.x, image.y = display.contentCenterX, display.contentCenterY end twitter.getProfileImage("chiralgame", imageCallback, "original")
Error Handling
It is possible to gracefully handle errors in your callback functions in the event that the plugin is unable to successfully connect to Twitter to make a request, or that the request returned an error. Callback functions for twitter.request and all convenience functions can accept up to three arguments:
- results: the returned data from Twitter (this can be either a JSON string or a Lua table depending on the function being used).
- isError: a boolean value that is true in the event of an error. Will be nil if there is no error.
- event: a Corona networkRequest event table containing full details on the unsuccessful request. Will be nil if there is no error.
By checking to see if isError is true, you can manage an error in whatever way you see fit. Here is a code snippet showing one way to do that in the event of an error:
local function myCallback(response, isError, event) if isError then print("ERROR! Here's some details:") print("Status code: " .. tostring(event.status)) print(event.response) else print("Success!") print("Twitter JSON response: " .. response) end end twitter.request({ endpoint = "search/tweets", method = "GET", parameters = { q = "@schroederapps", }, callback = myCallback, })
Other Plugin Features
- twitter.showAlerts is a boolean value that, when set to true, will show a native alert dialog any time the plugin encounters an error. It can be useful for testing, but you’d probably want to set it to false when building for distribution. It defaults to false (but is set to true in the demo project).
- twitter.user is a table containing some basic information on the currently logged-in user, including:
- twitter.user.screenName : the screen name for the currently logged-in user
- twitter.user.userID : the numeric user ID for the currently logged-in user
“Gotchas”
The only “gotcha” with this plugin is that it requires an extra step to run in the Windows Simulator. This is because the only way to log in a user and seamlessly obtain their authentication token is through the use of a native.newWebView() object and a URL listener, and that Corona API isn’t supported in the Windows simulator. As a workaround, calling twitter.login() in the Windows simulator will open up a separate browser window with a valid oAuth token string you must paste into a native text field that pops up in the simulator. Entering in that token string allows the login process to complete in the Windows simulator. Consequently, because native web views were only introduced to the Windows simulator in Corona SDK daily build # 2015.2695, you must be using that build or later to use the plugin in the Windows simulator.
Note that if you build for device, or run it in the OS X simulator, the plugin will work seamlessly, with no extra steps required. If and when the Windows simulator gets support for the native.newWebView() API, I will update the plugin to remove this extra step.
Demo Project
I’ve created a free demonstration project that you can load in the simulator or build for device to see the Twitter plugin in action. The project is fully self-contained, so all you need to do is download it and open it in the simulator. However, you will need to register a Twitter app and add your app’s API Key and API Secret to the twitter.init() function call on line 15 of the project’s main.lua for it to work properly.
Here is a video of the app running on an iPad:
TP:34472E16
Congrats on the release and I must say, I love that artwork/icon.
I’m looking forward to giving this a test-drive.
Thanks, Ed! But I can’t really take credit for the artwork. Twitter doesn’t really use the “fail whale” art anymore, but I always loved it so I decided to use it for this project, even if it’s a little out of date. But it was made by Australian artist Yiying Lu (http://www.yiyinglu.com/?portfolio=lifting-a-dreamer-aka-twitter-fail-whale). Used without permission, but with plenty ‘o love. 🙂
Very nice tutorial.
I just tried your plugin but I am not being able to call to perform a successful login. I keep receiving the error “TWITTER PLUGIN ERROR: Unable to obtain oAuth request token. Please double-check your API key and API secret.”.
I already double checked and even recreated the key/secret. Any ideas of what could be causing the problem?
Ok. I figured out the problem. I forgot to add the callback URL to on the Twitter panel (I added 1 URL when creating the app and I thought that that was the callback URL already, but it is not).
Now I am able to login with success.
One other thing: on your twitter.getUser sample code above, line 10 ( print (“VERIFIED: ” .. results.verified) ) creates a runtime error (attempt to concatenate field ‘verified’ (a boolean value)).
Thanks, Renato! It’s a failing of mine that I’m constantly forgetting that you can’t concatenate a non-string value using the .. operator. Fortunately, this isn’t an issue with the plugin itself, but only my sample code – which I’ve updated thanks to your friendly reminder! Hope you get some use from the plugin!
This is an amazing plugin, it has made my work so nice easier and cleaner. Thank you.
However, I was wondering if there was a way to tell if a user is currently logged in, either with the plugin or without?
Hi Cliff,
Thanks for the feedback! I may implement a more elegant solution than this – something like “twitter.isLoggedIn()” that returns true or false – but in the meantime you can check to see if twitter.user.screenName is nil or not. If there is a currently logged-in user, twitter.user.screenName will return a string value. If they are logged out, it’ll return nil.
Thanks again,
Jason
+1 for twitter.isLoggedIn()
Hi Jason,
Thanks for the quick response, It really helped with my work. I have no come across another problem. When an error occurs(such as Error 88: Rate limit reached), I’ve noticed it does not run the callback function. So I was wondering how i would check if an error has occurred so i can handle it.
Regards,
Cliff.
Hi Cliff,
Another great suggestion! I’ve had a few really good feature requests in the last couple of weeks and I hope to roll out an update soon that incorporates them. I’ll be sure to include some sort of error handling for problems like the one you described in that update. When I do, I’ll update the documentation with details. You can check back here, or follow @schroederapps on Twitter and you’ll see me tweet when the update goes live. Thanks again!
just wondering should i encrypt the twitter twitterPluginUserData.json file or is that info ok if user looked at it. (I am probably just be over protective)
Hi Scott,
Thanks for checking out the plugin! I personally didn’t see the need to encrypt that file. It only stores information that is tied to the user’s account (their user name, twitter ID, and the oAuth access token and secret for their specific account to authorize the app), and that’s not really a security concern for them to see it. Maybe in a future revision I’ll encrypt that file out of an excess of concern (what’s the harm?), but I don’t think there’s any real danger to leaving it unencrypted. Thanks for the feedback!
I may add that encryption sometimes is a requirement (even if the data has no value) when developing business apps. Getting to know that the plugin saved a file with plain text will make it a no-go for me using this.
But thanks anyway for developing it!
Renato and I had some back-and-forth outside the comments after this post. But I thought it was worth adding a public comment to say that thanks to his note about encryption being a possible requirement for client work (plus some awesome suggestions for other improvements to the plugin), encryption of Twitter user data is coming soon, along with a few other new goodies! Thanks, Renato!
I would like to suggest that the function getUser also return the profile_image_url property in the results.
I assume that the getUser convenience function is a implementation of the users/show request, right? If yes, you just need to map of profile_image_url property to the results.profileImageURL.
Can you make it so we only have init once and we are done?
Hi Scott,
Thanks for commenting, but I’m not certain I understand your question – as it stands, you should only have to call twitter.init() once in your app, preferably just after requiring the plugin. You’ll still need to make individual requests anytime you want to get or post data, but the initialization only needs to be called once. Likewise, you only need to call twitter.login() once, even across multiple sessions – the plugin will remember the login data from the last session unless you manually call twitter.logout(). Good luck!
Hi Jason. Nice API by the way but I seem to be having an issue with the twitter.tweet() function call. The problem is an error pops up that halts the progress only after a tweet with a picture.
Don’t know what I’m specifically doing wrong.
The tweet gets posted but doesn’t fire my function call back for a reason. And the error I keep getting is
Runtime error
?:0: attempt to index a nil value
stack trackback:
[C]: ?
?: in function
Strange as it only happens with the pictures. But the tweet gets posted so I really don’t know. Been on it for 3 hrs now still no result.
——————————————————————————————-
//called from somewhere in main
local r = MainRandom(1, 100);
functionTask = function() TwitterManager:tweet(‘Tweet… ‘ ..r, ‘image.jpg’); end
//In Twitter Manager.lua
function TwitterManager:tweet(message, image)
TwitterManager.command = TwitterManager.Commands.TWEET;
if TwitterManager.loggedIn then
local function thanksForTweeting(response)
native.showAlert(‘Thanks!’, response.text, {‘OK’}, twitterCallback);
end
twitter.tweet(message, image, thanksForTweeting);
else
_message = message;
_image = image;
TwitterManager:logIn();
end
end;
Hi Seye,
Thanks for commenting! The problem lies with the way you structure your code. You have a scope issue. Your function “thanksForTweeting” is local to the if/then statement that it resides in – meaning that anything outside of that block of code doesn’t know what “thanksForTweeting” is. So when you define “thanksForTweeting” as your callback function in twitter.tweet(), you are essentially passing in “nil” as your callback function, which is what that Runtime error is trying to tell you, although not very clearly. There are a number of ways to fix this, but the gist of it is that you can’t make a function local to a small block of code if you need to call that function from outside of that specific block (in this case, your if/then statement). Here’s a good primer on scope, specifically tailored to Corona SDK: https://coronalabs.com/blog/2015/06/16/tutorial-scope-for-beginners/
Feel free to get in touch if you still can’t work it out, but once you correct your scoping so that your twitter.tweet() call can reference your callback, you’ll be good to go!
Best,
Jason
Good job and Well Done,
How it can be integrated for Enterprise users?
Thank you.
Hi Tuny,
You’ll have to forgive me for not knowing all the ins and outs of using plugins on Enterprise, as I’m not an Enterprise user. But you can download the repo for the Twitter plugin from https://bitbucket.org/coronalabs/store-hosted-twitter – hopefully that’ll give you what you need to get it working in your Enterprise project.
Thanks,
Jason
Hi Jason,
I’m hitting a problem getting followers for the current user from Twitter after successfully logging in:
attempt to get length of field ‘users’ (a nil value)
This appears to be on the plugin side before it gets to my callback. Are others seeing this, too? Also, I think there’s a tempTable variable that must be used somewhere in the plugin that isn’t declared with local, since it’s tripping up the strict.lua module I use during dev. Lastly, do you have plans for an “Unfollow” option? Not that I want users to unfollow, but it seems polite to offer to them 🙂
Thanks!
Hi Mark,
Thanks for commenting! First of all, I apologize for the tempTable issue you’re experiencing – I don’t actually use the “tempTable” variable to point to any tables in the plugin (local or otherwise), but there was a leftover line of code that set the global “tempTable” variable to nil for no reason at all. Yikes! I’ll be pushing out an update to Corona’s build servers ASAP to fix this.
As for the issue with getting followers, I’ll investigate and fix if it needs fixing – can you tell me if you’re getting the same error when you use the “getFollowers” button in my sample project? If not, then it could point to an issue in your code — or possibly my documentation, if you’re following it to the letter. Let me know and we’ll get it resolved one way or another. I appreciate the feedback!
Best,
Jason
Hi Jason,
Great Plug-in. I wonder how can I obtain the oAuto tokens that are used in the login so that I can use them for Parse login (using the user twitter auto data).
I didn’t see in the doc a way to access this data.
Regards,
Adi
Hi Adi,
It’s not super-documented, but the twitter.user table does contain data beyond simply the user’s userID and screen name. If you iterate over that table (after a user has logged in, naturally), you’ll find additional fields such as “accessToken” that should help you out. Hope that helps!
You can iterate over the table and print the key/value pairs to the terminal using the code below. (You probably already knew this, but in case it helps any folks who are new to Lua):
for k, v in pairs(twitter.user) do print(k, v) end
ERROR: Runtime error
?:0: attempt to concatenate field ‘screenName’ (a nil value)
stack traceback:
[C]: ?
?: in function ‘?’
?: in function
my code
local twitter = require(“plugin.twitter”)
twitter.init(“tWyvq96jScH84drV0PBBEU6uU”, “fx801SlT0WE9zqMeOUAOfGt7YLU9EUvSPnzcvviFuB5Ld626cv”)
local function onSuccess()
print(“Twitter user ” .. twitter.user.screenName .. ” successfully logged in!”)
end
local function onFail()
print(“Twitter login attempt failed or was cancelled by user.”)
end
twitter.login(onSuccess, onFail)
cant event log in my account is this really working?
i also tried your demo and changed API_Secret and API_Key with my test app buy still nothing
ERROR: Runtime error
?:0: attempt to concatenate field ‘screenName’ (a nil value)
stack traceback:
[C]: ?
?: in function ‘?’
?: in function
on actual android device
“Unable to obtain oAuth request token. Please Double check your API KEY and API SECRET”
already did and even regenarated it still nothing
Hi Guiller,
I’ll reply to your comments directly via email so we can troubleshoot – but I’m unable to reproduce the errors you’re seeing, at least using the Demo project as a test case.
ERROR: Runtime error
?:0: attempt to concatenate field ‘screenName’ (a nil value)
stack traceback:
[C]: ?
?: in function ‘?’
?: in function
Very useful, thank you!
I have a question: the twitter login screen is not full screen on android devices. is it possible to make the bottom of the web view reach the bottom of the phone?
Resolved, in config.lua, if I change
yAlign = “top”,
to
yAlign = “center”,
everything goes well.
Hello! I bought your plugin.
In my app uses yAlign=”top” in config.lua and it can’t be changed.
because of this twitter web-interface displayed with scroll bar. It’s not acceptable.
I very much ask you to add variables to adjust the size webView.
Hi Ьшл,
Thanks for getting in touch – I just pushed an update to the plugin that will ensure the webview will always be fullscreen, regardless of the app’s config.lua settings (you are correct that in some cases, changing the yAlign value could result in the webview being placed strangely – something I hadn’t realized until you pointed it out).
Once you get the new version of the plugin, the Twitter login webview should always fill the whole screen as intended. It could take a few hours before the change is reflected on Corona Labs’ plugin server, but once the change takes effect, the new version of the plugin should download automatically when you run the simulator and make a new build.
Thanks for helping to make the plugin better!
Best,
Jason
Thank you so much!
Now everything works correctly!
Hello Jason! It’s me again with another problem 🙂
I found a bug in your twitter plugin.
The bug is in the .tweet() function – “image not found” when the function is called on an android device (if you use .tweet() on the corona simulator everything is ok).
You may use your demo project to check it.
Can you fix it please?
Havе youu ever tһought about including a littⅼe bit more tһan jսst your articles?
Ι mean, what you sɑy іѕ іmportant and aⅼl. Nevertheless imagine іf you аdded some great pictures օr video clips to
givе yoսr posts more, “pop”! Уour content is excellent but witһ pics aand videos, thiѕ sitte сould undeniably be one of the bеst in its field.
Ԍood blog!
Hi Jason,
Not sure if you are still maintaining this?? The show alerts flag does not appear to work, I get the alert regardless of what this set to.
Cheers,
Craig
Hi Craig,
I tried, and I’m unable to reproduce your issue. Please download the sample project (http://twitter.plugin.jasonschroeder.com/twitterDemo.zip) and change main.lua to turn off error alerts. The easiest way to trigger an alert is to enter an intentionally bad API key or secret. With alerts turned on, you’ll see a system popup notification. With alerts turned off, you’ll only see an error in the console.
Best,
Jason