. . .

Twitter Module


Using the Twitter module you can let your application users connect themselves with Twitter. Additionally, you can create tweets, read your timeline and mentions and send/receive direct messages.

images/download/attachments/61479799/db3-module-twitter.PNG

Twitter Module converted to Native Module

As of ApiOmat 2.6.0 this module is not a "Static Module" anymore, it is now delivered as Native Module. This transition have been made to offer you a more lean product which is extendable according to your individual needs. As our experience had shown that most of our customers do not need the Twitter module, we do not deliver it anymore by default and you can benefit from this save in space and memory. If you nevertheless need the Twitter Module on your installation, feel free to contact us.

Configuration

Consumer key

Consumer key of the Twitter app which you want to use to authenticate against.

Callback URL

Callback URL of the Twitter app which you want to use to forward after the App was authorized by the user.

Consumer secret

Consumer secret of the Twitter app which you want to use to authenticate against.

More information can be found in the twitter docs.

Usage

After setting the configuration parameters, you may call the following URL in your app to start authentication for a user, replacing {YOURAPPNAME} with the name of your app. Note that you have to deliver the user credentials with basic auth in header and don't forget to add the 'X-apiomat-system' header with the system (LIVE/STAGING/TEST) to your request. If the header is not added, it will fallback to the LIVE system.

https://{urlToYourInstallation}/yambas/rest/modules/Twitter/{YOURAPPNAME}/spec/auth

The user is presented the Twitter site asking him if the requesting app (with the ID set in the configuration) may be used to authenticate him. If the user clicks OK the authentication starts, otherwise it is cancelled.

If authentication was successful, the user object will have three values set on the dynamicAttributes map on the users object on server side: twitterOAuthToken, twitterOAuthVerifier and twitterOAuthSecret. To fetch these you have to do a simple reload of the user, so your code may look like this:

Android
callAuthURL();
// do other things
 
// later on get the actualized user object
user.loadMeAsync(new AOMEmptyCallback() {
 
@Override
public void isDone(boolean wasLoadedFromStorage, ApiomatRequestException exception) {
if (exception != null){
System.out.println("Auth code: " + user.getDynamicAttributes().get("oAuthToken"));
}
}
});
Objective-C
callAuthURL();
// do other things
 
// later on get the actualized user object
[user loadMeWithBlock:^(NSError *error) {
NSLog(@"Auth code: %@", [user getOAuthToken]);
}];
Swift
callAuthURL();
// do other things
 
// later on get the actualized user object
user.loadMe { (error) in
}
JavaScript
var user= new Apiomat.User();
 
callAuthUrl();
 
user.loadMe({
onOk : function() {
console.log("oAuthToken: " + user.data["dynamicAttributes"]["oAuthToken"]);
},
onError : function(error) {
}
});
TypeScript
var user = new User();
await user.loadMe();
console.log("oAuthToken: " + user.data["dynamicAttributes"]["oAuthToken"]);

Using these values you can access Twitter API without doing a rather complicated OAuth handshake by yourself.

Sending tweets

Android
Tweet t = new Tweet();
t.setText("my tweet from ApiOmat");
t.saveAsync(new AOMEmptyCallback() {
@Override
public void isDone(boolean wasLoadedFromStorage, ApiomatRequestException exception) {
if (exception != null) {
// ...
}
}
});
Objective-C
AOMTweet *t = [[AOMTweet alloc] init];
[t setText:@"my tweet from ApiOmat"];
[t saveAsyncWithBlock:^(NSError *error) {
}];
Swift
var t = Tweet()
t.text = "my tweet from ApiOmat"
t.save { (error) in
}
JavaScript
var t = new Apiomat.Tweet();
t.setText("my tweet from ApiOmat");
 
var saveCB = {
onOk : function() {
console.log("saved");
},
onError : function(error) {
console.log("Some error occured: (" + error.statusCode + ")" + error.message);
}
};
t.save(saveCB);
TypeScript
const t = new Tweet();
t.text = "my tweet from ApiOmat";
await t.save();

