5 ###############################################################################
6 # Monitors DGS for new games
10 dgsmon - Dragon Go Server Monitor
18 B<dgsmon> monitors Dragon Go Server
19 (http://www.dragongoserver.net) for you to check whether
20 it's your turn to move on one or more games. For each game,
21 it will print out the name of the opponent.
29 use HTML::TreeBuilder;
34 ###############################################################################
36 my $cookie_file = "$ENV{HOME}/.dgsmon.cookies";
37 my $config_file = "$ENV{HOME}/.dgsmonrc";
39 ###############################################################################
41 my ($cookie_jar, $request, $response, $output_format);
43 my (%config, $verbose);
45 ###############################################################################
53 Produce output in the format used by GKrellm FMonitor[1].
54 You can call B<dgsmon> regularly with this option from a
55 crontab, direct the output to a file, and set Gkrellm to
56 display the information.
58 A crontab entry that works every minute would look like:
60 * * * * * $HOME/bin/dgsmon -fmon > $HOME/.dgsmon.output
62 Then you would configure FMonitor to use
67 $output_format = 'NORMAL';
70 foreach my $arg (@ARGV) {
72 $output_format = 'FMON';
75 if ($arg =~ /verbose/) {
79 pod2usage(-verbose=>2) if @ARGV;
86 ###############################################################################
87 # Lecture du fichier de config
96 Upon startup, the file $HOME/.dgsmonrc is checked for
97 authentication information. This file is simple "key=value"
98 file, one value per line, and must define a key C<username>
99 containing your user identifier, and a ke C<passwd>
100 containing your password. To prevent other users from
101 accessing your login information, thie file must only be
102 accessible by you. B<dgsmon> will refuse to work if its
103 access mode is not 600.
113 die "$config_file: Unable to read\n" unless -r $config_file;
114 my $mode = (stat $config_file)[2];
115 die "$config_file must be 0600\n" if (($mode&0777) != 0600);
116 open my $fh, $config_file or die "$config_file: $!\n";
118 my ($key, $value) = /(\w+)=(.*)/;
119 die "illegal config line: $_\n" unless defined $key
121 $config{$key} = $value;
125 ###############################################################################
127 =item $HOME/.dgsmon.cookies
129 This file is managed by B<dgsmon>. It is used to store the
130 login cookies that Dragon Go Server sends back, so B<dgsmon>
131 can just re-use them if possible. This saves authenticating
132 yourself each time. To prevent other users from accessing
133 your cookie information, which would let them connect using
134 your account, this file must only be accessible by you.
135 B<dgsmon> will refuse to work if its access mode is
140 # Check if we've got cookies
141 if (-e $cookie_file) {
142 my $mode = (stat $cookie_file)[2];
143 die "$cookie_file must be 0600\n" if (($mode&0777) != 0600);
145 $cookie_jar = HTTP::Cookies->new;
146 $cookie_jar->load($cookie_file);
147 die "$cookie_file: $!\n" unless defined $cookie_jar;
150 my $user_agent = LWP::UserAgent->new;
152 # Try to log in with the current cookies
153 $user_agent->cookie_jar($cookie_jar);
154 $request = new HTTP::Request(
155 GET => "http://www.dragongoserver.net/status.php"
157 $response = $user_agent->request($request);
159 my $logged_in = !($response->content =~ /have to be logged in/);
161 ###############################################################################
164 warn "loggin in...\n" if $verbose;
167 $response = $user_agent->request(
169 GET => "http://www.dragongoserver.net/index.php"
172 die "Load login page failed: ".$response->status_line."\n" unless $response->is_success;
174 warn "login page loaded\n" if $verbose;
176 my $form = HTML::Form->parse($response);
177 die "No form on login page\n" unless defined $form;
179 $form->value("userid", $config{username});
180 $form->value("passwd", $config{passwd});
182 print "userid: ".$form->value("userid")."\n" if $verbose;
183 print "passwd: ".$form->value("passwd")."\n" if $verbose;
185 $request = $form->click("login");
186 die "clicking form failed\n" unless defined $request;
188 warn "filled form\n" if $verbose;
190 $response = $user_agent->request($request);
192 warn "form response received\n" if $verbose;
195 $cookie_jar = HTTP::Cookies->new;
196 $cookie_jar->extract_cookies($response);
197 my $old_umask = umask(0077);
198 $cookie_jar->save($cookie_file);
200 $user_agent->cookie_jar($cookie_jar);
202 warn "loading status page\n" if $verbose;
203 # Finally, get the status page
204 $request = new HTTP::Request(
205 GET => $response->header('location')
208 $response = $user_agent->request($request);
211 ###############################################################################
212 # At this stage, $response should contain the main page
215 # Get all the links containing 'game.php'
216 my $tree = HTML::TreeBuilder->new();
217 $tree->parse($response->content);
222 $tree->look_down( # !
225 my $href = $_[0]->attr('href');
226 return unless defined $href;
227 return unless $href =~ /game\.php/;
234 if ($output_format eq 'FMON') {
240 foreach my $game (@out) {
241 my @elems = $game->parent->parent->content_list;
242 my ($board, $sgf ,$player, $color, $size, $handi, $komi) =
243 map { $_->as_text; } @elems;
245 if ($output_format eq 'FMON') {
246 print "${player}::\n";
248 print "[$board] $player ($size x $size, handi $handi komi $komi)\n";
254 [1] The FMonitor plugin is available from
255 http://kmlinux.fjfi.cvut.cz/~makovick/gkrellm/index.html.
259 v1.1: Error message when login fails.
261 v1.0: First release. Works for me(tm).
265 This program is free software; you may redistribute it
266 and/or modify it under the same terms as Perl itself.
270 Yves "WhiteRabbit" Rutschle -- Challenge me on DGS! ;)
272 Send comments and bug reports to dgs@rutschle.net.