pry-send_tweet.rb 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ module Pry::SendTweet::TwitterAction::SuggestedActions
2
+ def suggested_topics
3
+ suggested_topics = twitter.suggestions lang: suggested_lang
4
+ page numbered_list("Suggested topics: ", suggested_topics) {|topic, index|
5
+ "#{index}. #{topic.slug}"
6
+ }
7
+ end
8
+
9
+ def suggested_users(topic)
10
+ topic = URI.escape(topic)
11
+ users = twitter.suggestions(topic, lang: suggested_lang).users
12
+ page numbered_list("Suggested users: ", users) {|user, index|
13
+ display_followed_or_unfollowed(user, index)
14
+ }
15
+ end
16
+
17
+ def suggested_lang
18
+ opts['suggested-lang'] || 'en'
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ class Pry::SendTweet::TwitterSearch < Pry::SendTweet::BaseCommand
2
+ match 'twitter-search'
3
+ description 'Search Twitter for a given query.'
4
+ command_options argument_required: true, shellwords: false
5
+ banner <<-BANNER
6
+ twitter-search [options] query
7
+
8
+ #{description}
9
+ BANNER
10
+
11
+ def options(o)
12
+ o.on 'c=', 'count=', "The number of tweets to show. Default is #{Pry::SendTweet::DEFAULT_READ_SIZE}."
13
+ end
14
+
15
+ def process(query)
16
+ super
17
+ tweets = filter twitter.search(query, search_options).to_a
18
+ if tweets.empty?
19
+ page "No results to show."
20
+ else
21
+ q = bright_blue(bold(query))
22
+ render_tweets(tweets, title: format("Showing search results for %{q}", q: q))
23
+ end
24
+ end
25
+
26
+ private def filter(tweets)
27
+ tweets.reject(&:retweet?)
28
+ end
29
+
30
+ private def search_options
31
+ {count: opts['count'] || Pry::SendTweet::DEFAULT_READ_SIZE, tweet_mode: 'extended'}
32
+ end
33
+
34
+ Pry.commands.add_command self
35
+ end
@@ -0,0 +1,78 @@
1
+ module Pry::SendTweet::TweetRenderer
2
+ include Timeout
3
+
4
+ def render_tweets(fetch_tweets, title:, timeout: _pry_.config.twitter.refresh_interval)
5
+ timeout = _pry_.config.twitter.refresh_interval
6
+ interval = if timeout == false
7
+ nil
8
+ else
9
+ timeout || (60*5)
10
+ end
11
+ pid = nil
12
+ timeout(interval) do
13
+ pid = Kernel.fork do
14
+ _pry_.pager.open do |pager|
15
+ __trap_signal(pager)
16
+ tweets = Proc === fetch_tweets ? fetch_tweets.call : fetch_tweets
17
+ tweets.empty? ? pager.write("No tweets to show.") :
18
+ pager.write(__render_tweets(title, tweets))
19
+
20
+ end
21
+ end
22
+ Process.wait(pid)
23
+ end
24
+ rescue Interrupt
25
+ __kill_pager!(pid)
26
+ system 'reset'
27
+ rescue Timeout::Error
28
+ __kill_pager!(pid)
29
+ system 'reset'
30
+ retry
31
+ end
32
+
33
+ def render_tweet(tweet)
34
+ line_width = _pry_.config.twitter.line_width || Pry::SendTweet::DEFAULT_LINE_WIDTH
35
+ text = tweet.attrs[:full_text] ? tweet.attrs[:full_text] : tweet.full_text
36
+ <<-TWEET.each_line.map{|s| s.chomp.strip}.join("\n")
37
+ #{render_tweet_title(tweet)}
38
+ #{tweet.url}
39
+ #{bold("-") * line_width}
40
+ #{word_wrap(CGI.unescapeHTML(text))}
41
+ TWEET
42
+ end
43
+
44
+ def render_tweet_title(tweet)
45
+ u = tweet.user
46
+ created_at = tweet.created_at.getlocal
47
+ <<-TWEET_TITLE.each_line.map{|s| s.chomp.strip}.join
48
+ #{bold("@#{u.screen_name}")}
49
+ #{bright_blue(" | ")}
50
+ #{created_at.ago.in_words}
51
+ #{bright_blue(" | ")}
52
+ #{created_at.strftime(time_format)}
53
+ TWEET_TITLE
54
+ end
55
+
56
+ private
57
+ # @api private
58
+ def __render_tweets(title, tweets)
59
+ title = bright_blue(bold((" " * 40) + title) + "\n\n")
60
+ title + tweets.map.with_index {|tweet, i|
61
+ "#{red bold('#')}#{red bold(i+1)}\n#{render_tweet(tweet)}"
62
+ }.join("\n\n")
63
+ end
64
+
65
+ # @api private
66
+ def __kill_pager!(pid)
67
+ Process.kill('SIGINT', pid)
68
+ end
69
+
70
+ # @api private
71
+ def __trap_signal(pager)
72
+ trap('SIGINT') {
73
+ # SimplePager does not have a PID, ignore NoMethodError
74
+ Process.kill('SIGKILL', pager.send(:pager).pid) rescue nil
75
+ Process.kill('SIGKILL', Process.pid)
76
+ }
77
+ end
78
+ end
@@ -1,5 +1,5 @@
1
1
  class Pry
