tweetline 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []