flumtter 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/CODE_OF_CONDUCT.md +74 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +41 -0
  7. data/Rakefile +2 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/exe/flumtter +5 -0
  11. data/flumtter.gemspec +31 -0
  12. data/lib/flumtter.rb +2 -0
  13. data/lib/flumtter/app/core/account_selector.rb +88 -0
  14. data/lib/flumtter/app/core/client.rb +148 -0
  15. data/lib/flumtter/app/core/command.rb +24 -0
  16. data/lib/flumtter/app/core/command/dm.rb +12 -0
  17. data/lib/flumtter/app/core/command/tweet.rb +24 -0
  18. data/lib/flumtter/app/core/command/user.rb +52 -0
  19. data/lib/flumtter/app/core/command/userlist.rb +8 -0
  20. data/lib/flumtter/app/core/core.rb +58 -0
  21. data/lib/flumtter/app/core/curses.rb +90 -0
  22. data/lib/flumtter/app/core/hash.rb +29 -0
  23. data/lib/flumtter/app/core/initializer.rb +28 -0
  24. data/lib/flumtter/app/core/keyboard.rb +54 -0
  25. data/lib/flumtter/app/core/plugins.rb +27 -0
  26. data/lib/flumtter/app/core/string.rb +148 -0
  27. data/lib/flumtter/app/core/terminal.rb +13 -0
  28. data/lib/flumtter/app/core/thread.rb +29 -0
  29. data/lib/flumtter/app/core/toast.rb +26 -0
  30. data/lib/flumtter/app/core/util.rb +107 -0
  31. data/lib/flumtter/app/core/windows/base.rb +16 -0
  32. data/lib/flumtter/app/core/windows/buf_window.rb +194 -0
  33. data/lib/flumtter/app/core/windows/dialog.rb +62 -0
  34. data/lib/flumtter/app/core/windows/dmbase.rb +28 -0
  35. data/lib/flumtter/app/core/windows/dynamic_view.rb +43 -0
  36. data/lib/flumtter/app/core/windows/favorite.rb +31 -0
  37. data/lib/flumtter/app/core/windows/follower.rb +20 -0
  38. data/lib/flumtter/app/core/windows/following.rb +20 -0
  39. data/lib/flumtter/app/core/windows/mention.rb +29 -0
  40. data/lib/flumtter/app/core/windows/popup.rb +35 -0
  41. data/lib/flumtter/app/core/windows/tweet.rb +31 -0
  42. data/lib/flumtter/app/core/windows/tweetbase.rb +24 -0
  43. data/lib/flumtter/app/core/windows/userbase.rb +43 -0
  44. data/lib/flumtter/app/main.rb +3 -0
  45. data/lib/flumtter/app/plugins/commands.rb +15 -0
  46. data/lib/flumtter/app/plugins/commands/account_changer.rb +9 -0
  47. data/lib/flumtter/app/plugins/commands/change_profile.rb +69 -0
  48. data/lib/flumtter/app/plugins/commands/conversation.rb +39 -0
  49. data/lib/flumtter/app/plugins/commands/delete.rb +26 -0
  50. data/lib/flumtter/app/plugins/commands/directmessage.rb +35 -0
  51. data/lib/flumtter/app/plugins/commands/directmessages.rb +33 -0
  52. data/lib/flumtter/app/plugins/commands/favorite.rb +22 -0
  53. data/lib/flumtter/app/plugins/commands/mention.rb +7 -0
  54. data/lib/flumtter/app/plugins/commands/new_tweet.rb +17 -0
  55. data/lib/flumtter/app/plugins/commands/reply.rb +26 -0
  56. data/lib/flumtter/app/plugins/commands/retweet.rb +30 -0
  57. data/lib/flumtter/app/plugins/commands/unfavorite.rb +26 -0
  58. data/lib/flumtter/app/plugins/commands/user.rb +77 -0
  59. data/lib/flumtter/app/plugins/commands/utility.rb +17 -0
  60. data/lib/flumtter/app/plugins/load.rb +16 -0
  61. data/lib/flumtter/app/plugins/pry.rb +12 -0
  62. data/lib/flumtter/app/plugins/timeline.rb +42 -0
  63. data/lib/flumtter/app/plugins/timeline/base.rb +74 -0
  64. data/lib/flumtter/app/plugins/timeline/deleted_tweet.rb +23 -0
  65. data/lib/flumtter/app/plugins/timeline/dm.rb +23 -0
  66. data/lib/flumtter/app/plugins/timeline/event.rb +11 -0
  67. data/lib/flumtter/app/plugins/timeline/fav.rb +43 -0
  68. data/lib/flumtter/app/plugins/timeline/tweet.rb +51 -0
  69. data/lib/flumtter/app/plugins/toast.rb +45 -0
  70. data/lib/flumtter/version.rb +3 -0
  71. metadata +213 -0