2
2
  module SendTweet
3
- VERSION = '0.6.0'
3
+ VERSION = '0.7.0'
4
4
  end
5
5
  end
@@ -4,7 +4,7 @@ Gem::Specification.new do |spec|
4
4
  spec.version = Pry::SendTweet::VERSION
5
5
  spec.authors = ["Robert Gleeson"]
6
6
  spec.email = "trebor.g@protonmail.com"
7
- spec.summary = "Extends the Pry REPL with the capabilities of a Twitter client."
7
+ spec.summary = "A Twitter client for the Pry REPL."
8
8
  spec.description = spec.summary
9
9
  spec.homepage = "https://github.com/r-obert/pry-send_tweet.rb"
10
10
  spec.licenses = ["MIT"]
@@ -12,4 +12,5 @@ Gem::Specification.new do |spec|
12
12
  spec.files = Dir["Dockerfile", "Gemfile", "*.{txt,gemspec,md}", "lib/**/*.rb"]
13
13
  spec.add_runtime_dependency "pry", "~> 0.12"
14
14
  spec.add_runtime_dependency "twitter", "~> 6.0"
15
+ spec.add_runtime_dependency "time-lord", "~> 1.0"
15
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pry-send_tweet.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Gleeson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-30 00:00:00.000000000 Z
11
+ date: 2019-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -38,7 +38,21 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '6.0'
41
- description: Extends the Pry REPL with the capabilities of a Twitter client.
41
+ - !ruby/object:Gem::Dependency
42
+ name: time-lord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ description: A Twitter client for the Pry REPL.
42
56
  email: trebor.g@protonmail.com
43
57
  executables: []
44
58
  extensions: []
@@ -50,11 +64,18 @@ files:
50
64
  - LICENSE.txt
51
65
  - README.md
52
66
  - lib/pry-send_tweet.rb
53
- - lib/pry/send_tweet/base_command.rb
54
- - lib/pry/send_tweet/mixins/tweet_renderer.rb
55
- - lib/pry/send_tweet/read_tweets_command.rb
56
- - lib/pry/send_tweet/send_tweet_command.rb
57
- - lib/pry/send_tweet/twitter_action_command.rb
67
+ - lib/pry/send_tweet/commands/base_command.rb
68
+ - lib/pry/send_tweet/commands/read_tweets.rb
69
+ - lib/pry/send_tweet/commands/send_tweet.rb
70
+ - lib/pry/send_tweet/commands/twitter_action.rb
71
+ - lib/pry/send_tweet/commands/twitter_action/delete_tweet_actions.rb
72
+ - lib/pry/send_tweet/commands/twitter_action/follow_actions.rb
73
+ - lib/pry/send_tweet/commands/twitter_action/like_actions.rb
74
+ - lib/pry/send_tweet/commands/twitter_action/mute_actions.rb
75
+ - lib/pry/send_tweet/commands/twitter_action/profile_actions.rb
76
+ - lib/pry/send_tweet/commands/twitter_action/suggested_actions.rb
77
+ - lib/pry/send_tweet/commands/twitter_search.rb
78
+ - lib/pry/send_tweet/renderers/tweet_renderer.rb
58
79
  - lib/pry/send_tweet/version.rb
59
80
  - pry-send_tweet.gemspec
60
81
  homepage: https://github.com/r-obert/pry-send_tweet.rb
@@ -77,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
98
  version: '0'
78
99
  requirements: []
