tweeter-bachue 0.0.1 → 0.0.2

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/README.md CHANGED
@@ -44,13 +44,13 @@ Then please edit them:
44
44
  1. Edit `config/key.yml`
45
45
  2. Replace with your consumer key/secret, oauth token, oauth token secret (google if you need help)
46
46
  3. Then edit `config/proxies.yml`
47
- 4. Add all your proxies info into this file. in this file, host, port and user are related to the ssh account, and gemset and path is related to `tweet` command
47
+ 4. Add all your proxies info into this file. in this file, host, port and user are related to the ssh account, and gemset and path is related to `tweet` command(To be security, password is totally forbidden)
48
48
  5. Don't forget to install and config `tweeter-bachue` in all your proxies in the same way
49
49
  6. You'd better delete `proxies.yml` if you haven't any proxy
50
50
 
51
51
  After all, try:
52
52
 
53
- $ tweet "This is my 'hello world', sent from `tweet-bachue` gem"
53
+ $ tweet "This is my 'hello world', sent from 'tweet-bachue' gem"
54
54
 
55
55
  `tweeter-bachue` will try to tweet it by itself. if it failed for 3 times, will try the same command on each of your proxies by ssh one by one, until anyone of them puts "Succeed". when the `tweeter-bachue` in your proxies failed for 3 times, it will also do the same thing, try its proxies.
56
56
 
@@ -58,7 +58,7 @@ If all tries are failed, `tweeter-bachue` will write the tweet in a file which i
58
58
 
59
59
  ## Contributing
60
60
 
61
- 1. Fork it from <https://gitcafe.com/bachue/tweeter.git>
61
+ 1. Fork it from `git@gitcafe.com:bachue/tweeter.git`
62
62
  2. Create your feature branch (`git checkout -b my-new-feature`)
63
63
  3. Commit your changes (`git commit -am 'Add some feature'`)
64
64
  4. Push to the branch (`git push origin my-new-feature`)
data/bin/tweet CHANGED
@@ -4,44 +4,127 @@ require 'rubygems'
4
4
  require 'twitter'
5
5
  require 'yaml'
6
6
  require 'socket'
7
+ require 'net/ssh'
7
8
  require 'active_support/all'
8
9
 
