gruby 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ # svn propset svn:ignore -F .svnignore .
2
+ # svn propedit svn:ignore .
3
+ doc
4
+ pkg
5
+ .rake_tasks
6
+ *.gem
@@ -0,0 +1,11 @@
1
+ == 0.2.1 / 2007-08-11
2
+ * added gruby.rb file
3
+
4
+ == 0.2.0 / 2007-08-05
5
+ * uri-open instead of socket in connection_params method
6
+ * few callback added
7
+ * readme files
8
+ * new rake file
9
+
10
+ == 0.1.0 / 2007-04-15
11
+ * initial version
@@ -0,0 +1,52 @@
1
+ == GRuby
2
+ http://gruby.rubyforge.org
3
+ http://fazibear.prv.pl
4
+
5
+ == DESCRIPTION:
6
+
7
+ Gadu-Gadu protocol implementation in Ruby language
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * loggin
12
+ * set status
13
+ * set status messages
14
+ * send messages
15
+ * recive messages
16
+
17
+ == SYNOPSIS:
18
+
19
+ require File.dirname(__FILE__) + '/../lib/GRuby'
20
+
21
+ gg_uin = ''
22
+ gg_pass = ''
23
+
24
+ gg = GG::new_session :uin => gg_uin, :password => gg_pass
25
+ gg.on_recive_message do |m|
26
+ gg.set_status :status => GG::STATUS_AVAIL_DESCR, :description => m.message
27
+ gg.send_message :uin => m.sender, :message => "Status '#{m.message}' was set"
28
+ end
29
+ gg.set_status :status => GG::STATUS_AVAIL_DESCR, :description => "Send me new status :)"
30
+
31
+ gets
32
+
33
+ == REQUIREMENTS:
34
+
35
+ * ruby
36
+ * gadu-gadu account
37
+
38
+ == INSTALL:
39
+
40
+ * sudo gem install gruby
41
+
42
+ == LICENSE:
43
+
44
+ GRuby - Gadu-Gadu protocol implementation in Ruby language
45
+
46
+ Copyright (C) 2007 Michal Kalbarczyk
47
+
48
+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
49
+
50
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
51
+
52
+ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "gruby"
8
+ gemspec.summary = "Gadu-Gadu protocol implementation in Ruby language"
9
+ gemspec.email = "fazibear@gmail.com"
10
+ gemspec.homepage = "http://github.com/fazibear/gruby"
11
+ gemspec.description = "Gadu-Gadu protocol implementation in Ruby language"
12
+ gemspec.authors = ["fazibear"]
13
+ end
14
+ rescue LoadError
15
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
16
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.1
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/GRuby'
4
+
5
+ gg_uin = ''
6
+ gg_pass = ''
7
+
8
+ gg = GG::new_session :uin => gg_uin, :password => gg_pass
9
+ gg.on_recive_message do |m|
10
+ gg.set_status :status => GG::STATUS_AVAIL_DESCR, :description => m.message
11
+ gg.send_message :uin => m.sender, :message => "Status '#{m.message}' was set"
12
+ end
13
+ gg.set_status :status => GG::STATUS_AVAIL_DESCR, :description => "Send me new status :)"
14
+
15
+ gets
@@ -0,0 +1,55 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{gruby}
8
+ s.version = "0.2.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["fazibear"]
12
+ s.date = %q{2009-11-23}
13
+ s.description = %q{Gadu-Gadu protocol implementation in Ruby language}
14
+ s.email = %q{fazibear@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "CHANGELOG.rdoc",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "examples/status.rb",
25
+ "gruby.gemspec",
26
+ "lib/GRuby/GG.rb",
27
+ "lib/GRuby/GG_constants.rb",
28
+ "lib/GRuby/GG_packets.rb",
29
+ "lib/GRuby/GG_utils.rb",
30
+ "lib/gruby.rb",
31
+ "test/test_GRuby.rb",
32
+ "test/test_helper.rb"
33
+ ]
34
+ s.homepage = %q{http://github.com/fazibear/gruby}
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.5}
38
+ s.summary = %q{Gadu-Gadu protocol implementation in Ruby language}
39
+ s.test_files = [
40
+ "test/test_helper.rb",
41
+ "test/test_GRuby.rb",
42
+ "examples/status.rb"
43
+ ]
44
+
45
+ if s.respond_to? :specification_version then
46
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
50
+ else
51
+ end
52
+ else
53
+ end
54
+ end
55
+
@@ -0,0 +1,145 @@
1
+ module GG
2
+
3
+ #
4
+ # Return new GG session
5
+ #
6
+ def self.new_session( params )
7
+ Session.new( params )
8
+ end
9
+
10
+ class Session
11
+
12
+ attr_reader :connected
13
+
14
+ def initialize( params )
15
+ @uin = params[:uin]
16
+ @password = params[:password]
17
+ @message_seq = 0
18
+ @connected = true
19
+ @logged = false
20
+ @socket = nil
21
+ @wait4login = true
22
+ @wait4login = params[:async] unless params[:async].nil?
23
+
24
+ # callbacks
25
+ @revice_msg_callback = nil
26
+ @login_failed_callback = lambda do exit end
27
+ @disconnecting_callback = lambda do exit end
28
+
29
+ socket_thread = Thread.new do
30
+ begin
31
+ params = GG::connection_params
32
+ @socket = TCPSocket.new( params['host'] , params['port'] )
33
+ while @connected do
34
+ begin
35
+ r_packet = PACKET.new
36
+ puts ":: Wait for data ..." if $DEBUG
37
+ r_packet.header = @socket.read r_packet.header_length
38
+ r_packet.data = @socket.read r_packet.length
39
+ rescue => e
40
+ @logged = false
41
+ @connected = false
42
+ end
43
+ case r_packet.type
44
+ when WELCOME
45
+ r_packet.type = PACKET_WELCOME
46
+ s_packet = PACKET.new
47
+ s_packet.type = PACKET_LOGIN60
48
+ s_packet.uin = @uin.to_i
49
+ s_packet.hash = GG::login_hash( @password, r_packet.seed )
50
+
51
+ @socket.write s_packet.packed
52
+ puts "++ #{s_packet} send" if $DEBUG
53
+ s_packet = s_packet.destroy
54
+ when LOGIN_OK
55
+ @logged = true
56
+ @wait4login = false
57
+ when RECV_MSG
58
+ r_packet.type = PACKET_RECV_MSG
59
+ @recive_msg_callback.call r_packet if @recive_msg_callback
60
+ when SEND_MSG_ACK
61
+ r_packet.type = PACKET_SEND_MSG_ACK
62
+ when LOGIN_FAILED
63
+ puts "!! Login failed" if $DEBUG
64
+ @login_failed_callback.call if @login_failed_callback
65
+ when DISCONNECTING
66
+ puts "!! Disconecting" if $DEBUG
67
+ @disconnecting_callback.call if @disconnecting_callback
68
+ else
69
+ puts "?? Unknown packet" if $DEBUG
70
+ end
71
+ r_packet = r_packet.destroy
72
+ end
73
+ puts ":: Disconected" if $DEBUG
74
+ rescue => e
75
+ puts "!! Exception: #{e}" if $DEBUG
76
+ puts "Something went wrong :)" unless $DEBUG
77
+ exit 0
78
+ end
79
+ end
80
+ while @wait4login do
81
+ sleep 1
82
+ end
83
+ end
84
+
85
+
86
+ #
87
+ # Recive message callback
88
+ #
89
+ def on_recive_message( &block )
90
+ @recive_msg_callback = block;
91
+ end
92
+
93
+ #
94
+ # Login failed callback
95
+ #
96
+ def on_login_failed( &block )
97
+ @login_failed = block;
98
+ end
99
+
100
+ #
101
+ # Disconnecting callback
102
+ #
103
+ def on_diconnect( &block )
104
+ @disconnecting_callback = block;
105
+ end
106
+
107
+ #
108
+ # Send message
109
+ # :uin => GG reciver number
110
+ # :message => message text
111
+ #
112
+ def send_message( params )
113
+ if @logged
114
+ s_packet = PACKET.new
115
+ s_packet.type = PACKET_SEND_MSG
116
+ s_packet.recipient = params[:uin]
117
+ s_packet.message = params[:message]
118
+
119
+ @socket.write s_packet.packed
120
+ puts "++ #{s_packet} send" if $DEBUG
121
+ s_packet = s_packet.destroy
122
+ end
123
+ end
124
+
125
+ #
126
+ # Set new status.
127
+ # :status => new status, see constans.
128
+ # :description => new description
129
+ #
130
+ def set_status( params )
131
+ if @logged
132
+ s_packet = PACKET.new
133
+ s_packet.type = PACKET_NEW_STATUS
134
+ s_packet.status = params[:status]
135
+ s_packet.description = params[:description]
136
+
137
+ @socket.write s_packet.packed
138
+ puts "++ #{s_packet} send" if $DEBUG
139
+ s_packet = s_packet.destroy
140
+ end
141
+ end
142
+
143
+ end
144
+ end
145
+
@@ -0,0 +1,42 @@
1
+ module GG
2
+ HEADER = 0x0000
3
+ NEW_STATUS = 0x0002
4
+ PONG = 0x0007
5
+ PING = 0x0008
6
+ SEND_MSG = 0x000b
7
+ LOGIN = 0x000c
8
+ ADD_NOTIFY = 0x000d
9
+ REMOVE_NOTIFY = 0x000e
10
+ NOTIFY_FIRST = 0x000f
11
+ NOTIFY_LAST = 0x0010
12
+ LIST_EMPTY = 0x0012
13
+ LOGIN_EXT = 0x0013
14
+ PUBDIR50_REQUEST = 0x0014
15
+ LOGIN60 = 0x0015
16
+ USERLIST_REQUEST = 0x0016
17
+
18
+ WELCOME = 0x0001
19
+ STATUS = 0x0002
20
+ LOGIN_OK = 0x0003
21
+ SEND_MSG_ACK = 0x0005
22
+ LOGIN_FAILED = 0x0009
23
+ RECV_MSG = 0x000a
24
+ DISCONNECTING = 0x000b
25
+ NOTIFY_REPLY = 0x000c
26
+ PUBDIR50_REPLY = 0x000e
27
+ STATUS60 = 0x000f
28
+ USERLIST_REPLY = 0x0010
29
+ NOTIFY_REPLY60 = 0x0011
30
+ NEED_EMAIL = 0x0014
31
+
32
+ STATUS_NOT_AVAIL = 0x0001
33
+ STATUS_NOT_AVAIL_DESCR = 0x0015
34
+ STATUS_AVAIL = 0x0002
35
+ STATUS_AVAIL_DESCR = 0x0004
36
+ STATUS_BUSY = 0x0003
37
+ STATUS_BUSY_DESCR = 0x0005
38
+ STATUS_INVISIBLE = 0x0014
39
+ STATUS_INVISIBLE_DESCR = 0x0016
40
+ STATUS_BLOCKED = 0x0006
41
+ STATUS_FRIENDS_MASK = 0x8000
42
+ end
@@ -0,0 +1,241 @@
1
+ module GG
2
+
3
+ #
4
+ # GG Packet class
5
+ #
6
+ class PACKET
7
+ def initialize
8
+ puts "++ #{self} created" if $DEBUG
9
+ end
10
+
11
+ def destroy
12
+ puts "++ #{self} destroyed" if $DEBUG
13
+ nil
14
+ end
15
+
16
+ def header=(data)
17
+ unpacked = data.unpack 'II'
18
+ @type, @length = unpacked
19
+ puts "++ #{self} recived header ... type:#{@type} length:#{@length}" if $DEBUG
20
+ end
21
+
22
+ def header_length
23
+ 8
24
+ end
25
+
26
+ def type
27
+ @type
28
+ end
29
+
30
+ def length
31
+ @length
32
+ end
33
+
34
+ def type=(type)
35
+ begin
36
+ self.extend type
37
+ puts "++ #{self} extend to #{type}" if $DEBUG
38
+ fields @data if @data
39
+ rescue => e
40
+ raise "class extend ... #{e}"
41
+ end
42
+ end
43
+
44
+ def data=(data)
45
+ @data = data
46
+ puts "++ #{self} recived data" if $DEBUG
47
+ end
48
+
49
+ def pack(pattern)
50
+ begin
51
+ puts "++ #{self} data packed" if $DEBUG
52
+ packet.pack pattern
53
+ rescue => e
54
+ raise "packet pack ... #{e}"
55
+ end
56
+ end
57
+ end
58
+
59
+ # RECV PACKETS #
60
+
61
+ module PACKET_WELCOME
62
+ attr_reader :seed
63
+
64
+ def type
65
+ WELCOME
66
+ end
67
+
68
+ def fields(data)
69
+ unpacked = data.unpack 'I'
70
+ @seed = unpacked[0]
71
+ end
72
+ end
73
+
74
+ module PACKET_RECV_MSG
75
+ attr_reader :sender # numer nadawcy
76
+ attr_reader :seq # numer sekwencyjny
77
+ attr_reader :time # czas nadania
78
+ attr_reader :class # klasa wiadomości
79
+ attr_reader :message # treść wiadomości
80
+
81
+ def type
82
+ RECV_MSG
83
+ end
84
+
85
+ def fields(data)
86
+ unpacked = data.unpack 'IIIIZ*'
87
+ @sender,
88
+ @seq,
89
+ @time,
90
+ @class,
91
+ @message = unpacked
92
+ end
93
+
94
+ end
95
+
96
+ module PACKET_SEND_MSG_ACK
97
+ attr_reader :status # stan wiadomości */
98
+ attr_reader :recipient # numer odbiorcy */
99
+ attr_reader :seq # numer sekwencyjny */
100
+
101
+ def type
102
+ SEND_MSG_ACK
103
+ end
104
+
105
+ def fields(data)
106
+ unpacked = data.unpack 'III'
107
+ @status,
108
+ @recipient,
109
+ @seq = unpacked
110
+ end
111
+ end
112
+
113
+ # SEND PACKECTS #
114
+
115
+ module PACKET_LOGIN60
116
+ attr_writer :uin # mój numerek
117
+ attr_writer :hash # hash hasła */
118
+ attr_writer :status # status na dzień dobry */
119
+ attr_writer :version # moja wersja klienta */
120
+ attr_writer :unknown1 # 0x00 */
121
+ attr_writer :local_ip # mój adres ip */
122
+ attr_writer :local_port # port, na którym słucham */
123
+ attr_writer :external_ip # zewnętrzny adres ip */
124
+ attr_writer :external_port # zewnętrzny port */
125
+ attr_writer :image_size # maksymalny rozmiar grafiki w KB */
126
+ attr_writer :unknown2 # 0xbe */
127
+ attr_writer :description # opis, nie musi wystąpić */
128
+ attr_writer :time # czas, nie musi wystąpić */
129
+
130
+ def type
131
+ LOGIN60
132
+ end
133
+
134
+ def packet
135
+ [
136
+ type,
137
+ length,
138
+ @uin ? @uin : 0,
139
+ @hash ? @hash : 0,
140
+ @status ? @status : 0,
141
+ @version ? @version : 0x22,
142
+ @unknown1 ? @unknown1 : 0,
143
+ @local_ip ? @local_ip : 0,
144
+ @local_port ? @local_port : 0,
145
+ @external_ip ? @external_ip : 0,
146
+ @external_port ? @external_port : 0,
147
+ @image_size ? @image_size : 0,
148
+ @unknown2 ? @unknown2 : 0xBE,
149
+ @description ? "#{@description}" : "\0",
150
+ @time ? @time : 0
151
+ ]
152
+ end
153
+
154
+ def length
155
+ 4+4+4+4+1+4+2+4+2+1+1+(@description ? @description.length : 1)+4
156
+ end
157
+
158
+ def packed
159
+ pack 'II IIIIcIsIsccA*I'
160
+ end
161
+
162
+ end
163
+
164
+ module PACKET_NEW_STATUS
165
+ attr_writer :status # na jaki zmienić? */
166
+ attr_writer :description # opis, nie musi wystąpić */
167
+ attr_writer :time # czas, nie musi wystąpić */
168
+
169
+ def type
170
+ NEW_STATUS
171
+ end
172
+
173
+ def packet
174
+ [
175
+ type,
176
+ length,
177
+ @status ? @status : 0,
178
+ @description ? "#{@description}" : "\0",
179
+ @time ? @time : 0
180
+ ]
181
+ end
182
+
183
+ def length
184
+ 4+(@description ? @description.length : 1)+4
185
+ end
186
+
187
+ def packed
188
+ pack 'II IA*I'
189
+ end
190
+ end
191
+
192
+ module PACKET_LIST_EMPTY
193
+ def type
194
+ LIST_EMPTY
195
+ end
196
+ def packet
197
+ [
198
+ type,
199
+ length
200
+ ]
201
+ end
202
+
203
+ def length
204
+ 0
205
+ end
206
+
207
+ def packed
208
+ pack 'II'
209
+ end
210
+ end
211
+
212
+ module PACKET_SEND_MSG
213
+ attr_writer :recipient # numer odbiorcy */
214
+ attr_writer :seq # numer sekwencyjny */
215
+ attr_writer :class # klasa wiadomości */
216
+ attr_writer :message # treść */
217
+
218
+ def type
219
+ SEND_MSG
220
+ end
221
+
222
+ def packet
223
+ [
224
+ type,
225
+ length,
226
+ @recipient ? @recipient : 0,
227
+ @seq ? @seq : 0,
228
+ @class ? @class : 0x0008,
229
+ @message ? "#{@message}" : "\0"
230
+ ]
231
+ end
232
+
233
+ def length
234
+ 4+4+4+@message.length
235
+ end
236
+
237
+ def packed
238
+ pack 'II IIIA*'
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,50 @@
1
+ module GG
2
+
3
+ #
4
+ # Return calculated password hash.
5
+ #
6
+ def self.login_hash ( password, seed )
7
+ x = 0;
8
+ y = seed;
9
+ z = 0;
10
+
11
+ password.each_byte do |char|
12
+ x = ( x & 0xffffff00 ) | char.to_i
13
+ y ^= x;
14
+ y &= 0xffffffff
15
+ y += x;
16
+ y &= 0xffffffff
17
+ x <<= 8;
18
+ x &= 0xffffffff
19
+ y ^= x;
20
+ y &= 0xffffffff
21
+ x <<= 8;
22
+ x &= 0xffffffff
23
+ y -= x;
24
+ y &= 0xffffffff
25
+ x <<= 8;
26
+ x &= 0xffffffff
27
+ y ^= x;
28
+ y &= 0xffffffff
29
+ z = y & 0x1f;
30
+ z &= 0xffffffff
31
+ y = (y << z) | (y >> (32 - z))
32
+ y &= 0xffffffff
33
+ end
34
+ return y;
35
+ end
36
+
37
+ #
38
+ # Return connection params returned from gg server.
39
+ #
40
+ def self.connection_params
41
+ require 'open-uri'
42
+ gg_connection = open("http://appmsg.gadu-gadu.pl/appsvc/appmsg4.asp?fmnumber=").readlines[0].split(/\s/)[2].split(':')
43
+ gg_connection_param = {
44
+ 'host' => gg_connection[0],
45
+ 'port' => gg_connection[1]
46
+ }
47
+ puts ":: Connection params ... host:#{gg_connection_param['host']} port:#{gg_connection_param['port']}" if $DEBUG
48
+ return gg_connection_param
49
+ end
50
+ end
@@ -0,0 +1 @@
1
+ Dir[File.join(File.dirname(__FILE__), 'GRuby/*.rb')].each { |lib| require lib }
@@ -0,0 +1,14 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestGRuby < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_hash
9
+ hash_t = GG::login_hash('GG_HASH_TEST', 12345)
10
+ hash_e = 2990357796
11
+ assert_equal( hash_t, hash_e )
12
+ end
13
+
14
+ end
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/GRuby'
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - fazibear
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-23 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Gadu-Gadu protocol implementation in Ruby language
17
+ email: fazibear@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - .gitignore
26
+ - CHANGELOG.rdoc
27
+ - README.rdoc
28
+ - Rakefile
29
+ - VERSION
30
+ - examples/status.rb
31
+ - gruby.gemspec
32
+ - lib/GRuby/GG.rb
33
+ - lib/GRuby/GG_constants.rb
34
+ - lib/GRuby/GG_packets.rb
35
+ - lib/GRuby/GG_utils.rb
36
+ - lib/gruby.rb
37
+ - test/test_GRuby.rb
38
+ - test/test_helper.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/fazibear/gruby
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --charset=UTF-8
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.5
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Gadu-Gadu protocol implementation in Ruby language
67
+ test_files:
68
+ - test/test_helper.rb
69
+ - test/test_GRuby.rb
70
+ - examples/status.rb