79
100
  rubyforge_project:
80
- rubygems_version: 2.7.7
101
+ rubygems_version: 2.7.8
81
102
  signing_key:
82
103
  specification_version: 4
83
- summary: Extends the Pry REPL with the capabilities of a Twitter client.
104
+ summary: A Twitter client for the Pry REPL.
84
105
  test_files: []
@@ -1,58 +0,0 @@
1
- module Pry::SendTweet::TweetRenderer
2
- include Timeout
3
-
4
- def render_tweets(fetch_tweets, title: , timeout: _pry_.config.twitter.refresh_interval)
5
- pid = nil
6
- refresh_interval = timeout == false ? (nil) : (timeout || 240)
7
- timeout(refresh_interval) do
8
- _pry_.pager.open do |pager|
9
- pid = pager.send(:pager).pid
10
- pager.write draw_tweets(
11
- title,
12
- Proc === fetch_tweets ? fetch_tweets.call : fetch_tweets
13
- )
14
- end
15
- end
16
- rescue Timeout::Error
17
- Process.kill 'SIGKILL', pid
18
- _pry_.output.puts bold(bright_yellow("\n\n** Refreshing Tweets **\n"))
19
- sleep 0.3
20
- system 'reset'
21
- retry
22
- end
23
-
24
- def render_tweet(tweet)
25
- text = tweet.attrs[:full_text] ? tweet.attrs[:full_text] : tweet.full_text
26
- <<-TWEET.each_line.map{|s| s.chomp.strip}.join("\n")
27
- #{tweet_title(tweet)}
28
- #{tweet.url}
29
- #{"-" * 80}
30
- #{word_wrap(CGI.unescapeHTML(text))}
31
- #{"-" * 80}
32
- TWEET
33
- end
34
-
35
- def tweet_title(tweet)
36
- if tweet.user
37
- u = tweet.user
38
- <<-TWEET_TITLE.each_line.map{|s| s.chomp.strip}.join
39
- @#{u.screen_name}
40
- #{bright_blue(" | ")}
41
- #{tweet_timestamp(tweet)}
42
- TWEET_TITLE
43
- end
44
- end
45
-
46
- def tweet_timestamp(tweet)
47
- tweet
48
- .created_at
49
- .getlocal
50
- .strftime("%-d %b %Y, %-I:%M%p")
51
- end
52
-
53
- def draw_tweets(heading, tweets)
54
- "#{heading}\n\n" + tweets.map.with_index {|tweet, i|
55
- "#{red bold('#')}#{red bold(i+1)}\n#{render_tweet(tweet)}"
56
- }.join("\n\n")
57
- end
58
- end
@@ -1,78 +0,0 @@
1
- class Pry::SendTweet::ReadTweets < Pry::SendTweet::BaseCommand
2
- DEFAULT_COUNT = 35
3
- match 'read-tweets'
4
- description "Read tweets"
5
- banner <<-B
6
- read-tweets [options]
7
-
8
- Read tweets from your timeline or the timeline of another user.
9
- B
10
-
11
- def options(o)
12
- o.on :t=,
13
- 'The username whose timeline you want to read.'
14
- o.on :c=,
15
- 'count=',
16
- 'The number of tweets to read. The maximum is 200.'
17
- o.on 'with-retweets',
18
- 'Include retweets.'
19
- o.on 'that-mention-me',
20
- 'Read tweets that @mention you.'
21
- o.on 'my-likes',
22
- 'Read tweets you have liked.'
23
- o.on 'liked-by=',
24
- 'The username whose likes you want to read.'
25
- end
26
-
27
- def process
28
- super
29
- case
30
- when opts.present?('liked-by') then render_user_likes(opts['liked-by'])
31
- when opts.present?('my-likes') then render_my_likes
32
- when opts.present?('that-mention-me') then render_tweets_that_mention_me
33
- else render_tweets_from_timeline(opts['t'])
34
- end
35
- end
36
-
37
- private
38
-
39
- def render_user_likes(str)
40
- sn = find_usernames_in(str).first
41
- asn = "@#{sn}"
42
- render_tweets ->() { client.favorites(sn, count: opts['count'] || DEFAULT_COUNT)},
43
- title: bright_white(bold("Tweets liked by #{bright_blue(asn)}"))
44
- end
45
-
46
- def render_my_likes
47
- render_tweets ->() { client.favorites(count: opts['count'] || DEFAULT_COUNT) },
48
- title: bright_blue(bold("Tweets liked by you"))
49
- end
50
-
51
- def render_tweets_that_mention_me
52
- render_tweets ->() { client.mentions(timeline_options) },
53
- title: bright_white(bold("Tweets that #{bright_blue('@mention')} #{bright_white(bold('you'))}"))
54
- end
55
-
56
- def render_tweets_from_timeline(target)
57
- render_tweets ->() {
58
- if target
59
- client.user_timeline(target, timeline_options)
60
- else
61
- client.home_timeline(timeline_options)
62
- end
63
- },
64
- title: target ?
65
- bright_white(bold("Tweets from #{bright_blue("@#{target}")}")) :
66
- bright_blue(bold('Twitter'))
67
- end
68
-
69
- def timeline_options
70
- {
71
- tweet_mode: 'extended',
72
- include_rts: opts.present?('with-retweets'),
73
- count: opts.present?('count') ? opts['count'] : DEFAULT_COUNT
74
- }
75
- end
76
-
77
- Pry.commands.add_command self
78
- end
@@ -1,96 +0,0 @@
1
- class Pry::SendTweet::SendTweetCommand < Pry::SendTweet::BaseCommand
2
- match 'send-tweet'
3
- description 'Send a tweet'
4
- command_options argument_required: false
5
- banner <<-BANNER
6
- send-tweet [options]
7
-
8
- Send a tweet.
9
- BANNER
10
-
11
- def options(opts)
12
- opts.on :f=,
13
- 'file=',
14
- 'A path to an image or other media to attach to a tweet'
15
- opts.on :r=,
16
- 'reply-to=',
17
- 'An absolute url to a tweet you want to reply to.'
18
- opts.on 'cowsay-text=',
19
- 'A string of text that "cowsay" will use.'
20
- opts.on 'cowsay-char=',
21
- 'Decides which character "cowsay" will use. Default is "cow".'
22
- end
23
-
24
- def process(args)
25
- super
26
- tweet = create_content_of_tweet
27
- if opts.present?(:file)
28
- media = File.new opts[:file], 'r'
29
- _pry_.output.puts client.update_with_media(tweet, media, tweet_options).url
30
- media.close
31
- else
32
- _pry_.output.puts client.update(tweet, tweet_options).url
33
- end
34
- end
35
-
36
- private
37
-
38
- def prepend_username_to_reply!(tweet_url, file)
39
- username = tweet_username_from(tweet_url)
40
- file.write "@#{username} "
41
- end
42
-
43
- def tweet_username_from(tweet_url)
44
- File.basename File.dirname(File.dirname(tweet_url))
45
- end
46
-
47
- def replying_to_other_tweet?
48
- opts.present?('reply-to')
49
- end
50
-
51
- def tweet_options
52
- options = {}
53
- options.merge!({
54
- in_reply_to_status_id: Integer(File.basename(opts['reply-to']))
55
- }) if replying_to_other_tweet?
56
- options
57
- end
58
-
59
- def create_content_of_tweet
60
- if opts.present?('cowsay-text')
61
- compose_tweet_with_cowsay
62
- else
63
- compose_tweet_with_editor
64
- end
65
- end
66
-
67
- def compose_tweet_with_editor
68
- Tempfile.open('pry-send_tweet--compose-tweet') do |file|
69
- if replying_to_other_tweet?
70
- # During experimentation I noticed that without prefixing who we are
71
- # replying to, the tweet we send will not be considered a reply even
72
- # with reply_to_status_id being set.
73
- prepend_username_to_reply!(opts['reply-to'], file)
74
- end
75
- file.rewind
76
- Pry::Editor.new(_pry_).invoke_editor(file.path, 0)
77
- file.read
78
- end
79
- end
80
-
81
- def compose_tweet_with_cowsay
82
- username = if replying_to_other_tweet?
83
- "@#{tweet_username_from(opts['reply-to'])} "
84
- end
85
- char = opts['cowsay-char'] || 'cow'
86
- txt = "#{username}#{opts['cowsay-text']}"
87
- `cowsay -f #{char.shellescape} #{txt.shellescape}`.tap do
88
- if !$?.success?
89
- raise Pry::CommandError,
90
- "Something went wrong. Is 'cowsay' installed?"
91
- end
92
- end
93
- end
94
-
95
- Pry.commands.add_command self
96
- end