Module: Termtter::Client

Defined in:
lib/plugins/l2.rb,
lib/plugins/me.rb,
lib/plugins/sl.rb,
lib/plugins/fib.rb,
lib/plugins/log.rb,
lib/plugins/say.rb,
lib/plugins/bomb.rb,
lib/plugins/cool.rb,
lib/plugins/exec.rb,
lib/plugins/clear.rb,
lib/plugins/devel.rb,
lib/plugins/grass.rb,
lib/plugins/group.rb,
lib/plugins/shell.rb,
lib/plugins/timer.rb,
lib/plugins/yhara.rb,
lib/plugins/yonda.rb,
lib/plugins/filter.rb,
lib/plugins/hatebu.rb,
lib/plugins/ignore.rb,
lib/plugins/otsune.rb,
lib/plugins/otsune.rb,
lib/plugins/primes.rb,
lib/plugins/random.rb,
lib/plugins/reblog.rb,
lib/plugins/scrape.rb,
lib/plugins/history.rb,
lib/plugins/outputz.rb,
lib/plugins/retweet.rb,
lib/plugins/reverse.rb,
lib/plugins/storage.rb,
lib/termtter/client.rb,
lib/plugins/addspace.rb,
lib/plugins/countter.rb,
lib/plugins/open_url.rb,
lib/plugins/uri-open.rb,
lib/plugins/quicklook.rb,
lib/plugins/fib_filter.rb,
lib/plugins/search_url.rb,
lib/plugins/typable_id.rb,
lib/plugins/multi_reply.rb,
lib/plugins/switch_user.rb,
lib/plugins/command_plus.rb,
lib/plugins/command_plus.rb,
lib/plugins/screen-notify.rb,
lib/plugins/system_status.rb,
lib/plugins/update_editor.rb,
lib/plugins/expand-tinyurl.rb,
lib/plugins/direct_messages.rb,
lib/plugins/update_timeline.rb,
lib/plugins/standard_plugins.rb,
lib/plugins/hatebu_and_update.rb

Class Method Summary collapse

Class Method Details

.add_filter(&b) ⇒ Object



32
33
34
# File 'lib/termtter/client.rb', line 32

def add_filter(&b)
  @filters << b
end

.add_task(*arg, &block) ⇒ Object



183
184
185
# File 'lib/termtter/client.rb', line 183

def add_task(*arg, &block)
  @task_manager.add_task(*arg, &block)
end

.alias_command(arg) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/plugins/command_plus.rb', line 12

def alias_command(arg)
  original, new = arg.split(/\s+/)
  if @commands[original.to_sym]
    @commands[new.to_sym] = @commands[original.to_sym].clone
    @commands[new.to_sym].name    = new.to_sym
    @commands[new.to_sym].aliases = []
    @commands[new.to_sym].help    = ''
    puts "alias '#{original}' to '#{new}'."
  else
    raise "#{original} command is not found."
  end
end

.apply_filters(statuses, event) ⇒ Object



121
122
123
124
125
126
127
# File 'lib/termtter/client.rb', line 121

def apply_filters(statuses, event)
    filtered = statuses.map(&:dup)
    @filters.each do |f|
      filtered = f.call(filtered, event)
    end
    filtered
end

.apply_filters_for_hook(statuses, hook_name) ⇒ Object



129
130
131
132
133
# File 'lib/termtter/client.rb', line 129

def apply_filters_for_hook(statuses, hook_name)
  # TODO
  filtered = statuses.map(&:dup)
  filtered
end

.call_commands(text, tw = nil) ⇒ Object

Raises:



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/termtter/client.rb', line 145