Receiving your timeline

Android
private void test() {
final Timeline t = new Timeline();
t.saveAsync(new AOMEmptyCallback() {
@Override
public void isDone(boolean wasLoadedFromStorage, ApiomatRequestException exception) {
if (exception != null) {
processTweets(t);
}
}
});
}
 
private void processTweets(final Timeline t) {
t.loadTweetsAsync("", new AOMEmptyCallback() {
@Override
public void isDone(boolean wasLoadedFromStorage, ApiomatRequestException exception) {
if (exception != null) {
List tweets = t.getTweets();
// process..
}
}
});
}
Objective-C
AOMTimeline *t = [[AOMTimeline alloc] init];
//just to get href back from server
[t saveAsyncWithBlock:^(NSError *error) {
[t loadTweetsAsync:@"" andWithBlock:^(NSError *error) {
NSMutableArray *tweets = [t tweets];
}];
}];
Swift
let t = Timeline()
//just to get href back from server
t.save { (error) in
t.loadTweets { (models, error) in
let tweets = t.tweets
}
}
JavaScript
function test() {
var t = new Apiomat.Timeline();
var saveCB = {
onOk : function() {
processTweets(t);
},
onError : function(error) {
console.log("Some error occured: (" + error.statusCode + ")" + error.message);
}
};
 
t.save(saveCB);
}
 
function processTweets(t) {
var loadTweetsCB = {
onOk : function() {
var tweets=t.getTweets();
//process
},
onError : function(error) {
console.log("Some error occured: (" + error.statusCode + ")" + error.message);
}
};
/* The first argument describes a filter query. If you do not want to filter the tweets, just pass undefined */
t.loadTweets(undefined, loadTweetsCB);
}
TypeScript
async function test() {
const t = new Timeline();
await t.save();
processTweets(t);
}
 
 
async function processTweets(t) {
await t.loadTweets(undefined);
const tweets = t.getTweets();
// process
}

Sending direct messages

Android
DirectMessage msg = new DirectMessage();
msg.setText("Hello world");
msg.setRecipientName("APIOMAT"); //insert the twitter user name of the receiver here
msg.saveAsync(new AOMEmptyCallback() {
public void isDone(ApiomatRequestException exception) {
if (exception != null) {
// ...
}
}
});
Objective-C
AOMDirectMessage *msg = [[AOMDirectMessage alloc] init];
[msg setText:@"Hello world"];
//insert the twitter user name of the receiver here
[msg setRecipientName:@"APIOMAT"];
[msg saveAsyncWithBlock:^(NSError *error) {
}];
Swift
var msg = DirectMessage()
msg.text = "Hello world"
//insert the twitter user name of the receiver here
msg.recipientName = "APIOMAT"
msg.save { (error) in
}
JavaScript
var msg = new Apiomat.DirectMessage();
msg.setText("Hello world");
msg.setRecipientName("APIOMAT"); //insert the twitter user name of the receiver here
 
var saveCB = {
onOk : function() {
console.log("saved");
},
onError : function(error) {
console.log("Some error occured: (" + error.statusCode + ")" + error.message);
}
};
msg.save(saveCB);
TypeScript
const msg = new DirectMessage();
msg.text = "Hello world";
msg.recipientName = "APIOMAT"; // insert the twitter user name of the receiver here
await msg.save();

Getting direct messages

Android
private void test() {
final DirectMessages msgContainer = new DirectMessages(); //Notice the container class is used here!
msgContainer.saveAsync(new AOMEmptyCallback() {
@Override
public void isDone(boolean wasLoadedFromStorage, ApiomatRequestException exception) {
if (exception != null) {
processDirectMessages(msgContainer);
}
}
});
}
 
