warchat 0.0.9 → 0.0.10
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/README.rdoc +8 -4
- data/lib/warchat.rb +13 -2
- data/lib/warchat/chat/ack.rb +7 -0
- data/lib/warchat/chat/client.rb +17 -13
- data/lib/warchat/chat/message.rb +19 -16
- data/lib/warchat/chat/presence.rb +23 -7
- data/lib/warchat/model.rb +53 -0
- data/lib/warchat/models/character.rb +51 -0
- data/lib/warchat/models/guild.rb +7 -0
- data/lib/warchat/network/binary_reader.rb +5 -1
- data/lib/warchat/network/connection.rb +7 -11
- data/lib/warchat/network/session.rb +5 -5
- data/lib/warchat/timer.rb +2 -2
- data/lib/warchat/version.rb +1 -1
- metadata +10 -6
data/README.rdoc
CHANGED
@@ -25,6 +25,10 @@ This is a simple chat client that will let you talk in guild chat and receive me
|
|
25
25
|
PASSWORD = ''
|
26
26
|
CHARACTER_NAME = ''
|
27
27
|
CHARACTER_REALM = ''
|
28
|
+
HOST = "m.us.wowarmory.com"
|
29
|
+
#HOST = "m.eu.wowarmory.com"
|
30
|
+
#HOST = "m.kr.wowarmory.com"
|
31
|
+
PORT = 8780
|
28
32
|
|
29
33
|
client = Warchat::Chat::Client.new
|
30
34
|
|
@@ -35,18 +39,18 @@ This is a simple chat client that will let you talk in guild chat and receive me
|
|
35
39
|
client.on_message = Proc.new do |message|
|
36
40
|
case message.type
|
37
41
|
when Warchat::Chat::Message::CHAT_MSG_TYPE_GUILD_CHAT
|
38
|
-
puts "[Guild] #{message.
|
42
|
+
puts "[Guild] #{message.character.name}: #{message.body}"
|
39
43
|
when Warchat::Chat::Message::CHAT_MSG_TYPE_GUILD_MOTD
|
40
44
|
puts "MOTD: #{message.body}"
|
41
45
|
when Warchat::Chat::Message::CHAT_MSG_TYPE_OFFICER_CHAT
|
42
|
-
puts "[Officer] #{message.
|
46
|
+
puts "[Officer] #{message.character.name}: #{message.body}"
|
43
47
|
when Warchat::Chat::Message::CHAT_MSG_TYPE_WHISPER
|
44
|
-
puts "[Whisper] #{message.
|
48
|
+
puts "[Whisper] #{message.character.name}: #{message.body}"
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
48
52
|
begin
|
49
|
-
client.start(USERNAME,PASSWORD)
|
53
|
+
client.start(USERNAME,PASSWORD,HOST,PORT)
|
50
54
|
loop do
|
51
55
|
msg = gets.chomp
|
52
56
|
client.message msg,Warchat::Chat::Message::CHAT_MSG_TYPE_GUILD_CHAT
|
data/lib/warchat.rb
CHANGED
@@ -1,7 +1,18 @@
|
|
1
1
|
# encoding: ASCII-8BIT
|
2
|
-
require 'active_support/
|
2
|
+
require 'active_support/all'
|
3
3
|
|
4
4
|
module Warchat
|
5
|
+
def self.debug message
|
6
|
+
puts message if self.debug?
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.debug?
|
10
|
+
@debug and true or false
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.enable_debug v
|
14
|
+
@debug = v
|
15
|
+
end
|
5
16
|
end
|
6
17
|
|
7
|
-
[[
|
18
|
+
[[],['network'],['srp'],['chat'],['models']].each do |p| Dir.glob(File.join(File.expand_path('../warchat',__FILE__),*(p << '*.rb')),&method(:require)) end
|
data/lib/warchat/chat/client.rb
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
# encoding: ASCII-8BIT
|
2
2
|
module Warchat
|
3
3
|
module Chat
|
4
|
-
class
|
5
|
-
attr_accessor :on_message,:on_presence,:on_logout,:on_fail,:on_establish
|
4
|
+
class Client
|
5
|
+
attr_accessor :on_message,:on_presence,:on_logout,:on_fail,:on_establish,:on_presence_change,:on_ack
|
6
6
|
attr_accessor :on_message_afk,:on_message_dnd,:on_message_guild_chat,:on_message_motd,:on_message_officer_chat,:on_message_whisper,:on_chat_logout
|
7
7
|
|
8
|
-
attr_reader :session,:character_name,:character_realm
|
8
|
+
attr_reader :session,:character_name,:character_realm,:online_characters,:last_whisper
|
9
9
|
|
10
10
|
def initialize
|
11
11
|
@session = Warchat::Network::Session.new
|
12
|
-
|
13
12
|
[:receive,:establish,:error].each do |m|
|
14
13
|
session.send("on_#{m}=".to_sym, method("session_#{m}".to_sym))
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
18
|
-
def start
|
17
|
+
def start account_name, account_password,host="m.us.wowarmory.com",port=8780
|
19
18
|
[username,password].each do |s| s.respond_to? :force_encoding and s.force_encoding(__ENCODING__) end
|
20
|
-
self.session.start(
|
19
|
+
self.session.start(account_name,account_password,host,port)
|
21
20
|
end
|
22
21
|
|
23
22
|
def session_error response
|
@@ -38,7 +37,7 @@ module Warchat
|
|
38
37
|
[character_name,character_realm].each do |s| s.respond_to? :force_encoding and s.force_encoding(__ENCODING__) end
|
39
38
|
request = Warchat::Network::Request.new("/chat-login",:options=>{:mature_filter=>'false'},:n=>character_name,:r=>character_realm)
|
40
39
|
session.send_request(request)
|
41
|
-
@timer = Warchat::Timer.new(
|
40
|
+
@timer = Warchat::Timer.new(60) do keep_alive end
|
42
41
|
end
|
43
42
|
|
44
43
|
def logout
|
@@ -46,28 +45,33 @@ module Warchat
|
|
46
45
|
end
|
47
46
|
|
48
47
|
def chat_logout response
|
49
|
-
|
48
|
+
Warchat.debug 'Logged out of chat'
|
50
49
|
@timer and @timer.stop
|
51
50
|
on_chat_logout and on_chat_logout.call response
|
52
51
|
session.close
|
53
52
|
end
|
54
53
|
|
55
54
|
def chat_login response
|
56
|
-
|
55
|
+
Warchat.debug "Logged into chat"
|
57
56
|
@chat_session_id = response["chatSessionId"]
|
58
57
|
end
|
58
|
+
|
59
|
+
def chat_presence presence
|
60
|
+
on_presence and on_presence.call(presence)
|
61
|
+
end
|
59
62
|
|
60
63
|
def chat response
|
61
64
|
response.extend(Warchat::Chat::ChatResponse)
|
62
65
|
if response.ack?
|
63
|
-
|
66
|
+
on_ack and on_ack.call response
|
64
67
|
elsif response.message?
|
65
68
|
message = Warchat::Chat::Message.new(response)
|
69
|
+
@last_whisper = message if message.whisper?
|
66
70
|
[on_message,send("on_message_#{message.type}".to_sym)].compact.each do |m| m.call(message) end
|
67
71
|
elsif response.presence?
|
68
|
-
|
72
|
+
chat_presence Warchat::Chat::Presence.new(response)
|
69
73
|
else
|
70
|
-
|
74
|
+
Warchat.debug "unhandled chat type: #{response.chat_type}"
|
71
75
|
end
|
72
76
|
end
|
73
77
|
|
@@ -82,7 +86,7 @@ module Warchat
|
|
82
86
|
end
|
83
87
|
|
84
88
|
def keep_alive
|
85
|
-
|
89
|
+
Warchat.debug 'keep alive'
|
86
90
|
request = Warchat::Network::Request.new("/ah-mail",:n=>character_name,:r=>character_realm)
|
87
91
|
session.send_request(request)
|
88
92
|
end
|
data/lib/warchat/chat/message.rb
CHANGED
@@ -2,10 +2,6 @@
|
|
2
2
|
module Warchat
|
3
3
|
module Chat
|
4
4
|
class Message
|
5
|
-
CHAT_ID_TYPE_CHARACTER = "character"
|
6
|
-
CHAT_ID_TYPE_GUILD = "guild"
|
7
|
-
CHAT_ID_TYPE_GUILD_MEMBER = "guild_member"
|
8
|
-
|
9
5
|
CHAT_MSG_TYPE_AFK = "afk"
|
10
6
|
CHAT_MSG_TYPE_DND = "dnd"
|
11
7
|
CHAT_MSG_TYPE_GUILD_CHAT = "guild_chat"
|
@@ -13,24 +9,31 @@ module Warchat
|
|
13
9
|
CHAT_MSG_TYPE_OFFICER_CHAT = "officer_chat"
|
14
10
|
CHAT_MSG_TYPE_WHISPER = "whisper"
|
15
11
|
|
16
|
-
attr_reader :type,:body
|
12
|
+
attr_reader :type,:body
|
17
13
|
|
18
14
|
def initialize response
|
15
|
+
@response = response
|
19
16
|
@type = response["messageType"]
|
20
17
|
@body = response['body']
|
21
|
-
@from = response["from"]
|
22
|
-
if @from
|
23
|
-
@from_type = from["chatIdType"]
|
24
|
-
@character_id = from["characterId"]
|
25
|
-
end
|
18
|
+
@from = (response["from"] or {})
|
26
19
|
end
|
27
|
-
|
28
|
-
def
|
29
|
-
@
|
20
|
+
|
21
|
+
def guild
|
22
|
+
return @guild if @guild or @from["guildId"].nil?
|
23
|
+
_,name,realm = @response['from']["guildId"].split(':')
|
24
|
+
@guild = Warchat::Models::Guild.find_or_create 'n' => name,'r'=>realm
|
30
25
|
end
|
31
|
-
|
32
|
-
def
|
33
|
-
@
|
26
|
+
|
27
|
+
def character
|
28
|
+
return @character if @character or @from["characterId"].nil?
|
29
|
+
_,name,realm = @from["characterId"].split(':')
|
30
|
+
@character = Warchat::Models::Character.find_or_create 'n' => name,'r'=>realm
|
31
|
+
end
|
32
|
+
|
33
|
+
constants.select do |c| c[0..13] == 'CHAT_MSG_TYPE_' end.map do |c| "Warchat::Chat::Message::#{c}" end.each do |c|
|
34
|
+
define_method "#{c.constantize}?".to_sym do
|
35
|
+
type == c.constantize
|
36
|
+
end
|
34
37
|
end
|
35
38
|
end
|
36
39
|
end
|
@@ -1,23 +1,39 @@
|
|
1
1
|
# encoding: ASCII-8BIT
|
2
2
|
module Warchat
|
3
3
|
module Chat
|
4
|
-
class Presence
|
5
|
-
|
6
|
-
|
4
|
+
class Presence
|
5
|
+
STATUS_OFFLINE = 'offline'
|
6
|
+
STATUS_ONLINE = 'online'
|
7
|
+
|
7
8
|
def initialize response
|
8
|
-
@
|
9
|
-
@
|
10
|
-
|
9
|
+
@response = response
|
10
|
+
@type = response["presenceType"]
|
11
|
+
|
12
|
+
character.respond_to? status.to_sym and character.send status.to_sym
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def character
|
17
|
+
@character ||= (@response["character"] and Warchat::Models::Character.find_or_create(@response["character"]) or nil)
|
11
18
|
end
|
12
19
|
|
13
20
|
def offline?
|
14
21
|
@type and @type.include? 'offline'
|
15
22
|
end
|
23
|
+
|
24
|
+
def status
|
25
|
+
return 'unknown' unless @type
|
26
|
+
@type.split('_').first
|
27
|
+
end
|
16
28
|
|
17
|
-
def
|
29
|
+
def client_type
|
18
30
|
return 'unknown' unless @type
|
19
31
|
@type.split('_')[1..-1].join '_'
|
20
32
|
end
|
33
|
+
|
34
|
+
def inspect
|
35
|
+
"<#{self.class.name} character:#{character.inspect} status:#{status.inspect} client_type:#{client_type.inspect}>"
|
36
|
+
end
|
21
37
|
end
|
22
38
|
end
|
23
39
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Warchat
|
2
|
+
class Model
|
3
|
+
class << self
|
4
|
+
def find_or_create data
|
5
|
+
find(data).tap do |m| m and m.update(data) end or new(data)
|
6
|
+
end
|
7
|
+
|
8
|
+
def find data
|
9
|
+
realm,name = data['r'],data['n']
|
10
|
+
mutex.synchronize do all[realm] and all[realm][name] or nil end
|
11
|
+
end
|
12
|
+
|
13
|
+
def mutex
|
14
|
+
@mutex ||= Mutex.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def all
|
18
|
+
@all ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def add m
|
23
|
+
mutex.synchronize do
|
24
|
+
all[m.realm] ||= {}
|
25
|
+
all[m.realm][m.name] and all[m.realm][m.name].update(m.data) or all[m.realm][m.name] = m
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_accessor :data
|
31
|
+
|
32
|
+
def initialize data
|
33
|
+
@data = data
|
34
|
+
self.class.send(:add,self)
|
35
|
+
end
|
36
|
+
|
37
|
+
def id
|
38
|
+
[self.class.name.underscore,name,realm].join ':'
|
39
|
+
end
|
40
|
+
|
41
|
+
def update data
|
42
|
+
@data = @data.merge data
|
43
|
+
end
|
44
|
+
|
45
|
+
def name
|
46
|
+
data['n']
|
47
|
+
end
|
48
|
+
|
49
|
+
def realm
|
50
|
+
data['r']
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Warchat
|
2
|
+
module Models
|
3
|
+
class Character < Warchat::Model
|
4
|
+
CLASSES = {1=>'Warrior',2=>'Paladin',3=>'Hunter',4=>'Rogue',5=>'Priest',6=>'Death Knight',7=>'Shaman',8=>'Mage',9=>'Warlock',11=>'Druid'}
|
5
|
+
RACES = {1=>'Human',2=>'Orc',3=>'Dwarf',4=>'Night Elf',5=>'Forsaken',6=>'Tauren',7=>'Gnome',8=>'Troll',9=>'Goblin',10=>'Blood Elf',11=>'Draenei',22=>'Worgen'}
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def online
|
9
|
+
all.select &:online?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize data
|
14
|
+
super
|
15
|
+
@count = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def level
|
19
|
+
data['l']
|
20
|
+
end
|
21
|
+
|
22
|
+
def rank
|
23
|
+
data['grank']
|
24
|
+
end
|
25
|
+
|
26
|
+
def klass
|
27
|
+
CLASSES[data['c']]
|
28
|
+
end
|
29
|
+
|
30
|
+
def race
|
31
|
+
RACES[data['ra']]
|
32
|
+
end
|
33
|
+
|
34
|
+
def online?
|
35
|
+
count > 0
|
36
|
+
end
|
37
|
+
|
38
|
+
def online
|
39
|
+
@count += 1
|
40
|
+
end
|
41
|
+
|
42
|
+
def offline
|
43
|
+
@count -= 1
|
44
|
+
end
|
45
|
+
|
46
|
+
def inspect
|
47
|
+
"<#{self.class.name} name:#{name.inspect} realm:#{realm.inspect} klass:#{klass.inspect} level:#{level.inspect} race:#{race.inspect}>"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -37,11 +37,15 @@ module Warchat
|
|
37
37
|
end.flatten(1)]
|
38
38
|
end
|
39
39
|
|
40
|
-
{16=>'n',32=>'N'
|
40
|
+
{16=>'n',32=>'N'}.each do |size,directive|
|
41
41
|
define_method "int_#{size}".to_sym do
|
42
42
|
substream(size/8).unpack(directive).first
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
def int_64
|
47
|
+
[substream(8).unpack('L_').first.to_s(16)].pack('H*').reverse.unpack('H*').first.hex
|
48
|
+
end
|
45
49
|
|
46
50
|
def boolean
|
47
51
|
byte == "\001"
|
@@ -6,19 +6,15 @@ module Warchat
|
|
6
6
|
module Network
|
7
7
|
class Connection
|
8
8
|
|
9
|
-
attr_accessor :
|
9
|
+
attr_accessor :on_send,:on_receive,:on_close
|
10
10
|
|
11
|
-
def initialize
|
12
|
-
options = args.pop if args.last.is_a? Hash
|
13
|
-
|
14
|
-
self.host = (args.shift or "m.us.wowarmory.com")
|
15
|
-
self.port = (args.shift or 8780)
|
11
|
+
def initialize
|
16
12
|
@closed = true
|
17
13
|
@queue = []
|
18
14
|
@mutex = Mutex.new
|
19
15
|
end
|
20
16
|
|
21
|
-
def start
|
17
|
+
def start host="m.us.wowarmory.com",port=8780
|
22
18
|
close
|
23
19
|
|
24
20
|
@closed = false;
|
@@ -59,8 +55,8 @@ module Warchat
|
|
59
55
|
sleep 0.01
|
60
56
|
end
|
61
57
|
rescue Exception => e
|
62
|
-
|
63
|
-
|
58
|
+
Warchat.debug e.message
|
59
|
+
Warchat.debug e.backtrace unless e.is_a? IOError
|
64
60
|
end
|
65
61
|
|
66
62
|
def handle_requests
|
@@ -78,8 +74,8 @@ module Warchat
|
|
78
74
|
sleep 0.01
|
79
75
|
end
|
80
76
|
rescue Exception => e
|
81
|
-
|
82
|
-
|
77
|
+
Warchat.debug e.message
|
78
|
+
Warchat.debug e.backtrace
|
83
79
|
end
|
84
80
|
end
|
85
81
|
end
|
@@ -13,11 +13,11 @@ module Warchat
|
|
13
13
|
@connection.on_receive = method(:connection_receive)
|
14
14
|
end
|
15
15
|
|
16
|
-
def start account_name,
|
16
|
+
def start account_name, account_password,host="m.us.wowarmory.com",port=8780
|
17
17
|
@account_name = account_name
|
18
|
-
@
|
18
|
+
@account_password = account_password
|
19
19
|
|
20
|
-
@connection.start
|
20
|
+
@connection.start host,port
|
21
21
|
|
22
22
|
@srp = Warchat::Srp::Client.new
|
23
23
|
|
@@ -55,7 +55,7 @@ module Warchat
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def stage_1 response
|
58
|
-
proof = @srp.auth1_proof(response["user"], @
|
58
|
+
proof = @srp.auth1_proof(response["user"], @account_password[0..15].upcase, response["salt"], response["B"])
|
59
59
|
send_request(Request.new("/authenticate2",:clientProof=>proof))
|
60
60
|
end
|
61
61
|
|
@@ -74,7 +74,7 @@ module Warchat
|
|
74
74
|
respond_to? m and send(m,response) or on_receive and on_receive.call(response)
|
75
75
|
else
|
76
76
|
error = response["body"]
|
77
|
-
|
77
|
+
Warchat.debug("error: " + error)
|
78
78
|
close(error) if respond_to? m
|
79
79
|
end
|
80
80
|
end
|
data/lib/warchat/timer.rb
CHANGED
data/lib/warchat/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: warchat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 11
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 10
|
10
|
+
version: 0.0.10
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Zachary Gavin
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-05-
|
18
|
+
date: 2011-05-27 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -66,10 +66,14 @@ files:
|
|
66
66
|
- Rakefile
|
67
67
|
- lib/warchat.rb
|
68
68
|
- lib/warchat/byte_string.rb
|
69
|
+
- lib/warchat/chat/ack.rb
|
69
70
|
- lib/warchat/chat/chat_response.rb
|
70
71
|
- lib/warchat/chat/client.rb
|
71
72
|
- lib/warchat/chat/message.rb
|
72
73
|
- lib/warchat/chat/presence.rb
|
74
|
+
- lib/warchat/model.rb
|
75
|
+
- lib/warchat/models/character.rb
|
76
|
+
- lib/warchat/models/guild.rb
|
73
77
|
- lib/warchat/network/binary_reader.rb
|
74
78
|
- lib/warchat/network/binary_writer.rb
|
75
79
|
- lib/warchat/network/connection.rb
|
@@ -110,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
114
|
requirements: []
|
111
115
|
|
112
116
|
rubyforge_project: warchat
|
113
|
-
rubygems_version: 1.
|
117
|
+
rubygems_version: 1.5.0
|
114
118
|
signing_key:
|
115
119
|
specification_version: 3
|
116
120
|
summary: A simple interface to World of Warcraft Remote Guild Chat based off Eike Siewertsen's C# implementation
|