tweetline 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Anthony Crumley
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,39 @@
1
+ This is the initial proof of concept for a twitter command line tool. Now that I understand the problem, I am currently in the process of writing a more robust implementation.
2
+
3
+ == Getting Started
4
+
5
+ 1. Install Tweetline at the command prompt if you haven't yet:
6
+
7
+ gem install tweetline
8
+
9
+ 2. Until Twitter approves xAuth for Tweetline, you will have to create a ~/.tweetlinerc yaml file with your authentication credentials like the following...
10
+
11
+ :consumer_key: "your-key"
12
+ :consumer_secret: "your-secret"
13
+ :oauth_token: "your-token"
14
+ :oauth_token_secret: "your-secret"
15
+
16
+ 3. Enter commands with tl:
17
+
18
+ tl ls
19
+
20
+ ESV Daily Verse (@esvdaily) [04:46 AM]
21
+ A friend loves at all times, and a brother is born for adversity. http://esv.to/Pr17.17 (54842265859915777)
22
+
23
+ DHH (@dhh) [04/02/11 11:43 AM]
24
+ I've tried many answers for "what do you get out of working on open source?", but the truth is the act of creation is its own reward. (54222543829213184)
25
+
26
+ == Tasks
27
+
28
+ tl cat [ID] # Display the details of a tweet with responses based on twitter id or piped in tweets.
29
+ tl follow [SCREEN_NAME] # Follows the twitter user based on their screen name or piped in tweets.
30
+ tl help [TASK] # Describe available tasks or one specific task
31
+ tl json # Lists tweets from the timeline in JSON format.
32
+ tl ls [SCREEN_NAME] # Lists tweets from the timeline.
33
+ tl retweet [ID] # Retweets the tweet by the Twitter id or a group of piped in tweets.
34
+ tl rm [ID] # Removes the tweet by it's id or a list of piped in tweets.
35
+ tl say # Speaks the tweet at the top of your timeline.
36
+ tl tail # Displays recent tweets in chronological order.
37
+ tl unfollow [SCREEN_NAME] # Unfollows the twitter user based on their screen name or piped in tweets.
38
+ tl update STATUS # Updates your current Twitter status.
39
+ tl yaml # Lists tweets from the timeline in YAML format.
data/bin/tl CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
3
  require 'rubygems'
4
- require 'lib/tweetline'
5
- require 'lib/tweetline/cli'
4
+ require 'tweetline'
5
+ require 'tweetline/cli'
6
6
 
7
7
  Tweetline::CLI.start
@@ -0,0 +1,146 @@
1
+ module Tweetline
2
+ class CLI < Thor
3
+ def initialize(*)
4
+ super
5
+ Tweetline.configure_twitter
6
+ Tweetline.configure_pipes
7
+ end
8
+
9
+ default_task :ls
10
+
11
+ desc "cat [ID]", "Display the details of a tweet with responses based on twitter id or piped in tweets."
12
+ def cat(twitter_id = "")
13
+ if twitter_id.strip.length > 0
14
+ tweet = Twitter.status(ARGV[1])
15
+ Tweetline.cat_tweet(tweet.id, tweet.created_at, tweet.user.name, tweet.user.screen_name, tweet.text)
16
+ else
17
+ Tweetline.each_tweet do |tweet|
18
+ Tweetline.cat_tweet(tweet["id"], tweet["created_at"], tweet["name"], tweet["screen_name"], tweet["text"])
19
+ end
20
+ end
21
+ end
22
+
23
+ desc "follow [SCREEN_NAME]", "Follows the twitter user based on their screen name or piped in tweets."
24
+ def follow(screen_name = "")
25
+ if screen_name.strip.length > 0
26
+ Twitter.follow(screen_name)
27
+ else
28
+ Tweetline.each_tweet do |tweet|
29
+ Twitter.follow(tweet["screen_name"])
30
+ puts "Followed -> #{tweet["screen_name"]}" unless Twitter.is_piped_to_tweetline?
31
+ end
32
+ end
33
+ end
34
+
35
+ desc "json", "Lists tweets from the timeline in JSON format."
36
+ def json
37
+ Tweetline.each_tweet do |tweet|
38
+ puts tweet.to_json
39
+ end
40
+ end
41
+
42
+ desc "ls [SCREEN_NAME]", "Lists tweets from the timeline."
43
+ def ls(screen_name = "")
44
+ options = {:count => 10}
45
+ options[:screen_name] = screen_name if screen_name.strip.length > 0
46
+ Tweetline.each_tweet(options) do |tweet|
47
+ Tweetline.put_tweet(tweet["id"], tweet["created_at"], tweet["name"], tweet["screen_name"], tweet["text"])
48
+ end
49
+ end
50
+
51
+ desc "raw", "Raw output for testing."
52
+ def raw
53
+ STDIN.each do |text|
54
+ puts text
55
+ end
56
+ end
57
+
58
+ desc "retweet [ID]", "Retweets the tweet by the Twitter id or a group of piped in tweets."
59
+ def retweet(twitter_id = "")
60
+ if twitter_id.strip.length > 0
61
+ Twitter.retweet(twitter_id)
62
+ else
63
+ Tweetline.each_tweet do |tweet|
64
+ Twitter.retweet(tweet["id"])
65
+ puts "Retweeted:" unless Twitter.is_piped_to_tweetline?
66
+ Twitter.put_tweet(tweet["id"], tweet["created_at"], tweet["name"], tweet["screen_name"], tweet["text"])
67
+ end
68
+ end
69
+ end
70
+
71
+ desc "rm [ID]", "Removes the tweet by it's id or a list of piped in tweets."
72
+ def rm(twitter_id = "")
73
+ if twitter_id.strip.length > 0
74
+ Twitter.status_destroy(twitter_id)
75
+ else
76
+ Tweetline.each_tweet do |tweet|
77
+ Twitter.status_destroy(tweet["id"])
78
+ puts "Removed:" unless Twitter.is_piped_to_tweetline?
79
+ Twitter.put_tweet(tweet["id"], tweet["created_at"], tweet["name"], tweet["screen_name"], tweet["text"])
80
+ end
81
+ end
82
+ end
83
+
84
+ desc "say", "Speaks the tweet at the top of your timeline."
85
+ def say
86
+ Tweetline.each_tweet(:count => 1) do |tweet|
87
+ Tweetline.say_tweet(tweet["id"], tweet["created_at"], tweet["name"], tweet["screen_name"], tweet["text"])
88
+ end
89
+ end
90
+
91
+ desc "tail", "Displays recent tweets in chronological order."
92
+ method_option :follow, :type => :boolean, :aliases => "-f", :defatul => false, :banner => "Continue following tweets as they are added."
93
+ method_option :number, :type => :numeric, :aliases => "-n", :default => 10, :banner => "Specifies the number of tweets to display."
94
+ def tail
95
+ opts = options.dup
96
+
97
+ Signal.trap("SIGINT") do
98
+ exit!
99
+ end
100
+
101
+ previous_id = "1"
102
+ begin
103
+ tweets = Twitter.home_timeline(:count => opts[:number], :since_id => previous_id) rescue []
104
+ tweets.reverse_each do |tweet|
105
+ Tweetline.put_tweet(tweet.id, tweet.created_at, tweet.user.name, tweet.user.screen_name, tweet.text)
106
+ previous_id = tweet.id
107
+ end
108
+
109
+ sleep(30) if opts[:follow]
110
+
111
+ end while opts[:follow]
112
+ end
113
+
114
+ desc "unfollow [SCREEN_NAME]", "Unfollows the twitter user based on their screen name or piped in tweets."
115
+ def unfollow(screen_name = "")
116
+ if screen_name.strip.length > 0
117
+ Twitter.unfollow(screen_name)
118
+ else
119
+ Tweetline.each_tweet do |tweet|
120
+ Twitter.unfollow(tweet["screen_name"])
121
+ puts "Followed -> #{tweet["screen_name"]}" unless Twitter.is_piped_to_tweetline?
122
+ end
123
+ end
124
+ end
125
+
126
+ desc "update STATUS", "Updates your current Twitter status."
127
+ def update(status)
128
+ if status.length > 140
129
+ puts ""
130
+ puts "This status is too long."
131
+ puts ""
132
+ puts " #{status[0..139]}"
133
+ puts ""
134
+ else
135
+ Twitter.update(status)
136
+ end
137
+ end
138
+
139
+ desc "yaml", "Lists tweets from the timeline in YAML format."
140
+ def yaml
141
+ Tweetline.each_tweet do |tweet|
142
+ puts tweet.to_yaml
143
+ end
144
+ end
145
+ end
146
+ end
data/lib/tweetline.rb ADDED
@@ -0,0 +1,82 @@
1
+ require 'thor'
2
+ require 'twitter'
3
+ require 'json'
4
+
5
+ module Tweetline
6
+ class << self
7
+
8
+ def cat_tweet(tweet_id, created_at, name, screen_name, text)
9
+ Tweetline.put_tweet(tweet_id, created_at, name, screen_name, text)
10
+
11
+ tweet = Twitter.status(tweet_id)
12
+ puts "Conversation:", "" if tweet.in_reply_to_status_id
13
+ while tweet.in_reply_to_status_id
14
+ tweet = Twitter.status(tweet.in_reply_to_status_id)
15
+ Tweetline.put_tweet(tweet.id, tweet.created_at, tweet.user.name, tweet.user.screen_name, tweet.text)
16
+ end
17
+ end
18
+
19
+ def configure_twitter
20
+ Twitter.configure do |config|
21
+ File.open(File.expand_path('~/.tweetlinerc')) do |yaml|
22
+ options = YAML.load(yaml)
23
+ config.consumer_key = options[:consumer_key]
24
+ config.consumer_secret = options[:consumer_secret]
25
+ config.oauth_token = options[:oauth_token]
26
+ config.oauth_token_secret = options[:oauth_token_secret]
27
+ end
28
+ end
29
+ end
30
+
31
+ def configure_pipes
32
+ STDOUT.sync = true
33
+ end
34
+
35
+ def each_tweet(options={:count => 10})
36
+ if STDIN.fcntl(Fcntl::F_GETFL, 0) == 0
37
+ STDIN.each do |line|
38
+ yield JSON.load(line)
39
+ end
40
+ else
41
+ if options[:screen_name]
42
+ screen_name = options.delete(:screen_name)
43
+ timeline = Twitter.user_timeline(screen_name, options)
44
+ else
45
+ timeline = Twitter.home_timeline(options)
46
+ end
47
+ timeline.each do |tweet|
48
+ yield({"id" => tweet.id, "created_at" => tweet.created_at, "name" => tweet.user.name, "screen_name" => tweet.user.screen_name, "text" => tweet.text})
49
+ end
50
+ end
51
+ end
52
+
53
+ def is_piped_to_tweetline?
54
+ @is_piped_to_tweetline |= `ps -ax -o pid,args | grep -E "^[ ]*#{Process.pid+1}"` =~ /\/tl[^\/]*$/
55
+ end
56
+
57
+ def put_tweet(tweet_id, created_at, name, screen_name, text)
58
+ if STDOUT.fcntl(Fcntl::F_GETFL, 0) == 1 and Tweetline.is_piped_to_tweetline?
59
+ puts({"id" => tweet_id, "created_at" => created_at, "name" => name, "screen_name" => screen_name, "text" => text}.to_json)
60
+ else
61
+ puts "#{name} (@#{screen_name}) [#{time_stamp(created_at)}]", " #{text} (#{tweet_id})", ""
62
+ end
63
+ end
64
+
65
+ def say_tweet(tweet_id, created_at, name, screen_name, text)
66
+ tweet_text = text.strip.gsub(/http:.*?( |$)/, '').gsub(/^RT/, '').gsub(/@/, '').split(/ /).map{|s| s.gsub(/[^A-Za-z0-9.!?,']/, '')}.join(' ')
67
+ connector = text.strip =~ /^RT/ ? " retweets " : "says"
68
+ # puts name, " #{connector} #{tweet_text}", ""
69
+ Tweetline.put_tweet(tweet_id, created_at, name, screen_name, text)
70
+ `say #{name} #{connector} "#{tweet_text}"`
71
+ end
72
+
73
+ def time_stamp(time)
74
+ time = Time.parse(time)
75
+ format = '%I:%M %p'
76
+ format = '%m/%d/%y ' + format unless time.yday == Time.now.yday
77
+
78
+ return time.strftime(format)
79
+ end
80
+
81
+ end
82
+ end
data/tweetline.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ Gem::Specification.new do |s|
2
+ s.platform = Gem::Platform::RUBY
3
+ s.name = "tweetline"
4
+ s.version = "0.0.4"
5
+ s.summary = "Command line client for Twitter."
6
+ s.description = "Tweetline is a command line Twitter client for those who can't imagine a better interface to anything than the command line. Also, some folks may find it useful for automating Twitter interactions."
7
+
8
+ s.required_ruby_version = ">= 1.8.7"
9
+ s.required_rubygems_version = ">= 1.3.6"
10
+
11
+ s.author = "Anthony Crumley"
12
+ s.email = "anthony.crumley@gmail.com"
13
+ s.homepage = "https://github.com/craftycode/tweetline"
14
+ s.rubyforge_project = "tweetline"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test}/*`.split("\n")
18
+
19
+ s.bindir = "bin"
20
+ s.executables = ["tl"]
21
+ s.default_executable = "tl"
22
+ s.require_paths = ['lib']
23
+
24
+ s.add_dependency('twitter', '~> 1.2.0')
25
+ s.add_dependency('json', '~> 1.5.1')
26
+ s.add_dependency('thor', '~> 0.14.6')
27
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tweetline
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
9
+ - 4
10
+ version: 0.0.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Anthony Crumley
@@ -75,7 +75,13 @@ extensions: []
75
75
  extra_rdoc_files: []
76
76
 
77
77
  files:
78
+ - .gitignore
79
+ - MIT-LICENSE
80
+ - README.rdoc
78
81
  - bin/tl
82
+ - lib/tweetline.rb
83
+ - lib/tweetline/cli.rb
84
+ - tweetline.gemspec
79
85
  has_rdoc: true
80
86
  homepage: https://github.com/craftycode/tweetline
81
87
  licenses: []