File Coverage

blib/lib/Parse/Colloquy/Bot.pm
Criterion Covered Total %
statement 32 102 31.3
branch 14 32 43.7
condition 13 36 36.1
subroutine 8 9 88.8
pod 1 3 33.3
total 68 182 37.3


line stmt bran cond sub pod time code
1             ############################################################
2             #
3             # $Id: Bot.pm 483 2006-05-22 21:36:46Z nicolaw $
4             # Parse::Colloquy::Bot - Parse Colloquy bot/client terminal output
5             #
6             # Copyright 2006 Nicola Worthington
7             #
8             # Licensed under the Apache License, Version 2.0 (the "License");
9             # you may not use this file except in compliance with the License.
10             # You may obtain a copy of the License at
11             #
12             # http://www.apache.org/licenses/LICENSE-2.0
13             #
14             # Unless required by applicable law or agreed to in writing, software
15             # distributed under the License is distributed on an "AS IS" BASIS,
16             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17             # See the License for the specific language governing permissions and
18             # limitations under the License.
19             #
20             ############################################################
21              
22             package Parse::Colloquy::Bot;
23             # vim:ts=4:sw=4:tw=78
24              
25 3     3   35783 use strict;
  3         8  
  3         117  
26 3     3   28 use Exporter;
  3         5  
  3         152  
27 3     3   16 use Carp qw(croak cluck confess carp);
  3         7  
  3         331  
28              
29 3     3   15 use vars qw($VERSION $DEBUG @EXPORT @EXPORT_OK %EXPORT_TAGS @ISA);
  3         6  
  3         636  
30              
31             $VERSION = '0.02' || sprintf('%d.%02d', q$Revision: 457 $ =~ /(\d+)/g);
32              
33             @ISA = qw(Exporter);
34             @EXPORT = qw();
35             @EXPORT_OK = qw(parse_line);
36             %EXPORT_TAGS = (all => \@EXPORT_OK);
37              
38             $DEBUG = $ENV{DEBUG} ? 1 : 0;
39              
40             BEGIN {
41             # It would be nice to have high resolution times if possible
42 3     3   8 eval { require Time::HiRes; import Time::HiRes qw(time); };
  3         4162  
  3         7033  
43             }
44              
45             sub parse_line {
46 4     4 1 41402 my @out = ();
47 4         15 for my $input (@_) {
48 4         13 push @out, _parse_line($input);
49             }
50 4 50       11 if (wantarray) {
51 4         20 return @out;
52             } else {
53 0 0       0 return $out[0] if @out == 1;
54 0         0 return \@out;
55             }
56             }
57              
58             sub _parse_line {
59 4     4   7 local $_ = $_[0];
60 4         11 s/[\n\r]//g;
61 4         45 s/^\s+|\s+$//g;
62              
63 4         8 my $raw = $_;
64 4 50       16 $_ = "RAW $_" if m/^\+\+\+/;
65 4 50       24 return unless m/^([A-Z]+\S*)(?:\s+(.+))?$/;
66              
67 4   50     97 my %args = (
      50        
      50        
68             "time" => time(),
69             "raw" => $raw,
70             "msgtype" => $1 || '',
71             "text" => $2 || '',
72             "args" => [ split(/\s+/,$_||'') ],
73             "command" => undef,
74             "cmdargs" => undef,
75             "list" => undef,
76             "person" => undef,
77             "respond" => undef,
78             );
79 4         13 local $_ = $args{text};
80              
81 4 50 33     121 if ($args{msgtype} =~ /^TALK|TELL$/ && /^(\S+)\s+[:>](.*)\s*$/) {
    50 33        
    50 33        
    50 33        
    50 33        
    50 33        
    50 33        
    50 33        
    50 33        
    50 33        
82 0         0 TRACE('TALK|TELL');
83 0         0 $args{person} = $1;
84 0         0 $args{text} = $2;
85 0         0 $args{args} = [ split(/\s+/,$args{text}) ];
86 0         0 $args{cmdargs} = [ @{$args{args}} ];
  0         0  
87 0         0 $args{command} = shift @{$args{cmdargs}};
  0         0  
88              
89             } elsif ($args{msgtype} eq 'LISTINVITE' && /((\S+)\s+invites\s+you\s+to\s+(\S+)\s+To\s+respond,\s+type\s+(.+))\s*$/) {
90 0         0 TRACE('LISTINVITE');
91 0         0 $args{text} = $1;
92 0         0 $args{person} = $2;
93 0         0 $args{list} = $3;
94 0         0 $args{respond} = $4;
95 0         0 $args{args} = [ split(/\s+/,$args{text}) ];
96              
97             } elsif ($args{msgtype} eq 'LISTTALK' && /^(\S+)\s*%(.*)\s+{(.+?)}\s*$/) {
98 0         0 TRACE('LISTTALK');
99 0         0 $args{person} = $1;
100 0         0 $args{text} = $2;
101 0         0 $args{args} = [ split(/\s+/,$args{text}) ];
102 0         0 $args{cmdargs} = [ @{$args{args}} ];
  0         0  
103 0         0 $args{command} = shift @{$args{cmdargs}};
  0         0  
104 0         0 $args{list} = '%'.$3;
105              
106             } elsif ($args{msgtype} eq 'LISTEMOTE' && /^%\s*(\S+)\s+(.*)\s+{(.+?)}\s*$/) {
107 0         0 TRACE('LISTEMOTE');
108 0         0 $args{person} = $1;
109 0         0 $args{text} = $2;
110 0         0 $args{args} = [ split(/\s+/,$args{text}) ];
111 0         0 $args{list} = '%'.$3;
112              
113             } elsif ($args{msgtype} eq 'OBSERVED' && /^(\S+)\s+(\S+)\s+(\S+)\s+\@(.+)\s+{(\@.+?)}\s*$/) {
114 0         0 TRACE("OBSERVED $2 (a)");
115 0         0 $args{group} = $args{list} = '@'.$1;
116 0         0 $args{msgtype} = "OBSERVED $2";
117 0         0 $args{person} = $3;
118 0         0 $args{text} = $4;
119 0         0 $args{args} = [ split(/\s+/,$args{text}) ];
120 0         0 $args{cmdargs} = [ @{$args{args}} ];
  0         0  
121 0         0 $args{command} = shift @{$args{cmdargs}};
  0         0  
122              
123             } elsif ($args{msgtype} eq 'OBSERVED' && /^(\S+)\s+(\S+)\s+(?:\@\s+)(\S+)\s+(.+)\s+{(\@.+?)}\s*$/) {
124 0         0 TRACE("OBSERVED $2 (b)");
125 0         0 $args{group} = $args{list} = '@'.$1;
126 0         0 $args{msgtype} = "OBSERVED $2";
127 0         0 $args{person} = $3;
128 0         0 $args{text} = $4;
129 0         0 $args{args} = [ split(/\s+/,$args{text}) ];
130              
131             } elsif ($args{msgtype} eq 'OBSERVED' && /^(\S+)\s+GROUPCHANGE\s+(\S+)\s+(.*)\s*$/) {
132 0         0 TRACE('OBSERVED GROUPCHANGE');
133 0         0 $args{group} = $args{list} = '@'.$1;
134 0         0 $args{msgtype} = 'OBSERVED GROUPCHANGE';
135 0         0 $args{person} = $2;
136 0         0 $args{text} = $3;
137 0         0 $args{args} = [ split(/\s+/,$args{text}) ];
138              
139             } elsif ($args{msgtype} eq 'SHOUT' && /^(\S+)\s+\!(.*)\s*$/) {
140 0         0 TRACE('SHOUT');
141 0         0 $args{person} = $1;
142 0         0 $args{text} = $2;
143 0         0 $args{args} = [ split(/\s+/,$args{text}) ];
144              
145             } elsif ($args{msgtype} eq 'CONNECT' && /^((\S+).+\s+(\S+)\.)\s*$/) {
146 0         0 TRACE('CONNECT');
147 0         0 $args{text} = $1;
148 0         0 $args{person} = $2;
149 0         0 $args{group} = $args{list} = '@'.$3;
150 0         0 $args{args} = [ split(/\s+/,$args{text}) ];
151              
152             } elsif ($args{msgtype} eq 'IDLE' && /^((\S+)(.*))\s*$/) {
153 0         0 TRACE('IDLE');
154 0         0 $args{text} = $1;
155 0         0 $args{person} = $2;
156 0         0 $args{args} = [ split(/\s+/,$args{text}) ];
157             }
158              
159 4         45 DUMP('%args',\%args);
160 4         19 return \%args;
161             }
162              
163             sub TRACE {
164 0 0   0 0 0 return unless $DEBUG;
165 0         0 warn(shift());
166             }
167              
168             sub DUMP {
169 4 50   4 0 14 return unless $DEBUG;
170 0           eval {
171 0           require Data::Dumper;
172 0           warn(shift().': '.Data::Dumper::Dumper(shift()));
173             }
174             }
175              
176             1;
177              
178             =pod
179              
180             =head1 NAME
181              
182             Parse::Colloquy::Bot - Parse Colloquy bot/client terminal output
183              
184             =head1 SYNOPSIS
185              
186             use strict;
187             use Parse::Colloquy::Bot qw(:all);
188             use Data::Dumper;
189            
190             # ... connect to Colloquy and read from the server ...
191             my $parsed = parse_line($raw_input);
192             print Dumper($parsed);
193            
194             =head1 DESCRIPTION
195              
196             This module will parse the raw "client" or "bot" terminal line
197             output from a connection to a Colloquy server.
198              
199             =head1 FUNCTIONS
200              
201             =head2 parse_line
202              
203             Accepts a single scalar input line or an array of input. Will
204             return a hash reference or array of hash references for each
205             input line, depending on the context that the function called.
206              
207             =head1 EXAMPLE
208              
209             The following input line from Colloquy:
210              
211             LISTTALK neech2 %hello my name is neech {perl}
212              
213             Will be parsed in to the following structure:
214              
215             $VAR1 = {
216             'raw' => 'LISTTALK neech2 %hello my name is neech {perl}',
217             'msgtype' => 'LISTTALK',
218             'person' => 'neech2',
219             'list' => '%perl'
220             'text' => 'hello my name is neech',
221             'args' => [
222             'hello',
223             'my',
224             'name',
225             'is',
226             'neech'
227             ],
228             'command' => 'hello',
229             'cmdargs' => [
230             'my',
231             'name',
232             'is',
233             'neech'
234             ],
235             'respond' => undef,
236             'time' => 1148224087,
237             };
238              
239             =head1 SEE ALSO
240              
241             L, L, L
242              
243             =head1 VERSION
244              
245             $Id: Bot.pm 483 2006-05-22 21:36:46Z nicolaw $
246              
247             =head1 AUTHOR
248              
249             Nicola Worthington
250              
251             L
252              
253             =head1 COPYRIGHT
254              
255             Copyright 2006 Nicola Worthington.
256              
257             This software is licensed under The Apache Software License, Version 2.0.
258              
259             L
260              
261             =cut
262              
263              
264             __END__