Skip to content

Instantly share code, notes, and snippets.

@arika
Created October 26, 2009 01:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arika/218364 to your computer and use it in GitHub Desktop.
Save arika/218364 to your computer and use it in GitHub Desktop.
termtter plugin: searches keywords automatically
# -*- coding: utf-8 -*-
config.plugins.auto_search.set_default(:keywords, [])
module Termtter::Client
public_storage[:auto_search] ||= {
:since_id => nil,
:keyword => {},
}
arg_apply = proc do |str, ab|
str.scan(%r!((["'])((?:\\\\|\\\2|[^\2])*?)\2|[^\s/]+)(?:/(\d+))?!).
map {|x| [x[2] || x[0], (x[3] || '3').to_i] }.
each {|kw, iv| ab.call(kw.split(/\s+/).sort.join(' '), iv) }
end
auto_search_trace = false
register_command(
:name => :auto_search_trace,
:help => ['auto_search_trace (on|off)', 'on/off auto search trace log'],
:exec => proc do |arg|
case arg.strip
when /^(?:on|yes|true)/i
auto_search_trace = true
when /^(?:off|no|false)/i
auto_search_trace = false
else
puts "trace #{auto_search_trace ? 'on' : 'off'}"
end
end
)
register_command(
:name => :auto_search,
:help => ["auto_search ((word|'word word')(/n)?)+", "add auto search keywords and interval"],
:exec => proc do |arg|
h = public_storage[:auto_search][:keyword]
arg_apply.call(arg, proc do |kw, iv|
public_storage[:hashtags] += kw.scan(/#([^\s]+)/).flatten # this line is copied from plugins/defaults/standard_completion.rb.
if h[kw]
h[kw][:interval] = iv
else
h[kw] = { :interval => iv, :next => nil, :since_id => nil }
end
end)
end
)
register_command(
:name => :remove_auto_search,
:help => ["remove_auto_search (word|'word word')+", "remove auto search keywords"],
:exec => proc do |arg|
h = public_storage[:auto_search][:keyword]
arg_apply.call(arg, proc {|kw, iv| h.delete(kw) })
end
)
register_command(
:name => :auto_search_debug,
:help => ["auto_search_debug", "dump auto search keyword list (for debug)"],
:exec => proc do
puts "auto search keyward info:"
public_storage[:auto_search][:keyword].each_pair do |k,i|
puts " #{k.dump} : iv = #{i[:interval]}, sid = #{i[:since_id]}, next = #{i[:next]}"
end
end
)
register_hook(
:name => :auto_search_init,
:point => :initialize,
:exec => proc do
config.plugins.auto_search.keywords.each do |kw|
call_commands("auto_search #{kw}")
end
end
)
register_hook(:auto_search_since_id, :point => :pre_exec_reload) do |command, arg|
public_storage[:auto_search][:since_id] = @since_id
end
register_hook(:auto_search, :point => :pre_filter) do |statuses, event|
st = public_storage[:auto_search]
if event == :update_friends_timeline && !st[:keyword].empty?
now = Time.now
target = []
st[:keyword].each do |kw, info|
if info[:next].nil?
info[:next] = now + rand((config.update_interval*info[:interval]).to_i)
#p [:keyword, kw, :init, info[:next] - now] if auto_search_trace # XXX: debug
else
if info[:next] < now
target << kw
#p [:keyword, kw, :exec, info[:next] - now] if auto_search_trace # XXX: debug
info[:next] = now + (config.update_interval*info[:interval]).to_i
else
#p [:keyword, kw, :skip, info[:next] - now] if auto_search_trace # XXX: debug
end
end
end
search_set = {}
target.each do |kw|
sid = st[:keyword][kw][:since_id] || st[:since_id] || nil
search_set[sid] ||= []
search_set[sid] << kw
end
max_status_id = statuses.inject(0) {|memo, t| memo < t[:id] ? t[:id] : memo }
result = []
search_set.each do |sid, kws|
patt = kws.join(' OR ')
since_arg = sid ? {:since_id => sid} : {}
ss = Termtter::API.twitter.search(patt, since_arg)
if ss.empty?
next_sid = max_status_id
else
next_sid = ss.inject(0) {|memo, s| memo < s[:id] ? s[:id] : memo }
end
next_sid = sid if sid && sid > next_sid
p [:search, patt, sid, ss.size, next_sid] if auto_search_trace # XXX: debug
if next_sid
kws.each {|kw| st[:keyword][kw][:since_id] = next_sid }
end
result += ss
end
unless result.empty?
# reduce duplicates.
ids = statuses.map {|x| x[:id]}
result.each do |x|
if ids.include?(x[:id])
p [:dup_found1, x[:id]] if auto_search_trace # XXX: debug
next
end
if public_storage[:typable_id]
if typable_id_status(x[:id])
p [:dup_found2, x[:id]] if auto_search_trace # XXX: debug
next
end
end
statuses << x
end
statuses.each {|x| p [x[:id], x[:created_at], x[:user][:name], x[:text]] } if auto_search_trace # XXX: debug
statuses.sort! {|a, b| a[:id] <=> b[:id] }
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment