diff --git a/TODO b/TODO index 353c2fe..86979a8 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,12 @@ 1. A way to filter tweets that contains something -3endi moshkeleh be shell.execStack , wain a7san ma7al to reset it !?!!!! \ No newline at end of file +3endi moshkeleh be shell.execStack , wain a7san ma7al to reset it !?!!!! + + +Usful command to check the tcpdump: +sudo tcpdump -i en1 -A -s 1024 -l | tee dump.log | grep twitter + + + +post %r{/twitter/timelines/(user_timeline|friends_timeline|mentions|retweeted_by_me|retweeted_to_me|retweets_of_me)} do |action| diff --git a/lib/extend/twitter_oauth/favorites.rb b/lib/extend/twitter_oauth/favorites.rb new file mode 100644 index 0000000..e4ad504 --- /dev/null +++ b/lib/extend/twitter_oauth/favorites.rb @@ -0,0 +1,18 @@ +module TwitterOAuth + class Client + + # The favorites method defined in twitter oauth doesn't allow u + # to specifiy the user using the screen_name param. So i am remaning the favorites to old_favorites + # and re-writting favorites. + #alias old_favorites favorites + alias_method :old_favorites, :to_s + + + def favorites(options = {}) + puts "XXXXXXXXXXXXXXXXXX" + puts options.inspect + args = options.map{|k,v| "#{k}=#{v}"}.join('&') + get("/favorites.json?#{args}") + end + end +end \ No newline at end of file diff --git a/lib/extend/twitter_oauth/search.rb b/lib/extend/twitter_oauth/search.rb new file mode 100644 index 0000000..5bb3e33 --- /dev/null +++ b/lib/extend/twitter_oauth/search.rb @@ -0,0 +1,11 @@ +module TwitterOAuth + class Client + # Find the mentions given the username. + # This function doesn't rely on twitter mentions api because api only returns + # mentions for the authenticated users. So i am using the search api get it. + def public_mentions(username,options) + puts "username == #{username}" + search("@#{username}", options) + end + end +end \ No newline at end of file diff --git a/public/js/usr/bin/iostream.js b/public/js/usr/bin/iostream.js index 06f634f..f80728d 100644 --- a/public/js/usr/bin/iostream.js +++ b/public/js/usr/bin/iostream.js @@ -37,7 +37,9 @@ shell.std.cerr = function(data){ /* Standard Logging: Use the mighty firebug for debugging .... fb i luvvvv uuuuuuuuu **/ shell.std.clog = function(data){ - console.log(data); + if (console && typeof console.log == "function"){ + console.log(data); + } } /* Clear the STD output **/ diff --git a/public/js/usr/bin/parsers.js b/public/js/usr/bin/parsers.js index 947333c..f632a84 100644 --- a/public/js/usr/bin/parsers.js +++ b/public/js/usr/bin/parsers.js @@ -42,7 +42,7 @@ shell.parsers.Tweet = function(tweet){ out += ''; out += '' + jQuery.relative_time(tweet['created_at']) +''; out += ''; - out += ' from ' + tweet['source'] + ' '; + out += ' from ' + jQuery.unescapeHTML(tweet['source']) + ' '; out += ''; out += ''; out += ''; @@ -51,6 +51,5 @@ shell.parsers.Tweet = function(tweet){ } shell.parsers.Users = function(arr){ - } diff --git a/public/js/usr/bin/syscalls.js b/public/js/usr/bin/syscalls.js index 4ad2f21..93081e2 100644 --- a/public/js/usr/bin/syscalls.js +++ b/public/js/usr/bin/syscalls.js @@ -191,28 +191,37 @@ shell.syscalls.mkdirHome = function(basedir , username){ shell.syscalls.mkdir(path); //timelines - var timeline_path = shell.twitter_FS.join(path , 'timeline'); - var mentions_path = shell.twitter_FS.join(path , 'mentions'); - var fr_timeline_path = shell.twitter_FS.join(path , 'friends_timeline'); - shell.syscalls.mkdir(timeline_path); - shell.syscalls.mkdir(mentions_path); - shell.syscalls.mkdir(fr_timeline_path); - shell.syscalls.mount(timeline_path, "ls","twitter/timelines/user_timeline" , "shell.callbacks.lsTweets"); - shell.syscalls.mount(mentions_path, "ls","twitter/timelines/mentions" , "shell.callbacks.lsTweets"); - shell.syscalls.mount(fr_timeline_path, "ls","twitter/timelines/friends_timeline", "shell.callbacks.lsTweets"); - - //retweets - var retweets = shell.twitter_FS.join(path , 'retweets'); - var retweets_byme = shell.twitter_FS.join(retweets , 'by_me'); - var retweets_tome = shell.twitter_FS.join(retweets , 'to_me'); - var retweets_offme = shell.twitter_FS.join(retweets , 'off_me'); - shell.syscalls.mkdir(retweets); - shell.syscalls.mkdir(retweets_byme); - shell.syscalls.mkdir(retweets_tome); - shell.syscalls.mkdir(retweets_offme); - shell.syscalls.mount(retweets_byme, "ls","twitter/timelines/retweeted_by_me" , "shell.callbacks.lsTweets"); - shell.syscalls.mount(retweets_tome, "ls","twitter/timelines/retweeted_to_me" , "shell.callbacks.lsTweets"); - shell.syscalls.mount(retweets_offme, "ls","twitter/timelines/retweets_of_me" , "shell.callbacks.lsTweets"); + // var fr_timeline_path = shell.twitter_FS.join(path , 'friends_timeline'); + // shell.syscalls.mkdir(timeline_path); + // shell.syscalls.mkdir(fr_timeline_path); + // shell.syscalls.mount(fr_timeline_path, "ls","twitter/timelines/friends_timeline", "shell.callbacks.lsTweets"); + + // [/home/USER/timelines/] + var timelines = shell.twitter_FS.join(path , 'timelines'); + shell.syscalls.mkdir(timelines); + shell.syscalls.mkdirAndMount(shell.twitter_FS.join(timelines , 'timeline') , "ls" ,"twitter/timelines/user_timeline","shell.callbacks.lsTweets") + + + + // If i am building my own homeDir + if(shell.twitter.loggedIn() && shell.config.user == username){ + shell.syscalls.mkdirAndMount(shell.twitter_FS.join(timelines , 'personal') , "ls" ,"twitter/timelines/home_timeline","shell.callbacks.lsTweets") + shell.syscalls.mkdirAndMount(shell.twitter_FS.join(path , 'mentions') , "ls" ,"twitter/mentions","shell.callbacks.lsTweets") + + // retweets + var retweets = shell.twitter_FS.join(path , 'retweets'); + shell.syscalls.mkdir(retweets); + shell.syscalls.mkdirAndMount(shell.twitter_FS.join(retweets , 'by_me'), "ls" , "twitter/retweets/by_me" , "shell.callbacks.lsTweets"); + shell.syscalls.mkdirAndMount(shell.twitter_FS.join(retweets , 'to_me'), "ls","twitter/retweets/to_me" , "shell.callbacks.lsTweets"); + shell.syscalls.mkdirAndMount(shell.twitter_FS.join(retweets , 'of_me'), "ls","twitter/retweets/of_me" , "shell.callbacks.lsTweets"); + + // fav/personal + shell.syscalls.mkdirAndMount(shell.twitter_FS.join(path , 'favorites'), "ls","twitter/favorites/private" , "shell.callbacks.lsTweets"); + }else{ + shell.syscalls.mkdirAndMount(shell.twitter_FS.join(path , 'mentions') , "ls" ,"twitter/public_mentions","shell.callbacks.lsTweets") + shell.syscalls.mkdirAndMount(shell.twitter_FS.join(path , 'favorites'), "ls","twitter/favorites/public" , "shell.callbacks.lsTweets"); + } + // friends and followers var friends_path = shell.twitter_FS.join(path , 'friends'); @@ -220,5 +229,11 @@ shell.syscalls.mkdirHome = function(basedir , username){ shell.syscalls.mkdir(friends_path); shell.syscalls.mkdir(followers_path); shell.syscalls.mount(friends_path, "ls","twitter/users/friends" ,"shell.callbacks.lsUsers"); - shell.syscalls.mount(followers_path, "ls","twitter/users/followers" ,"shell.callbacks.lsUsers"); + shell.syscalls.mount(followers_path, "ls","twitter/users/followers" ,"shell.callbacks.lsUsers"); +} + +// just to clean things out. +shell.syscalls.mkdirAndMount = function(full_path , cmd , mount_point , mount_callback){ + shell.syscalls.mkdir(full_path); + shell.syscalls.mount(full_path, cmd , mount_point , mount_callback); } \ No newline at end of file diff --git a/public/js/usr/bin/twitter_FS.js b/public/js/usr/bin/twitter_FS.js index 583b55c..4e5b401 100644 --- a/public/js/usr/bin/twitter_FS.js +++ b/public/js/usr/bin/twitter_FS.js @@ -26,6 +26,9 @@ shell.twitter_FS.initialize = function(current_user){ shell.syscalls.mkdir("/home" , "twitter/users"); shell.syscalls.mount("/home/" , "cd" ,"twitter/users" ,"shell.callbacks.getUser"); + shell.syscalls.mkdirAndMount("/public_timeline" , "ls" ,"twitter/timelines/public_timeline","shell.callbacks.lsTweets"); + + if(shell.twitter.loggedIn()){ shell.syscalls.mkdirHome("/home/",shell.config.user); shell.syscalls.chdir(shell.twitter_FS.join("/home/" , shell.config.user)); diff --git a/public/js/utilites.jquery.js b/public/js/utilites.jquery.js index 9aa83c5..4053a61 100644 --- a/public/js/utilites.jquery.js +++ b/public/js/utilites.jquery.js @@ -175,3 +175,7 @@ function ltrim(text) { function rtrim(text) { return text.replace(/\s+$/g, ""); } + +jQuery.unescapeHTML = function(html){ + return $("
"+html+"
").text(); +} \ No newline at end of file diff --git a/tweetsh.rb b/tweetsh.rb index f00a5dc..d32af98 100755 --- a/tweetsh.rb +++ b/tweetsh.rb @@ -21,6 +21,9 @@ # Extend the twitter_oauth library by adding few more functions to the Client class require 'lib/extend/twitter_oauth/user' +require 'lib/extend/twitter_oauth/search' +require 'lib/extend/twitter_oauth/favorites' + # Set the Mime-type for json mime :json, "application/json" @@ -71,13 +74,14 @@ user.to_json end -# Handel everything under timelines from mentions to user timelines +# Handel everything under timelines(public/user/home) # @TODO: # => Integrate pagination -post %r{/twitter/timelines/(user_timeline|friends_timeline|mentions|retweeted_by_me|retweeted_to_me|retweets_of_me)} do |action| +post %r{/twitter/timelines/(user_timeline|home_timeline|public_timeline)} do |action| # Extract the username - screen_name = (params['path'] =~ /\/([A-Za-z_0-9]+)\/user_timeline|friends_timeline|mentions|retweeted_by_me|retweeted_to_me|retweets_of_me/) ? $1 : nil + screen_name = (params['path'] =~ /\/([A-Za-z_0-9]+)\/timelines\/(timeline|personal)/) ? $1 : nil + #(user_timeline|friends_timeline|mentions|retweeted_by_me|retweeted_to_me|retweets_of_me) # Setup the options options = {} options[:screen_name] = screen_name unless screen_name.nil? @@ -90,6 +94,73 @@ tweets.to_json end +# Handel a call to mentions or public_mentions +# Note: mentions is a direct call to the api, while public_mentions +# calls the search engine to get the results back. +# @TODO: +# => Integrate pagination +post %r{/twitter/(mentions|public_mentions)} do |action| + # Extract the username, only used if the call is 2 public_mentions + screen_name = (params['path'] =~ /\/([A-Za-z_0-9]+)\/(mentions|public_mentions)/) ? $1 : nil + + # Setup the options + options = {} + options[:show_user] = true if action == 'public_mentions' + + # If its a a call to the public_mentions, meaning we are calling the search api. + if(action == 'public_mentions') + options[:show_user] = true + data = @client.send(action, screen_name , options) + tweets = (data.is_a?(Hash) && data.has_key?('error')) ? Base.new(data) : Tweets.new(Tweets.convertSearchResults2TweetsHash(data)) + else + data = @client.send(action , options) + tweets = (data.is_a?(Hash) && data.has_key?('error')) ? Base.new(data) : Tweets.new(data) + end + + # return data + tweets.to_json +end + +# Deal with retweets, it will only work if the user is logged in. +post %r{/twitter/retweets/(by_me|to_me|of_me)} do |action| + # Setup the options + options = {} + + # Get the data and parse it + # we have 3 actions defined in the twitter_oauth: + # => 1.retweeted_by_me 2.retweeted_to_me 3. retweets_of_me + # so we need cater for the retweets_ .. a simple if will do. + action_name = (action == 'of_me') ? "retweets_#{action}" : "retweeted_#{action}" + data = @client.send(action_name , options) + tweets = (data.is_a?(Hash) && data.has_key?('error')) ? Base.new(data) : Tweets.new(data) + + # return data + tweets.to_json +end + +# Handel a call to mentions or public_mentions +# Note: mentions is a direct call to the api, while public_mentions +# calls the search engine to get the results back. +# @TODO: +# => Integrate pagination +post %r{/twitter/favorites/(public|private)} do |action| + # Extract the username + screen_name = (params['path'] =~ /\/([A-Za-z_0-9]+)\/(favorites)/) ? $1 : nil + + # Setup the options + options = {} + + # Set the screen_name if its a public call. + options[:screen_name] = screen_name unless screen_name.nil? && action == 'public' + + + data = @client.send("favorites" , options) + tweets = (data.is_a?(Hash) && data.has_key?('error')) ? Base.new(data) : Tweets.new(data) + + # return data + tweets.to_json +end + # Handels the requests for the friends && followers # Possible actions (/friends/ for /followers/) post %r{/twitter/users/(friends|followers)} do |action| @@ -126,7 +197,6 @@ # this is configured on the Twitter application settings page get '/oauth/auth' do # Exchange the request token for an access token. - begin @access_token = @client.authorize( session[:request_token], @@ -134,10 +204,11 @@ :oauth_verifier => params[:oauth_verifier] ) rescue OAuth::Unauthorized + redirect '/' end if @client.authorized? - # Storing the access tokens so we don't have to go back to Twitter again + # Storing the access tokens so we don't have to go back to Twitter again # in this session. In a larger app you would probably persist these details somewhere. session[:access_token] = @access_token.token session[:secret_token] = @access_token.secret @@ -160,6 +231,7 @@ ######################### experimental ############################ +=begin get '/timeline' do @tweets = @client.friends_timeline erb :timeline @@ -196,11 +268,9 @@ @search = @client.search(params[:q], :page => params[:page], :per_page => params[:per_page]) erb :search end - - - -helpers do - def partial(name, options={}) - erb("_#{name.to_s}".to_sym, options.merge(:layout => false)) - end -end \ No newline at end of file +=end +#helpers do +# def partial(name, options={}) +# erb("_#{name.to_s}".to_sym, options.merge(:layout => false)) +# end +#end \ No newline at end of file diff --git a/wrappers/tweets.rb b/wrappers/tweets.rb index 78c378a..23cdd23 100644 --- a/wrappers/tweets.rb +++ b/wrappers/tweets.rb @@ -9,6 +9,26 @@ def initialize(tweets=[]) end end + + def self.convertSearchResults2TweetsHash(search_results) + results = search_results['results'] + converted = [] + # Map the returned value in original user object reposnce, , missing few params but will do. + user_keys = {'profile_image_url' => 'profile_image_url' , 'from_user' => 'screen_name' , 'from_user_id' => 'id'} + results.each do |result| + h = {} + h['user'] = {} + user_keys.each do |key,val| + h['user'][val] = result[key] + result.delete(key) + end + h.merge!(result) + converted << h + end + search_results.delete('results') + converted + end + # Convert the object to a json string def to_json(*a) {