atig 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/Gemfile +3 -0
- data/README.mkdn +52 -0
- data/Rakefile +15 -0
- data/atig.gemspec +25 -0
- data/bin/atig +74 -0
- data/docs/OMakefile +32 -0
- data/docs/OMakeroot +45 -0
- data/docs/_static/allow.png +0 -0
- data/docs/_static/emacs.png +0 -0
- data/docs/_static/irc_setting.png +0 -0
- data/docs/_static/irssi.png +0 -0
- data/docs/_static/limechat.png +0 -0
- data/docs/_static/limechat_s.png +0 -0
- data/docs/_static/oauth_channel.png +0 -0
- data/docs/_static/screenshot.png +0 -0
- data/docs/_static/structure.png +0 -0
- data/docs/_static/verify.png +0 -0
- data/docs/changelog.rst +96 -0
- data/docs/commandline_options.rst +21 -0
- data/docs/commands.rst +84 -0
- data/docs/conf.py +194 -0
- data/docs/config.rst +159 -0
- data/docs/feature.rst +41 -0
- data/docs/graphics.graffle +1995 -0
- data/docs/hacking_guide.rst +43 -0
- data/docs/index.rst +109 -0
- data/docs/irc.rst +31 -0
- data/docs/options.rst +75 -0
- data/docs/quickstart.rst +89 -0
- data/docs/resize.sh +7 -0
- data/docs/tiarra.rst +2 -0
- data/docs/tig.rst +21 -0
- data/lib/atig.rb +19 -0
- data/lib/atig/agent.rb +8 -0
- data/lib/atig/agent/agent.rb +38 -0
- data/lib/atig/agent/clenup.rb +23 -0
- data/lib/atig/agent/dm.rb +35 -0
- data/lib/atig/agent/following.rb +45 -0
- data/lib/atig/agent/full_list.rb +20 -0
- data/lib/atig/agent/list.rb +55 -0
- data/lib/atig/agent/list_status.rb +46 -0
- data/lib/atig/agent/mention.rb +13 -0
- data/lib/atig/agent/other_list.rb +18 -0
- data/lib/atig/agent/own_list.rb +18 -0
- data/lib/atig/agent/stream_follow.rb +38 -0
- data/lib/atig/agent/timeline.rb +13 -0
- data/lib/atig/agent/user_stream.rb +31 -0
- data/lib/atig/basic_twitter.rb +116 -0
- data/lib/atig/bitly.rb +52 -0
- data/lib/atig/channel.rb +5 -0
- data/lib/atig/channel/channel.rb +17 -0
- data/lib/atig/channel/dm.rb +14 -0
- data/lib/atig/channel/list.rb +76 -0
- data/lib/atig/channel/mention.rb +20 -0
- data/lib/atig/channel/retweet.rb +28 -0
- data/lib/atig/channel/timeline.rb +74 -0
- data/lib/atig/command.rb +21 -0
- data/lib/atig/command/autofix.rb +58 -0
- data/lib/atig/command/command.rb +24 -0
- data/lib/atig/command/command_helper.rb +95 -0
- data/lib/atig/command/destroy.rb +44 -0
- data/lib/atig/command/dm.rb +31 -0
- data/lib/atig/command/favorite.rb +27 -0
- data/lib/atig/command/info.rb +50 -0
- data/lib/atig/command/limit.rb +15 -0
- data/lib/atig/command/location.rb +23 -0
- data/lib/atig/command/name.rb +18 -0
- data/lib/atig/command/option.rb +37 -0
- data/lib/atig/command/refresh.rb +18 -0
- data/lib/atig/command/reply.rb +37 -0
- data/lib/atig/command/retweet.rb +63 -0
- data/lib/atig/command/search.rb +51 -0
- data/lib/atig/command/spam.rb +26 -0
- data/lib/atig/command/status.rb +41 -0
- data/lib/atig/command/thread.rb +44 -0
- data/lib/atig/command/time.rb +32 -0
- data/lib/atig/command/uptime.rb +32 -0
- data/lib/atig/command/user.rb +42 -0
- data/lib/atig/command/user_info.rb +27 -0
- data/lib/atig/command/version.rb +49 -0
- data/lib/atig/command/whois.rb +39 -0
- data/lib/atig/db/db.rb +60 -0
- data/lib/atig/db/followings.rb +131 -0
- data/lib/atig/db/listenable.rb +22 -0
- data/lib/atig/db/lists.rb +76 -0
- data/lib/atig/db/roman.rb +30 -0
- data/lib/atig/db/sized_uniq_array.rb +62 -0
- data/lib/atig/db/sql.rb +35 -0
- data/lib/atig/db/statuses.rb +147 -0
- data/lib/atig/db/transaction.rb +47 -0
- data/lib/atig/exception_util.rb +26 -0
- data/lib/atig/gateway.rb +62 -0
- data/lib/atig/gateway/channel.rb +99 -0
- data/lib/atig/gateway/session.rb +326 -0
- data/lib/atig/http.rb +95 -0
- data/lib/atig/ifilter.rb +7 -0
- data/lib/atig/ifilter/expand_url.rb +74 -0
- data/lib/atig/ifilter/retweet.rb +14 -0
- data/lib/atig/ifilter/retweet_time.rb +16 -0
- data/lib/atig/ifilter/sanitize.rb +18 -0
- data/lib/atig/ifilter/strip.rb +15 -0
- data/lib/atig/ifilter/utf7.rb +26 -0
- data/lib/atig/ifilter/xid.rb +36 -0
- data/lib/atig/levenshtein.rb +49 -0
- data/lib/atig/monkey.rb +4 -0
- data/lib/atig/oauth-patch.rb +40 -0
- data/lib/atig/oauth.rb +55 -0
- data/lib/atig/ofilter.rb +4 -0
- data/lib/atig/ofilter/escape_url.rb +102 -0
- data/lib/atig/ofilter/footer.rb +20 -0
- data/lib/atig/ofilter/geo.rb +17 -0
- data/lib/atig/ofilter/short_url.rb +47 -0
- data/lib/atig/option.rb +90 -0
- data/lib/atig/scheduler.rb +79 -0
- data/lib/atig/search.rb +22 -0
- data/lib/atig/search_twitter.rb +21 -0
- data/lib/atig/sized_hash.rb +33 -0
- data/lib/atig/stream.rb +66 -0
- data/lib/atig/twitter.rb +79 -0
- data/lib/atig/twitter_struct.rb +63 -0
- data/lib/atig/unu.rb +27 -0
- data/lib/atig/update_checker.rb +53 -0
- data/lib/atig/url_escape.rb +62 -0
- data/lib/atig/util.rb +16 -0
- data/lib/atig/version.rb +3 -0
- data/lib/memory_profiler.rb +77 -0
- data/spec/command/autofix_spec.rb +35 -0
- data/spec/command/destroy_spec.rb +98 -0
- data/spec/command/dm_spec.rb +28 -0
- data/spec/command/favorite_spec.rb +55 -0
- data/spec/command/limit_spec.rb +27 -0
- data/spec/command/location_spec.rb +25 -0
- data/spec/command/name_spec.rb +19 -0
- data/spec/command/option_spec.rb +133 -0
- data/spec/command/refresh_spec.rb +22 -0
- data/spec/command/reply_spec.rb +79 -0
- data/spec/command/retweet_spec.rb +66 -0
- data/spec/command/spam_spec.rb +27 -0
- data/spec/command/status_spec.rb +44 -0
- data/spec/command/thread_spec.rb +91 -0
- data/spec/command/time_spec.rb +52 -0
- data/spec/command/uptime_spec.rb +55 -0
- data/spec/command/user_info_spec.rb +42 -0
- data/spec/command/user_spec.rb +50 -0
- data/spec/command/version_spec.rb +67 -0
- data/spec/command/whois_spec.rb +78 -0
- data/spec/db/followings_spec.rb +100 -0
- data/spec/db/listenable_spec.rb +32 -0
- data/spec/db/lists_spec.rb +104 -0
- data/spec/db/roman_spec.rb +17 -0
- data/spec/db/sized_uniq_array_spec.rb +63 -0
- data/spec/db/statuses_spec.rb +180 -0
- data/spec/ifilter/expand_url_spec.rb +44 -0
- data/spec/ifilter/retweet_spec.rb +28 -0
- data/spec/ifilter/retweet_time_spec.rb +25 -0
- data/spec/ifilter/sanitize_spec.rb +25 -0
- data/spec/ifilter/sid_spec.rb +29 -0
- data/spec/ifilter/strip_spec.rb +23 -0
- data/spec/ifilter/tid_spec.rb +29 -0
- data/spec/ifilter/utf7_spec.rb +30 -0
- data/spec/levenshtein_spec.rb +24 -0
- data/spec/ofilter/escape_url_spec.rb +50 -0
- data/spec/ofilter/footer_spec.rb +32 -0
- data/spec/ofilter/geo_spec.rb +33 -0
- data/spec/ofilter/short_url_spec.rb +127 -0
- data/spec/option_spec.rb +91 -0
- data/spec/sized_hash_spec.rb +45 -0
- data/spec/spec_helper.rb +35 -0
- data/spec/update_checker_spec.rb +55 -0
- metadata +326 -0
data/lib/atig/gateway.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'atig/gateway/session'
|
2
|
+
|
3
|
+
Atig::Gateway::Session.agents = [
|
4
|
+
Atig::Agent::FullList,
|
5
|
+
Atig::Agent::Following,
|
6
|
+
Atig::Agent::ListStatus,
|
7
|
+
Atig::Agent::Mention,
|
8
|
+
Atig::Agent::Dm,
|
9
|
+
Atig::Agent::Timeline,
|
10
|
+
Atig::Agent::Cleanup,
|
11
|
+
Atig::Agent::UserStream,
|
12
|
+
]
|
13
|
+
|
14
|
+
Atig::Gateway::Session.ifilters = [
|
15
|
+
Atig::IFilter::Retweet,
|
16
|
+
Atig::IFilter::RetweetTime,
|
17
|
+
Atig::IFilter::Utf7,
|
18
|
+
Atig::IFilter::Sanitize,
|
19
|
+
Atig::IFilter::ExpandUrl,
|
20
|
+
Atig::IFilter::Strip.new(%w{ *tw* *Sh*}),
|
21
|
+
Atig::IFilter::Tid,
|
22
|
+
Atig::IFilter::Sid
|
23
|
+
]
|
24
|
+
|
25
|
+
Atig::Gateway::Session.ofilters = [
|
26
|
+
Atig::OFilter::EscapeUrl,
|
27
|
+
Atig::OFilter::ShortUrl,
|
28
|
+
Atig::OFilter::Geo,
|
29
|
+
Atig::OFilter::Footer,
|
30
|
+
]
|
31
|
+
|
32
|
+
Atig::Gateway::Session.commands = [
|
33
|
+
Atig::Command::Retweet,
|
34
|
+
Atig::Command::Reply,
|
35
|
+
Atig::Command::User,
|
36
|
+
Atig::Command::Favorite,
|
37
|
+
Atig::Command::Uptime,
|
38
|
+
Atig::Command::Destroy,
|
39
|
+
Atig::Command::Status,
|
40
|
+
Atig::Command::Thread,
|
41
|
+
Atig::Command::Time,
|
42
|
+
Atig::Command::Version,
|
43
|
+
Atig::Command::UserInfo,
|
44
|
+
Atig::Command::Whois,
|
45
|
+
Atig::Command::Option,
|
46
|
+
Atig::Command::Location,
|
47
|
+
Atig::Command::Name,
|
48
|
+
Atig::Command::Autofix,
|
49
|
+
Atig::Command::Limit,
|
50
|
+
Atig::Command::Search,
|
51
|
+
Atig::Command::Refresh,
|
52
|
+
Atig::Command::Spam,
|
53
|
+
Atig::Command::Dm,
|
54
|
+
]
|
55
|
+
|
56
|
+
Atig::Gateway::Session.channels = [
|
57
|
+
Atig::Channel::Timeline,
|
58
|
+
Atig::Channel::Mention,
|
59
|
+
Atig::Channel::Dm,
|
60
|
+
Atig::Channel::List,
|
61
|
+
Atig::Channel::Retweet,
|
62
|
+
]
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# -*- mode:ruby; coding:utf-8 -*-
|
2
|
+
|
3
|
+
module Atig
|
4
|
+
module Gateway
|
5
|
+
class Channel
|
6
|
+
class << self
|
7
|
+
def delegate(*ids)
|
8
|
+
ids.each do|id|
|
9
|
+
module_eval <<END
|
10
|
+
def on_#{id}(*args)
|
11
|
+
@handler && @handler.respond_to?(:on_#{id}) && @handler.on_#{id}(*args)
|
12
|
+
end
|
13
|
+
END
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
include Net::IRC::Constants
|
19
|
+
|
20
|
+
MAX_MODE_PARAMS = 3
|
21
|
+
|
22
|
+
def initialize(opts={})
|
23
|
+
@session = opts[:session]
|
24
|
+
@name = opts[:name]
|
25
|
+
@filters = opts[:filters] || []
|
26
|
+
@opts = opts[:opts]
|
27
|
+
@prefix = opts[:prefix]
|
28
|
+
@nick = opts[:nick]
|
29
|
+
@handler = opts[:handler]
|
30
|
+
end
|
31
|
+
|
32
|
+
delegate :invite, :kick, :who
|
33
|
+
|
34
|
+
def join_me
|
35
|
+
@session.post @prefix, JOIN, @name
|
36
|
+
@session.post @session.server_name, MODE, @name, "+mto", @nick
|
37
|
+
@session.post @session.server_name, MODE, @name, "+q", @nick
|
38
|
+
end
|
39
|
+
|
40
|
+
def part_me(msg)
|
41
|
+
@session.post @prefix, PART, @name, msg
|
42
|
+
end
|
43
|
+
|
44
|
+
def message(entry, command = PRIVMSG)
|
45
|
+
GC.start
|
46
|
+
user = entry.user
|
47
|
+
screen_name = user.screen_name
|
48
|
+
prefix = prefix user
|
49
|
+
str = run_filters entry
|
50
|
+
|
51
|
+
@session.post prefix, command, @name, str
|
52
|
+
end
|
53
|
+
|
54
|
+
def notify(str)
|
55
|
+
@session.post @session.server_name, NOTICE, @name, str.gsub(/\r\n|[\r\n]/, " ")
|
56
|
+
end
|
57
|
+
|
58
|
+
def topic(entry)
|
59
|
+
str = run_filters entry
|
60
|
+
@session.post @prefix, TOPIC, @name, str
|
61
|
+
end
|
62
|
+
|
63
|
+
def join(users)
|
64
|
+
params = []
|
65
|
+
users.each do |user|
|
66
|
+
prefix = prefix(user)
|
67
|
+
@session.post prefix, JOIN, @name
|
68
|
+
case
|
69
|
+
when user.protected
|
70
|
+
params << ["v", prefix.nick]
|
71
|
+
when user.only
|
72
|
+
params << ["o", prefix.nick]
|
73
|
+
end
|
74
|
+
next if params.size < MAX_MODE_PARAMS
|
75
|
+
|
76
|
+
@session.post @session.server_name, MODE, @name, "+#{params.map {|m,_| m }.join}", *params.map {|_,n| n}
|
77
|
+
params = []
|
78
|
+
end
|
79
|
+
@session.post @session.server_name, MODE, @name, "+#{params.map {|m,_| m }.join}", *params.map {|_,n| n}
|
80
|
+
end
|
81
|
+
|
82
|
+
def part(users)
|
83
|
+
users.each do|u|
|
84
|
+
@session.post prefix(u), PART, @name, ""
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
def run_filters(entry)
|
90
|
+
status = entry.status.merge(:tid=>entry.tid, :sid=>entry.sid)
|
91
|
+
@filters.inject(status) {|x, f| f.call x }.text
|
92
|
+
end
|
93
|
+
|
94
|
+
def prefix(u)
|
95
|
+
@session.prefix u
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,326 @@
|
|
1
|
+
# -*- mode:ruby; coding:utf-8 -*-
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'atig/util'
|
5
|
+
require "ostruct"
|
6
|
+
require "time"
|
7
|
+
require 'yaml'
|
8
|
+
require 'atig/url_escape'
|
9
|
+
require 'atig/twitter'
|
10
|
+
require 'atig/search_twitter'
|
11
|
+
require 'atig/stream'
|
12
|
+
require 'atig/oauth'
|
13
|
+
require 'atig/db/db'
|
14
|
+
require 'atig/gateway/channel'
|
15
|
+
require 'atig/option'
|
16
|
+
|
17
|
+
begin
|
18
|
+
require 'continuation'
|
19
|
+
rescue LoadError => e
|
20
|
+
end
|
21
|
+
|
22
|
+
module Atig
|
23
|
+
module Gateway
|
24
|
+
class Session < Net::IRC::Server::Session
|
25
|
+
include Util
|
26
|
+
|
27
|
+
class << self
|
28
|
+
def self.class_writer(*ids)
|
29
|
+
ids.each do|id|
|
30
|
+
module_eval <<END
|
31
|
+
def #{id}=(arg)
|
32
|
+
@@#{id} = arg
|
33
|
+
end
|
34
|
+
END
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class_writer :commands, :agents, :ifilters, :ofilters, :channels
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(*args)
|
42
|
+
super
|
43
|
+
@on_message = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def post(*args)
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
def update_status(ret, target, msg='')
|
51
|
+
@db.transaction do|db|
|
52
|
+
db.statuses.add(:source => :me, :status => ret, :user => ret.user )
|
53
|
+
end
|
54
|
+
|
55
|
+
msg = "(#{msg})" unless msg.empty?
|
56
|
+
self[target].notify "Status updated #{msg}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def channel(name,opts={})
|
60
|
+
opts.update(:session => self,
|
61
|
+
:name => name,
|
62
|
+
:filters => @ifilters,
|
63
|
+
:prefix => @prefix,
|
64
|
+
:nick => @nick,
|
65
|
+
:opts => @opts)
|
66
|
+
channel = Channel.new opts
|
67
|
+
@channels[name] = channel
|
68
|
+
channel
|
69
|
+
end
|
70
|
+
|
71
|
+
def [](name)
|
72
|
+
@channels[name]
|
73
|
+
end
|
74
|
+
|
75
|
+
def output_message(query)
|
76
|
+
@ofilters.inject(query) {|x, f| f.call x }
|
77
|
+
end
|
78
|
+
|
79
|
+
def ctcp_action(*commands, &block)
|
80
|
+
commands.each do |command|
|
81
|
+
@ctcp_actions[command] = block
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def prefix(u)
|
86
|
+
nick = u.screen_name
|
87
|
+
nick = "@#{nick}" if @opts.athack
|
88
|
+
user = "id=%.9d" % u.id
|
89
|
+
host = "twitter"
|
90
|
+
host += "/protected" if u.protected
|
91
|
+
|
92
|
+
Net::IRC::Prefix.new("#{nick}!#{user}@#{host}")
|
93
|
+
end
|
94
|
+
|
95
|
+
def topic(entry)
|
96
|
+
@channels.each{|_, ch| ch.topic entry }
|
97
|
+
end
|
98
|
+
|
99
|
+
protected
|
100
|
+
def on_message(m)
|
101
|
+
GC.start
|
102
|
+
@on_message.call(m) if @on_message
|
103
|
+
end
|
104
|
+
|
105
|
+
def on_user(m)
|
106
|
+
super
|
107
|
+
@thread_group = ThreadGroup.new
|
108
|
+
@thread_group.add Thread.current
|
109
|
+
@ctcp_actions = {}
|
110
|
+
@channels = {}
|
111
|
+
load_config
|
112
|
+
|
113
|
+
@opts = Atig::Option.parse @real
|
114
|
+
context = OpenStruct.new(:log=>@log, :opts=>@opts)
|
115
|
+
|
116
|
+
oauth = OAuth.new(context, @nick)
|
117
|
+
unless oauth.verified? then
|
118
|
+
channel = channel '#oauth'
|
119
|
+
channel.join_me
|
120
|
+
channel.notify "Please approve me at #{oauth.url}"
|
121
|
+
callcc{|cc|
|
122
|
+
@on_message = lambda{|x|
|
123
|
+
if x.command.downcase == 'privmsg' then
|
124
|
+
_, mesg = *x.params
|
125
|
+
if oauth.verify(mesg.strip)
|
126
|
+
channel.part_me "Verified"
|
127
|
+
save_config
|
128
|
+
@on_message = nil
|
129
|
+
cc.call
|
130
|
+
end
|
131
|
+
end
|
132
|
+
return true
|
133
|
+
}
|
134
|
+
return
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
log :debug, "initialize Twitter"
|
139
|
+
twitter = Twitter.new context, oauth.access
|
140
|
+
search = SearchTwitter.new context
|
141
|
+
stream = Stream.new context, @nick,@pass if @opts.stream
|
142
|
+
@api = Scheduler.new context, twitter, search, stream
|
143
|
+
|
144
|
+
log :debug, "initialize filter"
|
145
|
+
@ifilters = run_new @@ifilters, context
|
146
|
+
@ofilters = run_new @@ofilters, context
|
147
|
+
|
148
|
+
@api.delay(0) do|t|
|
149
|
+
me = t.post "account/update_profile"
|
150
|
+
unless me then
|
151
|
+
log :info, <<END
|
152
|
+
Failed to access API.
|
153
|
+
Please check Twitter Status <http://status.twitter.com/> and try again later.
|
154
|
+
END
|
155
|
+
finish
|
156
|
+
end
|
157
|
+
@prefix = prefix me
|
158
|
+
@user = @prefix.user
|
159
|
+
@host = @prefix.host
|
160
|
+
|
161
|
+
post server_name, MODE, @nick, "+o"
|
162
|
+
|
163
|
+
@db = Atig::Db::Db.new context, :me=>me, :size=> 100
|
164
|
+
run_new @@commands, context, self, @api, @db
|
165
|
+
run_new @@agents , context, @api, @db
|
166
|
+
run_new @@channels, context, self, @db
|
167
|
+
|
168
|
+
@db.statuses.add :user => me, :source => :me, :status => me.status
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def run_new(klasses,*args)
|
173
|
+
(klasses || []).map do|klass|
|
174
|
+
if klass.respond_to?(:new)
|
175
|
+
klass.new(*args)
|
176
|
+
else
|
177
|
+
klass
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def on_disconnected
|
183
|
+
(@thread_group.list - [Thread.current]).each {|t| t.kill }
|
184
|
+
end
|
185
|
+
|
186
|
+
CONFIG_FILE = File.expand_path("~/.atig/oauth")
|
187
|
+
def save_config
|
188
|
+
FileUtils.mkdir_p File.dirname(CONFIG_FILE)
|
189
|
+
File.open(CONFIG_FILE, "w") {|io|
|
190
|
+
YAML.dump(OAuth.dump,io)
|
191
|
+
}
|
192
|
+
FileUtils.chmod 0600, CONFIG_FILE
|
193
|
+
end
|
194
|
+
|
195
|
+
def load_config
|
196
|
+
FileUtils.mkdir_p File.dirname(CONFIG_FILE)
|
197
|
+
OAuth.load(YAML.load_file(CONFIG_FILE)) rescue nil
|
198
|
+
end
|
199
|
+
|
200
|
+
def on_privmsg(m)
|
201
|
+
target, mesg = *m.params
|
202
|
+
m.ctcps.each {|ctcp| on_ctcp(target, ctcp) } if m.ctcp?
|
203
|
+
|
204
|
+
case
|
205
|
+
when mesg.empty?
|
206
|
+
return
|
207
|
+
when mesg.sub!(/\A +/, "")
|
208
|
+
on_ctcp_action(target, mesg)
|
209
|
+
when target[0] != ?#
|
210
|
+
channel target
|
211
|
+
on_ctcp_action(target, "dm #{target} #{mesg}")
|
212
|
+
when (@opts.old_style_reply and mesg =~ /\A@(?>([A-Za-z0-9_]{1,15}))[^A-Za-z0-9_]/)
|
213
|
+
on_ctcp_action(target, "reply #{$1} #{mesg}")
|
214
|
+
else
|
215
|
+
on_ctcp_action(target, "status #{mesg}")
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def on_ctcp(target, mesg)
|
220
|
+
if mesg.respond_to? :encoding!
|
221
|
+
mesg.encoding! "UTF-8"
|
222
|
+
end
|
223
|
+
type, mesg = mesg.split(" ", 2)
|
224
|
+
method = "on_ctcp_#{type.downcase}".to_sym
|
225
|
+
send(method, target, mesg) if respond_to? method, true
|
226
|
+
end
|
227
|
+
|
228
|
+
def on_ctcp_action(target, mesg)
|
229
|
+
command, *args = mesg.split(" ")
|
230
|
+
last_match = nil
|
231
|
+
commond = command.to_s.downcase
|
232
|
+
_, action = @ctcp_actions.find{|define, f|
|
233
|
+
r = (define === command)
|
234
|
+
last_match = Regexp.last_match
|
235
|
+
r
|
236
|
+
}
|
237
|
+
if action then
|
238
|
+
safe {
|
239
|
+
action.call(target, mesg, last_match || command, args)
|
240
|
+
}
|
241
|
+
else
|
242
|
+
self[target].notify "[atig.rb] CTCP ACTION COMMANDS:"
|
243
|
+
@ctcp_actions.keys.each do |c|
|
244
|
+
self[target].notify c.to_s
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def on_invite(m)
|
250
|
+
nick, channel = *m.params
|
251
|
+
if not nick.screen_name? or @db.me.screen_name.casecmp(nick).zero?
|
252
|
+
post server_name, ERR_NOSUCHNICK, nick, "No such nick: #{nick}" # or yourself
|
253
|
+
return
|
254
|
+
end
|
255
|
+
|
256
|
+
unless @channels.key? channel
|
257
|
+
post server_name, ERR_NOSUCHNICK, nick, "No such channel: #{channel}"
|
258
|
+
return
|
259
|
+
end
|
260
|
+
|
261
|
+
@api.delay(0){|api| @channels[channel].on_invite(api, nick) }
|
262
|
+
end
|
263
|
+
|
264
|
+
def on_kick(m)
|
265
|
+
channel, nick, msg = *m.params
|
266
|
+
|
267
|
+
if not nick.screen_name? or @db.me.screen_name.casecmp(nick).zero?
|
268
|
+
post server_name, ERR_NOSUCHNICK, nick, "No such nick: #{nick}" # or yourself
|
269
|
+
return
|
270
|
+
end
|
271
|
+
|
272
|
+
unless @channels.key? channel
|
273
|
+
post server_name, ERR_NOSUCHNICK, nick, "No such channel: #{channel}"
|
274
|
+
return
|
275
|
+
end
|
276
|
+
|
277
|
+
@api.delay(0){|api| @channels[channel].on_kick(api, nick) }
|
278
|
+
end
|
279
|
+
|
280
|
+
def on_whois(m)
|
281
|
+
nick = m.params[0]
|
282
|
+
unless nick.screen_name?
|
283
|
+
post server_name, ERR_NOSUCHNICK, nick, "No such nick/channel"
|
284
|
+
return
|
285
|
+
end
|
286
|
+
on_ctcp_action(nil, "whois #{nick}")
|
287
|
+
end
|
288
|
+
|
289
|
+
def on_topic(m)
|
290
|
+
channel,topic = *m.params
|
291
|
+
on_ctcp_action(channel, "topic #{topic}")
|
292
|
+
end
|
293
|
+
|
294
|
+
def on_who(m)
|
295
|
+
channel = m.params[0]
|
296
|
+
|
297
|
+
unless @channels.key? channel
|
298
|
+
post server_name, ERR_NOSUCHNICK, nick, "No such channel: #{channel}"
|
299
|
+
return
|
300
|
+
end
|
301
|
+
@channels[channel].on_who do|user|
|
302
|
+
# "<channel> <user> <host> <server> <nick>
|
303
|
+
# ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
|
304
|
+
# :<hopcount> <real name>"
|
305
|
+
prefix = prefix(user)
|
306
|
+
server = 'twitter.com'
|
307
|
+
mode = case prefix.nick
|
308
|
+
when @nick then "~"
|
309
|
+
else "+"
|
310
|
+
end
|
311
|
+
real = user.name
|
312
|
+
post server_name, RPL_WHOREPLY, @nick, channel, prefix.user, prefix.host, server, prefix.nick, "H*#{mode}", "1 #{real}"
|
313
|
+
end
|
314
|
+
post server_name, RPL_ENDOFWHO, @nick, channel
|
315
|
+
end
|
316
|
+
|
317
|
+
def available_user_modes
|
318
|
+
"o"
|
319
|
+
end
|
320
|
+
|
321
|
+
def available_channel_modes
|
322
|
+
"mntiovah"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|