def call_commands(text, tw = nil)
  return if text.empty?

  command_found = false
  @commands.each do |key, command|
    next unless command.match?(text)
    command_found = true
    command_str, command_arg = Command.split_command_line(text)

    modified_arg = call_hooks(
                      "modify_arg_for_#{command.name.to_s}",
                      command_str,
                      command_arg) || command_arg || ''

    @task_manager.invoke_and_wait do
      begin
        call_hooks("pre_exec_#{command.name.to_s}", command, modified_arg)
        # exec command
        result = command.call(command_str, modified_arg, text)
        if result
          call_hooks("post_exec_#{command.name.to_s}", command_str, modified_arg, result)
        end
      rescue CommandCanceled
      end
    end
  end

  raise CommandNotFound, text unless command_found
end

.call_hooks(point, *args) ⇒ Object

return last hook return value



136
137
138
139
140
141
142
143
# File 'lib/termtter/client.rb', line 136

def call_hooks(point, *args)
  result = nil
  get_hooks(point).each {|hook|
    break if result == false # interrupt if hook return false
    result = hook.call(*args)
  }
  result
end

.clear_filterObject



36
37
38
# File 'lib/termtter/client.rb', line 36

def clear_filter
  @filters.clear
end

.default_loggerObject



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/termtter/client.rb', line 241

def default_logger
  logger = Logger.new(STDOUT)
  logger.formatter = lambda { |severity, time, progname, message|
    color =
      case severity
      when /^DEBUG/
        'blue'
      when /^INFO/
        'cyan'
      when /^WARN/
        'magenta'
      when /^ERROR/
        'red'
      when /^FATAL/
        'on_red'
      else
        'white'
      end
    TermColor.parse("<#{color}>" + TermColor.escape("[#{severity}] #{message}\n") + "</#{color}>")
  }
  logger
end

.delete_command(arg) ⇒ Object



4
5
6
7
8
9
10
# File 'lib/plugins/command_plus.rb', line 4

def delete_command(arg)
  if @commands.delete(arg.to_sym)
    puts "#{arg} command is deleted."
  else
    raise "#{arg} command is not found."
  end
end

.exitObject



187
188
189
190
191
192
# File 'lib/termtter/client.rb', line 187

def exit
  puts 'finalizing...'

  call_hooks(:exit)
  @task_manager.kill
end

.find_filter_candidates(a, b, filters) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/plugins/filter.rb', line 49

