pry-send_tweet.rb 0.6.0 → 0.7.0

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.
@@ -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