steam_hlds_log_parser 0.4.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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +69 -0
- data/Rakefile +6 -0
- data/example/example-1.rb +22 -0
- data/example/example-2.rb +24 -0
- data/lib/.DS_Store +0 -0
- data/lib/locales/en.yml +42 -0
- data/lib/locales/fr.yml +42 -0
- data/lib/steam_hlds_log_parser/client.rb +52 -0
- data/lib/steam_hlds_log_parser/displayer.rb +37 -0
- data/lib/steam_hlds_log_parser/handler.rb +103 -0
- data/lib/steam_hlds_log_parser/version.rb +3 -0
- data/lib/steam_hlds_log_parser.rb +16 -0
- data/spec/client_spec.rb +69 -0
- data/spec/displayer_spec.rb +59 -0
- data/spec/handler_spec.rb +138 -0
- data/spec/helper_spec.rb +39 -0
- data/steam_hlds_log_parser.gemspec +31 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 30af9317dcddbf6bebd31d3bb02ff5df117db707
|
4
|
+
data.tar.gz: ab06662bf153b61c2cdab5b9d64209ced673e4e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 774c7685110aca35822f3642a5a93bbca4bd196f6ddad776345938e29a76df62f3f3b72c866898925f64ed0128a064b8046e9581db9553e6eb4719ea200a07aa
|
7
|
+
data.tar.gz: 5b8c66867b180997d6769fbff9f047346a270bddfce355fc842eafe55c3af72df5a4ab0deaf3f21112704609393682cba8e5b064a9c2e97420e7631d10ece3f9
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
repo_token: WVARN24eiGJQ6GenqWAsqNQEZroHGj2SP
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Thomas VIAL
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Steam Hlds Log Parser
|
2
|
+
|
3
|
+
Creates a server with EventMachine which listens to HLDS logs, parse and returns readable content from your game server.
|
4
|
+
The returned content can be sent to a website, IRC or flowdock for match live streaming.
|
5
|
+
|
6
|
+
Mostly tested on Steam HLDS for Counter-Strike.
|
7
|
+
|
8
|
+
Note : content is sent in english or french at this time. Need i18n contributors!
|
9
|
+
|
10
|
+
## Build Status
|
11
|
+
|
12
|
+
[](https://travis-ci.org/tomav/steam_hlds_log_parser)
|
13
|
+
[](http://badge.fury.io/rb/steam_hlds_log_parser)
|
14
|
+
[](https://coveralls.io/r/tomav/steam_hlds_log_parser)
|
15
|
+
|
16
|
+
## Installation
|
17
|
+
|
18
|
+
Add this line to your application's Gemfile:
|
19
|
+
|
20
|
+
gem 'steam_hlds_log_parser'
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install steam_hlds_log_parser
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
1. Create your own displayer callback `class` which will receive parsed data
|
33
|
+
Ask this `class` to write a file, send content to IRC or flowdock... whatever... and give it as `:displayer` Hash option
|
34
|
+
2. Create a new client on desired IP / Port / Options
|
35
|
+
3. In your HLDS server: `logaddress 127.0.0.1 27035`
|
36
|
+
|
37
|
+
## Example
|
38
|
+
|
39
|
+
require "rubygems"
|
40
|
+
require "steam_hlds_log_parser"
|
41
|
+
|
42
|
+
class Formatter
|
43
|
+
def initialize(data)
|
44
|
+
# will 'puts' the translated content
|
45
|
+
SteamHldsLogParser::Displayer.new(data).display_translation
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
## These are default options
|
51
|
+
options = {
|
52
|
+
:locale => :en,
|
53
|
+
:display_kills => true,
|
54
|
+
:display_actions => true,
|
55
|
+
:display_changelevel => true,
|
56
|
+
:displayer => Formatter
|
57
|
+
}
|
58
|
+
|
59
|
+
parser = SteamHldsLogParser::Client.new("127.0.0.1", 27035, options)
|
60
|
+
parser.start
|
61
|
+
|
62
|
+
|
63
|
+
## Contributing
|
64
|
+
|
65
|
+
1. Fork it
|
66
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
67
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
68
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
69
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "steam_hlds_log_parser"
|
3
|
+
|
4
|
+
class Formatter
|
5
|
+
def initialize(data)
|
6
|
+
# will 'puts' the translated content
|
7
|
+
SteamHldsLogParser::Displayer.new(data).display_translation
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
## These are default options
|
13
|
+
options = {
|
14
|
+
:locale => :en,
|
15
|
+
:display_kills => true,
|
16
|
+
:display_actions => true,
|
17
|
+
:display_changelevel => true,
|
18
|
+
:displayer => Formatter
|
19
|
+
}
|
20
|
+
|
21
|
+
parser = SteamHldsLogParser::Client.new("127.0.0.1", 27035, options)
|
22
|
+
parser.start
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "steam_hlds_log_parser"
|
3
|
+
# require "flowdock"
|
4
|
+
|
5
|
+
## The displayer class that will be used to send content to Flowdock
|
6
|
+
class FlowdockPusher
|
7
|
+
def initialize(data)
|
8
|
+
# Get translated data
|
9
|
+
content = SteamHldsLogParser::Displayer.new(data).get_translation
|
10
|
+
# Source: https://github.com/flowdock/flowdock-api
|
11
|
+
flow = Flowdock::Flow.new(:api_token => "12345678901234567890123456789012", :external_user_name => "HLDS-Live")
|
12
|
+
flow.push_to_chat(:content => content)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
options = {
|
17
|
+
:locale => :fr,
|
18
|
+
:display_kills => true,
|
19
|
+
:display_actions => true,
|
20
|
+
:display_changelevel => true,
|
21
|
+
:displayer => FlowdockPusher
|
22
|
+
}
|
23
|
+
|
24
|
+
SteamHldsLogParser::Client.new("127.0.0.1", 27035, options).start
|
data/lib/.DS_Store
ADDED
Binary file
|
data/lib/locales/en.yml
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
en:
|
2
|
+
# client
|
3
|
+
client_connect: "HLDS connected and sending data"
|
4
|
+
client_disconnect: "HLDS disconnected? No data is received."
|
5
|
+
client_stop: "HLDS Log Parser stopped."
|
6
|
+
# team
|
7
|
+
full_team_name_te: "Terrorist"
|
8
|
+
full_team_name_ct: "Counter-Terrorist"
|
9
|
+
short_team_name_te: "TE"
|
10
|
+
short_team_name_ct: "CT"
|
11
|
+
# round conclusion types
|
12
|
+
all_hostages_rescued: "All hostages have been rescued"
|
13
|
+
bomb_defused: "Bomb has been defused"
|
14
|
+
cts_preventescape: "The CT's have prevented most of the terrorists from escaping"
|
15
|
+
cts_win: "Counter-Terrorists Win"
|
16
|
+
hostages_not_rescued: "Hostages have not been rescued"
|
17
|
+
target_bombed: "Target Successfully Bombed!"
|
18
|
+
target_saved: "Target has been saved"
|
19
|
+
terrorists_escaped: "Terrorists have escaped"
|
20
|
+
terrorists_not_escaped: "Terrorists have not escaped"
|
21
|
+
terrorists_win: "Terrorists Win"
|
22
|
+
vip_assassinated: "The VIP has been assassinated"
|
23
|
+
vip_escaped: "The VIP has escaped"
|
24
|
+
vip_not_escaped: "VIP has not escaped"
|
25
|
+
# user actions
|
26
|
+
begin_bomb_defuse_with_kit: "begin bomb defuse with kit"
|
27
|
+
begin_bomb_defuse_without_kit: "begin bomb defuse without kit"
|
28
|
+
defused_the_bomb: "defused the bomb"
|
29
|
+
dropped_the_bomb: "dropped the bomb"
|
30
|
+
got_the_bomb: "got the bomb"
|
31
|
+
killed_a_hostage: "killed a hostage"
|
32
|
+
planted_the_bomb: "planted the bom"
|
33
|
+
rescued_a_hostage: "rescued a hostage"
|
34
|
+
spawned_with_the_bomb: "spawned with the bomb"
|
35
|
+
touched_a_hostage: "touched a hostage"
|
36
|
+
# events
|
37
|
+
map_ends: "Map ends: %{winner} => %{score}"
|
38
|
+
victory: "[CT] %{score_ct} - %{score_t} [T]"
|
39
|
+
kill: "[%{killer_team}] %{killer} killed [%{killed_team}] %{killed} with %{weapon}"
|
40
|
+
suicide: "%{killed} commited suicide"
|
41
|
+
event: "[%{person_team}] %{person} %{event_i18n}"
|
42
|
+
loading_map: "Loading %{map}"
|
data/lib/locales/fr.yml
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
fr:
|
2
|
+
# client
|
3
|
+
client_connect: "HLDS vient de se connecter et transmets des données."
|
4
|
+
client_disconnect: "HLDS s'est déconnecté ?"
|
5
|
+
client_stop: "HLDS Log Parser stoppé."
|
6
|
+
# team
|
7
|
+
full_team_name_te: "Terroriste"
|
8
|
+
full_team_name_ct: "Anti-Terroriste"
|
9
|
+
short_team_name_te: "TE"
|
10
|
+
short_team_name_ct: "CT"
|
11
|
+
# round conclusion types
|
12
|
+
all_hostages_rescued: "Tous les otages ont été sauvés"
|
13
|
+
bomb_defused: "La bombe a été désamorçée"
|
14
|
+
cts_preventescape: "Les CT ont empéché l'évasion des Terroristes"
|
15
|
+
cts_win: "Victoire des Anti-Terroristes"
|
16
|
+
hostages_not_rescued: "Les otages n'ont pas été sauvés"
|
17
|
+
target_bombed: "La cible a été détruite !"
|
18
|
+
target_saved: "La cible a été protégée"
|
19
|
+
terrorists_escaped: "Les Terroristes se sont échappés"
|
20
|
+
terrorists_not_escaped: "Les Terroristes ne se sont pas échappés"
|
21
|
+
terrorists_win: "Victoire des Terroristes"
|
22
|
+
vip_assassinated: "Le VIP a été assassiné"
|
23
|
+
vip_escaped: "Le VIP s'est échappé"
|
24
|
+
vip_not_escaped: "Le VIP ne s'est pas échappé"
|
25
|
+
# user actions
|
26
|
+
begin_bomb_defuse_with_kit: "commence à désamorcer la bombe avec un kit"
|
27
|
+
begin_bomb_defuse_without_kit: "commence à désamorcer la bombe sans kit"
|
28
|
+
defused_the_bomb: "a désamorcé la bombe"
|
29
|
+
dropped_the_bomb: "a perdu la bombe"
|
30
|
+
got_the_bomb: "a récupéré la bombe"
|
31
|
+
killed_a_hostage: "a tué un otage"
|
32
|
+
planted_the_bomb: "a posé la bombe"
|
33
|
+
rescued_a_hostage: "a sauvé un otage"
|
34
|
+
spawned_with_the_bomb: "a la bombe"
|
35
|
+
touched_a_hostage: "a récupéré un otage"
|
36
|
+
# events
|
37
|
+
map_ends: "Fin de partie : Score des %{winner} => %{score}"
|
38
|
+
victory: "[CT] %{score_ct} - %{score_t} [TE]"
|
39
|
+
kill: "[%{killer_team}] %{killer} a tué [%{killed_team}] %{killed} au %{weapon}"
|
40
|
+
suicide: "%{killed} s'est tué"
|
41
|
+
event: "[%{person_team}] %{person} %{event_i18n}"
|
42
|
+
loading_map: "Chargement de %{map}"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module SteamHldsLogParser
|
2
|
+
|
3
|
+
class Client
|
4
|
+
|
5
|
+
attr_reader :host, :port, :options
|
6
|
+
|
7
|
+
# Creates a new client
|
8
|
+
#
|
9
|
+
# @host [String] Hostname / IP Address the server will be running
|
10
|
+
# @port [Integer] Port to listen to
|
11
|
+
# @options [Hash] Other options
|
12
|
+
#
|
13
|
+
# ==== Options
|
14
|
+
#
|
15
|
+
# * +locale+ - Set the language of returned content
|
16
|
+
# * +display_kills+ Enable kills / frags detail (default=true)
|
17
|
+
# * +display_actions+ Enable players actions / defuse / ... detail (default=true)
|
18
|
+
# * +display_changelevel+ Enable changelevel (map) display (default=true)
|
19
|
+
# * +displayer+ Class that will be use to display content (default=HldsReturnDisplayer)
|
20
|
+
#
|
21
|
+
def initialize(host, port, options = {})
|
22
|
+
default_options = {
|
23
|
+
:locale => :en,
|
24
|
+
:display_kills => true,
|
25
|
+
:display_actions => true,
|
26
|
+
:display_changelevel => true
|
27
|
+
}
|
28
|
+
@host, @port = host, port
|
29
|
+
@options = default_options.merge(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Starts the client which will receive HLDS logs (using UDP)
|
33
|
+
def start
|
34
|
+
# setting locale
|
35
|
+
I18n.locale = @options[:locale] || I18n.default_locale
|
36
|
+
EM.run {
|
37
|
+
# catch CTRL+C
|
38
|
+
Signal.trap("INT") { EM.stop }
|
39
|
+
Signal.trap("TERM") { EM.stop }
|
40
|
+
# Let's start
|
41
|
+
EM::open_datagram_socket(@host, @port, Handler, @host, @port, @options)
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
# Stops the client
|
46
|
+
def stop
|
47
|
+
puts "## #{@host}:#{@port} => #{I18n.t('client_stop')}"
|
48
|
+
EM::stop_event_loop
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module SteamHldsLogParser
|
2
|
+
|
3
|
+
# Default Displayer
|
4
|
+
#
|
5
|
+
# @data [Hash] Data returned by 'receive_data'
|
6
|
+
#
|
7
|
+
class Displayer
|
8
|
+
|
9
|
+
attr_reader :data
|
10
|
+
|
11
|
+
def initialize(data)
|
12
|
+
@data = data
|
13
|
+
end
|
14
|
+
|
15
|
+
# Return data
|
16
|
+
def get_data
|
17
|
+
return @data
|
18
|
+
end
|
19
|
+
|
20
|
+
# Display data
|
21
|
+
def display_data
|
22
|
+
puts get_data
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return data translation
|
26
|
+
def get_translation
|
27
|
+
return I18n.t(@data[:type], @data[:params]) unless @data[:type].nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
# Display data translation
|
31
|
+
def display_translation
|
32
|
+
puts get_translation
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module SteamHldsLogParser
|
2
|
+
|
3
|
+
class Handler < EM::Connection
|
4
|
+
|
5
|
+
attr_reader :host, :port, :options
|
6
|
+
|
7
|
+
# Initialize Handler from Client options
|
8
|
+
#
|
9
|
+
# @host [String] Hostname / IP Address the server will be running
|
10
|
+
# @port [Integer] Port to listen to
|
11
|
+
# @options [Hash] Other options
|
12
|
+
#
|
13
|
+
def initialize(host, port, options)
|
14
|
+
@host, @port, @options = host, port, options
|
15
|
+
end
|
16
|
+
|
17
|
+
# Triggered when HLDS connects
|
18
|
+
def post_init
|
19
|
+
puts "## #{@host}:#{@port} => #{I18n.t('client_connect')}"
|
20
|
+
end
|
21
|
+
|
22
|
+
# Triggered when HLDS disconnects
|
23
|
+
def unbind
|
24
|
+
puts "## #{@host}:#{@port} => #{I18n.t('client_disconnect')}"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get data from Client and parse using Regexp
|
28
|
+
#
|
29
|
+
# * match end of map, with winner team and score
|
30
|
+
# * match the end of round, with score and victory type
|
31
|
+
# * match who killed who with what (frags)
|
32
|
+
# * match suicides
|
33
|
+
# * match who did what (defuse, drop the bomb...)
|
34
|
+
# * match changelevel
|
35
|
+
#
|
36
|
+
# @data [String] Data received by Client from HLDS server (a line of log)
|
37
|
+
#
|
38
|
+
def receive_data(data)
|
39
|
+
|
40
|
+
# L 05/10/2000 - 12:34:56: Team "CT" scored "17" with "0" players
|
41
|
+
if data.gsub(/Team "(.+)" scored "(\d+)" with "(\d+)"/).count > 0
|
42
|
+
winner, winner_score = data.match(/Team "(.+)" scored "(\d+)" with/).captures
|
43
|
+
content = { :type => 'map_ends', :params => { :winner => get_short_team_name(winner), :score => winner_score } }
|
44
|
+
|
45
|
+
# L 05/10/2000 - 12:34:56: Team "CT" triggered "CTs_Win" (CT "3") (T "0")
|
46
|
+
elsif data.gsub(/(: Team ")/).count > 0
|
47
|
+
winner, type, score_ct, score_t = data.match(/Team "([A-Z]+)" triggered "([A-Za-z_]+)" \(CT "(\d+)"\) \(T "(\d+)"\)/i).captures
|
48
|
+
content = { :type => 'victory', :params => { :score_ct => score_ct, :score_t => score_t } }
|
49
|
+
|
50
|
+
# L 05/10/2000 - 12:34:56: "Killer | Player<66><STEAM_ID_LAN><TERRORIST>" killed "Killed | Player<60><STEAM_ID_LAN><CT>" with "ak47"
|
51
|
+
elsif @options[:display_kills] && data.gsub(/(\>" killed ")/).count > 0
|
52
|
+
killer, killer_team, killed, killed_team, weapon = data.match(/"(.+)<\d+><STEAM_ID_LAN><(.+)>" killed "(.+)<\d+><STEAM_ID_LAN><(.+)>" with "(.+)"/i).captures
|
53
|
+
content = { :type => 'kill', :params => { :killer_team => get_short_team_name(killer_team), :killer => killer, :killed_team => get_short_team_name(killed_team), :killed => killed, :weapon => weapon } }
|
54
|
+
|
55
|
+
# L 05/10/2000 - 12:34:56: "Player<66><STEAM_ID_LAN><TERRORIST>" committed suicide with "worldspawn" (world)
|
56
|
+
elsif @options[:display_kills] && data.gsub(/>" committed suicide/).count > 0
|
57
|
+
killed = data.match(/: "(.+)<\d+>/).captures.first
|
58
|
+
content = { :type => 'suicide', :params => { :killed => killed } }
|
59
|
+
|
60
|
+
# L 05/10/2000 - 12:34:56: "Killer | Player<66><STEAM_ID_LAN><CT>" triggered "Defused_The_Bomb"
|
61
|
+
elsif @options[:display_actions] && data.gsub(/<STEAM_ID_LAN><.+>" triggered "(.+)"$/).count > 0
|
62
|
+
person, person_team, event = data.match(/: "(.+)<\d+><STEAM_ID_LAN><(.+)>" triggered "(.+)"/i).captures
|
63
|
+
content = { :type => 'event', :params => { :person_team => get_short_team_name(person_team), :person => person, :event_item => event, :event_i18n => I18n.t(event.downcase)} }
|
64
|
+
|
65
|
+
# L 05/10/2000 - 12:34:56: Loading map "de_dust2"
|
66
|
+
elsif @options[:display_changelevel] && data.gsub(/: Loading map "(.+)"/).count > 0
|
67
|
+
map = data.match(/: Loading map "(.+)"/i).captures.first
|
68
|
+
content = { :type => 'loading_map', :params => { :map => map } }
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
if @options[:displayer].nil?; return(content) else @options[:displayer].new(content) end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
# Format team name with long format (textual)
|
77
|
+
#
|
78
|
+
# @winner [String] Round winner (+CT+ or +T+) from logs
|
79
|
+
#
|
80
|
+
def get_full_team_name(winner)
|
81
|
+
case winner
|
82
|
+
when "T"
|
83
|
+
return "#{I18n.t('full_team_name_te')}"
|
84
|
+
else
|
85
|
+
return "#{I18n.t('full_team_name_ct')}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Format team name with short format (initials)
|
90
|
+
#
|
91
|
+
# @team [String] Round winner (+CT+ or +TERRORIST+) from logs
|
92
|
+
#
|
93
|
+
def get_short_team_name(team)
|
94
|
+
case team
|
95
|
+
when "TERRORIST"
|
96
|
+
return "#{I18n.t('short_team_name_te')}"
|
97
|
+
else
|
98
|
+
return "#{I18n.t('short_team_name_ct')}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "eventmachine"
|
3
|
+
require "i18n"
|
4
|
+
require "rdoc"
|
5
|
+
|
6
|
+
require "steam_hlds_log_parser/version"
|
7
|
+
require "steam_hlds_log_parser/client"
|
8
|
+
require "steam_hlds_log_parser/handler"
|
9
|
+
require "steam_hlds_log_parser/displayer"
|
10
|
+
|
11
|
+
module SteamHldsLogParser
|
12
|
+
|
13
|
+
I18n.load_path = Dir.glob( File.dirname(__FILE__) + "/locales/*.yml" )
|
14
|
+
I18n.default_locale = :en
|
15
|
+
|
16
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require "helper_spec"
|
2
|
+
|
3
|
+
module SteamHldsLogParser
|
4
|
+
|
5
|
+
describe "SteamHldsLogParser" do
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
@client = Client.new("0.0.0.0", 27035)
|
9
|
+
@options = @client.options
|
10
|
+
@custom_options = custom_options
|
11
|
+
@custom_client = Client.new("127.0.0.1", 27045, @custom_options)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "Client" do
|
15
|
+
|
16
|
+
it "raises an exception when parameters are missing" do
|
17
|
+
expect { Client.new }.to raise_error(ArgumentError)
|
18
|
+
end
|
19
|
+
|
20
|
+
subject { @client }
|
21
|
+
context "when a 'Client' is created without options"
|
22
|
+
it { should be_an_instance_of Client }
|
23
|
+
it "has a 'host'" do
|
24
|
+
@client.host.should_not be_nil
|
25
|
+
@client.host.should eq("0.0.0.0")
|
26
|
+
end
|
27
|
+
it "has a 'port'" do
|
28
|
+
@client.port.should_not be_nil
|
29
|
+
@client.port.should eq(27035)
|
30
|
+
end
|
31
|
+
it "has a default 'options' Hash" do
|
32
|
+
@client.options.should_not be_nil
|
33
|
+
@client.options.should_not be(nil)
|
34
|
+
@client.options.class.should be(Hash)
|
35
|
+
@client.options.should eq(@options)
|
36
|
+
end
|
37
|
+
|
38
|
+
subject(:custom_client) { @custom_client }
|
39
|
+
context "when custom options are given"
|
40
|
+
it "can get a custom 'options' Hash" do
|
41
|
+
@custom_client.options.should_not be_nil
|
42
|
+
@custom_client.options.class.should be(Hash)
|
43
|
+
@custom_client.options.should eq(@custom_options)
|
44
|
+
@custom_client.options[:displayer].should eq(RSpecDisplayer)
|
45
|
+
@custom_client.options[:locale].should be(:fr)
|
46
|
+
@custom_client.options[:display_kills].should be(false)
|
47
|
+
@custom_client.options[:display_actions].should be(false)
|
48
|
+
@custom_client.options[:display_changelevel].should be(false)
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#start and #stop" do
|
52
|
+
|
53
|
+
context "when 'start' and 'stop' are triggered one after the other"
|
54
|
+
it "starts then stops an eventmachine with appropriate messages" do
|
55
|
+
EM.run {
|
56
|
+
capture_stdout { @client.start }.should eq("## 0.0.0.0:27035 => HLDS connected and sending data\n")
|
57
|
+
EM.add_timer(0.2) {
|
58
|
+
capture_stdout { @client.stop }.should eq("## 0.0.0.0:27035 => HLDS Log Parser stopped.\n")
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "helper_spec"
|
2
|
+
|
3
|
+
module SteamHldsLogParser
|
4
|
+
|
5
|
+
describe "SteamHldsLogParser" do
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
@data = {:type=>"victory", :params=>{:score_ct=>"3", :score_t=>"0"}}
|
9
|
+
@displayer = Displayer.new(@data)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "Displayer" do
|
13
|
+
|
14
|
+
context "when 'data' is missing" do
|
15
|
+
it "raises an exception" do
|
16
|
+
expect { Displayer.new }.to raise_error(ArgumentError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when 'data' is given" do
|
21
|
+
|
22
|
+
it "creates a 'Displayer'" do
|
23
|
+
@displayer.should be_an_instance_of Displayer
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#get_data" do
|
27
|
+
it "returns 'data' given as argument" do
|
28
|
+
@displayer.get_data.should_not be_nil
|
29
|
+
@displayer.get_data.should be(@data)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#display_data" do
|
34
|
+
it "displays 'data' given as argument" do
|
35
|
+
eval(capture_stdout { @displayer.display_data }).should eq(@data)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#get_translation" do
|
40
|
+
it "returns translated 'data' given as argument" do
|
41
|
+
@displayer.get_translation.should_not be_nil
|
42
|
+
@displayer.get_translation.class.should be(String)
|
43
|
+
@displayer.get_translation.should eq("[CT] 3 - 0 [T]")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#display_translation" do
|
48
|
+
it "displays translated 'data' given as argument" do
|
49
|
+
capture_stdout { @displayer.display_translation }.should eq("[CT] 3 - 0 [T]\n")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require "helper_spec"
|
2
|
+
|
3
|
+
module SteamHldsLogParser
|
4
|
+
|
5
|
+
describe "SteamHldsLogParser" do
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
@client = Client.new("0.0.0.0", 27035)
|
9
|
+
@options = @client.options
|
10
|
+
@handler = Handler.new("", "0.0.0.0", 27035, @options)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "Handler" do
|
14
|
+
|
15
|
+
context "when parameters are missing" do
|
16
|
+
it "raises an exception" do
|
17
|
+
expect { Handler.new }.to raise_error(ArgumentError)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when parameters are given" do
|
22
|
+
subject { @handler }
|
23
|
+
|
24
|
+
context "when 'host' and 'port' are given"
|
25
|
+
it { should be_an_instance_of Handler }
|
26
|
+
it "has a 'host'" do
|
27
|
+
@handler.host.should_not be_nil
|
28
|
+
@handler.host.should eq("0.0.0.0")
|
29
|
+
end
|
30
|
+
it "has a 'port'" do
|
31
|
+
@handler.port.should_not be_nil
|
32
|
+
@handler.port.should eq(27035)
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#post_init" do
|
36
|
+
it "displays a console message when hlds connects" do
|
37
|
+
capture_stdout { @handler.post_init }.should eq("## 0.0.0.0:27035 => HLDS connected and sending data\n")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#unbind" do
|
42
|
+
it "displays a console message when hlds disconnects" do
|
43
|
+
capture_stdout { @handler.unbind }.should eq("## 0.0.0.0:27035 => HLDS disconnected? No data is received.\n")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#receive_data" do
|
48
|
+
|
49
|
+
context "when data is not supported" do
|
50
|
+
it "returns anything" do
|
51
|
+
data = '# L 05/10/2000 - 12:34:56: I am a fake line of log'
|
52
|
+
@handler.receive_data(data).should eq(nil)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when data is 'map_ends'" do
|
57
|
+
it "returns Hash on map_ends" do
|
58
|
+
data = '# L 05/10/2000 - 12:34:56: Team "CT" scored "17" with "0" players"'
|
59
|
+
expected = {:type=>"map_ends", :params=>{:winner=>"CT", :score=>"17"}}
|
60
|
+
@handler.receive_data(data).class.should eq(Hash)
|
61
|
+
@handler.receive_data(data).should eq(expected)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when data is 'victory'" do
|
66
|
+
it "returns Hash on victory" do
|
67
|
+
data = '# L 05/10/2000 - 12:34:56: Team "CT" triggered "CTs_Win" (CT "3") (T "0")'
|
68
|
+
expected = {:type=>"victory", :params=>{:score_ct=>"3", :score_t=>"0"}}
|
69
|
+
@handler.receive_data(data).class.should eq(Hash)
|
70
|
+
@handler.receive_data(data).should eq(expected)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "when data is 'killed'" do
|
75
|
+
it "returns Hash on killed" do
|
76
|
+
data = '# L 05/10/2000 - 12:34:56: "Killer | Player<66><STEAM_ID_LAN><TERRORIST>" killed "Killed | Player<60><STEAM_ID_LAN><CT>" with "ak47"'
|
77
|
+
expected = {:type=>"kill", :params => {:killer_team=>"TE", :killer=>"Killer | Player", :killed_team=>"CT", :killed=>"Killed | Player", :weapon=>"ak47"}}
|
78
|
+
@handler.receive_data(data).class.should eq(Hash)
|
79
|
+
@handler.receive_data(data).should eq(expected)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "when data is 'suicide'" do
|
84
|
+
it "returns Hash on suicide" do
|
85
|
+
data = '# L 05/10/2000 - 12:34:56: "Player<66><STEAM_ID_LAN><TERRORIST>" committed suicide with "worldspawn" (world)'
|
86
|
+
expected = {:type=>"suicide", :params=>{:killed=>"Player"}}
|
87
|
+
@handler.receive_data(data).class.should eq(Hash)
|
88
|
+
@handler.receive_data(data).should eq(expected)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "when data is 'event'" do
|
93
|
+
it "returns Hash on event" do
|
94
|
+
data = '# L 05/10/2000 - 12:34:56: "Killer | Player<66><STEAM_ID_LAN><CT>" triggered "Defused_The_Bomb"'
|
95
|
+
expected = {:type=>"event", :params=> {:person_team=>"CT", :person=>"Killer | Player", :event_item=>"Defused_The_Bomb", :event_i18n=>"defused the bomb"}}
|
96
|
+
@handler.receive_data(data).class.should eq(Hash)
|
97
|
+
@handler.receive_data(data).should eq(expected)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "when data is 'changelevel'" do
|
102
|
+
it "returns Hash on changelevel" do
|
103
|
+
data = '# L 05/10/2000 - 12:34:56: Loading map "de_dust2"'
|
104
|
+
expected = {:type=>"loading_map", :params=>{:map=>"de_dust2"}}
|
105
|
+
@handler.receive_data(data).class.should eq(Hash)
|
106
|
+
@handler.receive_data(data).should eq(expected)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "#get_full_team_name" do
|
113
|
+
|
114
|
+
context "when short name is given"
|
115
|
+
it "returns full name" do
|
116
|
+
@handler.get_full_team_name("T").should eq("Terrorist")
|
117
|
+
@handler.get_full_team_name("CT").should eq("Counter-Terrorist")
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "#get_short_team_name" do
|
123
|
+
|
124
|
+
context "when full name is given"
|
125
|
+
it "returns short name" do
|
126
|
+
@handler.get_short_team_name("TERRORIST").should eq("TE")
|
127
|
+
@handler.get_short_team_name("CT").should eq("CT")
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
data/spec/helper_spec.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require "simplecov"
|
2
|
+
require "coveralls"
|
3
|
+
require "rspec"
|
4
|
+
|
5
|
+
# Simplecov / Coverall configuration
|
6
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
7
|
+
SimpleCov.start do
|
8
|
+
add_filter "/example/"
|
9
|
+
add_filter "/spec/"
|
10
|
+
end
|
11
|
+
|
12
|
+
# Get ouput content of the given block
|
13
|
+
# Source: https://github.com/cldwalker/hirb/blob/master/test/test_helper.rb
|
14
|
+
def capture_stdout(&block)
|
15
|
+
original_stdout = $stdout
|
16
|
+
$stdout = fake = StringIO.new
|
17
|
+
begin
|
18
|
+
yield
|
19
|
+
ensure
|
20
|
+
$stdout = original_stdout
|
21
|
+
end
|
22
|
+
fake.string
|
23
|
+
end
|
24
|
+
|
25
|
+
class RSpecDisplayer
|
26
|
+
end
|
27
|
+
|
28
|
+
require "steam_hlds_log_parser"
|
29
|
+
|
30
|
+
# Returns custom options as a Hash
|
31
|
+
def custom_options
|
32
|
+
options = {
|
33
|
+
:locale => :fr,
|
34
|
+
:display_kills => false,
|
35
|
+
:display_actions => false,
|
36
|
+
:display_changelevel => false,
|
37
|
+
:displayer => RSpecDisplayer
|
38
|
+
}
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'steam_hlds_log_parser/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "steam_hlds_log_parser"
|
8
|
+
spec.version = SteamHldsLogParser::VERSION
|
9
|
+
spec.authors = ["Thomas VIAL"]
|
10
|
+
spec.email = ["github@ifusio.com"]
|
11
|
+
spec.description = %q{Steam HLDS Log Parser receives logs from your Steam game server and parses them in real time to give you usable content for your website, irc channel / flowdock... Works well with Counter-Strike and others Half-life based games.}
|
12
|
+
spec.summary = %q{Steam HLDS Log Parser receives logs from your Steam game server and parses them in real time to give you usable content for your website, irc channel / flowdock... Works well with Counter-Strike and others Half-life based games.}
|
13
|
+
spec.homepage = "https://github.com/tomav/steam_hlds_log_parser"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_dependency "rake"
|
23
|
+
spec.add_dependency "eventmachine", "~> 1.0.3"
|
24
|
+
spec.add_dependency "i18n"
|
25
|
+
|
26
|
+
spec.add_development_dependency "simplecov"
|
27
|
+
spec.add_development_dependency "coveralls"
|
28
|
+
spec.add_development_dependency "rspec-core"
|
29
|
+
spec.add_development_dependency "rspec"
|
30
|
+
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: steam_hlds_log_parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Thomas VIAL
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2013-08-13 00:00:00 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
prerelease: false
|
17
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: "1.3"
|
22
|
+
type: :runtime
|
23
|
+
version_requirements: *id001
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: rake
|
26
|
+
prerelease: false
|
27
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- &id004
|
30
|
+
- ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id002
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: eventmachine
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ~>
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.0.3
|
43
|
+
type: :runtime
|
44
|
+
version_requirements: *id003
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: i18n
|
47
|
+
prerelease: false
|
48
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- *id004
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id005
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: simplecov
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- *id004
|
59
|
+
type: :development
|
60
|
+
version_requirements: *id006
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: coveralls
|
63
|
+
prerelease: false
|
64
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- *id004
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id007
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-core
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- *id004
|
75
|
+
type: :development
|
76
|
+
version_requirements: *id008
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: rspec
|
79
|
+
prerelease: false
|
80
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- *id004
|
83
|
+
type: :development
|
84
|
+
version_requirements: *id009
|
85
|
+
description: Steam HLDS Log Parser receives logs from your Steam game server and parses them in real time to give you usable content for your website, irc channel / flowdock... Works well with Counter-Strike and others Half-life based games.
|
86
|
+
email:
|
87
|
+
- github@ifusio.com
|
88
|
+
executables: []
|
89
|
+
|
90
|
+
extensions: []
|
91
|
+
|
92
|
+
extra_rdoc_files: []
|
93
|
+
|
94
|
+
files:
|
95
|
+
- .coveralls.yml
|
96
|
+
- .gitignore
|
97
|
+
- .rspec
|
98
|
+
- .travis.yml
|
99
|
+
- Gemfile
|
100
|
+
- LICENSE.txt
|
101
|
+
- README.md
|
102
|
+
- Rakefile
|
103
|
+
- example/example-1.rb
|
104
|
+
- example/example-2.rb
|
105
|
+
- lib/.DS_Store
|
106
|
+
- lib/locales/en.yml
|
107
|
+
- lib/locales/fr.yml
|
108
|
+
- lib/steam_hlds_log_parser.rb
|
109
|
+
- lib/steam_hlds_log_parser/client.rb
|
110
|
+
- lib/steam_hlds_log_parser/displayer.rb
|
111
|
+
- lib/steam_hlds_log_parser/handler.rb
|
112
|
+
- lib/steam_hlds_log_parser/version.rb
|
113
|
+
- spec/client_spec.rb
|
114
|
+
- spec/displayer_spec.rb
|
115
|
+
- spec/handler_spec.rb
|
116
|
+
- spec/helper_spec.rb
|
117
|
+
- steam_hlds_log_parser.gemspec
|
118
|
+
homepage: https://github.com/tomav/steam_hlds_log_parser
|
119
|
+
licenses:
|
120
|
+
- MIT
|
121
|
+
metadata: {}
|
122
|
+
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- *id004
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- *id004
|
134
|
+
requirements: []
|
135
|
+
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 2.0.3
|
138
|
+
signing_key:
|
139
|
+
specification_version: 4
|
140
|
+
summary: Steam HLDS Log Parser receives logs from your Steam game server and parses them in real time to give you usable content for your website, irc channel / flowdock... Works well with Counter-Strike and others Half-life based games.
|
141
|
+
test_files:
|
142
|
+
- spec/client_spec.rb
|
143
|
+
- spec/displayer_spec.rb
|
144
|
+
- spec/handler_spec.rb
|
145
|
+
- spec/helper_spec.rb
|