def self.find_filter_candidates(a, b, filters)
  if a.empty?
    filters.to_a
  else
    filters.grep(/^#{Regexp.quote a}/i)
  end.
  map {|u| b % u }
end

.find_group_candidates(a, b) ⇒ Object



19
20
21
22
23
# File 'lib/plugins/group.rb', line 19

def self.find_group_candidates(a, b)
  config.plugins.group.groups.keys.map {|k| k.to_s}.
    grep(/^#{Regexp.quote a}/).
    map {|u| b % u }
end

.find_plugin_candidates(a, b) ⇒ Object

Termtter reply command

== Usage
=== list
* 


500
501
502
503
504
# File 'lib/plugins/standard_plugins.rb', line 500

def self.find_plugin_candidates(a, b)
  public_storage[:plugins].
    grep(/^#{Regexp.quote a}/i).
    map {|u| b % u }
end

.find_status_ids(text) ⇒ Object



506
507
508
# File 'lib/plugins/standard_plugins.rb', line 506

def self.find_status_ids(text)
  public_storage[:status_ids].select {|id| /#{Regexp.quote(text)}/ =~ id.to_s}
end

.find_user_candidates(a, b) ⇒ Object



514
515
516
517
518
519
520
521
522
# File 'lib/plugins/standard_plugins.rb', line 514

def self.find_user_candidates(a, b)
  users = 
    if a.nil? || a.empty?
      public_storage[:users].to_a
    else
      public_storage[:users].grep(/^#{Regexp.quote a}/i)
    end
  users.map {|u| b % u }
end

.find_users(text) ⇒ Object



510
511
512
# File 'lib/plugins/standard_plugins.rb', line 510

def self.find_users(text)
  public_storage[:users].select {|user| /^#{Regexp.quote(text)}/ =~ user}
end

.formatted_help(helps) ⇒ Object



324
325
326
327
328
329
330
331
# File 'lib/plugins/standard_plugins.rb', line 324

def self.formatted_help(helps)
  helps = helps.sort_by {|help| help[0] }
  width = helps.map {|n, _| n.size }.max
  space = 3
  helps.map {|name, desc|
    name.to_s.ljust(width + space) + desc.to_s
  }.join("\n")
end

.get_command(name) ⇒ Object



74
75
76
# File 'lib/termtter/client.rb', line 74

def get_command(name)
  @commands[name]
end

.get_command_completion_procObject



78
79
80
81
82
83
84
85
86
# File 'lib/termtter/client.rb', line 78

def get_command_completion_proc()
  lambda {|input|
    begin
      @commands.map {|name, command| command.complement(input) }.flatten.compact
    rescue => e
      handle_error(e)
    end
  }
end

.get_group_of(screen_name) ⇒ Object



25
26
27
# File 'lib/plugins/group.rb', line 25

def self.get_group_of(screen_name)
  config.plugins.group.groups.select{ |k, v| v.include? screen_name}.map{|a| a.first}
end

.get_hook(name) ⇒ Object



52
53
54
# File 'lib/termtter/client.rb', line 52

def get_hook(name)
  @hooks[name]
end

.get_hooks(point) ⇒ Object



56
57
58
59
60
# File 'lib/termtter/client.rb', line 56

def get_hooks(point)
  @hooks.values.select do |hook|
    hook.match?(point)
  end
end

.handle_error(e) ⇒ Object



289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/termtter/client.rb', line 289

def handle_error(e)
  if logger
    logger.error("#{e.class.to_s}: #{e.message}")
    logger.error(e.backtrace.join("\n")) if config.devel
  else
    raise e
  end
  get_hooks(:on_error).each {|hook| hook.call(e) }
rescue Exception => e
  puts "Error: #{e}"
  puts e.backtrace.join("\n")
end

.initObject



15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/termtter/client.rb', line 15

def init
  @hooks = {}
  @commands = {}
  @filters = []
  @since_id = nil
  @task_manager = Termtter::TaskManager.new
  config.set_default(:logger, nil)
  config.set_default(:update_interval, 300)
  config.set_default(:prompt, '> ')
  config.set_default(:devel, false)
  Thread.abort_on_exception = true
end

.input_editorObject



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/plugins/update_editor.rb', line 14

def self.input_editor
  file = Tempfile.new('termtter')
  editor = config.plugins.update_editor.editor
  if config.plugins.update_editor.add_completion
    file.puts "\n"*100 + "__END__\n" + public_storage[:users].to_a.join(' ')
  end
  file.close
  system("#{editor} #{file.path}")
  result = file.open.read
  file.close(false)
  result
end

.legacy_config_supportObject



208
209
210
211
212
213
214
215
# File 'lib/termtter/client.rb', line 208

def legacy_config_support
  case File.ftype(File.expand_path('~/.termtter'))
  when 'directory'
    # nop
  when 'file'
    move_legacy_config_file
  end
end

.load_configObject



199
200
201
202
203
204
205
206
# File 'lib/termtter/client.rb', line 199

def load_config
  legacy_config_support() if File.exist? Termtter::CONF_DIR
  unless File.exist?(Termtter::CONF_FILE)
    require 'termtter/config_setup'
    ConfigSetup.run
  end
  load Termtter::CONF_FILE
end

.load_default_pluginsObject



194
195
196
197
# File 'lib/termtter/client.rb', line 194

def load_default_plugins
  plugin 'standard_plugins'
  plugin 'stdout'
end

.load_historyObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/plugins/history.rb', line 17

def self.load_history
  filename = File.expand_path(config.plugins.history.filename)
  keys = config.plugins.history.keys

  if File.exist?(filename)
    begin
      history = Marshal.load Zlib::Inflate.inflate(File.read(filename))
    end
    if history
      keys.each do |key|
        public_storage[key] = history[key] if history[key]
      end
      Readline::HISTORY.push *history[:history] if history[:history]
      puts "history loaded(#{File.size(filename)/1000}kb)"
    end
  end
end

.loggerObject



233
234
235
# File 'lib/termtter/client.rb', line 233

def logger
  @logger
end

.move_legacy_config_fileObject



217
218
219
220
221
222
223
224
225
# File 'lib/termtter/client.rb', line 217

def move_legacy_config_file
  FileUtils.mv(
    Termtter::CONF_DIR,
    File.expand_path('~/.termtter___'))
  Dir.mkdir(Termtter::CONF_DIR)
  FileUtils.mv(
    File.expand_path('~/.termtter___'),
    Termtter::CONF_FILE)
end

.open_uri(uri) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/plugins/open_url.rb', line 6

def self.open_uri(uri)
  unless config.plugins.open_url.browser.empty?
    system config.plugins.open_url.browser, uri
  else
    case RUBY_PLATFORM
    when /linux/
      system 'firefox', uri
    when /mswin(?!ce)|mingw|bccwin/
      system 'explorer', uri
    else
      system 'open', uri
    end
  end
end

.output(statuses, event) ⇒ Object

statuses => [status, status, …] status => {

  :id => status id,
  :created_at => created time,
  :user_id => user id,
  :name => user name,
  :screen_name => user screen_name,
  :source => source,
  :reply_to => reply_to status id,
  :text => status,
  :original_data => original data,
}


108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/termtter/client.rb', line 108

def output(statuses, event)
  return if statuses.nil? || statuses.empty?

  statuses = statuses.sort_by{|s|s.id}
  call_hooks(:pre_filter, statuses, event)
  filtered = apply_filters(statuses, event)
  call_hooks(:post_filter, filtered, event)
  get_hooks(:output).each do |hook|
    filtered_for_hook = apply_filters_for_hook(filtered, hook.name)
    hook.call(filtered_for_hook, event)
  end
end

.pauseObject



175
176
177
# File 'lib/termtter/client.rb', line 175

def pause
  @task_manager.pause
end

.post_config_loadObject



227
228
229
230
231
# File 'lib/termtter/client.rb', line 227

def post_config_load()
  if config.devel
    plugin 'devel'
  end
end

.post_retweet(s) ⇒ Object



6
7
8
9
10
# File 'lib/plugins/retweet.rb', line 6

def self.post_retweet(s)
  text = ERB.new(config.plugins.retweet.format).result(binding)
  Termtter::API.twitter.update(text)
  puts "=> #{text}"
end

.public_storageObject



28
29
30
# File 'lib/termtter/client.rb', line 28

def public_storage
  @public_storage ||= {}
end

.register_command(arg) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/termtter/client.rb', line 62

def register_command(arg)
  command = case arg
    when Command
      arg
    when Hash
      Command.new(arg)
    else
      raise ArgumentError, 'must be given Termtter::Command or Hash'
    end
  @commands[command.name] = command
end

.register_hook(arg) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/termtter/client.rb', line 40

def register_hook(arg)
  hook = case arg
    when Hook
      arg
    when Hash
      Hook.new(arg)
    else
      raise ArgumentError, 'must be given Termtter::Hook or Hash'
    end
  @hooks[hook.name] = hook
end

.register_macro(name, macro, options = {}) ⇒ Object



88
89
90
91
92
93
94
# File 'lib/termtter/client.rb', line 88

def register_macro(name, macro, options = {})
  command = {
    :name => name.to_sym,
    :exec_proc => lambda {|arg| call_commands(macro % arg)}
  }.merge(options)
  register_command(command)
end

.resumeObject



179
180
181
# File 'lib/termtter/client.rb', line 179

def resume
  @task_manager.resume
end

.runObject



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/termtter/client.rb', line 264

def run
  load_default_plugins()
  load_config()
  Termtter::API.setup()
  setup_logger()
  post_config_load()

  config.system.eval_scripts.each do |script|
    begin
      eval script
    rescue Exception => e
      handle_error(e)
    end
  end

  config.system.run_commands.each { |cmd| call_commands(cmd) }

  unless config.system.cmd_mode
    call_hooks(:initialize)
    plugin('update_timeline')
    @task_manager.run()
    call_hooks(:before_task_thread_run)
  end
end

.save_historyObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/plugins/history.rb', line 35

def self.save_history
  filename = File.expand_path(config.plugins.history.filename)
  keys = config.plugins.history.keys
  history = { }
  keys.each do |key|
    history[key] = public_storage[key]
  end
  max_of_history = config.plugins.history.max_of_history
  history[:history] = Readline::HISTORY.to_a.reverse.uniq.reverse
  if history[:history].size > max_of_history
    history[:history] = history[:history][-max_of_history..-1]
  end

  File.open(filename, 'w') do |f|
    f.write Zlib::Deflate.deflate(Marshal.dump(history))
  end
  puts "history saved(#{File.size(filename)/1000}kb)"
end

.scrape_group(group) ⇒ Object



14
15
16
17
# File 'lib/plugins/scrape.rb', line 14

def self.scrape_group(group)
  members = config.plugins.group.groups[group] || []
  scrape_members(members)
end

.scrape_members(members) ⇒ Object



5
6
7
8
9
10
11
12
# File 'lib/plugins/scrape.rb', line 5

def self.scrape_members(members)
  statuses = []
  members.each_with_index do |member, index|
    puts "member #{index+1}/#{members.size} #{member}"
    statuses += Termtter::API.twitter.user_timeline(member)
  end
  statuses
end

.setup_loggerObject



237
238
239
# File 'lib/termtter/client.rb', line 237

def setup_logger
  @logger = config.logger || default_logger
end

.show_settings(conf, level = 0) ⇒ Object



248
249
250
251
252
253
254
255
256
257
258
# File 'lib/plugins/standard_plugins.rb', line 248

def self.show_settings(conf, level = 0)
  conf.__values__.each do |k, v|
    if v.instance_of? Termtter::Config
      puts "#{k}:"
      show_settings v, level + 1
    else
      print '  ' * level
      puts "#{k} = #{v.nil? ? 'nil' : v.inspect}"
    end
  end
end

.typable_id?(id) ⇒ Boolean

Returns:

  • (Boolean)


58
59
60
61
62
63
64
# File 'lib/plugins/typable_id.rb', line 58

def self.typable_id?(id)
  if public_storage[:typable_id].assoc(id.to_s)
    return true
  else
    return false
  end
end

.typable_id_convert(id) ⇒ Object



39
40
41
42
43
44
45
46
47
# File 'lib/plugins/typable_id.rb', line 39

def self.typable_id_convert(id)
  if current_id = public_storage[:typable_id].assoc(id.to_s)
    return current_id[1]
  elsif current_id = public_storage[:typable_id].rassoc(id.to_s)
    return current_id[0]
  else
    return nil
  end
end

.typable_id_status(id) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/plugins/typable_id.rb', line 49

def self.typable_id_status(id)
  if current_id = (public_storage[:typable_id].assoc(id.to_s)||\
                   public_storage[:typable_id].rassoc(id.to_s))
    return current_id[2]
  else
    return nil
  end
end

.update_with_user_and_id(text, username, id) ⇒ Object



456
457
458
459
460
461
# File 'lib/plugins/standard_plugins.rb', line 456

def self.update_with_user_and_id(text, username, id)
  text = ERB.new("@#{username} #{text}").result(binding).gsub(/\n/, ' ')
  result = Termtter::API.twitter.update(text, {'in_reply_to_status_id' => id})
  puts "=> #{text}"
  result
end