ruggby 0.3.0
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.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
|