forked from tommyrot/superseriousstats
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser_eggdrop.php
149 lines (130 loc) · 6.28 KB
/
parser_eggdrop.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?php
/**
* Copyright (c) 2007-2016, Jos de Ruijter <jos@dutnie.nl>
*/
/**
* Parse instructions for the Eggdrop logfile format.
*
* Line Format Notes
* ---------------------------------------------------------------------------------------------------------------------
* Normal <NICK> MSG Skip empty lines.
* Action Action: NICK MSG Skip empty actions.
* Slap Action: NICK slaps MSG Slaps may lack a (valid) target.
* Nickchange Nick change: NICK -> NICK
* Join NICK (HOST) joined CHAN.
* Part NICK (HOST) left CHAN (MSG). Part message may be absent, or empty due to
* normalization.
* Quit NICK (HOST) left irc: MSG Quit message may be empty due to normalization.
* Mode CHAN: mode change '+o-v NICK NICK' by NICK!HOST Only check for combinations of ops (+o) and
* voices (+v). Host may be absent.
* Topic Topic changed on CHAN by NICK!HOST: MSG Skip empty topics. Host may be absent.
* Kick NICK kicked from CHAN by NICK: MSG Kick message may be empty due to normalization.
* Repeat Last message repeated NUM time(s).
* ---------------------------------------------------------------------------------------------------------------------
*
* Notes:
* - normalize_line() scrubs all lines before passing them on to parse_line().
* - Given that nicks can't contain "<", ">" or ":" the order of the regular expressions below is irrelevant (current
* order aims for best performance).
* - The most common channel prefixes are "#&!+".
* - Some converted mIRC logs do include "!" in "mode" and "topic" lines while there is no host. Legacy feature.
* - In certain cases $matches[] won't contain index items if these optionally appear at the end of a line. We use
* empty() to check whether an index item is both set and has a value.
*/
class parser_eggdrop extends parser
{
/**
* Variables that shouldn't be tampered with.
*/
private $repeatlock = false;
/**
* Parse a line for various chat data.
*/
protected function parse_line($line)
{
/**
* "Normal" lines.
*/
if (preg_match('/^\[(?<time>\d{2}:\d{2}(:\d{2})?)\] <(?<nick>\S+)> (?<line>.+)$/', $line, $matches)) {
$this->set_normal($matches['time'], $matches['nick'], $matches['line']);
/**
* "Join" lines.
*/
} elseif (preg_match('/^\[(?<time>\d{2}:\d{2}(:\d{2})?)\] (?<nick>\S+) \(\S+\) joined [#&!+]\S+\.$/', $line, $matches)) {
$this->set_join($matches['time'], $matches['nick']);
/**
* "Quit" lines.
*/
} elseif (preg_match('/^\[(?<time>\d{2}:\d{2}(:\d{2})?)\] (?<nick>\S+) \(\S+\) left irc:( .+)?$/', $line, $matches)) {
$this->set_quit($matches['time'], $matches['nick']);
/**
* "Mode" lines.
*/
} elseif (preg_match('/^\[(?<time>\d{2}:\d{2}(:\d{2})?)\] [#&!+]\S+: mode change \'(?<modes>[-+][ov]+([-+][ov]+)?) (?<nicks_undergoing>\S+( \S+)*)\' by (?<nick_performing>\S+?)(!(\S+)?)?$/', $line, $matches)) {
$modenum = 0;
$nicks_undergoing = explode(' ', $matches['nicks_undergoing']);
for ($i = 0, $j = strlen($matches['modes']); $i < $j; $i++) {
$mode = substr($matches['modes'], $i, 1);
if ($mode === '-' || $mode === '+') {
$modesign = $mode;
} else {
$this->set_mode($matches['time'], $matches['nick_performing'], $nicks_undergoing[$modenum], $modesign.$mode);
$modenum++;
}
}
/**
* "Action" and "slap" lines.
*/
} elseif (preg_match('/^\[(?<time>\d{2}:\d{2}(:\d{2})?)\] Action: (?<line>(?<nick_performing>\S+) ((?<slap>[sS][lL][aA][pP][sS]( (?<nick_undergoing>\S+)( .+)?)?)|(.+)))$/', $line, $matches)) {
if (!empty($matches['slap'])) {
$this->set_slap($matches['time'], $matches['nick_performing'], (!empty($matches['nick_undergoing']) ? $matches['nick_undergoing'] : null));
}
$this->set_action($matches['time'], $matches['nick_performing'], $matches['line']);
/**
* "Nickchange" lines.
*/
} elseif (preg_match('/^\[(?<time>\d{2}:\d{2}(:\d{2})?)\] Nick change: (?<nick_performing>\S+) -> (?<nick_undergoing>\S+)$/', $line, $matches)) {
$this->set_nickchange($matches['time'], $matches['nick_performing'], $matches['nick_undergoing']);
/**
* "Part" lines.
*/
} elseif (preg_match('/^\[(?<time>\d{2}:\d{2}(:\d{2})?)\] (?<nick>\S+) \(\S+\) left [#&!+]\S+( \(.*\))?\.$/', $line, $matches)) {
$this->set_part($matches['time'], $matches['nick']);
/**
* "Topic" lines.
*/
} elseif (preg_match('/^\[(?<time>\d{2}:\d{2}(:\d{2})?)\] Topic changed on [#&!+]\S+ by (?<nick>\S+?)(!(\S+)?)?: (?<line>.+)$/', $line, $matches)) {
$this->set_topic($matches['time'], $matches['nick'], $matches['line']);
/**
* "Kick" lines.
*/
} elseif (preg_match('/^\[(?<time>\d{2}:\d{2}(:\d{2})?)\] (?<line>(?<nick_undergoing>\S+) kicked from [#&!+]\S+ by (?<nick_performing>\S+):( .+)?)$/', $line, $matches)) {
$this->set_kick($matches['time'], $matches['nick_performing'], $matches['nick_undergoing'], $matches['line']);
/**
* Eggdrop logs repeated lines (case insensitive matches) in the format: "Last message repeated NUM
* time(s).". We process the previous line NUM times.
*/
} elseif (preg_match('/^\[(?<time>\d{2}:\d{2}(:\d{2})?)\] Last message repeated (?<num>\d+) time\(s\)\.$/', $line, $matches)) {
/**
* Prevent the parser from repeating a preceding repeat line. Also, skip processing if we find a
* repeat line but $prevline isn't set.
*/
if ($this->prevline === '' || $this->repeatlock) {
return null;
}
$this->linenum--;
$this->repeatlock = true;
output::output('debug', __METHOD__.'(): repeating line '.$this->linenum.': '.$matches['num'].' time'.(($matches['num'] !== '1') ? 's' : ''));
for ($i = 1, $j = (int) $matches['num']; $i <= $j; $i++) {
$this->parse_line($this->prevline);
}
$this->linenum++;
$this->repeatlock = false;
/**
* Skip everything else.
*/
} elseif ($line !== '') {
output::output('debug', __METHOD__.'(): skipping line '.$this->linenum.': \''.$line.'\'');
}
}
}