@@ -0,0 +1,26 @@
1
+ module Flumtter
2
+ plugin do
3
+ def delete(obj, twitter)
4
+ if obj.user.id == twitter.account.id
5
+ begin
6
+ twitter.rest.destroy_status(obj.id)
7
+ rescue Twitter::Error::NotFound => e
8
+ raise ExecutedError, e.message
9
+ end
10
+ else
11
+ raise ExecutedError, "You may not delete another user's status."
12
+ end
13
+ end
14
+
15
+ Keyboard.add("k", "Delete") do |m,twitter|
16
+ error_handler do
17
+ obj, _ = index_with_dialog(m[1], "Delete Screen", <<~EOF)
18
+ Please input target index.
19
+ EOF
20
+ if_tweet(obj, twitter) do |tweet|
21
+ delete(tweet, twitter)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ module Flumtter
2
+ plugin do
3
+ def directmessage(user, text, twitter)
4
+ case user
5
+ when Twitter::User
6
+ twitter.rest.create_direct_message(user.id, text)
7
+ else
8
+ twitter.rest.create_direct_message(user, text)
9
+ end
10
+ end
11
+
12
+ Keyboard.add("d", "Direct Message") do |m, twitter|
13
+ error_handler do
14
+ obj, m2 = index_with_dialog(m[1], "DirectMessage Screen", <<~EOF, true)
15
+ Please input target (index or screen_name) and DM content.
16
+ Syntax: '\#{index} \#{content}'
17
+ EOF
18
+ raise NoContentError if m2.empty?
19
+
20
+ case obj
21
+ when Twitter::Tweet, Twitter::Streaming::Event
22
+ if_tweet(obj, twitter) do |tweet|
23
+ directmessage(tweet.user, m2, twitter)
24
+ end
25
+ when Twitter::DirectMessage
26
+ directmessage(obj.sender, m2, twitter)
27
+ when String
28
+ directmessage(obj, m2, twitter)
29
+ else
30
+ raise UnSupportError
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ module Flumtter
2
+ plugin do
3
+ class self::Buf < Window::Buf::Buf
4
+ Options = {count: 50}
5
+
6
+ def initialize(twitter)
7
+ @twitter = twitter
8
+ super(Window::DMBase)
9
+ end
10
+
11
+ def prefetch
12
+ adds(
13
+ @twitter.rest.direct_messages(
14
+ @buf.last.nil? ? Options : Options.merge(max_id: @buf.last.id-1)
15
+ )
16
+ )
17
+ end
18
+ end
19
+
20
+ class self::DirectMessage < Window::Buf::Screen
21
+ include Command::DM
22
+
23
+ def initialize(twitter)
24
+ super(Plugins::Directmessages::Buf.new(twitter), "#{twitter.account.screen_name}'s DirectMessages")
25
+ add_command(twitter)
26
+ end
27
+ end
28
+
29
+ Keyboard.add("b", "DirectMessages") do |m, twitter|
30
+ self::DirectMessage.new(twitter).show
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ module Flumtter
2
+ plugin do
3
+ def favorite(obj, twitter)
4
+ if obj.favorited?
5
+ raise ExecutedError, "already favorited"
6
+ else
7
+ twitter.rest.favorite(obj.id)
8
+ end
9
+ end
10
+
11
+ Keyboard.add("f", "Favorite") do |m,twitter|
12
+ error_handler do
13
+ obj, _ = index_with_dialog(m[1], "Favorite Screen", <<~EOF)
14
+ Please input target index.
15
+ EOF
16
+ if_tweet(obj, twitter) do |tweet|
17
+ favorite(tweet, twitter)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,7 @@
1
+ module Flumtter
2
+ plugin do
3
+ Keyboard.add("m", "Mention") do |m, twitter|
4
+ Window::Mention.new(twitter).show
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module Flumtter
2
+ plugin do
3
+ Keyboard.add("n", "New Tweet") do |m, twitter|
4
+ if m[1].empty?
5
+ dialog = Window::Dialog.new("Tweet Screen", <<~EOF)
6
+ Please input tweet content.
7
+ EOF
8
+ dialog.command(/(.+)/) do |m|
9
+ twitter.rest.update(m[1])
10
+ end
11
+ dialog.show(true, false)
12
+ else
13
+ twitter.rest.update(m[1])
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ module Flumtter
2
+ plugin do
3
+ def update(obj,text,twitter)
4
+ twitter.rest.update("@#{obj.user.screen_name} #{text}", :in_reply_to_status_id => obj.id)
5
+ end
6
+
7
+ Keyboard.add("r", "Reply") do |m, twitter|
8
+ error_handler do
9
+ obj, m2 = index_with_dialog(m[1], "Reply Screen", <<~EOF)
10
+ Please input target index and tweet content.
11
+ Syntax: '\#{index} \#{content}'
12
+ EOF
13
+ case obj
14
+ when Twitter::Tweet, Twitter::Streaming::Event
15
+ if_tweet(obj, twitter) do |tweet|
16
+ update(tweet, m2, twitter)
17
+ end
18
+ when Twitter::DirectMessage
19
+ twitter.rest.create_direct_message(obj.sender.id, m2)
20
+ else
21
+ raise UnSupportError
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ module Flumtter
2
+ plugin do
3
+ def retweet(obj, twitter)
4
+ if obj.retweeted?
5
+ raise ExecutedError, "already retweeted"
6
+ else
7
+ begin
8
+ twitter.rest.retweet(obj.id)
9
+ rescue Twitter::Error::Forbidden => e
10
+ if e.message == "You have already retweeted this tweet."
11
+ raise ExecutedError, "already retweeted"
12
+ else
13
+ raise e
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ Keyboard.add("t", "Retweet") do |m, twitter|
20
+ error_handler do
21
+ obj, _ = index_with_dialog(m[1], "Retweet Screen", <<~EOF)
22
+ Please input target index.
23
+ EOF
24
+ if_tweet(obj, twitter) do |tweet|
25
+ retweet(tweet, twitter)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ module Flumtter
2
+ plugin do
3
+ def unfavorite(obj, twitter)
4
+ begin
5
+ twitter.rest.unfavorite(obj.id)
6
+ rescue Twitter::Error::NotFound => e
7
+ if e.message == "No status found with that ID."
8
+ raise ExecutedError, "not favorited"
9
+ else
10
+ raise e
11
+ end
12
+ end
13
+ end
14
+
15
+ Keyboard.add("l", "UnFavorite") do |m,twitter|
16
+ error_handler do
17
+ obj, _ = index_with_dialog(m[1], "UnFavorite Screen", <<~EOF)
18
+ Please input target index.
19
+ EOF
20
+ if_tweet(obj, twitter) do |tweet|
21
+ unfavorite(tweet, twitter)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,77 @@
1
+ module Flumtter
2
+ plugin do
3
+ class self::Profile < Window::DynamicView
4
+ include Command::User
5
+
6
+ def initialize(object, twitter)
7
+ @twitter = twitter
8
+ parse(object)
9
+ super("#{@user.screen_name}'s profile", "")
10
+ @width = 60
11
+ dynamic_view do
12
+ user = twitter.rest.user(@user)
13
+ <<~EOF
14
+ #{mutual.rjust(@width - 3)}
15
+ #{profile(user)}
16
+
17
+ #{statistics(user)}
18
+ EOF
19
+ end
20
+ add_command(@user, twitter)
21
+ show(true)
22
+ end
23
+
24
+ private
25
+ def mutual
26
+ friendship = @twitter.rest.friendship(@twitter.account.id, @user)
27
+ following = friendship.source.following? ? ">" : "/"
28
+ follower = friendship.source.followed_by? ? "<": "/"
29
+ "@#{@twitter.account.screen_name} #{following}=#{follower} @#{@user.screen_name}"
30
+ end
31
+
32
+ def profile(user)
33
+ {
34
+ name: user.name,
35
+ description: user.description.split_num(44),
36
+ location: user.location,
37
+ url: user.website.to_s
38
+ }.indent
39
+ end
40
+
41
+ def statistics(user)
42
+ {
43
+ tweets: user.tweets_count,
44
+ follow: user.friends_count,
45
+ follower: user.followers_count,
46
+ favorite: user.favorites_count
47
+ }.indent
48
+ end
49
+
50
+ def parse(obj)
51
+ @user = case obj
52
+ when Twitter::Tweet
53
+ obj.user
54
+ when Twitter::DirectMessage
55
+ ob.sender
56
+ when Twitter::Streaming::Event
57
+ ob.source
58
+ when Twitter::Streaming::DeletedTweet
59
+ obj.user
60
+ when String
61
+ @twitter.rest.user(obj)
62
+ else
63
+ raise UnSupportError
64
+ end
65
+ end
66
+ end
67
+
68
+ Keyboard.add("p", "User Profile") do |m, twitter|
69
+ error_handler do
70
+ obj, _ = index_with_dialog(m[1], "Select User Screen", <<~EOF, true)
71
+ Please input target (index or screen_name) and DM content.
72
+ EOF
73
+ self::Profile.new(obj, twitter)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,17 @@
1
+ module Flumtter
2
+ plugin do
3
+ Keyboard.add("e", "Exit") do
4
+ puts "終了します".color
5
+ exit
6
+ end
7
+
8
+ Keyboard.add("q", "Clear Terminal Screen") do
9
+ print "\e[2J\e[f"
10
+ end
11
+
12
+ Keyboard.add("^", "Reconnection") do |m, twitter|
13
+ twitter.kill
14
+ twitter.start
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Flumtter
2
+ plugin do
3
+ add_opt do |opt, options|
4
+ opt.on('--timeline_load VALUE', 'load timeline num'){|v|options[:timeline_load] = v.to_i}
5
+ opt.on('--[no-]timeline_load?', 'load timeline on init'){|v|options[:timeline_load?] = v}
6
+ end
7
+
8
+ on_event(:init) do |twitter|
9
+ if Setting[:timeline_load?]
10
+ twitter.rest.home_timeline(count: Setting[:timeline_load] || 20).reverse_each do |object|
11
+ puts TimeLine::Tweet.new(object, twitter).to_s
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ module Flumtter
2
+ plugin do
3
+ add_opt do |opt, options|
4
+ opt.on('--pry', 'console mode'){|v|options[:pry] = v}
5
+ end
6
+
7
+ run_opt(:pry) do
8
+ binding.pry
9
+ exit
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,42 @@
1
+ module Flumtter
2
+ sarastire 'plugins/timeline'
3
+
4
+ plugin do
5
+ Client.on_event(:tweet) do |object, twitter|
6
+ type = object.type(twitter.account)
7
+ cls = if type.include?(:quote)
8
+ TimeLine::Quote
9
+ elsif type.include?(:retweet)
10
+ TimeLine::Retweet
11
+ elsif type.include?(:self_tweet)
12
+ TimeLine::SelfTweet
13
+ elsif type.include?(:reply_to_me)
14
+ TimeLine::ReplyTweet
15
+ else
16
+ TimeLine::Tweet
17
+ end
18
+ puts cls.new(object, twitter).to_s
19
+ end
20
+
21
+ Client.on_event(:event) do |object, twitter|
22
+ type = object.type(twitter.account)
23
+ cls = if type.include?(:favorite)
24
+ TimeLine::Favorite
25
+ elsif type.include?(:unfavorite)
26
+ TimeLine::UnFavorite
27
+ end
28
+ puts cls.new(object, twitter).to_s if cls
29
+ end
30
+
31
+ Client.on_event(:directmessage) do |object, twitter|
32
+ puts TimeLine::DirectMessage.new(object, twitter).to_s
33
+ end
34
+
35
+ Client.on_event(:deletedtweet) do |object, twitter|
36
+ begin
37
+ puts TimeLine::DeletedTweet.new(object, twitter).to_s
38
+ rescue TimeLine::DeletedTweet::TweetNotFound
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,74 @@
1
+ module Flumtter
2
+ module TimeLine
3
+ class Base
4
+ @@elements = []
5
+
6
+ def self.[](key)
7
+ @@elements[key]
8
+ end
9
+
10
+ def initialize(object, twitter)
11
+ @object = object
12
+ @twitter = twitter
13
+ @@elements << object
14
+ end
15
+
16
+ def to_s
17
+ text = <<~EOF.color(fg_color)
18
+ #{header}
19
+ #{user}
20
+ #{body}
21
+ #{footer}
22
+ EOF
23
+ bg_color.nil? ? text : text.background_color(bg_color)
24
+ end
25
+
26
+ private
27
+ def user
28
+ "#{@object.user.name} (@#{@object.user.screen_name})"
29
+ end
30
+
31
+ def color
32
+ :white
33
+ end
34
+
35
+ def fg_color
36
+ case color
37
+ when Symbol
38
+ color
39
+ when Array
40
+ color[0]
41
+ end
42
+ end
43
+
44
+ def bg_color
45
+ case color
46
+ when Symbol
47
+ nil
48
+ when Array
49
+ color[1]
50
+ end
51
+ end
52
+
53
+ def created_at
54
+ @object.created_at.strftime("%Y/%m/%d %H:%M:%S")
55
+ end
56
+
57
+ def index
58
+ @@elements.rindex(@object)
59
+ end
60
+
61
+ def header
62
+ "#{index} ".ljust(Terminal.x, ?-)
63
+ end
64
+
65
+ def body
66
+ @object.text.nl
67
+ end
68
+
69
+ def footer
70
+ "#{created_at}".ljust(Terminal.x, nil, @object.via)
71
+ end
72
+ end
73
+ end
74
+ end