1 #**************************************************************************
2 # Copyright (C) 2009 by Michael Andreen <harvATruinDOTnu> *
4 # This program is free software; you can redistribute it and/or modify *
5 # it under the terms of the GNU General Public License as published by *
6 # the Free Software Foundation; either version 2 of the License, or *
7 # (at your option) any later version. *
9 # This program is distributed in the hope that it will be useful, *
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 # GNU General Public License for more details. *
14 # You should have received a copy of the GNU General Public License *
15 # along with this program; if not, write to the *
16 # Free Software Foundation, Inc., *
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 #**************************************************************************/
25 use NDIRC::Dispatcher;
28 help => q(syntax: .+user username [pnick] | username must be alphanum characters, if no pnick is given then it will be set to the same as username),
30 }, class extends NDIRC::Command {
31 method execute ($c,$msg) {
32 my ($nick,$pnick) = $msg =~ /^(\w+)(?: ([^.\s]+))?$/ or die 'ARGS';
37 my $host = "$pnick.users.netgamers.org";
38 my ($username,$hostname,$p_nick) = $dbh->selectrow_array(q{
39 SELECT username, hostmask,pnick
40 FROM users WHERE username = $1 OR hostmask = $2 OR pnick = $3
41 },undef,$nick,$host,$pnick);
43 if (defined $username){
44 $c->reply("<b>$username ($p_nick)</b> already exists with host: <b>$hostname</b>");
47 INSERT INTO users (username,hostmask,pnick,password) VALUES(?,?,?,'')
48 },undef,$nick,$host,$pnick);
49 $c->reply("Added <b>$nick(/$pnick)</b> with host: <b>$host</b>");
55 help => q(syntax: .-user nick | nick must be alphanum characters, if no pnick is given then it will be set to nick),
56 acl => 'irc_deactivateuser'
57 }, class extends NDIRC::Command {
58 method execute ($c,$msg) {
59 my ($nick) = $msg =~ /^(\S+)$/ or die 'ARGS';
62 my $f = $dbh->prepare(q{SELECT uid,username FROM users WHERE username ILIKE ?});
64 my ($uid,$username) = $f->fetchrow();
67 my $updated = $dbh->do(q{
68 UPDATE users SET hostmask = ?, password = '' WHERE uid = ?
69 },undef,$username,$uid);
71 my $groups = $dbh->do(q{DELETE FROM groupmembers WHERE uid = ?},undef,$uid);
73 $c->reply("<b>$username</b> has been deactivated. Removed from $groups groups.");
75 $c->reply("Something went wrong when trying to modify <b>$username</b>");
77 }elsif ($f->rows == 0){
78 $c->reply("No hit, maybe spelling mistake, or add % as wildcard");
80 $c->reply("More than 1 user matched, please refine the search");
87 help => q(syntax: .chattr username [-]flags | % can be used for wildcards \%arro% will match barrow, if a - is given then flags will be removed, otherwise added),
89 }, class extends NDIRC::Command {
90 method execute ($c,$msg) {
91 my ($nick, $mode, $flags) = $msg =~ /^(\S+) (\+|-)?(\w+)$/ or die 'ARGS';
94 my $f = $dbh->prepare(q{SELECT uid,username FROM users WHERE username ILIKE ?});
96 my $user = $f->fetchrow_hashref;
100 $update = $dbh->prepare(q{
101 DELETE FROM groupmembers WHERE uid = $1 AND gid = ANY($2)
104 $update = $dbh->prepare(q{
105 INSERT INTO groupmembers (uid,gid)
106 (SELECT $1,gid FROM unnest($2::text[]) gid WHERE
107 gid NOT IN (SELECT gid FROM groupmembers WHERE uid = $1)
108 AND gid IN (SELECT gid FROM groups))
111 my @flags = split /\W*/,$flags;
112 $update->execute($user->{uid},\@flags);
113 $update = $dbh->prepare(q{
114 SELECT array_to_string(array_agg(gid),'')
115 FROM (SELECT uid,gid FROM groupmembers ORDER BY uid,gid ) g
118 $flags = $dbh->selectrow_array($update,undef,$user->{uid});
119 $c->reply("Flags for <b>$user->{username}</b> are now: $flags");
120 }elsif ($f->rows == 0){
121 $c->reply("No hit, maybe spelling mistake, or add % as wildcard");
123 $c->reply("More than 1 user matched, please refine the search");
130 help => q(Lists all the available flags),
132 }, class extends NDIRC::Command {
133 method execute ($c,$msg) {
135 my ($flags) = $dbh->selectrow_array(q{
136 SELECT array_to_string(array_agg(gid||':'||groupname),', ') FROM groups
138 $c->reply("Current flags: $flags");
143 help => q(syntax: .whois username | % can be used for wildcards \%arro% will match barrow.),
145 }, class extends NDIRC::Command {
146 method execute ($c,$msg) {
147 my ($nick) = $msg =~ /^(\S+)$/ or die 'ARGS';
151 my $f = $dbh->prepare(q{
152 SELECT username, pnick, hostmask, array_to_string(array_agg(gid),'') AS flags
154 LEFT OUTER JOIN (SELECT uid,gid FROM groupmembers ORDER BY uid,gid
156 WHERE username ILIKE ?
157 GROUP BY username,pnick,hostmask LIMIT 5
160 while (my $user = $f->fetchrow_hashref){
161 $c->reply("<b>$user->{username} (/$user->{pnick})</b> flags: ($user->{flags}) host: $user->{hostmask}");
164 $c->reply("No hit, maybe spelling mistake, or add % as wildcard");
170 help => q(syntax: .flag flag [-noflags] | Lists all users with the given flag. Can specify a second argument to remove members that has any of those flags. .flag M -C lists all members that doesn't have community flag),
172 }, class extends NDIRC::Command {
173 method execute ($c,$msg) {
174 my ($flag,$noflag) = $msg =~ /^(\w)(?: -(\w+))?$/ or die 'ARGS';
177 my $f = $c->model->prepare(q{
178 SELECT array_to_string(array_agg(username),', '),count(username)
179 FROM (SELECT uid, username FROM users ORDER BY username) u
180 JOIN groupmembers gm USING (uid)
181 WHERE gid = $1 AND uid NOT IN (SELECT uid FROM groupmembers WHERE gid = ANY($2))
183 my @noflag = split //, $noflag;
184 my ($users,$count) = $c->model->selectrow_array($f,undef,$flag,\@noflag);
185 $c->reply("<b>$count</b> Users with flag <b>$flag</b>: $users");
190 help => q(syntax: .laston flag [days] | lists users and the number of days since they were last seen (irc|forum|claim). If days is specified it will only list users with at least that amount of idle time. Days can also specify forum and claim with irc|forum|claim syntax),
192 }, class extends NDIRC::Command {
193 method execute ($c,$msg) {
194 my ($flag,$min,$forum,$claim) = $msg =~ /^(\w)(?: (\d+)(?:\|(\d+)\|(\d+))?)?$/
198 my $f = $c->model->prepare(q{
199 SELECT username, COALESCE(last::text,'?') AS last
200 ,COALESCE(lastforum::text,'?') AS lastforum
201 ,COALESCE(lastclaim::text,'?') AS lastclaim
202 FROM (SELECT username
203 ,date_part('day',now() - laston)::int AS last
204 ,date_part('day',now() -
205 (SELECT max(time) FROM forum_thread_visits WHERE uid = u.uid)) AS lastforum
206 ,date_part('day',now() -
207 (SELECT max(timestamp) FROM raid_claims WHERE uid = u.uid)) AS lastclaim
209 NATURAL JOIN groupmembers
212 WHERE COALESCE(last >= $2,TRUE) AND COALESCE(lastforum >= $3,TRUE)
213 AND COALESCE(lastclaim >= $4,TRUE)
214 ORDER BY a.last DESC, a.lastforum DESC, a.lastclaim DESC
216 $f->execute($flag,$min,$forum,$claim);
220 while (my $user = $f->fetchrow_hashref){
221 $text .= "$user->{username}($user->{last}|$user->{lastforum}|$user->{lastclaim}) ";
224 $c->reply("<b>$i</b> Users(days) with flag <b>$flag</b>: $text");
229 command lastseen => {
230 help => q(syntax: .lastseen username | Shows the number of days since the user(s) last visited irc, forum and raids),
231 acl => 'irc_lastseen'
232 }, class extends NDIRC::Command {
233 method execute ($c,$msg) {
234 my ($username) = $msg =~ /^(\S+)$/ or die 'ARGS';
236 my $f = $c->model->prepare(q{
237 SELECT username, COALESCE(date_part('day',now() - laston)::text,'?') AS last
238 ,COALESCE(date_part('day',now() - (SELECT max(time)
239 FROM forum_thread_visits WHERE uid = u.uid))::text,'?') AS lastforum
240 ,COALESCE(date_part('day',now() - (SELECT max(timestamp)
241 FROM raid_claims WHERE uid = u.uid))::text,'?') AS lastclaim
243 WHERE username ILIKE $1 ORDER BY username
245 $f->execute($username);
249 while (my $user = $f->fetchrow_hashref){
250 $text .= "$user->{username}($user->{last}|$user->{lastforum}|$user->{lastclaim}) ";
253 $c->reply("<b>$i</b> Users(days): $text");
257 command getships => {
258 help => q(Usage: .getships ship | % can be used as wildcard, e.g. beet%, shipshome shows the number of ships currently home),
259 alias => 'shipshome',
260 acl => 'irc_getships'
261 }, class extends NDIRC::Command {
262 method execute ($c,$msg) {
263 my ($ship) = $msg =~ /^(\S+)$/ or die 'ARGS';
266 my $f = $dbh->prepare(q{
267 SELECT username,SUM(fs.amount) AS amount
269 JOIN (SELECT DISTINCT ON (pid) pid,fid FROM fleets
270 WHERE mission = 'Full fleet' AND name <> 'Unit'
271 ORDER BY pid,tick DESC,fid DESC
273 JOIN fleet_ships fs USING (fid)
274 WHERE ship ILIKE $1 AND uid IN (SELECT uid FROM groupmembers WHERE gid = 'M')
275 GROUP BY username ORDER BY amount DESC
277 if ($self->name eq 'shipshome'){
278 $f = $dbh->prepare(q{
279 SELECT username,SUM(amount) AS amount
281 WHERE ship ILIKE ? AND uid IN (SELECT uid FROM groupmembers WHERE gid = 'M')
282 GROUP BY username ORDER BY amount DESC
289 while (my $user = $f->fetchrow_hashref){
290 $text .= "$user->{username}: $user->{amount} ";
292 $total += $user->{amount};
295 $c->reply("<b>$i</b> Users with <b>$total $ship</b>: $text");
297 $c->reply("Couldn't find any user with <b>$ship</b>");
302 command getfleet => {
303 help => q(Usage: .getfleet username | % can be used as wildcard, e.g. barr%),
304 acl => q(irc_getfleet)
305 }, class extends NDIRC::Command {
306 method execute ($c,$msg) {
307 my ($nick) = $msg =~ /^(\S+)$/ or die 'ARGS';
310 my $f = $dbh->prepare(q{
311 SELECT fs.ship, fs.amount, username
313 JOIN (SELECT fid,username
315 JOIN users u USING (pid)
316 WHERE mission = 'Full fleet' AND name <> 'Unit'
317 AND username ILIKE $1
318 ORDER BY pid,tick DESC,fid DESC
326 while (my $ship = $f->fetchrow_hashref){
327 unless (defined $username) {
328 $username = $ship->{username};
329 $text = "<b>$username</b> has: "
331 $text .= "$ship->{ship} $ship->{amount} ";
336 $c->reply("Couldn't find any fleet for $nick");
342 help => q(Usage: .sethost username [host] | if host isn't given then it resets to netgamers host),
343 acl => q(irc_sethost)
344 }, class extends NDIRC::Command {
345 method execute ($c,$msg) {
346 my ($nick,$host) = $msg =~ /^(\S+)(?: (\S+))?$/ or die 'ARGS';
349 my $f = $dbh->prepare(q{
350 SELECT uid,username,pnick,hostmask FROM users WHERE username ILIKE ?
353 my $user = $f->fetchrow_hashref;
355 $host //= "$user->{pnick}.users.netgamers.org";
357 $dbh->do(q{UPDATE users SET hostmask = ? WHERE uid = ?}
358 ,undef,$host,$user->{uid});
359 $c->reply("Updated <b>$user->{username}</b>'s host to: <b>$host</b>");
362 if ($@ =~ /duplicate key value violates unique constraint/){
363 my ($username, $hostname) = $dbh->selectrow_array(q{
364 SELECT username,hostmask FROM users WHERE hostmask = $1
366 $c->reply("<c04>Problem</c>, <b>$username</b> already uses host <b>$hostname</b>.");
371 }elsif ($f->rows == 0){
372 $c->reply("No hit, maybe spelling mistake, or add % as wildcard");
374 $c->reply("More than 1 user matched, please refine the search");
380 command setpnick => {
381 help => q(Usage: .setpnick username pnick | Changes a user's pnick),
382 acl => q(irc_setpnick)
383 }, class extends NDIRC::Command {
384 method execute ($c,$msg) {
385 my ($nick,$pnick) = $msg =~ /^(\S+) (\S+)$/ or die 'ARGS';
388 my $f = $dbh->prepare(q{SELECT uid,username FROM users WHERE username ILIKE ?});
390 my $user = $f->fetchrow_hashref;
392 my $hostname = "$pnick.users.netgamers.org";
394 $dbh->do(q{UPDATE users SET pnick = ?, hostmask = ? WHERE uid = ?}
395 ,undef,$pnick,$hostname,$user->{uid});
396 $c->reply("Updated <b>$user->{username}</b>'s pnick to: <b>$pnick</b> and hostname to <b>$hostname</b>");
399 if ($@ =~ /duplicate key value violates unique constraint/){
400 my ($username, $hostname, $pnick) = $dbh->selectrow_array(q{
401 SELECT username,hostmask,pnick FROM users WHERE hostmask = $1 OR pnick = $2
402 },undef,$hostname, $pnick);
403 $c->reply("<c04>Problem</c>, <b>$username</b> already uses host <b>$hostname</b> and pnick <b>$pnick</b>.");
408 }elsif ($f->rows == 0){
409 $c->reply("No hit, maybe spelling mistake, or add % as wildcard");
411 $c->reply("More than 1 user matched, please refine the search");
417 my $points = class extends NDIRC::Command {
423 method execute ($c,$msg) {
424 my ($nick,$points) = $msg =~ /^(\S+)(?: (-?(:?\d+|\d*\.\d+)))?$/ or die 'ARGS';
426 return unless $self->check($c,$nick);
432 if ($points*$points > 400){
433 $c->reply("Values between -20 and 20 please");
437 my $f = $dbh->prepare(q{SELECT uid,username FROM users WHERE username ILIKE ?});
439 my $user = $f->fetchrow_hashref;
441 my $type .= $self->point . "_points";
442 $dbh->do(qq{UPDATE users SET $type = $type + ? WHERE uid = ?}
443 ,undef,$points,$user->{uid});
444 $c->reply("$user->{username} has been given $points $type");
445 }elsif ($f->rows == 0){
446 $c->reply("No hit, maybe spelling mistake, or add % as wildcard");
448 $c->reply("More than 1 user matched, please refine the search");
452 method check ($c,$nick) {
458 help => q(Usage: .a username [points] | % can be used for wildcards %arro% will match barrow, if the number of points isn't specified, then 1 will be assumed.),
462 extends $points->name;
463 method check ($c,$nick) {
464 my ($fleets) = $c->model->selectrow_array(q{
465 SELECT count(*) FROM raids r
466 JOIN raid_targets rt ON r.id = rt.raid
467 JOIN raid_claims rc ON rt.id = rc.target
468 WHERE not launched AND tick + 24 > tick()
469 AND uid = (SELECT uid FROM users WHERE username ILIKE $1);
472 if ($fleets > 0 && $points > 0){
473 $c->reply("$nick has $fleets claimed waves the last 24 ticks that aren't marked as launched, so no points.");
481 help => q(Usage: .d username [points] | % can be used for wildcards %arro% will match barrow, if the number of points isn't specified, then 1 will be assumed.),
488 help => q(Usage: .s username [points] | % can be used for wildcards %arro% will match barrow, if the number of points isn't specified, then 1 will be assumed.),
494 help => q(Usage: .h username [points] | % can be used for wildcards %arro% will match barrow, if the number of points isn't specified, then 1 will be assumed.),