private void processDirectMessages(final DirectMessages msgContainer) {
msgContainer.loadDirectMessagesAsync("", new AOMEmptyCallback() {
@Override
public void isDone(boolean wasLoadedFromStorage, ApiomatRequestException exception) {
if (exception != null) {
List<DirectMessage> myMessages = msgContainer.getDirectMessages();
// ...
}
}
});
}
Objective-C
AOMDirectMessages *msgContainer = [[AOMDirectMessages alloc] init]; //Notice the container class is used here!
//just to get href back from server
[msgContainer saveAsyncWithBlock:^(NSError *error) {
[msgContainer loadDirectMessagesAsync:@"" andWithBlock:^(NSError *error) {
NSMutableArray *myMessages = [msgContainer directMessages];
}];
}];
Swift
let msgContainer = DirectMessages() //Notice the container class is used here!
//just to get href back from server
msgContainer.save { (error) in
msgContainer.loadDirectMessages { (models, error) in
let myMessages = msgContainer.directMessages
}
}
JavaScript
function test() {
var msgContainer = new Apiomat.DirectMessages(); //Notice the container class is used here!
var saveCB = {
onOk : function() {
processDirectMessages(msgContainer);
},
onError : function(error) {
console.log("Some error occured: (" + error.statusCode + ")" + error.message);
}
};
msgContainer.save(saveCB);
}
function processDirectMessages(msgContainer) {
var loadDirectMessagesCB = {
onOk : function() {
var myMessages = msgContainer.getDirectMessages();
},
onError : function(error) {
console.log("Some error occured: (" + error.statusCode + ")" + error.message);
}
};
msgContainer.loadDirectMessages(loadDirectMessagesCB);
}
TypeScript
async function test() {
const msgContainer = new DirectMessages(); // Notice the container class is used here!
await msgContainer.save();
processDirectMessages(msgContainer);
}
 
 
async function processDirectMessages(msgContainer) {
await msgContainer.loadDirectMessages();
const myMessages = msgContainer.getDirectMessages();
}

Native Module related changes and update process

As of ApiOmat 2.6.0 this module is not a "Static Module" anymore, it is now delivered as Native Module. This transition have been made to offer you a more lean product which is extendable according to your individual needs. As our experience had shown that most of our customers do not need the Twitter module, we do not deliver it anymore by default and you can benefit from this save in space and memory. If you nevertheless need the Twitter Module on your installation, feel free to contact us.

If you upgrade to ApiOmat 2.6.0, it will automatically detect whether the module is used in other modules or in a backend on your installation and will then be converted to a dynamic module with any of the classes, which can be seen as a placeholder. As it is just a placeholder, it does not include the logic and you have to upload it as native module with the SuperAdmin account nevertheless. If it is not used by any backend or any module, it will simply be deleted and you can upload it with any user you want.

Potentially breaking changes and improvements

We list the changes that had been made in comparison to the static module here. These changes may need your interaction if you already use the module

  • The reference field directMessages in class DirectMessage does not return instances of Tweet anymore. Instead it will return the correct DirectMessage class.

  • DirectMessage objects will not be stored partially in the MongoDB, instead they are now fully transient. Therefore they have no MongoDB ObjectID anymore and are now identified directly by its ID from Twitter.

  • In the static module you had to create instances of DirectMessages and Timeline and persist them to get the direct messages and timeline tweets and mentions. These objects are not persisted anymore.

  • The "auth" REST endpoint had changed:

    • The name of the backend is now after the "Twitter" and before "spec" part of the url

    • The endpoint does not take memberId or userId and the usedSystem as query parameter anymore, instead these information will be taken from the authorization header and the x-apiomat-system header from your request. This also means, that you don't have to find out the id of the User object and can instead simply use its userName

  • The user object does not have the getters and setters for the OAuth token, secret and verifier anymore. You have to get these values over the dynamicAttributes map stored on the user.

  • The keys "oauthToken", "oAuthSecret" and "oAuthVerifier" in the dynamicAttributes-Map that are stored after authorization, have been renamed to "twitterOAuthToken", "twitterOAuthSecret" and "twitterOAuthVerifier".