twterm 2.1.0 → 2.2.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.
- checksums.yaml +5 -5
- data/.travis.yml +4 -1
- data/lib/twterm.rb +1 -1
- data/lib/twterm/abstract_persistable_configuration.rb +118 -0
- data/lib/twterm/app.rb +21 -1
- data/lib/twterm/environment.rb +38 -0
- data/lib/twterm/event/message/abstract_message.rb +23 -0
- data/lib/twterm/event/message/error.rb +10 -0
- data/lib/twterm/event/message/info.rb +10 -0
- data/lib/twterm/event/message/success.rb +10 -0
- data/lib/twterm/event/message/warning.rb +10 -0
- data/lib/twterm/event/notification/abstract_notification.rb +17 -12
- data/lib/twterm/event/notification/direct_message.rb +30 -0
- data/lib/twterm/event/notification/favorite.rb +35 -0
- data/lib/twterm/event/notification/follow.rb +33 -0
- data/lib/twterm/event/notification/list_member_added.rb +33 -0
- data/lib/twterm/event/notification/mention.rb +35 -0
- data/lib/twterm/event/notification/quote.rb +35 -0
- data/lib/twterm/event/notification/retweet.rb +35 -0
- data/lib/twterm/key_mapper/abstract_key_mapper.rb +4 -4
- data/lib/twterm/list.rb +2 -1
- data/lib/twterm/message_window.rb +81 -0
- data/lib/twterm/notification_backend/abstract_notification_backend.rb +16 -0
- data/lib/twterm/notification_backend/inline_backend.rb +20 -0
- data/lib/twterm/notification_backend/terminal_notifier_backend.rb +23 -0
- data/lib/twterm/notification_backend/tmux_backend.rb +17 -0
- data/lib/twterm/notification_dispatcher.rb +36 -0
- data/lib/twterm/persistable_configuration_proxy.rb +82 -0
- data/lib/twterm/preferences.rb +66 -0
- data/lib/twterm/repository/abstract_expirable_entity_repository.rb +1 -1
- data/lib/twterm/rest_client.rb +12 -14
- data/lib/twterm/scheduler.rb +1 -1
- data/lib/twterm/screen.rb +1 -1
- data/lib/twterm/search_query_window.rb +2 -2
- data/lib/twterm/streaming_client.rb +54 -17
- data/lib/twterm/tab/base.rb +2 -3
- data/lib/twterm/tab/new/list.rb +2 -4
- data/lib/twterm/tab/new/start.rb +10 -0
- data/lib/twterm/tab/new/user.rb +2 -2
- data/lib/twterm/tab/preferences/index.rb +74 -0
- data/lib/twterm/tab/preferences/notification_backend.rb +85 -0
- data/lib/twterm/tab/scrollable.rb +0 -1
- data/lib/twterm/tab/searchable.rb +7 -7
- data/lib/twterm/tab/user_list_management.rb +3 -3
- data/lib/twterm/tab/user_tab.rb +6 -8
- data/lib/twterm/tab_manager.rb +4 -4
- data/lib/twterm/tweetbox.rb +1 -1
- data/lib/twterm/uri_opener.rb +2 -2
- data/lib/twterm/user.rb +2 -1
- data/lib/twterm/version.rb +1 -1
- data/twterm.gemspec +4 -2
- metadata +59 -14
- data/lib/twterm/event/favorite.rb +0 -18
- data/lib/twterm/event/follow.rb +0 -17
- data/lib/twterm/event/notification/error.rb +0 -13
- data/lib/twterm/event/notification/info.rb +0 -13
- data/lib/twterm/event/notification/success.rb +0 -13
- data/lib/twterm/event/notification/warning.rb +0 -13
- data/lib/twterm/notifier.rb +0 -82
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bce2d4276a631793204a44044b38afaa43f02d2c16bcc6daf68653288d1c5e12
|
4
|
+
data.tar.gz: e1307f6b9623eb96f2659406377888283d5a912fd30caf0d20737852a62e9b9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43c9cce69344a7e7cc8107793bc79f133ffe1ff134ec422eacbae4ae449661c0b57e7f6b15a241bb5d69db4c58d6bc22065badc9b85f1203bc29e130d8711fb9
|
7
|
+
data.tar.gz: fdad1dfb3aff8e7f66a94d00db63e5bd3d1e274072c17664e23ebb3de0a38dc26ebc2f9229f8172b14e84c1d71971cea05aba7ca9133eb7f537f03c33dbc8508
|
data/.travis.yml
CHANGED
data/lib/twterm.rb
CHANGED
@@ -26,7 +26,7 @@ require 'twterm/extensions/string'
|
|
26
26
|
require 'twterm/search_query_window'
|
27
27
|
require 'twterm/friendship'
|
28
28
|
require 'twterm/list'
|
29
|
-
require 'twterm/
|
29
|
+
require 'twterm/message_window'
|
30
30
|
require 'twterm/screen'
|
31
31
|
require 'twterm/scheduler'
|
32
32
|
require 'twterm/status'
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Twterm
|
2
|
+
# @abstract
|
3
|
+
class AbstractPersistableConfiguration
|
4
|
+
# @param [Hash<Symbol, Object>] configuration A hash object to initialize configuration
|
5
|
+
def initialize(configuration = {})
|
6
|
+
@configuration = configuration
|
7
|
+
end
|
8
|
+
|
9
|
+
# Gets a value associated to the given key.
|
10
|
+
# @abstract
|
11
|
+
def [](*)
|
12
|
+
raise NotImplementedError, '`#[]` method must be implemented'
|
13
|
+
end
|
14
|
+
|
15
|
+
# Sets the given value to the given key.
|
16
|
+
# @abstract
|
17
|
+
def []=(*)
|
18
|
+
raise NotImplementedError, '`#[]=` method must be implemented'
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the default instance for the configuration.
|
22
|
+
# @abstract
|
23
|
+
def self.default
|
24
|
+
raise NotImplementedError, '`.default` method must be implemented'
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Boolean]
|
28
|
+
def self.has_same_structure?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [self]
|
33
|
+
def complete_missing_items!
|
34
|
+
traverse(self.class.default.to_h) do |path, default_value|
|
35
|
+
value = dig(configuration, path)
|
36
|
+
|
37
|
+
if value.nil? || !(dig!(self.class.structure, path) === value)
|
38
|
+
bury!(path, default_value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
# Converts to a hash object.
|
46
|
+
#
|
47
|
+
# @abstract
|
48
|
+
# @return [Hash] Configuration as a hash
|
49
|
+
def to_h
|
50
|
+
raise NotImplementedError, '`#to_h` method must be implemented'
|
51
|
+
end
|
52
|
+
|
53
|
+
# A tree-like object representing the structure of the configuration.
|
54
|
+
# Each node must respond to {#===} method which determines whether a value is acceptable.
|
55
|
+
#
|
56
|
+
# @abstract
|
57
|
+
# @return [Hash] A tree-like hash object
|
58
|
+
def self.structure
|
59
|
+
raise NotImplementedError, '`.structure` method must be implemented'
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
attr_reader :configuration
|
65
|
+
|
66
|
+
def bury!(path, value)
|
67
|
+
go = lambda do |hash, rest_path|
|
68
|
+
k, *ks = rest_path
|
69
|
+
|
70
|
+
if ks.empty?
|
71
|
+
hash[k] = value
|
72
|
+
else
|
73
|
+
hash[k] = {} unless hash[k].is_a?(Hash)
|
74
|
+
go.call(hash[k], ks)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
go.call(configuration, path)
|
79
|
+
|
80
|
+
configuration
|
81
|
+
end
|
82
|
+
|
83
|
+
def dig(hash, path)
|
84
|
+
k, *ks = path
|
85
|
+
ks.empty? ? hash[k] : dig(hash[k], ks)
|
86
|
+
rescue NoMethodError
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
|
90
|
+
def dig!(hash, path)
|
91
|
+
k, *ks = path
|
92
|
+
ks.empty? ? hash[k] : dig(hash[k], ks)
|
93
|
+
rescue NoMethodError
|
94
|
+
raise ArgumentError, "path #{path} not found for hash #{hash}"
|
95
|
+
end
|
96
|
+
|
97
|
+
# Traverses tree-like {Hash} object and calls the given block on every node with its path
|
98
|
+
#
|
99
|
+
# @yieldparam [Array<Symbol>] path the path of the current node
|
100
|
+
# @yieldparam [Object] v the value of the current node
|
101
|
+
# @yieldreturn [void]
|
102
|
+
def traverse(tree, &f)
|
103
|
+
go = lambda do |subtree, current_path|
|
104
|
+
subtree.each do |k, v|
|
105
|
+
path = [*current_path, k]
|
106
|
+
|
107
|
+
if v.is_a?(Hash)
|
108
|
+
go.call(v, path)
|
109
|
+
else
|
110
|
+
f.call(path, v)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
go.call(tree, [])
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/twterm/app.rb
CHANGED
@@ -2,7 +2,12 @@ require 'curses'
|
|
2
2
|
|
3
3
|
require 'twterm/completion_manager'
|
4
4
|
require 'twterm/direct_message_composer'
|
5
|
+
require 'twterm/environment'
|
5
6
|
require 'twterm/event/screen/resize'
|
7
|
+
require 'twterm/message_window'
|
8
|
+
require 'twterm/notification_dispatcher'
|
9
|
+
require 'twterm/persistable_configuration_proxy'
|
10
|
+
require 'twterm/preferences'
|
6
11
|
require 'twterm/repository/direct_message_repository'
|
7
12
|
require 'twterm/repository/friendship_repository'
|
8
13
|
require 'twterm/repository/hashtag_repository'
|
@@ -17,10 +22,20 @@ module Twterm
|
|
17
22
|
class App
|
18
23
|
include Publisher
|
19
24
|
|
20
|
-
attr_reader :screen
|
25
|
+
attr_reader :environment, :preferences, :screen
|
21
26
|
|
22
27
|
DATA_DIR = "#{ENV['HOME']}/.twterm".freeze
|
23
28
|
|
29
|
+
def initialize
|
30
|
+
@environment = Environment.new
|
31
|
+
@preferences = Preferences.default
|
32
|
+
end
|
33
|
+
|
34
|
+
def load_preferences_from_file!
|
35
|
+
@preferences = PersistableConfigurationProxy
|
36
|
+
.load_from_file!(Preferences, "#{DATA_DIR}/preferences.toml")
|
37
|
+
end
|
38
|
+
|
24
39
|
def completion_manager
|
25
40
|
@completion_manager ||= CompletionManager.new(self)
|
26
41
|
end
|
@@ -50,11 +65,16 @@ module Twterm
|
|
50
65
|
|
51
66
|
Auth.authenticate_user(config) if config[:user_id].nil?
|
52
67
|
|
68
|
+
load_preferences_from_file!
|
69
|
+
|
53
70
|
KeyMapper.instance
|
54
71
|
|
55
72
|
@screen = Screen.new(self, client)
|
56
73
|
|
57
74
|
SearchQueryWindow.instance
|
75
|
+
MessageWindow.instance
|
76
|
+
|
77
|
+
@notification_dispatcher = NotificationDispatcher.new(preferences)
|
58
78
|
|
59
79
|
timeline = Tab::Statuses::Home.new(self, client)
|
60
80
|
tab_manager.add_and_show(timeline)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'terminal-notifier'
|
2
|
+
|
3
|
+
module Twterm
|
4
|
+
class Environment
|
5
|
+
def initialize
|
6
|
+
@uname = `uname`.strip
|
7
|
+
|
8
|
+
@terminal_notifier_available = TerminalNotifier.available?
|
9
|
+
@with_eog = system('which eog 2>&1 >/dev/null')
|
10
|
+
@with_tmux = system('which tmux 2>&1 >/dev/null') && !ENV['TMUX'].nil?
|
11
|
+
@with_qlmanage = system('which qlmanage 2>&1 >/dev/null')
|
12
|
+
end
|
13
|
+
|
14
|
+
def darwin?
|
15
|
+
@uname == 'Darwin'
|
16
|
+
end
|
17
|
+
|
18
|
+
def linux?
|
19
|
+
@uname == 'Linux'
|
20
|
+
end
|
21
|
+
|
22
|
+
def terminal_notifier_available?
|
23
|
+
@terminal_notifier_available
|
24
|
+
end
|
25
|
+
|
26
|
+
def with_eog?
|
27
|
+
@with_eog
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_qlmanage?
|
31
|
+
@with_qlmanage
|
32
|
+
end
|
33
|
+
|
34
|
+
def with_tmux?
|
35
|
+
@with_tmux
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'twterm/event/base'
|
2
|
+
|
3
|
+
module Twterm
|
4
|
+
module Event
|
5
|
+
module Message
|
6
|
+
class AbstractMessage < Twterm::Event::Base
|
7
|
+
attr_reader :time
|
8
|
+
|
9
|
+
def initialize(message)
|
10
|
+
super(CGI.unescapeHTML(message))
|
11
|
+
|
12
|
+
@time = Time.now
|
13
|
+
end
|
14
|
+
|
15
|
+
def fields
|
16
|
+
{
|
17
|
+
body: String
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -3,23 +3,28 @@ require 'twterm/event/base'
|
|
3
3
|
module Twterm
|
4
4
|
module Event
|
5
5
|
module Notification
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
# @abstract
|
7
|
+
class AbstractNotification < Event::Base
|
8
|
+
# @abstract
|
9
|
+
# @return [String] notification body
|
10
|
+
def body
|
11
|
+
raise NotImplementedError, '`body` must be implemented'
|
12
|
+
end
|
11
13
|
|
12
|
-
|
14
|
+
# @return [String] a fallback text
|
15
|
+
def fallback
|
16
|
+
"#{title}: #{body}"
|
13
17
|
end
|
14
18
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
+
# @abstract
|
20
|
+
# @return [String] notification title
|
21
|
+
def title
|
22
|
+
raise NotImplementedError, '`fallback` must be implemented'
|
19
23
|
end
|
20
24
|
|
21
|
-
|
22
|
-
|
25
|
+
# @return [String, nil] notification URL
|
26
|
+
def url
|
27
|
+
nil
|
23
28
|
end
|
24
29
|
end
|
25
30
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'twterm/event/notification/abstract_notification'
|
2
|
+
|
3
|
+
module Twterm
|
4
|
+
module Event
|
5
|
+
module Notification
|
6
|
+
class DirectMessage < AbstractNotification
|
7
|
+
# @param [Twterm::DirectMessage] message
|
8
|
+
# @param [Twterm::User] user
|
9
|
+
def initialize(message, user)
|
10
|
+
@message = message
|
11
|
+
@user = user
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [String] notification body
|
15
|
+
def body
|
16
|
+
message.text
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [String] notification title
|
20
|
+
def title
|
21
|
+
"@#{user.screen_name} has sent you a message"
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :message, :user
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'twterm/event/notification/abstract_notification'
|
2
|
+
|
3
|
+
module Twterm
|
4
|
+
module Event
|
5
|
+
module Notification
|
6
|
+
class Like < AbstractNotification
|
7
|
+
# @param [Twterm::Status] status
|
8
|
+
# @param [Twterm::User] user
|
9
|
+
def initialize(status, user)
|
10
|
+
@status = status
|
11
|
+
@user = user
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [String] notification body
|
15
|
+
def body
|
16
|
+
status.text
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [String] notification title
|
20
|
+
def title
|
21
|
+
"@#{user.screen_name} has liked your tweet"
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [String] notification url
|
25
|
+
def url
|
26
|
+
status.url
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :status, :user
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'twterm/event/notification/abstract_notification'
|
2
|
+
|
3
|
+
module Twterm
|
4
|
+
module Event
|
5
|
+
module Notification
|
6
|
+
class Follow < AbstractNotification
|
7
|
+
# @param [Twterm::User] user
|
8
|
+
def initialize(user)
|
9
|
+
@user = user
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [String] notification body
|
13
|
+
def body
|
14
|
+
user.description
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [String] notification title
|
18
|
+
def title
|
19
|
+
"@#{user.screen_name} has followed you"
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [String] notification url
|
23
|
+
def url
|
24
|
+
user.url
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :user
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|