em-msn 0.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +60 -0
- data/lib/em-msn.rb +1 -0
- data/lib/msn/challenge.rb +2 -1
- data/lib/msn/contact.rb +15 -0
- data/lib/msn/message.rb +2 -0
- data/lib/msn/messenger.rb +83 -11
- data/lib/msn/nexus.rb +1 -0
- data/lib/msn/notification_server.rb +1 -0
- data/lib/msn/protocol.rb +1 -0
- data/lib/msn/switchboard.rb +1 -0
- data/lib/msn/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -0,0 +1,60 @@
|
|
1
|
+
# em-msn
|
2
|
+
|
3
|
+
MSN client (EventMachine + Ruby)
|
4
|
+
|
5
|
+
## Project Pages
|
6
|
+
|
7
|
+
* [Docs](http://rdoc.info/gems/em-msn)
|
8
|
+
* [GitHub](https://github.com/manastech/em-msn)
|
9
|
+
|
10
|
+
# Usage
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
gem install em-msn
|
15
|
+
|
16
|
+
## Gemfile
|
17
|
+
|
18
|
+
gem 'em-msn'
|
19
|
+
|
20
|
+
## Example
|
21
|
+
|
22
|
+
require 'rubygems'
|
23
|
+
require 'em-msn'
|
24
|
+
|
25
|
+
EM.run do
|
26
|
+
EM.schedule do
|
27
|
+
msn = Msn::Messenger.new 'johndoe@hotmail.com', 'password'
|
28
|
+
|
29
|
+
msn.on_login_failed do |reason|
|
30
|
+
puts "Oops... #{reason}"
|
31
|
+
end
|
32
|
+
|
33
|
+
msn.on_ready do
|
34
|
+
msn.set_online_status :online
|
35
|
+
end
|
36
|
+
|
37
|
+
msn.on_message do |message|
|
38
|
+
puts "Got message from #{message.email}: #{message.text}"
|
39
|
+
|
40
|
+
msn.send_message message.email, "Hi #{message.display_name}!"
|
41
|
+
end
|
42
|
+
|
43
|
+
msn.on_contact_request do |email, display_name|
|
44
|
+
puts "Contact request from #{display_name} <#{email}>"
|
45
|
+
|
46
|
+
msn.add_contact email
|
47
|
+
end
|
48
|
+
|
49
|
+
msn.connect
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Contributions
|
54
|
+
|
55
|
+
All contributions are welcome. The gem doesn't have many tests and a lot of things
|
56
|
+
can be improved, as some parts of the protocol are not yet implemented.
|
57
|
+
|
58
|
+
# Author
|
59
|
+
|
60
|
+
[Ary Borenszweig](http://github.com/asterite)
|
data/lib/em-msn.rb
CHANGED
data/lib/msn/challenge.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# :nodoc:
|
1
2
|
class Msn::Challenge
|
2
3
|
ProductKey = "RG@XY*28Q5QHS%Q5"
|
3
4
|
ProductId = "PROD0113H11T8$X_"
|
@@ -37,7 +38,7 @@ class Msn::Challenge
|
|
37
38
|
new_hash_parts[2] ^= high;
|
38
39
|
new_hash_parts[3] ^= low;
|
39
40
|
|
40
|
-
new_hash_parts.map do |num|
|
41
|
+
new_hash_parts.map do |num|
|
41
42
|
str = num.to_s(16)
|
42
43
|
str = "#{'0' * (8 - str.length)}#{str}" if str.length != 8
|
43
44
|
str.scan(/.{2}/).reverse.join
|
data/lib/msn/contact.rb
CHANGED
@@ -1,16 +1,31 @@
|
|
1
|
+
# A contact returned from Msn::Messenger#get_contacts.
|
1
2
|
class Msn::Contact
|
3
|
+
|
4
|
+
# The contact's email
|
2
5
|
attr_accessor :email
|
6
|
+
|
7
|
+
# The contact's display name
|
3
8
|
attr_accessor :display_name
|
9
|
+
|
10
|
+
# Is the contact in your allow list?
|
4
11
|
attr_accessor :allow
|
12
|
+
|
13
|
+
# Is the contact in your blocked list?
|
5
14
|
attr_accessor :block
|
15
|
+
|
16
|
+
# Is the contact in your reverse list? (does she has you?)
|
6
17
|
attr_accessor :reverse
|
18
|
+
|
19
|
+
# Is the contact in your pending list? (you stil didn't approve her)
|
7
20
|
attr_accessor :pending
|
8
21
|
|
22
|
+
# :nodoc:
|
9
23
|
def initialize(email, display_name = nil)
|
10
24
|
@email = email
|
11
25
|
@display_name = display_name
|
12
26
|
end
|
13
27
|
|
28
|
+
# :nodoc:
|
14
29
|
def to_s
|
15
30
|
if display_name && display_name.length > 0
|
16
31
|
str = "#{display_name} <#{email}>"
|
data/lib/msn/message.rb
CHANGED
data/lib/msn/messenger.rb
CHANGED
@@ -1,27 +1,29 @@
|
|
1
|
+
# Main class to communicate with MSN.
|
1
2
|
class Msn::Messenger
|
2
3
|
attr_reader :username
|
3
4
|
attr_reader :password
|
4
5
|
|
5
|
-
|
6
|
-
attr_accessor :logger
|
7
|
-
|
8
|
-
def log_info(message)
|
9
|
-
return unless logger
|
10
|
-
|
11
|
-
logger.info message
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
|
6
|
+
# Create an MSN connection with a username (email) and password.
|
16
7
|
def initialize(username, password)
|
17
8
|
@username = username
|
18
9
|
@password = password
|
19
10
|
end
|
20
11
|
|
12
|
+
# Connects to the MSN server. Event handlers should be set before calling this method.
|
21
13
|
def connect
|
22
14
|
@notification_server = EM.connect 'messenger.hotmail.com', 1863, Msn::NotificationServer, self
|
23
15
|
end
|
24
16
|
|
17
|
+
# Sets your online status. Status can be:
|
18
|
+
# * :available, :online
|
19
|
+
# * :busy
|
20
|
+
# * :idle
|
21
|
+
# * :brb, :be_right_back
|
22
|
+
# * :away
|
23
|
+
# * :phone, :on_the_phone
|
24
|
+
# * :lunch, :out_to_lunch
|
25
|
+
# It is advisable to call this method as soon as you connect, otherwise you
|
26
|
+
# won't be able to perform certain actions (like sending messages).
|
25
27
|
def set_online_status(status)
|
26
28
|
case status
|
27
29
|
when :available, :online
|
@@ -43,91 +45,161 @@ class Msn::Messenger
|
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
48
|
+
# Adds a contact. Technically, this adds it to your Friends List.
|
46
49
|
def add_contact(email)
|
47
50
|
send_contact_command email, 'ADL', '1'
|
48
51
|
end
|
49
52
|
|
53
|
+
# Removes a contact. Technically, this removes it from your Friends List.
|
50
54
|
def remove_contact(email)
|
51
55
|
send_contact_command email, 'RML', '1'
|
52
56
|
end
|
53
57
|
|
58
|
+
# Blocks a contact. Technically, this removes it from your Allowed List.
|
54
59
|
def block_contact(email)
|
55
60
|
send_contact_command email, 'RML', '2'
|
56
61
|
end
|
57
62
|
|
63
|
+
# Unblocks a contact. Technically, this adds it to your Allowed List.
|
58
64
|
def unblock_contact(email)
|
59
65
|
send_contact_command email, 'ADL', '2'
|
60
66
|
end
|
61
67
|
|
68
|
+
# Returns all contacts associated to this Messenger account.
|
69
|
+
# This is an array of Msn::Contact.
|
62
70
|
def get_contacts
|
63
71
|
@notification_server.get_contacts
|
64
72
|
end
|
65
73
|
|
74
|
+
# Invoked when this Messenger gets connected to the server.
|
75
|
+
#
|
76
|
+
# msn.on_ready do
|
77
|
+
# msn.set_online_status :online
|
78
|
+
# end
|
66
79
|
def on_ready(&handler)
|
67
80
|
@on_ready_handler = handler
|
68
81
|
end
|
69
82
|
|
83
|
+
# Invoked when the username/password are incorrect.
|
84
|
+
#
|
85
|
+
# msn.on_login_failed do |reason|
|
86
|
+
# puts "Login failed: #{reason} :-("
|
87
|
+
# msn.close
|
88
|
+
# end
|
70
89
|
def on_login_failed(&handler)
|
71
90
|
@on_login_failed = handler
|
72
91
|
end
|
73
92
|
|
93
|
+
# Invoked when this Messenger gets disconnected from the server.
|
94
|
+
#
|
95
|
+
# msn.on_disconnect do
|
96
|
+
# # Try to reconnect
|
97
|
+
# msn.connect
|
98
|
+
# end
|
74
99
|
def on_disconnect(&handler)
|
75
100
|
@on_disconnect = handler
|
76
101
|
end
|
77
102
|
|
103
|
+
# Invoked when somebody sends a messages to this account, with an Msn::Message.
|
104
|
+
#
|
105
|
+
# msn.on_message do |msg|
|
106
|
+
# # msg is an Msn:Message instance
|
107
|
+
# end
|
78
108
|
def on_message(&handler)
|
79
109
|
@on_message_handler = handler
|
80
110
|
end
|
81
111
|
|
112
|
+
# Invoked after a message is sent by this Messenger, to know
|
113
|
+
# what happened with it.
|
114
|
+
#
|
115
|
+
# msn.on_message_ack do |message_id, status|
|
116
|
+
# # status can be :ack, :nak or :offline
|
117
|
+
# # message_id is the one you got from send_message
|
118
|
+
# end
|
82
119
|
def on_message_ack(&handler)
|
83
120
|
@on_message_ack_handler = handler
|
84
121
|
end
|
85
122
|
|
123
|
+
# Invoked when there is a contact request.
|
124
|
+
#
|
125
|
+
# msn.on_contact_request do |email, display_name|
|
126
|
+
# ...
|
127
|
+
# end
|
86
128
|
def on_contact_request(&handler)
|
87
129
|
@on_contact_request = handler
|
88
130
|
end
|
89
131
|
|
132
|
+
# Sends a message to the given email with the given text.
|
133
|
+
# Returns an ID (a number) that can be used to relate the
|
134
|
+
# send messages to ACKs.
|
90
135
|
def send_message(email, text)
|
91
136
|
@notification_server.send_message email, text
|
92
137
|
end
|
93
138
|
|
139
|
+
# Closes the connection to the MSN server.
|
94
140
|
def close
|
95
141
|
@notification_server.close_connection
|
96
142
|
end
|
97
143
|
|
144
|
+
# :nodoc:
|
98
145
|
def send_contact_command(email, command, list)
|
99
146
|
username, domain = email.split '@', 2
|
100
147
|
@notification_server.send_payload_command_and_wait command, %Q(<ml><d n="#{domain}"><c n="#{username}" t="1" l="#{list}" /></d></ml>)
|
101
148
|
end
|
102
149
|
|
150
|
+
# :nodoc:
|
103
151
|
def accept_message(message)
|
104
152
|
call_handler @on_message_handler, message
|
105
153
|
end
|
106
154
|
|
155
|
+
# :nodoc:
|
107
156
|
def accept_message_ack(id, status)
|
108
157
|
call_handler @on_message_ack_handler, id, status
|
109
158
|
end
|
110
159
|
|
160
|
+
# :nodoc:
|
111
161
|
def contact_request(email, display_name)
|
112
162
|
call_handler @on_contact_request, email, display_name
|
113
163
|
end
|
114
164
|
|
165
|
+
# :nodoc:
|
115
166
|
def ready
|
116
167
|
call_handler @on_ready_handler
|
117
168
|
end
|
118
169
|
|
170
|
+
# :nodoc:
|
119
171
|
def login_failed(message)
|
120
172
|
call_handler @on_login_failed, message
|
121
173
|
end
|
122
174
|
|
175
|
+
# :nodoc:
|
123
176
|
def disconnected
|
124
177
|
call_handler @on_disconnect
|
125
178
|
end
|
126
179
|
|
180
|
+
# :nodoc:
|
127
181
|
def call_handler(handler, *args)
|
128
182
|
if handler
|
129
183
|
Fiber.new { handler.call(*args) }.resume
|
130
184
|
end
|
131
185
|
end
|
186
|
+
|
187
|
+
# Sets a logger that will get logged as info all communication to the MSN server
|
188
|
+
# (but not all communication to the MSN nexus server).
|
189
|
+
def self.logger=(logger)
|
190
|
+
@logger = logger
|
191
|
+
end
|
192
|
+
|
193
|
+
# :nodoc:
|
194
|
+
def self.logger
|
195
|
+
@logger
|
196
|
+
end
|
197
|
+
|
198
|
+
# :nodoc:
|
199
|
+
def self.log_info(message)
|
200
|
+
return unless logger
|
201
|
+
|
202
|
+
logger.info message
|
203
|
+
end
|
132
204
|
end
|
133
205
|
|
data/lib/msn/nexus.rb
CHANGED
data/lib/msn/protocol.rb
CHANGED
data/lib/msn/switchboard.rb
CHANGED
data/lib/msn/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-msn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|