Skip to content

Instantly share code, notes, and snippets.

@aaronksaunders
Created September 22, 2011 07:16
Show Gist options
  • Select an option

  • Save aaronksaunders/1234233 to your computer and use it in GitHub Desktop.

Select an option

Save aaronksaunders/1234233 to your computer and use it in GitHub Desktop.
works on android with appcelerator
BH = new BirdHouse({
service : 'twitter',
consumer_key: "xxxxxxxxxxxx",
consumer_secret: "xxxxxxxxxxxxxxxxxxxxxxx"
});
BH.short_tweet("hello motto")
// --------------------------------------------------------
// birdhouse.js
//
// BirdHouse is a Titanium Developer plugin for
// authenticating and sending API calls to Twitter.
//
// Copyright 2011 (c) iEntry, Inc
//
// Licensed 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.
//
// Author: Joseph D. Purcell, iEntry Inc / Modified BY Aaron K. Saunders
// Version: 0.9
// Modified: September 2011
// --------------------------------------------------------
// INCLUDES
Ti.include('/lib/oauth.js');
Ti.include('/lib/sha1.js');
Ti.include('/lib/OAuthSimple.js');
// THE CLASS
function BirdHouse(params) {
var urls_requestToken = {
'linkedin' : "https://api.linkedin.com/uas/oauth/requestToken",
'twitter' : 'https://api.twitter.com/oauth/request_token'
};
var urls_requestVerifier = {
'linkedin' : "https://api.linkedin.com/uas/oauth/authorize?oauth_token=",
'twitter' : "http://api.twitter.com/oauth/authorize?oauth_token="
}
var urls_requestAuthorize = {
'linkedin' : "https://api.linkedin.com/uas/oauth/authorize",
'twitter' : 'https://api.twitter.com/oauth/authorize'
}
var urls_requestAccessToken = {
'linkedin' : "https://api.linkedin.com/uas/oauth/accessToken",
'twitter' : 'https://api.twitter.com/oauth/access_token'
}
// --------------------------------------------------------
// ==================== PRIVATE ===========================
// --------------------------------------------------------
// VARIABLES
var cfg = {
// user config
oauth_consumer_key : "",
consumer_secret : "",
show_login_toolbar : false,
service : "",
// system config
oauth_version : "1.0",
oauth_token : "",
oauth_signature_method : "HMAC-SHA1",
request_token : "",
request_token_secret : "",
request_verifier : "",
access_token : "",
access_token_secret : "",
callback_url : ""
};
var accessor = {
consumerSecret : cfg.consumer_secret,
tokenSecret : cfg.access_token_secret
};
var authorized = false;
var service = cfg.service;
// --------------------------------------------------------
// set_message
//
// Creates a message to send to the Twitter service with
// the given parameters, and adds the consumer key,
// signature method, timestamp, and nonce.
//
// In Parameters:
// url (String) - the url to send the message to
// method (String) - 'POST' or 'GET'
// params (String) - parameters to add to the
// message in URL form, i.e. var1=2&var2=3
//
// Returns:
// message (Array) - the message parameters to send
// to Twitter
// --------------------------------------------------------
function set_message(url, method, params) {
var message = {
action : url,
method : (method == 'GET') ? method : 'POST',
parameters : (params != null) ? OAuth.decodeForm(params) : []
};
message.parameters.push(['oauth_consumer_key', cfg.oauth_consumer_key]);
message.parameters.push(['oauth_signature_method', cfg.oauth_signature_method]);
message.parameters.push(["oauth_timestamp", OAuth.timestamp().toFixed(0)]);
message.parameters.push(["oauth_nonce", OAuth.nonce(42)]);
message.parameters.push(["oauth_version", "1.0"]);
return message;
}
// --------------------------------------------------------
// get_request_token
//
// Sets the request token and token secret.
//
// In Parameters:
// callback (Function) - a function to call after
// the user has been authorized; note that it won't
// be executed until get_access_token()
// --------------------------------------------------------
function get_request_token(callback) {
//var url = 'https://api.twitter.com/oauth/request_token';
var url = urls_requestToken[service];
var params = (cfg.callback_url != "") ? 'oauth_callback=' + escape(cfg.callback_url) : '';
api(url, 'POST', params, function(resp) {
if(resp != false) {
var responseParams = OAuth.getParameterMap(resp);
cfg.request_token = responseParams['oauth_token'];
cfg.request_token_secret = responseParams['oauth_token_secret'];
get_request_verifier(callback);
Ti.API.debug("get_request_token " + resp)
}
}, false, true, false);
}
// --------------------------------------------------------
// get_request_verifier
//
// Sets the request verifier. There is no reason to call
// this unless you have the request token and token secret.
// In fact, it should only be called from get_request_token()
// for that very reason.
//
// In Parameters:
// callback (Function) - a function to call after
// the user has been authorized; note that it won't
// be executed until get_access_token()
// --------------------------------------------------------
function get_request_verifier(callback) {
//var url = "http://api.twitter.com/oauth/authorize?oauth_token="+cfg.request_token;
var url = urls_requestVerifier[service] + cfg.request_token;
var win = Ti.UI.createWindow({
top : 0,
//modal : true,
fullscreen : true
});
// add close button on iPhone
if(Ti.Platform.osname == 'iphone' && cfg.show_login_toolbar) {
var webView = Ti.UI.createWebView({
url : url,
scalesPageToFit : true,
touchEnabled : true,
top : 43,
backgroundColor : '#FFF'
});
var toolbar = Ti.UI.createToolbar({
top : 0
});
var toolbarLabel = Ti.UI.createLabel({
text : L("twitter_login_title"),
font : {
fontSize : 16,
fontWeight : 'bold',
//fontColor: st.appSettingTextColor,
fontFamily : st.appSettingFont
},
color : '#FFF',
textAlign : 'center'
});
var flexSpace = Titanium.UI.createButton({
systemButton : Titanium.UI.iPhone.SystemButton.FLEXIBLE_SPACE
});
var btnClose = Titanium.UI.createButton({
title : L("cancel_text"),
style : Titanium.UI.iPhone.SystemButtonStyle.BORDERED
});
toolbar.items = [flexSpace, flexSpace, toolbarLabel, flexSpace, btnClose];
win.add(toolbar);
// close login window
btnClose.addEventListener('click', function() {
webView.stopLoading();
win.remove(webView);
win.hide();
});
} else {
var webView = Ti.UI.createWebView({
url : url,
scalesPageToFit : true,
touchEnabled : true,
top : 0,
backgroundColor : '#FFF'
});
}
var request_token = "";
var url_base = "";
var params = "";
var loading = false;
// since the 'loading' property on webView is broke, use this
var loads = 0;
// number of times webView has loaded a URl
var doinOurThing = false;
// whether or not we are checking for oauth tokens
// add the webview to the window and open the window
win.add(webView);
win.open();
// since there is no difference between the 'success' or 'denied' page apart from content,
// we need to wait and see if Twitter redirects to the callback to determine success
function checkStatus() {
if(!doinOurThing) {
// access denied or something else was clicked
if(!loading) {
webView.stopLoading();
win.remove(webView);
win.hide();
if( typeof (callback) == 'function') {
callback(false);
}
return false;
}
} else {
}
}
webView.addEventListener('beforeload', function() {
loading = true;
});
webView.addEventListener('load', function(e) {
loads++;
// the first time load, ignore, because it is the initial 'allow' page
// set timeout to check for something other than 'allow', if 'allow' was clicked
// then loads==3 will cancel this
if(loads == 2) {
// something else was clicked
//if (e.url!='https://api.twitter.com/oauth/authorize') {
if(e.url != urls_requestAuthorize[service]) {
webView.stopLoading();
win.remove(webView);
win.hide();
if( typeof (callback) == 'function') {
callback(false);
}
return false;
}
// wait a bit to see if Twitter will redirect
else {
setTimeout(checkStatus, 1000);
}
}
// Twitter has redirected the page to our callback URL (most likely)
else if(loads == 3) {
doinOurThing = true;
// kill the timeout b/c we are doin our thing
// success!
params = "";
var parts = (e.url).replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m, key, value) {
params = params + m;
if(key == 'oauth_verifier') {
cfg.request_verifier = value;
}
});
if(cfg.request_verifier != "") {
// my attempt at making sure the stupid webview dies
webView.stopLoading();
win.remove(webView);
win.hide();
get_access_token(callback);
return true;
// we are done here
}
}
// we are done loading the page
loading = false;
});
}
// --------------------------------------------------------
// get_access_token
//
// Trades the request token, token secret, and verifier
// for a user's access token.
//
// In Parameters:
// callback (Function) - a function to call after
// the user has been authorized; this is where
// it will get executed after being authorized
// --------------------------------------------------------
function get_access_token(callback) {
//var url = 'https://api.twitter.com/oauth/access_token';
var url = urls_requestAccessToken[service];
api(url, 'POST', 'oauth_token=' + cfg.request_token + '&oauth_verifier=' + cfg.request_verifier, function(resp) {
if(resp != false) {
var responseParams = OAuth.getParameterMap(resp);
cfg.access_token = responseParams['oauth_token'];
cfg.access_token_secret = responseParams['oauth_token_secret'];
cfg.user_id = responseParams['user_id'];
cfg.screen_name = responseParams['screen_name'];
accessor.tokenSecret = cfg.access_token_secret;
save_access_token();
authorized = load_access_token();
// execute the callback function
if( typeof (callback) == 'function') {
callback(true);
}
} else {
// execute the callback function
if( typeof (callback) == 'function') {
callback(false);
}
}
}, false, true, false);
}
// --------------------------------------------------------
// load_access_token
//
// Loads the access token and token secret from
// 'twitter.config' to the class configuration.
// --------------------------------------------------------
function get_config() {
// try to find file
var file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, service + '.config');
if(!file.exists()) {
Ti.API.error(service + '.config is missing');
return false;
}
// try to read file
var contents = file.read();
if(contents == null) {
Ti.API.error(service + '.config is empty');
return false;
}
// try to parse file into json
try {
var resp = JSON.parse(contents.text);
resp.request_verifier = cfg.request_verifier;
resp.request_token = cfg.request_token;
resp.access_token_secret = cfg.request_token_secret;
resp.oauth_token = cfg.oauth_token;
resp.oauth_token_secret = cfg.access_token_secret;
return resp;
} catch(e) {
return false;
}
}
// --------------------------------------------------------
// load_access_token
//
// Loads the access token and token secret from
// 'twitter.config' to the class configuration.
// --------------------------------------------------------
function load_access_token() {
// try to find file
var file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, service + '.config');
if(!file.exists()) {
Ti.API.error(service + '.config is missing');
return false;
}
// try to read file
var contents = file.read();
if(contents == null) {
Ti.API.error(service + '.config is empty');
return false;
}
// try to parse file into json
try {
var config = JSON.parse(contents.text);
} catch(e) {
return false;
}
// set config
if(config.access_token) {
cfg.access_token = config.access_token;
}
if(config.access_token_secret) {
cfg.access_token_secret = config.access_token_secret;
accessor.tokenSecret = cfg.access_token_secret;
}
return true;
}
// --------------------------------------------------------
// save_access_token
//
// Writes the access token and token secret to
// 'twitter.config'. Saving the config in a file instead
// of using Ti.App.Property jazz allows the config to
// stay around even if the app has been recompiled.
// --------------------------------------------------------
function save_access_token() {
// get file if it exists
var file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, service + '.config');
// create file if it doesn't exist
if(file == null) {
file = Ti.Filesystem.createFile(Ti.Filesystem.applicationDataDirectory, service + '.config');
}
// write config
var config = {
access_token : cfg.access_token,
access_token_secret : cfg.access_token_secret
};
file.write(JSON.stringify(config));
}
// --------------------------------------------------------
// api
//
// Makes a Twitter API call to the given URL by the
// specified method with the given parameters.
//
// In Parameters:
// url (String) - the url to send the XHR to
// method (String) - POST or GET
// params (String) - the parameters to send in URL
// form
// callback (Function) - after execution, call
// this function and send the XHR data to it
// auth (Bool) - whether or not to force auth
// setUrlParams (Bool) - set the params in the URL
// setHeader (Bool) - set "Authorization" HTML header
//
// Notes:
// - the setUrlParams and setHeader should only need
// to be set whenever getting request tokens; values
// should be 'true' and 'false' respectively
// - take advantage of the callback function, if you
// want to tweet a message and then display an alert:
// BH.tweet("some text",function(){
// alertDialog = Ti.UI.createAlertDialog({
// message:'Tweet posted!'
// });
// alertDialog.show();
// });
//
// Returns: false on failure and the responseText on
// success.
// --------------------------------------------------------
function api(url, method, params, callback, auth, setUrlParams, setHeader) {
var finalUrl = '';
// authorize user if not authorized, and call this in the callback
if(!authorized && ( typeof (auth) == 'undefined' || auth === true)) {
authorize(function(retval) {
if(!retval) {
// execute the callback function
if( typeof (callback) == 'function') {
callback(false);
}
return false;
} else {
api(url, method, params, callback, auth);
}
});
}
// user is authorized so execute API
else {
// VALIDATE INPUT
if(method != "POST" && method != "GET") {
return false;
}
if(params == null || typeof (params) == "undefined") {
params = "";
}
// VARIABLES
var initparams = params;
if(params != null) {
params = params + "&";
}
if(cfg.access_token != '') {
params = params + "oauth_token=" + cfg.access_token;
}
var message = set_message(url, method, params);
OAuth.SignatureMethod.sign(message, accessor);
// if we are getting request tokens, all params have to be set in URL
if( typeof (setUrlParams) != 'undefined' && setUrlParams == true) {
finalUrl = OAuth.addToURL(message.action, message.parameters);
}
// for all other requests only custom params need set in the URL
else {
finalUrl = OAuth.addToURL(message.action, initparams);
}
var XHR = Ti.Network.createHTTPClient();
// on success, grab the request token
XHR.onload = function() {
// execute the callback function
if( typeof (callback) == 'function') {
callback(XHR.responseText);
}
return XHR.responseText;
};
// on error, show message
XHR.onerror = function(e) {
// execute the callback function
if( typeof (callback) == 'function') {
callback(false);
}
return false;
}
XHR.open(method, finalUrl, false);
// if we are getting request tokens do not set the HTML header
if( typeof (setHeader) == 'undefined' || setHeader == true) {
var init = true;
var header = "OAuth ";
for(var i = 0; i < message.parameters.length; i++) {
if(init) {
init = false;
} else {
header = header + ",";
}
header = header + message.parameters[i][0] + '="' + escape(message.parameters[i][1]) + '"';
}
XHR.setRequestHeader("Authorization", header);
}
XHR.send();
}
}
// --------------------------------------------------------
// tweet
//
// Opens a tweet dialog box for the user to make a tweet
// to their page after checking if the user is authorized
// with the app. If the user is unauthorized, the
// authorization process will be initiated first.
//
// In Parameters:
// text (String) - the default text for the text area
// callback (Function) - function to use on callback
// --------------------------------------------------------
function tweet(text, callback) {
// VALIDATE INPUT
// just in case someone only wants to send a callback
if( typeof (text) == 'function' && typeof (callback) == 'undefined') {
callback = text;
text = '';
}
if( typeof (text) == 'undefined') {
text = '';
}
var obj = this;
obj.mytweet = text;
if(authorized === false) {
authorize(function(resp) {
if(resp) {
obj.tweet(obj.mytweet);
return true;
} else {
// execute the callback function
if( typeof (callback) == 'function') {
callback(false);
}
return false;
}
});
} else {
var chars = ( typeof (text) != 'undefined' && text != null) ? text.length : 0;
var winBG = Titanium.UI.createWindow({
backgroundColor : '#000',
opacity : 0.60
});
// the UI window looks completely different on iPhone vs. Android
// iPhone UI
if(Ti.Platform.osname == 'iphone') {
var winTW = Titanium.UI.createWindow({
height : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 15), // half because the keyboard takes up half
width : (Ti.Platform.displayCaps.platformWidth - 20),
top : 10,
right : 10,
left : 10,
borderColor : '#224466',
borderWidth : 3,
backgroundColor : '#559abb',
borderRadius : 10
});
var tweet = Ti.UI.createTextArea({
value : text,
height : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 100),
width : (Ti.Platform.displayCaps.platformWidth - 48),
font : {
fontSize : 16,
//fontColor: st.appSettingTextColor,
fontFamily : st.appSettingFont
},
top : 14,
left : 14,
right : 14
});
var btnTW = Ti.UI.createButton({
title : L("tweet_text_exclaim"),
width : 100,
height : 30,
top : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 75),
right : 24
});
var btnCancel = Ti.UI.createButton({
title : L("cancel_text"),
width : 100,
height : 30,
top : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 75),
left : 24
});
var charcount = Ti.UI.createLabel({
top : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 55),
left : (Ti.Platform.displayCaps.platformWidth - 60), // 30 px from right side,
color : '#FFF',
text : (parseInt((140 - chars)) + '')
});
// show keyboard on load
winTW.addEventListener('open', function() {
tweet.focus();
});
}
// Android UI
else {
var winTW = Titanium.UI.createWindow({
height : 264,
top : 10,
right : 10,
left : 10,
borderColor : '#224466',
borderWidth : 3,
backgroundColor : '#559abb',
borderRadius : 3.0
});
var tweet = Ti.UI.createTextArea({
value : text,
height : 160,
top : 14,
left : 14,
right : 14
});
var btnTW = Ti.UI.createButton({
title : L("tweet_text"),
width : 100,
top : 182,
right : 24
});
var btnCancel = Ti.UI.createButton({
title : L("cancel_text"),
width : 100,
top : 182,
left : 24
});
var charcount = Ti.UI.createLabel({
bottom : 10,
right : 14,
color : '#FFF',
text : (parseInt((140 - chars)) + '')
});
}
tweet.addEventListener('change', function(e) {
chars = (140 - e.value.length);
if(chars < 11) {
if(charcount.color != '#D40D12') {
charcount.color = '#D40D12';
}
} else if(chars < 20) {
if(charcount.color != '#5C0002') {
charcount.color = '#5C0002';
}
} else {
if(charcount.color != '#FFF') {
charcount.color = '#FFF';
}
}
charcount.text = parseInt(chars) + '';
});
btnTW.addEventListener('click', function() {
send_tweet("status=" + escape(tweet.value), function(retval) {
if(retval === false) {
// execute the callback function
if( typeof (callback) == 'function') {
callback(false);
}
return false;
} else {
// hide the keyboard on Android because it doesn't automatically
if(Ti.Platform.osname == 'android') {
Titanium.UI.Android.hideSoftKeyboard();
}
// execute the callback function
if( typeof (callback) == 'function') {
callback(true);
}
winBG.close();
winTW.close();
return true;
}
});
});
btnCancel.addEventListener('click', function() {
// hide the keyboard on Android because it doesn't automatically
if(Ti.Platform.osname == 'android') {
Titanium.UI.Android.hideSoftKeyboard();
}
winBG.close();
winTW.close();
});
winTW.add(charcount);
winTW.add(tweet);
winTW.add(btnTW);
winTW.add(btnCancel);
winBG.open();
winTW.open();
}
}
// --------------------------------------------------------
// short_tweet
//
// Opens a tweet dialog box for the user to make a tweet
// to their page after checking if the user is authorized
// with the app. If the user is unauthorized, the
// authorization process will be initiated first. Also,
// a 'Shorten' button is provided to shorten any links
// in the tweet before posting.
//
// In Parameters:
// text (String) - the default text for the text area
// callback (Function) - function to use on callback
// --------------------------------------------------------
function short_tweet(text, callback) {
// VALIDATE INPUT
// just in case someone only wants to send a callback
if( typeof (text) == 'function' && typeof (callback) == 'undefined') {
callback = text;
text = '';
}
if( typeof (text) == 'undefined') {
text = '';
}
var obj = this;
obj.mytweet = text;
if(authorized === false) {
authorize(function(resp) {
if(resp) {
obj.tweet(obj.mytweet);
return true;
} else {
// execute the callback function
if( typeof (callback) == 'function') {
callback(false);
}
return false;
}
});
} else {
var chars = ( typeof (text) != 'undefined' && text != null) ? text.length : 0;
var winBG = Titanium.UI.createWindow({
backgroundColor : '#000',
opacity : 0.60
});
// the UI window looks completely different on iPhone vs. Android
// iPhone UI
if(Ti.Platform.osname == 'iphone') {
var winTW = Titanium.UI.createWindow({
height : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 15), // half because the keyboard takes up half
width : (Ti.Platform.displayCaps.platformWidth - 20),
top : 10,
right : 10,
left : 10,
borderColor : '#224466',
borderWidth : 3,
backgroundColor : '#559abb',
borderRadius : 10
});
var tweet = Ti.UI.createTextArea({
value : text,
height : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 100),
width : (Ti.Platform.displayCaps.platformWidth - 48),
font : {
fontSize : 16,
//fontColor: st.appSettingTextColor,
fontFamily : st.appSettingFont
},
top : 14,
left : 14,
right : 14
});
var btnShorten = Ti.UI.createButton({
title : L("shorten_text"),
width : 80,
height : 30,
top : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 75)
});
var btnTW = Ti.UI.createButton({
title : L("tweet_text"),
width : 80,
height : 30,
top : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 75),
right : 24
});
var btnCancel = Ti.UI.createButton({
title : L("cancel_text"),
width : 80,
height : 30,
top : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 75),
left : 24
});
var charcount = Ti.UI.createLabel({
top : ((Ti.Platform.displayCaps.platformHeight * 0.5) - 55),
left : (Ti.Platform.displayCaps.platformWidth - 60), // 30 px from right side,
color : '#FFF',
text : (parseInt((140 - chars)) + '')
});
// show keyboard on load
winTW.addEventListener('open', function() {
tweet.focus();
});
}
// Android UI
else {
var winTW = Titanium.UI.createWindow({
height : 264,
top : 10,
right : 10,
left : 10,
borderColor : '#224466',
borderWidth : 3,
backgroundColor : '#559abb',
borderRadius : 3.0
});
var tweet = Ti.UI.createTextArea({
value : text,
height : 160,
top : 14,
left : 14,
right : 14
});
var btnShorten = Ti.UI.createButton({
title : "shorten_text",
width : 100,
top : 182
});
var btnTW = Ti.UI.createButton({
title : "tweet_text",
width : 100,
top : 182,
right : 24
});
var btnCancel = Ti.UI.createButton({
title : "cancel_text",
width : 100,
top : 182,
left : 24
});
var charcount = Ti.UI.createLabel({
bottom : 10,
right : 14,
color : '#FFF',
text : (parseInt((140 - chars)) + '')
});
}
tweet.addEventListener('change', function(e) {
chars = (140 - e.value.length);
if(chars < 11) {
if(charcount.color != '#D40D12') {
charcount.color = '#D40D12';
}
} else if(chars < 20) {
if(charcount.color != '#5C0002') {
charcount.color = '#5C0002';
}
} else {
if(charcount.color != '#FFF') {
charcount.color = '#FFF';
}
}
charcount.text = parseInt(chars) + '';
});
btnShorten.addEventListener('click', function() {
var actInd = Titanium.UI.createActivityIndicator({
style : Titanium.UI.iPhone.ActivityIndicatorStyle.BIG,
height : 30,
width : 30,
top : 30
});
indWin = Titanium.UI.createWindow();
indWin.add(actInd);
indWin.open();
actInd.show();
// replace URLs in the text with shortened URLs
var urlRegex = /(https?:\/\/[^\s]+)/gi;
var urls = [];
(tweet.value).replace(urlRegex, function(url) {
urls.push(url);
});
for(var i = 0; i < urls.length; i++) {
// get shorturl
shorten_url(urls[i], function(shorturl, url) {
if(shorturl != false) {
tweet.value = (tweet.value).replace(url, shorturl);
indWin.close();
actInd.hide();
return true;
} else {
indWin.close();
actInd.hide();
return false;
}
});
}
});
btnTW.addEventListener('click', function() {
send_tweet("status=" + escape(tweet.value), function(retval) {
if(retval === false) {
// execute the callback function
if( typeof (callback) == 'function') {
callback(false);
}
return false;
} else {
// hide the keyboard on Android because it doesn't automatically
if(Ti.Platform.osname == 'android') {
Titanium.UI.Android.hideSoftKeyboard();
}
// execute the callback function
if( typeof (callback) == 'function') {
callback(true);
}
winBG.close();
winTW.close();
return true;
}
});
});
btnCancel.addEventListener('click', function() {
// hide the keyboard on Android because it doesn't automatically
if(Ti.Platform.osname == 'android') {
Titanium.UI.Android.hideSoftKeyboard();
}
winBG.close();
winTW.close();
});
winTW.add(charcount);
winTW.add(tweet);
winTW.add(btnShorten);
winTW.add(btnTW);
winTW.add(btnCancel);
winBG.open();
winTW.open();
}
}
// --------------------------------------------------------
// send_tweet
//
// Makes an API call to Twitter to post a tweet.
//
// In Parameters:
// params (String) - the string of optional and
// required parameters in url form
// callback (Function) - function to call on completion
// --------------------------------------------------------
function send_tweet(params, callback) {
api('http://api.twitter.com/1/statuses/update.json', 'POST', params, function(resp) {
if(resp != false) {
if( typeof (callback) == 'function') {
callback(true);
}
return true;
} else {
if( typeof (callback) == 'function') {
callback(false);
}
return false;
}
});
}
// --------------------------------------------------------
// shorten_url
//
// Shortens a URL using twe.ly.
//
// In Parameters:
// url (String) - the url to shorten
//
// Returns:
// shorturl (String) - the shortened URL, else false
// callback (Function) - function to call on completion
// --------------------------------------------------------
function shorten_url(url, callback) {
var XHR = Titanium.Network.createHTTPClient();
XHR.open("GET", "http://www.twe.ly/short.php?url=" + url + "&json=1");
XHR.onload = function() {
try {
shorturl = JSON.parse(XHR.responseText);
} catch(e) {
shorturl = false;
}
if(shorturl != false && shorturl.substr(0, 5) == 'Sorry') {
shorturl = false;
}
if( typeof (callback) == 'function') {
callback(shorturl, url);
}
return shorturl;
};
XHR.onerror = function(e) {
if( typeof (callback) == 'function') {
callback(false);
}
return false;
};
XHR.send();
}
// --------------------------------------------------------
// get_tweets
//
// Makes a TWitter API call to get tweets.
//
// In Parameters:
// params (String) - the string of optional and
// required parameters in url form
// callback (Function) - function to use on callback
// --------------------------------------------------------
function get_tweets(params, callback) {
// just in case someone only wants to send a callback
if( typeof (params) == 'function' && typeof (callback) == 'undefined') {
callback = params;
params = '';
}
api("https://api.twitter.com/1/statuses/friends_timeline.json", "GET", params, function(tweets) {
try {
tweets = JSON.parse(tweets);
} catch (e) {
tweets = false;
}
// execute the callback function
if( typeof (callback) == 'function') {
callback(tweets);
}
return tweets;
})
}
// --------------------------------------------------------
// authorize
//
// The whole authorization sequence begins with
// get_request_token(), which calls get_request_verifier()
// which finally calls get_access_token() which then
// saves the token in a file.
//
// In Parameters:
// callback (Function) - a function to call after
// the user has been authorized; note that it won't
// be executed until get_access_token(), unless we
// are already authorized.
//
// Returns: true if the user is authorized
// --------------------------------------------------------
function authorize(callback) {
Ti.API.debug("authorize " + service);
if(!authorized) {
get_request_token(callback);
// get_request_token or a function it calls will call callback
} else {
// execute the callback function
if( typeof (callback) == 'function') {
callback(authorized);
}
}
Ti.API.error(service + ' is authorized ' + authorized);
return authorized;
}
// --------------------------------------------------------
// deauthorize
//
// Delete the stored access token file, delete the tokens
// from the config and accessor, and set authorized to
// load_access_token() which should return false since
// we deleted the file, thus resulting in a deauthroized
// state.
//
// In Parameters:
// callback (Function) - function to call after
// user is deauthorized
//
// Returns: true if the user is deauthorized
// --------------------------------------------------------
function deauthorize(callback) {
if(authorized) {
var file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, service + '.config');
file.deleteFile();
authorized = load_access_token();
accessor.tokenSecret = "";
cfg.access_token = "";
cfg.access_token_secret = "";
cfg.request_verifier = "";
// execute the callback function
if( typeof (callback) == 'function') {
callback(!authorized);
}
} else {
// execute the callback function
if( typeof (callback) == 'function') {
callback(!authorized);
}
}
return !authorized;
}
var sendTwitterImage = function(postParams, pSuccessCallback, pErrorCallback) {
var finalUrl = '';
// authorize user if not authorized, and call this in the callback
if(!authorized && ( typeof (auth) == 'undefined' || auth === true)) {
authorize(function(retval) {
if(!retval) {
// execute the callback function
if( typeof (callback) == 'function') {
callback(false);
}
return false;
} else {
api(url, method, params, callback, auth);
}
});
}
// user is authorized so execute API
else {
var url = "http://upload.twitter.com/1/statuses/update_with_media.json";
// VARIABLES
var initparams = params;
if(params != null) {
params = params + "&";
}
if(cfg.access_token != '') {
params = params + "oauth_token=" + cfg.access_token;
}
var message = set_message(url, "POST");
OAuth.SignatureMethod.sign(message, accessor);
var XHR = Ti.Network.createHTTPClient();
// on success, grab the request token
XHR.onload = function() {
// execute the callback function
if( typeof (callback) == 'function') {
callback(XHR.responseText);
}
return XHR.responseText;
};
// on error, show message
XHR.onerror = function(e) {
// execute the callback function
if( typeof (callback) == 'function') {
callback(false);
}
return false;
}
XHR.open(method, finalUrl, false);
// if we are getting request tokens do not set the HTML header
if( typeof (setHeader) == 'undefined' || setHeader == true) {
var init = true;
var header = "OAuth ";
for(var i = 0; i < message.parameters.length; i++) {
if(init) {
init = false;
} else {
header = header + ",";
}
header = header + message.parameters[i][0] + '="' + escape(message.parameters[i][1]) + '"';
}
XHR.setRequestHeader("Authorization", header);
XHR.setRequestHeader("Content-Type", "multipart/form-data");
}
XHR.send();
}
};
this.sendTwitterImage = sendTwitterImage;
// --------------------------------------------------------
// ===================== PUBLIC ===========================
// --------------------------------------------------------
this.authorize = authorize;
this.deauthorize = deauthorize;
this.api = api;
this.authorized = function() {
return authorized;
}
this.getConfig = get_config;
this.get_tweets = get_tweets;
this.tweet = tweet;
this.short_tweet = short_tweet;
this.shorten_url = shorten_url;
// added for fun
this.request_token = cfg.request_token;
this.token_secret = cfg.request_token_secret;
this.oauth_token = cfg.oauth_token;
this.oauth_verifier = cfg.request_verifier;
// --------------------------------------------------------
// =================== INITIALIZE =========================
// --------------------------------------------------------
if( typeof params == 'object') {
if(params.consumer_key != undefined) {
cfg.oauth_consumer_key = params.consumer_key;
}
if(params.service != undefined) {
cfg.service = params.service;
service = params.service;
}
if(params.consumer_secret != undefined) {
cfg.consumer_secret = params.consumer_secret;
accessor.consumerSecret = cfg.consumer_secret;
}
if(params.callback_url != undefined) {
cfg.callback_url = params.callback_url;
}
if(params.show_login_toolbar != undefined) {
cfg.show_login_toolbar = params.show_login_toolbar;
}
}
Ti.API.debug("BH params " + JSON.stringify(params));
authorized = load_access_token();
// load the token on startup to see if authorized
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment