irconnect 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.
- checksums.yaml +7 -0
- data/lib/command.rb +41 -0
- data/lib/connection.rb +123 -0
- data/lib/irconnect.rb +3 -0
- metadata +46 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dceeaa4921ecd73f225a56d9d117012c87a3d21d
|
4
|
+
data.tar.gz: 973ba8dd099a6004a67712c85ffc225186a32876
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7526d562c12c5be0dafa89a712b06c5d7822c936d418f1e842e2e75398f269c0e54f1471ce61c9ccf0aa63cb51062aebf3f5cc6de89a1f222d9517e53e59b7d1
|
7
|
+
data.tar.gz: 70326593920dcb75fe539d10cdfca50b30586c4d06a5b67dc3ee427640978812ba74a0d965e4348422ae38fc4dbb5601495f56a01ae3b0f7fc2d62f8f4281e4e
|
data/lib/command.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
module IRConnect
|
3
|
+
# represents an IRC Command received from the server
|
4
|
+
class Command
|
5
|
+
attr_reader :prefix, :command, :params, :last_param
|
6
|
+
|
7
|
+
# IRC message format:
|
8
|
+
# :<prefix> <command> <params> :<trailing>
|
9
|
+
# info on parsing commands:
|
10
|
+
# http://goo.gl/N3YGLq
|
11
|
+
def initialize(command_string)
|
12
|
+
fail 'Bad IRC command format' unless command_string =~ /
|
13
|
+
\A (?::([^\040]+)\040)? # prefix
|
14
|
+
([A-Za-z]+|\d{3}) # command
|
15
|
+
((?:\040[^:][^\040]+)*) # all but the last param
|
16
|
+
(?:\040:?(.*))? # last param
|
17
|
+
\Z
|
18
|
+
/x
|
19
|
+
@prefix, @command = Regexp.last_match(1), Regexp.last_match(2)
|
20
|
+
parse_params(Regexp.last_match(3), Regexp.last_match(4))
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(other)
|
24
|
+
prefix == other.prefix &&
|
25
|
+
command == other.command &&
|
26
|
+
params == other.params
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def parse_params(param, param_last)
|
32
|
+
if param.empty?
|
33
|
+
@params = []
|
34
|
+
else
|
35
|
+
@params = param.split
|
36
|
+
@params << param_last unless param_last.nil?
|
37
|
+
end
|
38
|
+
@last_param = params.last
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/connection.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require './lib/command'
|
3
|
+
|
4
|
+
module IRConnect
|
5
|
+
# Simple wrapper around common IRC commands
|
6
|
+
class Connection
|
7
|
+
DEFAULT_OPTIONS = { port: 6667, socket_class: TCPSocket }
|
8
|
+
|
9
|
+
attr_reader :socket, :port, :connected, :nick, :server, :command_buffer
|
10
|
+
|
11
|
+
LOGIN_COMMANDS = {
|
12
|
+
'001' => 'RPL_WELCOME',
|
13
|
+
'431' => 'ERR_NONICKNAMEGIVEN',
|
14
|
+
'432' => 'ERR_ERRONEUSNICKNAME',
|
15
|
+
'433' => 'ERR_NICKNAMEINUSE',
|
16
|
+
'436' => 'ERR_NICKCOLLISION',
|
17
|
+
'461' => 'ERR_NEEDMOREPARAMS',
|
18
|
+
'462' => 'ERR_ALREADYREGISTERED'
|
19
|
+
}
|
20
|
+
|
21
|
+
JOIN_COMMANDS = {
|
22
|
+
'461' => 'ERR_NEEDMOREPARAMS',
|
23
|
+
'471' => 'ERR_CHANNELISFULL',
|
24
|
+
'473' => 'ERR_INVITEONLYCHAN',
|
25
|
+
'474' => 'ERR_BANNEDFROMCHAN',
|
26
|
+
'475' => 'ERR_BADCHANNELKEY',
|
27
|
+
'476' => 'ERR_BADCHANMASK',
|
28
|
+
'403' => 'ERR_NOSUCHCHANNEL',
|
29
|
+
'405' => 'ERR_TOOMANYCHANNELS',
|
30
|
+
'332' => 'RPL_TOPIC',
|
31
|
+
'353' => 'RPL_NAMREPLY'
|
32
|
+
}
|
33
|
+
|
34
|
+
def initialize(server, options = {})
|
35
|
+
options = DEFAULT_OPTIONS.merge(options)
|
36
|
+
@server = server
|
37
|
+
@port = options[:port]
|
38
|
+
@nick = options[:nick]
|
39
|
+
@socket = options[:socket_class].new(@server, @port)
|
40
|
+
@command_buffer = []
|
41
|
+
end
|
42
|
+
|
43
|
+
def nick(name)
|
44
|
+
unless name =~ /\A[a-z_\-\[\]\\^{}|`][a-z0-9_\-\[\]\\^{}|`]+\z/i
|
45
|
+
fail 'Invalid NICK'
|
46
|
+
end
|
47
|
+
send("NICK #{name}")
|
48
|
+
end
|
49
|
+
|
50
|
+
# host and server are typically ignored by servers
|
51
|
+
# for security reasons
|
52
|
+
def user(nickname, hostname, servername, fullname)
|
53
|
+
send("USER #{nickname} #{hostname} #{servername} :#{fullname}")
|
54
|
+
end
|
55
|
+
|
56
|
+
def login(nickname, hostname, servername, fullname)
|
57
|
+
nick(nickname)
|
58
|
+
user(nickname, hostname, servername, fullname)
|
59
|
+
reply = receive_until { |c| LOGIN_COMMANDS.include?(c.command) }
|
60
|
+
|
61
|
+
fail 'Login error, no response from server' if reply.nil?
|
62
|
+
if reply.command != '001'
|
63
|
+
fail "Login error: #{reply.last_param}\n" \
|
64
|
+
"Received: #{reply.command} -> #{LOGIN_COMMANDS[reply.command]}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def join_channel(chan)
|
69
|
+
send("JOIN #{chan}")
|
70
|
+
reply = receive_until { |c| JOIN_COMMANDS.include?(c.command) }
|
71
|
+
|
72
|
+
fail 'Unable to join channel, unknown error' if reply.nil?
|
73
|
+
unless reply.command == '332' || reply.command == '353'
|
74
|
+
fail "Error joining #{chan}: #{reply.last_param} \n" \
|
75
|
+
"Received: #{reply.command} -> #{JOIN_COMMANDS[reply.command]}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def privmsg(target, message)
|
80
|
+
send("PRIVMSG #{target} :#{message}")
|
81
|
+
end
|
82
|
+
|
83
|
+
def receive
|
84
|
+
return command_buffer.shift unless command_buffer.empty?
|
85
|
+
|
86
|
+
command = receive_command
|
87
|
+
command.nil? ? nil : IRConnect::Command.new(command)
|
88
|
+
end
|
89
|
+
|
90
|
+
def receive_until
|
91
|
+
skip_commands = []
|
92
|
+
|
93
|
+
while (command = receive)
|
94
|
+
if yield(command)
|
95
|
+
command_buffer.unshift(*skip_commands)
|
96
|
+
return command
|
97
|
+
else
|
98
|
+
skip_commands << command
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def receive_command
|
106
|
+
command = socket.gets
|
107
|
+
return nil if command.nil?
|
108
|
+
|
109
|
+
if command =~ /\APING (.*?)\r\n\Z/
|
110
|
+
send("PONG #{Regexp.last_match(1)}")
|
111
|
+
receive_command
|
112
|
+
else
|
113
|
+
command.sub(/\r\n\Z/, '')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def send(cmd)
|
118
|
+
socket.print("#{cmd}\r\n")
|
119
|
+
rescue IOError
|
120
|
+
raise
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/lib/irconnect.rb
ADDED
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: irconnect
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Speers
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-05 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Wrapper around basic IRC Client functionality
|
14
|
+
email: speersj@fastmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/command.rb
|
20
|
+
- lib/connection.rb
|
21
|
+
- lib/irconnect.rb
|
22
|
+
homepage: https://github.com/jaspeers/irconnect
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
metadata: {}
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 2.4.5
|
43
|
+
signing_key:
|
44
|
+
specification_version: 4
|
45
|
+
summary: irconnect
|
46
|
+
test_files: []
|