net-irc 0.0.1 → 0.0.2
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.
- 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
|
+
|