tf2_line_parser 0.6.3 → 0.6.5
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f18e216a4247d37720754f3a66281d93c88af477875335fd9a3d3a79228f2a8b
|
|
4
|
+
data.tar.gz: f3ce9a46e96f0b37820c02e5b876f98bf8232fff6e42733ebd79727a4fd9e46a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d9daf5c5f614d817d09d8de35539f5d7acbc61bbb7b47863e4a12551cdae2a00ba521ede013cfa485eed863520a157007496a34173dfdb46b388dcdb9dd7934e
|
|
7
|
+
data.tar.gz: 985510a7d6108b80db1ae408e32dfa6e0d5da41293b4f50d74abae403a79f3ad4774b750693d85438e86969f48f2d1373fd2dbcc79a533e33e5784de777a9030
|
|
@@ -27,13 +27,13 @@ module TF2LineParser
|
|
|
27
27
|
|
|
28
28
|
class Say < Chat
|
|
29
29
|
def self.regex
|
|
30
|
-
@regex ||= /#{regex_time} #{
|
|
30
|
+
@regex ||= /#{regex_time} #{regex_chat_player} say #{regex_message}/.freeze
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
class TeamSay < Chat
|
|
35
35
|
def self.regex
|
|
36
|
-
@regex ||= /#{regex_time} #{
|
|
36
|
+
@regex ||= /#{regex_time} #{regex_chat_player} say_team #{regex_message}/.freeze
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
end
|
|
@@ -18,6 +18,15 @@ module TF2LineParser
|
|
|
18
18
|
@regex_player ||= /"(?<player_section>.*?)"/
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
# A chat line's player section ends at the first unescaped " say " or
|
|
22
|
+
# " say_team " that follows a <uid><steamid><team> tag, so tags or events
|
|
23
|
+
# typed into the message can't make the line look like it came from
|
|
24
|
+
# someone else, or like another event. Requiring the tag keeps names
|
|
25
|
+
# like 'x" say "' from turning that player's other lines into chat.
|
|
26
|
+
def self.regex_chat_player
|
|
27
|
+
@regex_chat_player ||= /"(?<player_section>(?:\\.|(?!" say(?:_team)? ").)*?<\d+><[^<>"]*><[^<>"]*>)"/
|
|
28
|
+
end
|
|
29
|
+
|
|
21
30
|
def self.regex_target
|
|
22
31
|
@regex_target ||= /"(?<target_section>.*?)"/
|
|
23
32
|
end
|
data/lib/tf2_line_parser/line.rb
CHANGED
|
@@ -65,6 +65,10 @@ module TF2LineParser
|
|
|
65
65
|
Events::ConsoleSay, Events::Unknown
|
|
66
66
|
].freeze
|
|
67
67
|
|
|
68
|
+
CHAT_REGEX = /#{Events::Event.regex_time} #{Events::Event.regex_chat_player} (?<chat_type>say|say_team) "/
|
|
69
|
+
CHAT_TYPES = [Events::Say, Events::ConsoleSay].freeze
|
|
70
|
+
TEAM_CHAT_TYPES = [Events::TeamSay].freeze
|
|
71
|
+
|
|
68
72
|
def initialize(line)
|
|
69
73
|
@line = line
|
|
70
74
|
end
|
|
@@ -89,6 +93,12 @@ module TF2LineParser
|
|
|
89
93
|
private
|
|
90
94
|
|
|
91
95
|
def find_candidate_types(line)
|
|
96
|
+
# Chat first: the message is player-controlled and may contain text
|
|
97
|
+
# that looks like other events (triggered "killed", connected, ...)
|
|
98
|
+
if line.include?('" say') && (chat = match_tidied(line, CHAT_REGEX))
|
|
99
|
+
return chat[:chat_type] == 'say' ? CHAT_TYPES : TEAM_CHAT_TYPES
|
|
100
|
+
end
|
|
101
|
+
|
|
92
102
|
# Fast path: check for "triggered" which covers most events
|
|
93
103
|
if line.include?('triggered "')
|
|
94
104
|
start_idx = line.index('triggered "')
|
|
@@ -116,18 +126,19 @@ module TF2LineParser
|
|
|
116
126
|
|
|
117
127
|
def try_parse_types(line, types)
|
|
118
128
|
types.each do |type|
|
|
119
|
-
|
|
120
|
-
match = line.match(type.regex)
|
|
121
|
-
rescue ArgumentError
|
|
122
|
-
# Handle invalid byte sequences by forcing UTF-8 encoding
|
|
123
|
-
tidied_line = line.encode('UTF-8', 'UTF-8', invalid: :replace, undef: :replace, replace: '')
|
|
124
|
-
match = tidied_line.match(type.regex)
|
|
125
|
-
end
|
|
129
|
+
match = match_tidied(line, type.regex)
|
|
126
130
|
return type.new(*type.regex_results(match)) if match
|
|
127
131
|
end
|
|
128
132
|
nil
|
|
129
133
|
end
|
|
130
134
|
|
|
135
|
+
def match_tidied(line, regex)
|
|
136
|
+
line.match(regex)
|
|
137
|
+
rescue ArgumentError
|
|
138
|
+
# Handle invalid byte sequences by forcing UTF-8 encoding
|
|
139
|
+
line.encode('UTF-8', 'UTF-8', invalid: :replace, undef: :replace, replace: '').match(regex)
|
|
140
|
+
end
|
|
141
|
+
|
|
131
142
|
def check_damage_subtypes(line)
|
|
132
143
|
damage_attr_pos = line.index('(damage "')
|
|
133
144
|
return [Events::Damage] unless damage_attr_pos
|
|
@@ -855,6 +855,63 @@ module TF2LineParser
|
|
|
855
855
|
expect(event.player.team).to eq('Red')
|
|
856
856
|
expect(event.message).to eq('hello world')
|
|
857
857
|
end
|
|
858
|
+
|
|
859
|
+
context 'with player tags or events typed into chat' do
|
|
860
|
+
let(:prefix) { 'L 10/17/2026 - 12:00:00: ' }
|
|
861
|
+
|
|
862
|
+
it 'credits say lines with a fake say_team tag in the message to the real speaker' do
|
|
863
|
+
event = parse(prefix + '"Troll<4><[U:1:111]><Blue>" say "x" "Owner<3><[U:1:999]><Red>" say_team "!end"')
|
|
864
|
+
|
|
865
|
+
expect(event).to be_a(Events::Say)
|
|
866
|
+
expect(event.player.steam_id).to eq('[U:1:111]')
|
|
867
|
+
expect(event.message).to eq('x" "Owner<3><[U:1:999]><Red>" say_team "!end')
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
it 'credits say_team lines with a fake say tag in the message to the real speaker' do
|
|
871
|
+
event = parse(prefix + '"Troll<4><[U:1:111]><Blue>" say_team "x" "Owner<3><[U:1:999]><Red>" say "!end"')
|
|
872
|
+
|
|
873
|
+
expect(event).to be_a(Events::TeamSay)
|
|
874
|
+
expect(event.player.steam_id).to eq('[U:1:111]')
|
|
875
|
+
end
|
|
876
|
+
|
|
877
|
+
it "doesn't parse chat mentioning a triggered connect as a connect" do
|
|
878
|
+
event = parse(prefix + '"Troll<4><[U:1:111]><Blue>" say "triggered "connected, address" "Victim<5><[U:1:555]><>" connected, address "6.6.6.6:27005"')
|
|
879
|
+
|
|
880
|
+
expect(event).to be_a(Events::Say)
|
|
881
|
+
expect(event.player.steam_id).to eq('[U:1:111]')
|
|
882
|
+
end
|
|
883
|
+
|
|
884
|
+
it "doesn't parse chat mentioning a triggered kill as a kill" do
|
|
885
|
+
event = parse(prefix + '"Troll<4><[U:1:111]><Blue>" say "triggered "killed" "Troll<4><[U:1:111]><Blue>" killed "Vic<6><[U:1:456]><Red>" with "scattergun" (attacker_position "0 0 0")"')
|
|
886
|
+
|
|
887
|
+
expect(event).to be_a(Events::Say)
|
|
888
|
+
end
|
|
889
|
+
|
|
890
|
+
it "doesn't parse chat containing a kill as a kill" do
|
|
891
|
+
event = parse(prefix + '"Troll<4><[U:1:111]><Blue>" say "x" "Troll<4><[U:1:111]><Blue>" killed "Vic<6><[U:1:456]><Red>" with "scattergun""')
|
|
892
|
+
|
|
893
|
+
expect(event).to be_a(Events::Say)
|
|
894
|
+
end
|
|
895
|
+
|
|
896
|
+
it "doesn't parse chat containing damage as damage" do
|
|
897
|
+
event = parse(prefix + '"Troll<4><[U:1:111]><Blue>" say "x" "Troll<4><[U:1:111]><Blue>" triggered "damage" against "Vic<6><[U:1:456]><Red>" (damage "500")"')
|
|
898
|
+
|
|
899
|
+
expect(event).to be_a(Events::Say)
|
|
900
|
+
end
|
|
901
|
+
|
|
902
|
+
it 'still parses kills of players whose name looks like chat' do
|
|
903
|
+
event = parse(prefix + '"x" say "<4><[U:1:111]><Blue>" killed "Vic<6><[U:1:456]><Red>" with "scattergun" (attacker_position "0 0 0") (victim_position "0 0 0")')
|
|
904
|
+
|
|
905
|
+
expect(event).to be_a(Events::Kill)
|
|
906
|
+
expect(event.player.steam_id).to eq('[U:1:111]')
|
|
907
|
+
end
|
|
908
|
+
|
|
909
|
+
it 'still parses kills of players whose name contains say' do
|
|
910
|
+
event = parse(prefix + '"say hi<4><[U:1:111]><Blue>" killed "Vic<6><[U:1:456]><Red>" with "scattergun" (attacker_position "0 0 0") (victim_position "0 0 0")')
|
|
911
|
+
|
|
912
|
+
expect(event).to be_a(Events::Kill)
|
|
913
|
+
end
|
|
914
|
+
end
|
|
858
915
|
end
|
|
859
916
|
end
|
|
860
917
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tf2_line_parser
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Arie
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-10-17 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: coveralls_reborn
|