2010-03-22 08:33:44 +01:00
|
|
|
# File: BotAdmins.pm
|
2010-03-24 07:47:40 +01:00
|
|
|
# Author: pragma_
|
2010-03-22 08:33:44 +01:00
|
|
|
#
|
|
|
|
# Purpose: Manages list of bot admins and whether they are logged in.
|
|
|
|
|
2017-03-05 22:33:31 +01:00
|
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
2010-03-22 08:33:44 +01:00
|
|
|
package PBot::BotAdmins;
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
|
2019-07-11 03:40:53 +02:00
|
|
|
use feature 'unicode_strings';
|
|
|
|
|
2010-08-15 10:25:35 +02:00
|
|
|
use PBot::DualIndexHashObject;
|
2014-05-18 02:27:57 +02:00
|
|
|
use PBot::BotAdminCommands;
|
2010-08-15 10:25:35 +02:00
|
|
|
|
2010-03-22 08:33:44 +01:00
|
|
|
use Carp ();
|
|
|
|
|
|
|
|
sub new {
|
2019-12-31 04:37:21 +01:00
|
|
|
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
|
2010-03-22 08:33:44 +01:00
|
|
|
my ($class, %conf) = @_;
|
|
|
|
my $self = bless {}, $class;
|
|
|
|
$self->initialize(%conf);
|
|
|
|
return $self;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub initialize {
|
|
|
|
my ($self, %conf) = @_;
|
2019-12-31 04:37:21 +01:00
|
|
|
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
|
|
|
|
$self->{admins} = PBot::DualIndexHashObject->new(name => 'Admins', filename => $conf{filename}, pbot => $conf{pbot});
|
|
|
|
$self->{commands} = PBot::BotAdminCommands->new(pbot => $conf{pbot});
|
2014-05-18 02:27:57 +02:00
|
|
|
$self->load_admins;
|
2010-03-22 08:33:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub add_admin {
|
|
|
|
my $self = shift;
|
2014-05-17 22:08:19 +02:00
|
|
|
my ($name, $channel, $hostmask, $level, $password, $dont_save) = @_;
|
2020-01-04 05:39:13 +01:00
|
|
|
$channel = '.*' if $channel !~ m/^#/;
|
2020-01-15 03:10:53 +01:00
|
|
|
|
|
|
|
my $data = {
|
|
|
|
name => $name,
|
|
|
|
level => $level,
|
|
|
|
password => $password
|
|
|
|
};
|
|
|
|
|
2014-05-18 22:09:05 +02:00
|
|
|
$self->{pbot}->{logger}->log("Adding new level $level admin: [$name] [$hostmask] for channel [$channel]\n");
|
2020-01-15 03:10:53 +01:00
|
|
|
$self->{admins}->add($channel, $hostmask, $data, $dont_save);
|
2010-03-22 08:33:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub remove_admin {
|
|
|
|
my $self = shift;
|
|
|
|
my ($channel, $hostmask) = @_;
|
2020-01-15 03:10:53 +01:00
|
|
|
return $self->{admins}->remove($channel, $hostmask);
|
2010-03-22 08:33:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub load_admins {
|
|
|
|
my $self = shift;
|
|
|
|
my $filename;
|
|
|
|
|
2020-01-15 03:10:53 +01:00
|
|
|
if (@_) { $filename = shift; } else { $filename = $self->{admins}->{filename}; }
|
2010-03-22 08:33:44 +01:00
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not defined $filename) {
|
2010-03-22 08:33:44 +01:00
|
|
|
Carp::carp "No admins path specified -- skipping loading of admins";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-18 22:09:05 +02:00
|
|
|
$self->{admins}->load;
|
2019-06-26 18:34:19 +02:00
|
|
|
|
2010-03-22 08:33:44 +01:00
|
|
|
my $i = 0;
|
2020-01-15 03:10:53 +01:00
|
|
|
foreach my $channel (sort keys %{ $self->{admins}->{hash} } ) {
|
|
|
|
foreach my $hostmask (sort keys %{ $self->{admins}->{hash}->{$channel} }) {
|
|
|
|
next if $hostmask eq '_name';
|
2010-08-15 10:25:35 +02:00
|
|
|
$i++;
|
2020-01-15 03:10:53 +01:00
|
|
|
my $name = $self->{admins}->{hash}->{$channel}->{$hostmask}->{name};
|
|
|
|
my $level = $self->{admins}->{hash}->{$channel}->{$hostmask}->{level};
|
|
|
|
my $password = $self->{admins}->{hash}->{$channel}->{$hostmask}->{password};
|
2010-03-22 08:33:44 +01:00
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not defined $name or not defined $level or not defined $password) {
|
2020-01-15 03:10:53 +01:00
|
|
|
Carp::croak "An admin in $filename is missing critical data\n";
|
2010-08-15 10:25:35 +02:00
|
|
|
}
|
|
|
|
|
2020-01-15 03:10:53 +01:00
|
|
|
my $chan = $channel eq '.*' ? 'global' : $channel;
|
|
|
|
$self->{pbot}->{logger}->log("Adding new level $level $chan admin: $name $hostmask\n");
|
2010-08-15 10:25:35 +02:00
|
|
|
}
|
2010-03-22 08:33:44 +01:00
|
|
|
}
|
|
|
|
|
2014-05-18 22:09:05 +02:00
|
|
|
$self->{pbot}->{logger}->log(" $i admins loaded.\n");
|
2010-03-22 08:33:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub save_admins {
|
|
|
|
my $self = shift;
|
2014-05-18 22:09:05 +02:00
|
|
|
$self->{admins}->save;
|
2010-03-22 08:33:44 +01:00
|
|
|
}
|
|
|
|
|
2010-03-24 07:47:40 +01:00
|
|
|
sub find_admin {
|
2010-03-29 14:30:35 +02:00
|
|
|
my ($self, $from, $hostmask) = @_;
|
2010-03-24 07:47:40 +01:00
|
|
|
|
2014-05-17 22:08:19 +02:00
|
|
|
$from = $self->{pbot}->{registry}->get_value('irc', 'botnick') if not defined $from;
|
2010-03-29 14:30:35 +02:00
|
|
|
$hostmask = '.*' if not defined $hostmask;
|
2017-11-23 00:25:14 +01:00
|
|
|
$hostmask = lc $hostmask;
|
2010-03-24 07:47:40 +01:00
|
|
|
|
|
|
|
my $result = eval {
|
2020-01-15 03:10:53 +01:00
|
|
|
foreach my $channel_regex (keys %{ $self->{admins}->{hash} }) {
|
2020-01-04 04:20:25 +01:00
|
|
|
if ($from !~ m/^#/ or $from =~ m/^$channel_regex$/i) {
|
2020-01-15 03:10:53 +01:00
|
|
|
foreach my $hostmask_regex (keys %{ $self->{admins}->{hash}->{$channel_regex} }) {
|
|
|
|
next if $hostmask_regex eq '_name';
|
2020-01-04 06:39:22 +01:00
|
|
|
if ($hostmask_regex =~ m/[*?]/) {
|
|
|
|
# contains * or ? so it's converted to a regex
|
2020-01-04 05:39:13 +01:00
|
|
|
my $hostmask_quoted = quotemeta $hostmask_regex;
|
2020-01-04 06:39:22 +01:00
|
|
|
$hostmask_quoted =~ s/\\\*/.*?/g;
|
|
|
|
$hostmask_quoted =~ s/\\\?/./g;
|
2020-01-15 03:10:53 +01:00
|
|
|
return $self->{admins}->{hash}->{$channel_regex}->{$hostmask_regex} if $hostmask =~ m/^$hostmask_quoted$/i;
|
2020-01-04 05:39:13 +01:00
|
|
|
} else {
|
|
|
|
# direct comparison
|
2020-01-15 03:10:53 +01:00
|
|
|
return $self->{admins}->{hash}->{$channel_regex}->{$hostmask_regex} if $hostmask eq lc $hostmask_regex;
|
2020-01-04 05:39:13 +01:00
|
|
|
}
|
2010-03-24 07:47:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return undef;
|
|
|
|
};
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($@) {
|
2014-05-18 22:09:05 +02:00
|
|
|
$self->{pbot}->{logger}->log("Error in find_admin parameters: $@\n");
|
2010-03-24 07:47:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2010-03-22 08:33:44 +01:00
|
|
|
sub loggedin {
|
|
|
|
my ($self, $channel, $hostmask) = @_;
|
2010-03-24 07:47:40 +01:00
|
|
|
my $admin = $self->find_admin($channel, $hostmask);
|
2010-03-22 08:33:44 +01:00
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (defined $admin && $admin->{loggedin}) {
|
2010-03-24 07:47:40 +01:00
|
|
|
return $admin;
|
2010-03-22 08:33:44 +01:00
|
|
|
} else {
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub login {
|
|
|
|
my ($self, $channel, $hostmask, $password) = @_;
|
2010-03-24 07:47:40 +01:00
|
|
|
my $admin = $self->find_admin($channel, $hostmask);
|
2010-03-22 08:33:44 +01:00
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not defined $admin) {
|
2014-05-18 22:09:05 +02:00
|
|
|
$self->{pbot}->{logger}->log("Attempt to login non-existent [$channel][$hostmask] failed\n");
|
2010-03-29 14:30:35 +02:00
|
|
|
return "You do not have an account in $channel.";
|
2010-03-22 08:33:44 +01:00
|
|
|
}
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($admin->{password} ne $password) {
|
2014-05-18 22:09:05 +02:00
|
|
|
$self->{pbot}->{logger}->log("Bad login password for [$channel][$hostmask]\n");
|
2010-03-22 08:33:44 +01:00
|
|
|
return "I don't think so.";
|
|
|
|
}
|
|
|
|
|
2010-03-24 07:47:40 +01:00
|
|
|
$admin->{loggedin} = 1;
|
2014-05-18 22:09:05 +02:00
|
|
|
$self->{pbot}->{logger}->log("$hostmask logged into $channel\n");
|
2010-03-29 14:30:35 +02:00
|
|
|
return "Logged into $channel.";
|
2010-03-22 08:33:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub logout {
|
|
|
|
my ($self, $channel, $hostmask) = @_;
|
2010-03-24 07:47:40 +01:00
|
|
|
my $admin = $self->find_admin($channel, $hostmask);
|
|
|
|
delete $admin->{loggedin} if defined $admin;
|
2010-03-22 08:33:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
1;
|