net-irc 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +27 -0
- data/Rakefile +2 -1
- data/examples/client.rb +23 -0
- data/examples/lig.rb +306 -108
- data/examples/lingr.rb +333 -0
- data/examples/nig.rb +144 -0
- data/examples/tig.rb +153 -48
- data/examples/wig.rb +40 -15
- data/lib/net/irc.rb +95 -77
- data/spec/net-irc_spec.rb +385 -0
- data/spec/spec.opts +1 -0
- metadata +8 -3
data/examples/lingr.rb
ADDED
@@ -0,0 +1,333 @@
|
|
1
|
+
# Ruby client for the Lingr[http://www.lingr.com] API. For more details and tutorials, see the
|
2
|
+
# {Lingr API Reference}[http://wiki.lingr.com/dev/show/API+Reference] pages on the {Lingr Developer Wiki}[http://wiki.lingr.com].
|
3
|
+
#
|
4
|
+
# All methods return a hash with two keys:
|
5
|
+
# * :succeeded - <tt>true</tt> if the method succeeded, <tt>false</tt> otherwise
|
6
|
+
# * :response - a Hash version of the response document received from the server
|
7
|
+
#
|
8
|
+
# = api_client.rb
|
9
|
+
#
|
10
|
+
# Lingr API client
|
11
|
+
#
|
12
|
+
#
|
13
|
+
# Original written by Lingr.
|
14
|
+
# Modified by cho45 <cho45@lowreal.net>
|
15
|
+
# * Use json gem instead of gsub/eval.
|
16
|
+
# * Raise APIError when api fails.
|
17
|
+
# * Rename class name to Lingr::Client.
|
18
|
+
|
19
|
+
$KCODE = 'u' # used by json
|
20
|
+
require "rubygems"
|
21
|
+
require "net/http"
|
22
|
+
require "json"
|
23
|
+
require "uri"
|
24
|
+
|
25
|
+
module Lingr
|
26
|
+
class Client
|
27
|
+
class ClientError < StandardError; end
|
28
|
+
class APIError < ClientError
|
29
|
+
def initialize(error)
|
30
|
+
@error = error || {
|
31
|
+
"message" => "socket error",
|
32
|
+
"code" => 0,
|
33
|
+
}
|
34
|
+
super(@error["message"])
|
35
|
+
end
|
36
|
+
|
37
|
+
def code
|
38
|
+
@error["code"]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_accessor :api_key
|
43
|
+
# 0 = quiet, 1 = some debug info, 2 = more debug info
|
44
|
+
attr_accessor :verbosity
|
45
|
+
attr_accessor :session
|
46
|
+
attr_accessor :timeout
|
47
|
+
|
48
|
+
def initialize(api_key, verbosity=0, hostname='www.lingr.com')
|
49
|
+
@api_key = api_key
|
50
|
+
@host = hostname
|
51
|
+
@verbosity = verbosity
|
52
|
+
@timeout = 120
|
53
|
+
end
|
54
|
+
|
55
|
+
# Create a new API session
|
56
|
+
#
|
57
|
+
def create_session(client_type='automaton')
|
58
|
+
if @session
|
59
|
+
@error_info = nil
|
60
|
+
raise ClientError, "already in a session"
|
61
|
+
end
|
62
|
+
|
63
|
+
ret = do_api :post, 'session/create', { :api_key => @api_key, :client_type => client_type }, false
|
64
|
+
@session = ret["session"]
|
65
|
+
ret
|
66
|
+
end
|
67
|
+
|
68
|
+
# Verify a session id. If no session id is passed, verifies the current session id for this ApiClient
|
69
|
+
#
|
70
|
+
def verify_session(session_id=nil)
|
71
|
+
do_api :get, 'session/verify', { :session => session_id || @session }, false
|
72
|
+
end
|
73
|
+
|
74
|
+
# Destroy the current API session
|
75
|
+
#
|
76
|
+
def destroy_session
|
77
|
+
ret = do_api :post, 'session/destroy', { :session => @session }
|
78
|
+
@session = nil
|
79
|
+
ret
|
80
|
+
end
|
81
|
+
|
82
|
+
# Get a list of the currently hot rooms
|
83
|
+
#
|
84
|
+
def get_hot_rooms(count=nil)
|
85
|
+
do_api :get, 'explore/get_hot_rooms', { :api_key => @api_key }.merge(count ? { :count => count} : {}), false
|
86
|
+
end
|
87
|
+
|
88
|
+
# Get a list of the newest rooms
|
89
|
+
#
|
90
|
+
def get_new_rooms(count=nil)
|
91
|
+
do_api :get, 'explore/get_new_rooms', { :api_key => @api_key }.merge(count ? { :count => count} : {}), false
|
92
|
+
end
|
93
|
+
|
94
|
+
# Get a list of the currently hot tags
|
95
|
+
#
|
96
|
+
def get_hot_tags(count=nil)
|
97
|
+
do_api :get, 'explore/get_hot_tags', { :api_key => @api_key }.merge(count ? { :count => count} : {}), false
|
98
|
+
end
|
99
|
+
|
100
|
+
# Get a list of all tags
|
101
|
+
#
|
102
|
+
def get_all_tags(count=nil)
|
103
|
+
do_api :get, 'explore/get_all_tags', { :api_key => @api_key }.merge(count ? { :count => count} : {}), false
|
104
|
+
end
|
105
|
+
|
106
|
+
# Search room name, description, and tags for keywords. Keywords can be a String or an Array.
|
107
|
+
#
|
108
|
+
def search(keywords)
|
109
|
+
do_api :get, 'explore/search', { :api_key => @api_key, :q => keywords.is_a?(Array) ? keywords.join(',') : keywords }, false
|
110
|
+
end
|
111
|
+
|
112
|
+
# Search room tags. Tagnames can be a String or an Array.
|
113
|
+
#
|
114
|
+
def search_tags(tagnames)
|
115
|
+
do_api :get, 'explore/search_tags', { :api_key => @api_key, :q => tagnames.is_a?(Array) ? tagnames.join(',') : tagnames }, false
|
116
|
+
end
|
117
|
+
|
118
|
+
# Search archives. If room_id is non-nil, the search is limited to the archives of that room.
|
119
|
+
#
|
120
|
+
def search_archives(query, room_id=nil)
|
121
|
+
params = { :api_key => @api_key, :q => query }
|
122
|
+
params.merge!({ :id => room_id }) if room_id
|
123
|
+
do_api :get, 'explore/search_archives', params, false
|
124
|
+
end
|
125
|
+
|
126
|
+
# Authenticate a user within the current API session
|
127
|
+
#
|
128
|
+
def login(email, password)
|
129
|
+
do_api :post, 'auth/login', { :session => @session, :email => email, :password => password }
|
130
|
+
end
|
131
|
+
|
132
|
+
# Log out the currently-authenticated user in the session, if any
|
133
|
+
#
|
134
|
+
def logout
|
135
|
+
do_api :post, 'auth/logout', { :session => @session }
|
136
|
+
end
|
137
|
+
|
138
|
+
# Get information about the currently-authenticated user
|
139
|
+
#
|
140
|
+
def get_user_info
|
141
|
+
do_api :get, 'user/get_info', { :session => @session }
|
142
|
+
end
|
143
|
+
|
144
|
+
# Start observing the currently-authenticated user
|
145
|
+
#
|
146
|
+
def start_observing_user
|
147
|
+
do_api :post, 'user/start_observing', { :session => @session }
|
148
|
+
end
|
149
|
+
|
150
|
+
# Observe the currently-authenticated user, watching for profile changes
|
151
|
+
#
|
152
|
+
def observe_user(ticket, counter)
|
153
|
+
do_api :get, 'user/observe', { :session => @session, :ticket => ticket, :counter => counter }
|
154
|
+
end
|
155
|
+
|
156
|
+
# Stop observing the currently-authenticated user
|
157
|
+
#
|
158
|
+
def stop_observing_user(ticket)
|
159
|
+
do_api :post, 'user/stop_observing', { :session => @session, :ticket =>ticket }
|
160
|
+
end
|
161
|
+
|
162
|
+
# Get information about a chatroom, including room description, current occupants, recent messages, etc.
|
163
|
+
#
|
164
|
+
def get_room_info(room_id, counter=nil, password=nil)
|
165
|
+
params = { :api_key => @api_key, :id => room_id }
|
166
|
+
params.merge!({ :counter => counter }) if counter
|
167
|
+
params.merge!({ :password => password }) if password
|
168
|
+
do_api :get, 'room/get_info', params, false
|
169
|
+
end
|
170
|
+
|
171
|
+
# Create a chatroom
|
172
|
+
#
|
173
|
+
# options is a Hash containing any of the parameters allowed for room.create. If the :image key is present
|
174
|
+
# in options, its value must be a hash with the keys :filename, :mime_type, and :io
|
175
|
+
#
|
176
|
+
def create_room(options)
|
177
|
+
do_api :post, 'room/create', options.merge({ :session => @session })
|
178
|
+
end
|
179
|
+
|
180
|
+
# Change the settings for a chatroom
|
181
|
+
#
|
182
|
+
# options is a Hash containing any of the parameters allowed for room.create. If the :image key is present
|
183
|
+
# in options, its value must be a hash with the keys :filename, :mime_type, and :io. To change the id for
|
184
|
+
# a room, use the key :new_id
|
185
|
+
#
|
186
|
+
def change_settings(room_id, options)
|
187
|
+
do_api :post, 'room/change_settings', options.merge({ :session => @session })
|
188
|
+
end
|
189
|
+
|
190
|
+
# Delete a chatroom
|
191
|
+
#
|
192
|
+
def delete_room(room_id)
|
193
|
+
do_api :post, 'room/delete', { :id => room_id, :session => @session }
|
194
|
+
end
|
195
|
+
|
196
|
+
# Enter a chatroom
|
197
|
+
#
|
198
|
+
def enter_room(room_id, nickname=nil, password=nil, idempotent=false)
|
199
|
+
params = { :session => @session, :id => room_id }
|
200
|
+
params.merge!({ :nickname => nickname }) if nickname
|
201
|
+
params.merge!({ :password => password }) if password
|
202
|
+
params.merge!({ :idempotent => 'true' }) if idempotent
|
203
|
+
do_api :post, 'room/enter', params
|
204
|
+
end
|
205
|
+
|
206
|
+
# Poll for messages in a chatroom
|
207
|
+
#
|
208
|
+
def get_messages(ticket, counter, user_messages_only=false)
|
209
|
+
do_api :get, 'room/get_messages', { :session => @session, :ticket => ticket, :counter => counter, :user_messages_only => user_messages_only }
|
210
|
+
end
|
211
|
+
|
212
|
+
# Observe a chatroom, waiting for events to occur in the room
|
213
|
+
#
|
214
|
+
def observe_room(ticket, counter)
|
215
|
+
do_api :get, 'room/observe', { :session => @session, :ticket => ticket, :counter => counter }
|
216
|
+
end
|
217
|
+
|
218
|
+
# Set your nickname in a chatroom
|
219
|
+
#
|
220
|
+
def set_nickname(ticket, nickname)
|
221
|
+
do_api :post, 'room/set_nickname', { :session => @session, :ticket => ticket, :nickname => nickname }
|
222
|
+
end
|
223
|
+
|
224
|
+
# Say something in a chatroom. If target_occupant_id is not nil, a private message
|
225
|
+
# is sent to the indicated occupant.
|
226
|
+
#
|
227
|
+
def say(ticket, msg, target_occupant_id = nil)
|
228
|
+
params = { :session => @session, :ticket => ticket, :message => msg }
|
229
|
+
params.merge!({ :occupant_id => target_occupant_id}) if target_occupant_id
|
230
|
+
do_api :post, 'room/say', params
|
231
|
+
end
|
232
|
+
|
233
|
+
# Exit a chatroom
|
234
|
+
#
|
235
|
+
def exit_room(ticket)
|
236
|
+
do_api :post, 'room/exit', { :session => @session, :ticket => ticket }
|
237
|
+
end
|
238
|
+
|
239
|
+
private
|
240
|
+
|
241
|
+
def do_api(method, path, parameters, require_session=true)
|
242
|
+
if require_session and !@session
|
243
|
+
raise ClientError, "not in a session"
|
244
|
+
end
|
245
|
+
|
246
|
+
response = JSON.parse(self.send(method, url_for(path), parameters.merge({ :format => 'json' })))
|
247
|
+
|
248
|
+
unless success?(response)
|
249
|
+
raise APIError, response["error"]
|
250
|
+
end
|
251
|
+
|
252
|
+
response
|
253
|
+
end
|
254
|
+
|
255
|
+
def url_for(method)
|
256
|
+
"http://#{@host}/#{@@PATH_BASE}#{method}"
|
257
|
+
end
|
258
|
+
|
259
|
+
def get(url, params)
|
260
|
+
uri = URI.parse(url)
|
261
|
+
path = uri.path
|
262
|
+
q = params.inject("?") {|s, p| s << "#{p[0].to_s}=#{URI.encode(p[1].to_s, /./)}&"}.chop
|
263
|
+
path << q if q.length > 0
|
264
|
+
|
265
|
+
begin
|
266
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
267
|
+
http.read_timeout = @timeout
|
268
|
+
req = Net::HTTP::Get.new(path)
|
269
|
+
req.basic_auth(uri.user, uri.password) if uri.user
|
270
|
+
parse_result http.request(req)
|
271
|
+
end
|
272
|
+
rescue Exception
|
273
|
+
warn "exception on HTTP GET: #{$!}"
|
274
|
+
nil
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def post(url, params)
|
279
|
+
if !params.find {|p| p[1].is_a?(Hash)}
|
280
|
+
begin
|
281
|
+
parse_result Net::HTTP.post_form(URI.parse(url), params)
|
282
|
+
rescue Exception
|
283
|
+
warn "exception on HTTP POST: #{$!}"
|
284
|
+
nil
|
285
|
+
end
|
286
|
+
else
|
287
|
+
boundary = 'lingr-api-client' + (0x1000000 + rand(0x1000000).to_s(16))
|
288
|
+
|
289
|
+
query = params.collect { |p|
|
290
|
+
ret = ["--#{boundary}"]
|
291
|
+
|
292
|
+
if p[1].is_a?(Hash)
|
293
|
+
ret << "Content-Disposition: form-data; name=\"#{URI.encode(p[0].to_s)}\"; filename=\"#{p[1][:filename]}\""
|
294
|
+
ret << "Content-Transfer-Encoding: binary"
|
295
|
+
ret << "Content-Type: #{p[1][:mime_type]}"
|
296
|
+
ret << ""
|
297
|
+
ret << p[1][:io].read
|
298
|
+
else
|
299
|
+
ret << "Content-Disposition: form-data; name=\"#{URI.encode(p[0].to_s)}\""
|
300
|
+
ret << ""
|
301
|
+
ret << p[1]
|
302
|
+
end
|
303
|
+
|
304
|
+
ret.join("\r\n")
|
305
|
+
}.join('') + "--#{boundary}--\r\n"
|
306
|
+
|
307
|
+
uri = URI.parse(url)
|
308
|
+
begin
|
309
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
310
|
+
http.read_timeout = @timeout
|
311
|
+
parse_result http.post2(uri.path, query, "Content-Type" => "multipart/form-data; boundary=#{boundary}")
|
312
|
+
end
|
313
|
+
rescue Exception
|
314
|
+
warn "exception on multipart POST: #{$!}"
|
315
|
+
nil
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
def parse_result(result)
|
321
|
+
return nil if !result || result.code != '200' || (!result['Content-Type'] || result['Content-Type'].index('text/javascript') != 0)
|
322
|
+
result.body
|
323
|
+
end
|
324
|
+
|
325
|
+
def success?(response)
|
326
|
+
return false if !response
|
327
|
+
response["status"] and response["status"] == 'ok'
|
328
|
+
end
|
329
|
+
|
330
|
+
|
331
|
+
@@PATH_BASE = 'api/'
|
332
|
+
end
|
333
|
+
end
|
data/examples/nig.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
|
4
|
+
# nig.rb
|
5
|
+
|
6
|
+
nowa IRC Gateway
|
7
|
+
|
8
|
+
## Launch
|
9
|
+
|
10
|
+
$ ruby nig.rb # daemonized
|
11
|
+
|
12
|
+
If you want to help:
|
13
|
+
|
14
|
+
$ ruby nig.rb --help
|
15
|
+
|
16
|
+
## Configuration
|
17
|
+
|
18
|
+
Options specified by after irc realname.
|
19
|
+
|
20
|
+
Configuration example for Tiarra ( http://coderepos.org/share/wiki/Tiarra ).
|
21
|
+
|
22
|
+
nowa {
|
23
|
+
host: localhost
|
24
|
+
port: 16671
|
25
|
+
name: username@example.com athack
|
26
|
+
password: password on nowa
|
27
|
+
in-encoding: utf8
|
28
|
+
out-encoding: utf8
|
29
|
+
}
|
30
|
+
|
31
|
+
### athack
|
32
|
+
|
33
|
+
If `athack` client option specified,
|
34
|
+
all nick in join message is leading with @.
|
35
|
+
|
36
|
+
So if you complemente nicks (ex. Irssi),
|
37
|
+
it's good for twitter like reply command (@nick).
|
38
|
+
|
39
|
+
In this case, you will see torrent of join messages after connected,
|
40
|
+
because NAMES list can't send @ leading nick (it interpreted op.)
|
41
|
+
|
42
|
+
## Licence
|
43
|
+
|
44
|
+
Ruby's by cho45
|
45
|
+
|
46
|
+
=end
|
47
|
+
|
48
|
+
$LOAD_PATH << File.dirname(__FILE__)
|
49
|
+
|
50
|
+
require "tig.rb"
|
51
|
+
|
52
|
+
class NowaIrcGateway < TwitterIrcGateway
|
53
|
+
def server_name
|
54
|
+
"nowagw"
|
55
|
+
end
|
56
|
+
|
57
|
+
def server_version
|
58
|
+
"0.0.0"
|
59
|
+
end
|
60
|
+
|
61
|
+
def main_channel
|
62
|
+
"#nowa"
|
63
|
+
end
|
64
|
+
|
65
|
+
def api_base
|
66
|
+
URI("http://api.nowa.jp/")
|
67
|
+
end
|
68
|
+
|
69
|
+
def api_source
|
70
|
+
"nig.rb"
|
71
|
+
end
|
72
|
+
|
73
|
+
def jabber_bot_id
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
if __FILE__ == $0
|
79
|
+
require "optparse"
|
80
|
+
|
81
|
+
opts = {
|
82
|
+
:port => 16671,
|
83
|
+
:host => "localhost",
|
84
|
+
:log => nil,
|
85
|
+
:debug => false,
|
86
|
+
}
|
87
|
+
|
88
|
+
OptionParser.new do |parser|
|
89
|
+
parser.instance_eval do
|
90
|
+
self.banner = <<-EOB.gsub(/^\t+/, "")
|
91
|
+
Usage: #{$0} [opts]
|
92
|
+
|
93
|
+
EOB
|
94
|
+
|
95
|
+
separator ""
|
96
|
+
|
97
|
+
separator "Options:"
|
98
|
+
on("-p", "--port [PORT=#{opts[:port]}]", "port number to listen") do |port|
|
99
|
+
opts[:port] = port
|
100
|
+
end
|
101
|
+
|
102
|
+
on("-h", "--host [HOST=#{opts[:host]}]", "host name or IP address to listen") do |host|
|
103
|
+
opts[:host] = host
|
104
|
+
end
|
105
|
+
|
106
|
+
on("-l", "--log LOG", "log file") do |log|
|
107
|
+
opts[:log] = log
|
108
|
+
end
|
109
|
+
|
110
|
+
on("--debug", "Enable debug mode") do |debug|
|
111
|
+
opts[:log] = $stdout
|
112
|
+
opts[:debug] = true
|
113
|
+
end
|
114
|
+
|
115
|
+
parse!(ARGV)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
opts[:logger] = Logger.new(opts[:log], "daily")
|
120
|
+
opts[:logger].level = opts[:debug] ? Logger::DEBUG : Logger::INFO
|
121
|
+
|
122
|
+
def daemonize(debug=false)
|
123
|
+
return yield if $DEBUG || debug
|
124
|
+
Process.fork do
|
125
|
+
Process.setsid
|
126
|
+
Dir.chdir "/"
|
127
|
+
trap("SIGINT") { exit! 0 }
|
128
|
+
trap("SIGTERM") { exit! 0 }
|
129
|
+
trap("SIGHUP") { exit! 0 }
|
130
|
+
File.open("/dev/null") {|f|
|
131
|
+
STDIN.reopen f
|
132
|
+
STDOUT.reopen f
|
133
|
+
STDERR.reopen f
|
134
|
+
}
|
135
|
+
yield
|
136
|
+
end
|
137
|
+
exit! 0
|
138
|
+
end
|
139
|
+
|
140
|
+
daemonize(opts[:debug]) do
|
141
|
+
Net::IRC::Server.new(opts[:host], opts[:port], NowaIrcGateway, opts).start
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|