ruggby 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +2 -0
- data/Gemfile +2 -0
- data/MIT-LICENSE +20 -0
- data/Manifest +38 -0
- data/README.md +187 -0
- data/Rakefile +12 -0
- data/init.rb +1 -0
- data/lib/ruggby.rb +72 -0
- data/lib/ruggby/action/base.rb +16 -0
- data/lib/ruggby/action/change_status.rb +30 -0
- data/lib/ruggby/action/create_message.rb +27 -0
- data/lib/ruggby/action/login.rb +40 -0
- data/lib/ruggby/action/mark.rb +27 -0
- data/lib/ruggby/action/new_message.rb +28 -0
- data/lib/ruggby/action/ping.rb +40 -0
- data/lib/ruggby/action/read.rb +49 -0
- data/lib/ruggby/callback.rb +22 -0
- data/lib/ruggby/client.rb +95 -0
- data/lib/ruggby/converter.rb +57 -0
- data/lib/ruggby/logger.rb +67 -0
- data/lib/ruggby/packet/factory.rb +39 -0
- data/lib/ruggby/packet/incoming/base.rb +31 -0
- data/lib/ruggby/packet/incoming/login_status.rb +28 -0
- data/lib/ruggby/packet/incoming/message.rb +35 -0
- data/lib/ruggby/packet/incoming/welcome.rb +33 -0
- data/lib/ruggby/packet/outgoing/base.rb +67 -0
- data/lib/ruggby/packet/outgoing/change_status.rb +57 -0
- data/lib/ruggby/packet/outgoing/login.rb +75 -0
- data/lib/ruggby/packet/outgoing/mark.rb +28 -0
- data/lib/ruggby/packet/outgoing/message.rb +47 -0
- data/lib/ruggby/packet/outgoing/ping.rb +27 -0
- data/lib/ruggby/password.rb +19 -0
- data/lib/ruggby/socket.rb +67 -0
- data/lib/ruggby/string_encoder.rb +42 -0
- data/lib/ruggby/threader.rb +21 -0
- data/lib/ruggby/version.rb +5 -0
- data/ruggby.gemspec +35 -0
- data/spec/callback_spec.rb +40 -0
- data/spec/spec_helper.rb +7 -0
- metadata +142 -0
data/CHANGELOG.rdoc
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Maciej Mensfeld
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
CHANGELOG.rdoc
|
2
|
+
Gemfile
|
3
|
+
MIT-LICENSE
|
4
|
+
README.md
|
5
|
+
Rakefile
|
6
|
+
init.rb
|
7
|
+
lib/ruggby.rb
|
8
|
+
lib/ruggby/action/base.rb
|
9
|
+
lib/ruggby/action/change_status.rb
|
10
|
+
lib/ruggby/action/create_message.rb
|
11
|
+
lib/ruggby/action/login.rb
|
12
|
+
lib/ruggby/action/mark.rb
|
13
|
+
lib/ruggby/action/new_message.rb
|
14
|
+
lib/ruggby/action/ping.rb
|
15
|
+
lib/ruggby/action/read.rb
|
16
|
+
lib/ruggby/callback.rb
|
17
|
+
lib/ruggby/client.rb
|
18
|
+
lib/ruggby/converter.rb
|
19
|
+
lib/ruggby/logger.rb
|
20
|
+
lib/ruggby/packet/factory.rb
|
21
|
+
lib/ruggby/packet/incoming/base.rb
|
22
|
+
lib/ruggby/packet/incoming/login_status.rb
|
23
|
+
lib/ruggby/packet/incoming/message.rb
|
24
|
+
lib/ruggby/packet/incoming/welcome.rb
|
25
|
+
lib/ruggby/packet/outgoing/base.rb
|
26
|
+
lib/ruggby/packet/outgoing/change_status.rb
|
27
|
+
lib/ruggby/packet/outgoing/login.rb
|
28
|
+
lib/ruggby/packet/outgoing/mark.rb
|
29
|
+
lib/ruggby/packet/outgoing/message.rb
|
30
|
+
lib/ruggby/packet/outgoing/ping.rb
|
31
|
+
lib/ruggby/password.rb
|
32
|
+
lib/ruggby/socket.rb
|
33
|
+
lib/ruggby/string_encoder.rb
|
34
|
+
lib/ruggby/threader.rb
|
35
|
+
lib/ruggby/version.rb
|
36
|
+
spec/callback_spec.rb
|
37
|
+
spec/spec_helper.rb
|
38
|
+
Manifest
|
data/README.md
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
# ruGGby - Gadu Gadu protocol client implementation in pure Ruby language
|
2
|
+
|
3
|
+
## Install
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
gem install ruggby
|
7
|
+
```
|
8
|
+
|
9
|
+
and in your Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'ruggby'
|
13
|
+
```
|
14
|
+
|
15
|
+
## About
|
16
|
+
|
17
|
+
ruGGby is a Gadu-Gadu (Polish messenger similar to ICQ) protocol client, which allows you to:
|
18
|
+
|
19
|
+
* Login to your Gadu-Gadu account
|
20
|
+
* Set and change status and description
|
21
|
+
* Receive messages
|
22
|
+
* Send messages
|
23
|
+
* Perform callbacks on almost every event connected to GG handling
|
24
|
+
* Works with big GG numbers
|
25
|
+
* Works with polish letters and other UTF-8 characters
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
Let's start with a simple example:
|
30
|
+
|
31
|
+
### Simple example
|
32
|
+
```ruby
|
33
|
+
gg = RuGGby::Client.new
|
34
|
+
|
35
|
+
gg.login!(LOGIN, PASSWORD)
|
36
|
+
gg.message(RECEIVER_GG, 'this is a message')
|
37
|
+
gg.logout!
|
38
|
+
```
|
39
|
+
|
40
|
+
So, what have we done? We've created an Gadu-Gadu instance client, logged in, sent a message and logged out. Easy enough ;)
|
41
|
+
|
42
|
+
### Login in and login out
|
43
|
+
|
44
|
+
Log in/out process is fairly simple:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
gg = RuGGby::Client.new
|
48
|
+
|
49
|
+
gg.login!(LOGIN, PASSWORD)
|
50
|
+
gg.logout!
|
51
|
+
```
|
52
|
+
|
53
|
+
We can also pass two additional parameters to *login!* method:
|
54
|
+
|
55
|
+
* :status - initial GG status
|
56
|
+
* :description - initial GG description
|
57
|
+
|
58
|
+
So the "full" login would look like:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
gg = RuGGby::Client.new
|
62
|
+
|
63
|
+
gg.login!(LOGIN, PASSWORD, :status => :busy, :description => '2Busy')
|
64
|
+
```
|
65
|
+
|
66
|
+
### Updating status and description
|
67
|
+
|
68
|
+
Sometimes we want to update our status. In order to do so, invoke a *change_status* method with two parameters:
|
69
|
+
|
70
|
+
* status - status symbol
|
71
|
+
* description (optional) - optional description for status
|
72
|
+
|
73
|
+
The allowed statuses are:
|
74
|
+
|
75
|
+
* :available
|
76
|
+
* :busy
|
77
|
+
* :invisible
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
gg.change_status(:busy, 'I\'m so busy right now!')
|
81
|
+
```
|
82
|
+
|
83
|
+
### Keeping ruGGby bot alive
|
84
|
+
|
85
|
+
To keep the bot working, just invoke the *wait* method and it will exit:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
gg = RuGGby::Client.new
|
89
|
+
|
90
|
+
gg.on_new_message do |uid, time, message|
|
91
|
+
gg.message(uid, message)
|
92
|
+
end
|
93
|
+
|
94
|
+
gg.login!(LOGIN, PASSWORD)
|
95
|
+
gg.wait
|
96
|
+
```
|
97
|
+
|
98
|
+
### Logger
|
99
|
+
|
100
|
+
By default RuGGby uses a *RuGGby::Logger* logger, which only prints output to console. However, you can replace it with any logger that support following methods:
|
101
|
+
|
102
|
+
* *debug*(message)
|
103
|
+
* *info*(message)
|
104
|
+
* *error*(message)
|
105
|
+
* *fatal*(message)
|
106
|
+
|
107
|
+
To do so, create an *RuGGby::Client* instance and assign your own logger:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
require 'logger'
|
111
|
+
|
112
|
+
gg = RuGGby::Client.new
|
113
|
+
gg.logger = Logger.new('gg.log', :weekly)
|
114
|
+
```
|
115
|
+
|
116
|
+
In order to change log level, just assing a new one like this:
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
RuGGby::Client.log_level = :error
|
120
|
+
```
|
121
|
+
|
122
|
+
### Events
|
123
|
+
|
124
|
+
RuGGby supports events, so you can assign your own events on demand. Events list:
|
125
|
+
|
126
|
+
* :read - event triggered on each read from RuGGby::Socket
|
127
|
+
* :ping - event triggered on each GG Server Ping
|
128
|
+
* :new_message - event triggered on new message receive
|
129
|
+
* :mark - event triggered when we send mark packet to GG Server
|
130
|
+
* :login - event triggered after login
|
131
|
+
* :create_message - event triggered after message has been send
|
132
|
+
* :change_status - event triggered after our status/description change
|
133
|
+
|
134
|
+
Each event block is triggered with parameters:
|
135
|
+
|
136
|
+
* :read(packet) - *RuGGby::Packet* instance (build using *RuGGby::Packet::Factory*)
|
137
|
+
* :ping - no parameters
|
138
|
+
* :new_message(uin, timestamp, message)
|
139
|
+
* :mark - no parameters
|
140
|
+
* :login - no parameters
|
141
|
+
* :create_message(uin, message)
|
142
|
+
* :change_status(status, description)
|
143
|
+
|
144
|
+
In order to assign an action to an event, pass a block into events hash:
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
gg = RuGGby::Client.new
|
148
|
+
|
149
|
+
gg.actions[:new_message] = proc do |uin, created_at, msg|
|
150
|
+
# uin is a sender GG number (Integer)
|
151
|
+
# created_at - Time.at when message has been sent
|
152
|
+
# msg - String containing message
|
153
|
+
print "#{uin}-#{created_at}: #{msg}\n"
|
154
|
+
end
|
155
|
+
```
|
156
|
+
|
157
|
+
However most of the events don't need an action so you can use *on_new_message* method to assign a block:
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
gg = RuGGby::Client.new
|
161
|
+
|
162
|
+
gg.on_new_message do |uid, time, message|
|
163
|
+
gg.message(uid, message)
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
167
|
+
The *:new_message* event is triggered in a separate thread so the socket read process is still going. The above code will (after login!) return a message to it's sender.
|
168
|
+
|
169
|
+
## TODO
|
170
|
+
|
171
|
+
* Tests (currently there is no :()
|
172
|
+
* More sophisticated GG actions (friends, etc)
|
173
|
+
|
174
|
+
## Note on Patches/Pull Requests
|
175
|
+
|
176
|
+
* Fork the project.
|
177
|
+
* Make your feature addition or bug fix.
|
178
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
179
|
+
* Commit, do not mess with Rakefile, version, or history.
|
180
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
181
|
+
* Send me a pull request. Bonus points for topic branches.
|
182
|
+
|
183
|
+
## Copyright
|
184
|
+
|
185
|
+
Copyright (c) 2012 Maciej Mensfeld. See LICENSE for details.
|
186
|
+
|
187
|
+
Based on http://toxygen.net/libgadu/protocol
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('ruggby', '0.3.0') do |p|
|
6
|
+
p.description = 'Gadu Gadu protocol client implementation in Ruby language'
|
7
|
+
p.url = 'https://github.com/mensfeld/ruGGby'
|
8
|
+
p.author = 'Maciej Mensfeld'
|
9
|
+
p.email = 'maciej@mensfeld.pl'
|
10
|
+
p.ignore_pattern = ['tmp/*', 'script/*']
|
11
|
+
p.development_dependencies = ['rspec >=2.0.0', 'mocha']
|
12
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'ruggby'
|
data/lib/ruggby.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# RuGGby is a simple (not completed) implementation of a GG written in Ruby
|
2
|
+
# It allows us to login to our account and receive/send messages
|
3
|
+
|
4
|
+
# Currently due to lack of time this are the only actions that are available
|
5
|
+
|
6
|
+
# Usage example:
|
7
|
+
|
8
|
+
# gg = RuGGby::Client.new
|
9
|
+
#
|
10
|
+
# gg.on_new_message do |uid, message|
|
11
|
+
# gg.message(uid, message)
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# gg.login!(gg_nr, Pass)
|
15
|
+
# gg.wait
|
16
|
+
# gg.logout!
|
17
|
+
|
18
|
+
$:.unshift File.dirname(__FILE__)
|
19
|
+
|
20
|
+
module RuGGby
|
21
|
+
|
22
|
+
autoload :Version, 'ruggby/version.rb'
|
23
|
+
|
24
|
+
module Packet
|
25
|
+
# Factory used to build incoming packets out of raw socket messages
|
26
|
+
autoload :Factory, 'ruggby/packet/factory.rb'
|
27
|
+
|
28
|
+
# Incoming packets used to wrap the raw socket messages send by GG server
|
29
|
+
module Incoming
|
30
|
+
path = 'ruggby/packet/incoming'
|
31
|
+
autoload :Base, "#{path}/base.rb"
|
32
|
+
autoload :LoginStatus, "#{path}/login_status.rb"
|
33
|
+
autoload :Message, "#{path}/message.rb"
|
34
|
+
autoload :Welcome, "#{path}/welcome.rb"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Outgoing packets send to GG server
|
38
|
+
module Outgoing
|
39
|
+
path = 'ruggby/packet/outgoing'
|
40
|
+
autoload :Base, "#{path}/base.rb"
|
41
|
+
autoload :Login, "#{path}/login.rb"
|
42
|
+
autoload :Mark, "#{path}/mark.rb"
|
43
|
+
autoload :Message, "#{path}/message.rb"
|
44
|
+
autoload :Ping, "#{path}/ping.rb"
|
45
|
+
autoload :ChangeStatus, "#{path}/change_status.rb"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Available actions (we can hookup to all of them)
|
50
|
+
module Action
|
51
|
+
path = 'ruggby/action'
|
52
|
+
autoload :Base, "#{path}/base.rb"
|
53
|
+
autoload :CreateMessage, "#{path}/create_message.rb"
|
54
|
+
autoload :Login, "#{path}/login.rb"
|
55
|
+
autoload :Mark, "#{path}/mark.rb"
|
56
|
+
autoload :NewMessage, "#{path}/new_message.rb"
|
57
|
+
autoload :Ping, "#{path}/ping.rb"
|
58
|
+
autoload :Read, "#{path}/read.rb"
|
59
|
+
autoload :ChangeStatus, "#{path}/change_status.rb"
|
60
|
+
end
|
61
|
+
|
62
|
+
# Other stuff that is needed
|
63
|
+
autoload :Socket, 'ruggby/socket'
|
64
|
+
autoload :Logger, 'ruggby/logger'
|
65
|
+
autoload :Callback, 'ruggby/callback'
|
66
|
+
autoload :Converter, 'ruggby/converter'
|
67
|
+
autoload :Password, 'ruggby/password'
|
68
|
+
autoload :Threader, 'ruggby/threader'
|
69
|
+
autoload :StringEncoder, 'ruggby/string_encoder'
|
70
|
+
autoload :Client, 'ruggby/client'
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RuGGby
|
2
|
+
|
3
|
+
module Action
|
4
|
+
|
5
|
+
# Action invoken when we want to change status
|
6
|
+
class ChangeStatus < Base
|
7
|
+
|
8
|
+
attr_reader :status, :description
|
9
|
+
|
10
|
+
def initialize(client, status, description)
|
11
|
+
@client = client
|
12
|
+
@block = client.actions[:change_status]
|
13
|
+
@status = status
|
14
|
+
@description = description
|
15
|
+
end
|
16
|
+
|
17
|
+
def run!
|
18
|
+
@client.logger.debug('RuGGby::Action::ChangeStatus')
|
19
|
+
|
20
|
+
msg = Packet::Outgoing::ChangeStatus.new(@status, @description)
|
21
|
+
@client.socket.write(msg)
|
22
|
+
|
23
|
+
@block.call(@status, @description) if @block
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RuGGby
|
2
|
+
|
3
|
+
module Action
|
4
|
+
|
5
|
+
# Sending message action
|
6
|
+
class CreateMessage < Base
|
7
|
+
|
8
|
+
def initialize(client, uin, message)
|
9
|
+
@client = client
|
10
|
+
@block = client.actions[:create_message]
|
11
|
+
@uin = uin
|
12
|
+
@message = message
|
13
|
+
end
|
14
|
+
|
15
|
+
def run!
|
16
|
+
@client.logger.debug('RuGGby::Action::CreateMessage')
|
17
|
+
|
18
|
+
msg = Packet::Outgoing::Message.new(@uin, @message)
|
19
|
+
@client.socket.write(msg)
|
20
|
+
@block.call(@uin, @message) if @block
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module RuGGby
|
2
|
+
|
3
|
+
module Action
|
4
|
+
|
5
|
+
# Login action - will log user in to a GG account
|
6
|
+
class Login < Base
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
@block = client.actions[:login]
|
11
|
+
end
|
12
|
+
|
13
|
+
def run!
|
14
|
+
@client.logger.debug('RuGGby::Action::Login')
|
15
|
+
|
16
|
+
welcome = RuGGby::Packet::Factory.new(@client.socket).build
|
17
|
+
|
18
|
+
login = Packet::Outgoing::Login.new(
|
19
|
+
:uin => @client.login,
|
20
|
+
:hash => Password.hash(@client.password, welcome.seed),
|
21
|
+
:status => @client.status,
|
22
|
+
:description => @client.description
|
23
|
+
)
|
24
|
+
|
25
|
+
@client.logger.debug('RuGGby::Action::Login sending Login packet')
|
26
|
+
@client.socket.write(login)
|
27
|
+
|
28
|
+
login_status = RuGGby::Packet::Factory.new(@client.socket).build
|
29
|
+
|
30
|
+
@client.logger.debug("RuGGby::Action::Login #{login_status.class}")
|
31
|
+
|
32
|
+
@client.logged = login_status.successful?
|
33
|
+
@block.call if @block
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|