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.
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ require './lib/command.rb'
2
+ require './lib/connection.rb'
3
+
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: []