9
- def lost_file_name(path)
10
- name = Time.now.to_f.to_s.sub('.', '') + '.tweet'
11
- File.join(path, name)
12
- end
13
-
14
- if ARGV.first.downcase == 'proxy'
15
- is_proxy = true
16
- ARGV.shift
17
- end
18
-
19
- tweet = ARGV.join(' ')
20
-
21
- exit if tweet.blank?
22
-
23
- root_dir = File.expand_path File.join(File.dirname(__FILE__), '..')
24
- config_dir = File.join(root_dir, 'config')
25
- lost_dir = File.join(root_dir, 'lost')
26
- client_info = YAML.load_file(File.join(config_dir, 'key.yml')).symbolize_keys
27
- proxies_info = YAML.load_file(File.join(config_dir, 'proxies.yml')).map(&:symbolize_keys) rescue []
28
-
29
- @client = Twitter::Client.new(client_info)
30
- retry_count = 0
31
- begin
32
- retry_count += 1
33
- @client.update(tweet)
34
- puts 'Succeed'
35
- rescue
36
- retry if retry_count < 3
37
- puts "Failed to tweet by #{Socket.gethostname}, ask the proxies"
38
- proxies_info = proxies_info.map { |proxy| [proxy[:host], proxy[:port], proxy[:user], proxy[:path], proxy[:gemset]] }
39
- catch(:succ) {
40
- proxies_info.each { |host, port, user, path, gemset|
41
- puts input = "ssh #{"#{user}@" if user.present?}#{host} #{"-p #{port}" if port.present?} \"#{"rvm use #{gemset} &&" if gemset.present?} #{path.present? ? path : 'tweet' } proxy '#{tweet}'\""
42
- puts output = system(input) rescue next
43
- throw :succ if output =~ /Succeed/
10
+ URL_REGEX = /((http|https):\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?/ix
11
+ TWEET_MAX_LENGTH = 150 # The real value is 140, but set 150 here because the length limitation function is not exact
12
+ SHORT_URL_LENGTH = 23
13
+
14
+ def start!
15
+ exit_if_no_args!
16
+ set_proxy_if_it_is!
17
+ exit_if_invalid!(tweet)
18
+ twitter(tweet)
19
+ end
20
+
21
+ def twitter(tweet)
22
+ retry_count = 0
23
+ begin
24
+ retry_count += 1
25
+ client.update(tweet)
26
+ puts 'Succeed'
27
+ rescue
28
+ return if can_handle?
29
+ retry if retry_count < 3
30
+ puts "Failed to tweet by #{Socket.gethostname}, ask the proxies"
31
+ catch(:succ) {
32
+ proxies_info.each { |proxy|
33
+ remote_twitter proxy[:host], proxy[:port], proxy[:user], proxy[:path], proxy[:gemset]
34
+ }
35
+ File.write(lost_file, tweet) unless $is_proxy # reach here means failed in all proxies
36
+ exit 1
44
37
  }
45
- File.open(lost_file_name(lost_dir), 'w') { |f| f << tweet } unless is_proxy
38
+ end
39
+ end
40
+
41
+ def remote_twitter(host, port, user, path, gemset)
42
+ options = {:keys_only => true, :compression => true} # Password is forbidden here
43
+ options.merge! :port => port if port.present?
44
+ output = Net::SSH.start(host, user, :keys_only => true) { |ssh|
45
+ ssh.exec! <<-SHELL
46
+ #{"rvm use #{gemset} &&" if gemset.present?}
47
+ #{path.present? ? path : 'tweet'} proxy #{tweet.dump}
48
+ SHELL
46
49
  }
50
+ throw :succ if output =~ /Succeed/
51
+ end
52
+
53
+ def can_handle?
54
+ case $!.message
55
+ when /Status is a duplicate/
56
+ puts 'Succeed'
57
+ true
58
+ when /Could not authenticate you/
59
+ puts 'Failed to authenticate'
60
+ exit 4
61
+ when /Status is over \d+ characters/
62
+ puts 'Too long'
63
+ exit 3
64
+ else
65
+ false
66
+ end
67
+ end
68
+
69
+ def exit_if_invalid!(tweet)
70
+ unless valid?(tweet)
71
+ puts 'Too long'
72
+ exit 3
73
+ end
74
+ end
75
+
76
+ def valid?(tweet)
77
+ tweet.gsub(URL_REGEX, '*' * SHORT_URL_LENGTH).size <= TWEET_MAX_LENGTH
78
+ end
79
+
80
+ def exit_if_no_args!
81
+ exit 2 if ARGV.blank?
82
+ end
83
+
84
+ def set_proxy_if_it_is!
85
+ if ARGV.first.downcase == 'proxy'
86
+ $is_proxy = true
87
+ ARGV.shift
88
+ end
89
+ end
90
+
91
+ def tweet
92
+ @tweet ||= ARGV.join(' ')
47
93
  end
94
+
95
+ def lost_file
96
+ name = Time.now.to_f.to_s.sub('.', '') + '.tweet'
97
+ lost_path(name)
98
+ end
99
+
100
+ def root_path(filename = nil)
101
+ file = File.expand_path File.join(File.dirname(__FILE__), '..')
102
+ file = File.join(file, filename) if filename.present?
103
+ file
104
+ end
105
+
106
+ def config_path(filename = nil)
107
+ file = root_path('config')
108
+ file = File.join(file, filename) if filename.present?
109
+ file
110
+ end
111
+
112
+ def lost_path(filename = nil)
113
+ file = root_path('lost')
114
+ file = File.join(file, filename) if filename.present?
115
+ file
116
+ end
117
+
118
+ def client_info
119
+ @client_info ||= YAML.load_file(config_path('key.yml')).symbolize_keys
120
+ end
121
+
122
+ def proxies_info
123
+ @proxies_info ||= YAML.load_file(config_path('proxies.yml')).map(&:symbolize_keys) rescue []
124
+ end
125
+
126
+ def client
127
+ @client ||= Twitter::Client.new(client_info)
128
+ end
129
+
130
+ start!
@@ -1,3 +1,3 @@
1
1
  module Tweeter
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -19,6 +19,7 @@ Gem::Specification.new do |gem|
19
19
  gem.add_dependency 'twitter'
20
20
  gem.add_dependency 'activesupport', '>= 3.0.0'
21
21
  gem.add_dependency 'rake'
22
+ gem.add_dependency 'net-ssh'
22
23
  gem.add_development_dependency 'pry'
23
24
  gem.add_development_dependency 'pry-doc'
24
25
  gem.add_development_dependency 'pry-nav'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tweeter-bachue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-12 00:00:00.000000000 Z
12
+ date: 2013-01-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: twitter
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: net-ssh
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
62
78
  - !ruby/object:Gem::Dependency
63
79
  name: pry
64
80
  requirement: !ruby/object:Gem::Requirement
@@ -157,7 +173,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
173
  version: '0'
158
174
  segments:
159
175
  - 0
160
- hash: -2088777374129425809
176
+ hash: 670411791857878890
161
177
  required_rubygems_version: !ruby/object:Gem::Requirement
162
178
  none: false
163
179
  requirements:
@@ -166,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
182
  version: '0'
167
183
  segments:
168
184
  - 0
169
- hash: -2088777374129425809
185
+ hash: 670411791857878890
170
186
  requirements: []
171
187
  rubyforge_project:
172
188
  rubygems_version: 1.8.24