The Twitter app I am having problems with generates tweets from an Arduino device, passing them through a series of C++ and then Python apps on their way to Twitter. I am performing the required OAuth functions in the Python app running on the Google AppEngine.
I am having trouble passing my OAuth tokens to Twitter via an app (“arduino-tweet1.appspot.com”) running on Google AppEngine. My own error-checking code is telling me that OAuth is failing with a “Token is not set” code that is referring to the “self token” which I am inferring to be the “oauth_token” or Twitter access token I received when I registered my app with Twitter.
When setting up the app I was advised to set a “callback URL” of the form “http://arduino-tweet1.appspot.com/oauth/twitter/callback” which I entered OAuth Settings page as I did the initial registration.
First question: since this is not a website application where I am authorizing (other) users to read or post tweets (the keys are hardcoded as there is only one authorized user - me, or rather my Arduino device), is this callback URL necessary? Is it somehow interfering with the transfer of my access token to my OAuth process running on GAE? BTW, I do not have the path “…/oauth/twitter/callback” defined anywhere…this seems more like an example of a path I should have rather than an actual path that exists on the server where “arduino-tweet1.appspot.com” resides.
Second, the GAE app (written in Python) seems to be set up and deployed OK…it’s up and running, tests OK, and returns this output:
connecting …
HTTP/1.0 500 Internal Server Error
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Vary: Accept-Encoding
Date: Mon, 16 Jul 2012 23:28:51 GMT
Server: Google Frontend
Error 500 - token is not set
failed : code 500
Are there any simple tests I can perform to see if the basics are indeed happening? Any ideas on where to start debugging? Thanks!
This excerpt is from a simple running on an Arduino:
// Your Token to Tweet (registered with Twitter app arduino-tweet1/)
Twitter twitter("xxxxxxxxxxxxxxxxxxxxxxxxx");
...
// Message to post
char msg[] = "Hello, World! I'm Arduino!";
...
if (twitter.post(msg)) {
// Specify &Serial to output received response to Serial.
// If no output is required, you can just omit the argument, e.g.
// int status = twitter.wait();
int status = twitter.wait(&Serial);
if (status == 200) {
Serial.println("OK.");
} else {
Serial.print("failed : code ");
Serial.println(status);
}
...
This tweet is handled by a simple CPP library that formats a simple Twitter message (“bool Twitter::post(const char *msg)”) for the GAE to app to eventually handle:
#include <string.h>
#include "Twitter.h"
#define LIB_DOMAIN "arduino-tweet1.appspot.com"
#if defined(ARDUINO) && ARDUINO < 100
static uint8_t server[] = {0,0,0,0}; // IP address of LIB_DOMAIN
Twitter::Twitter(const char *token) : client(server, 80), token(token)
{
}
#else
Twitter::Twitter(const char *token) : token(token)
{
}
#endif
bool Twitter::post(const char *msg)
{
#if defined(ARDUINO) && ARDUINO < 100
DNSError err = EthernetDNS.resolveHostName(LIB_DOMAIN, server);
if (err != DNSSuccess) {
return false;
}
#endif
parseStatus = 0;
statusCode = 0;
#if defined(ARDUINO) && ARDUINO < 100
if (client.connect()) {
#else
if (client.connect(LIB_DOMAIN, 80)) {
#endif
client.println("POST http://" LIB_DOMAIN "/update HTTP/1.0");
client.print("Content-Length: ");
client.println(strlen(msg)+strlen(token)+14);
client.println();
client.print("token=");
client.print(token);
client.print("&status=");
client.println(msg);
} else {
return false;
}
return true;
}
which in turn calls the following OAuth-based App which resides on Google AppEngine:
OAUTH_APP_SETTINGS = {
'twitter': {
'consumer_key': 'xxxxxxxxxxxxxxx',
'consumer_secret': 'yyyyyyyyyyyyyyyyyyyy',
'request_token_url': 'https://twitter.com/oauth/request_token',
'access_token_url': 'https://twitter.com/oauth/access_token',
'user_auth_url': 'http://twitter.com/oauth/authorize',
'default_api_prefix': 'http://api.twitter.com/1',
'default_api_suffix': '.json',
},
}