Files
aleesa-telegram/lib/BotLib/Admin.pm
eleksir 8f6ccfba04 Add export_settings.pl to save chat settings in json
Add missing functions to lib/BotLib/Admin.pm to be able to expoprt
chat settings for for particular chats.
Add extract_chatlist.txt.pl to extract chat list from debug.log
2026-01-02 15:56:08 +03:00

813 lines
16 KiB
Perl

package BotLib::Admin;
use 5.018; ## no critic (ProhibitImplicitImport)
use strict;
use warnings;
use utf8;
use open qw (:std :utf8);
use English qw ( -no_match_vars );
use CHI ();
use CHI::Driver::BerkeleyDB ();
use BotLib::Conf qw (LoadConf);
use BotLib::Util qw (utf2sha1);
use version; our $VERSION = qw (1.1);
use Exporter qw (import);
# to export array we need @ISA here
our @ISA = qw / Exporter /; ## no critic (ClassHierarchies::ProhibitExplicitISA)
our @EXPORT_OK = qw (@ForbiddenMessageTypes @PluginList
GetForbiddenTypes AddForbiddenType DelForbiddenType ListForbidden EnabledForbidden
FortuneToggle FortuneStatus FortuneEnabled FortuneToggleList
ChanMsgToggle ChanMsgStatus ChanMsgEnabled ChanMsgToggleList
GreetMsgToggle GreetMsgStatus GreetMsgEnabled GreetMsgToggleList
GoodbyeMsgToggle GoodbyeMsgStatus GoodbyeMsgEnabled GoodbyeMsgToggleList
PluginToggle PluginStatus PluginEnabled
MuteByAdminToggle MuteByAdminStatus MuteByAdminEnabled MuteByAdminToggleList
MigrateSettingsToNewChatID
IsCensored
GetSlackGreetRememberId
SetSlackGreetRememberId
);
my $c = LoadConf ();
my $cachedir = $c->{cachedir};
# this list is not yet used
our @PluginList = qw (oboobs obutts); ## no critic (Variables::ProhibitPackageVars)
our @ForbiddenMessageTypes = qw (audio voice photo video video_note animation sticker dice game poll document); ## no critic (Variables::ProhibitPackageVars)
sub GetForbiddenTypes {
my $chatid = shift;
my $messageTypes;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'censor' . '_' . utf2sha1 ($chatid),
);
foreach (@ForbiddenMessageTypes) {
my $type = $cache->get ($_);
if ($type) {
$messageTypes->{$_} = 1;
} else {
unless (defined $type) {
$cache->set ($_, 0, 'never');
}
$messageTypes->{$_} = 0;
}
}
return $messageTypes;
}
sub AddForbiddenType {
my $chatid = shift;
my $type = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'censor' . '_' . utf2sha1 ($chatid),
);
$cache->set ($type, 1, 'never');
return;
}
sub DelForbiddenType {
my $chatid = shift;
my $type = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'censor' . '_' . utf2sha1 ($chatid),
);
$cache->remove ($type);
return;
}
sub ListForbidden {
my $chatid = shift;
my @list;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'censor' . '_' . utf2sha1 ($chatid),
);
foreach (@ForbiddenMessageTypes) {
my $type = $cache->get ($_);
if ($type) {
push @list, sprintf 'Тип сообщения %s удаляется', $_;
} else {
unless (defined $type) {
$cache->set ($_, 0, 'never');
}
push @list, sprintf 'Тип сообщения %s не удаляется', $_;
}
}
return join "\n", @list;
}
sub EnabledForbidden {
my $chatid = shift;
my $ftype = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'censor' . '_' . utf2sha1 ($chatid),
);
my $type = $cache->get ($ftype);
if ($type) {
return 1;
} else {
unless (defined $type) {
$cache->set ($ftype, 0, 'never');
}
return 0;
}
}
sub FortuneToggle (@) {
my $chatid = shift;
my $action = shift // undef;
my $phrase = 'Фортунка с утра ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'fortune',
);
my $state = $cache->get ($chatid);
if (defined $action) {
if ($action) {
$cache->set ($chatid, 1, 'never');
$phrase .= 'будет показываться.';
} else {
if (defined $state) {
$cache->remove ($chatid);
}
$phrase .= 'не будет показываться.';
}
} else {
if (defined $state && $state) {
$cache->remove ($chatid);
$phrase .= 'не будет показываться.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'будет показываться.';
}
}
return $phrase;
}
sub FortuneStatus ($) {
my $chatid = shift;
my $phrase = 'Фортунка с утра ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'fortune',
);
my $state = $cache->get ($chatid);
if (defined $state && $state) {
$phrase .= 'показывается.';
} else {
$phrase .= 'не показывается.';
}
return $phrase;
}
sub FortuneEnabled ($) {
my $chatid = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'fortune',
);
my $state = $cache->get ($chatid);
if (defined $state && $state) {
return 1;
} else {
return 0;
}
}
sub FortuneToggleList () {
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'fortune',
);
return $cache->get_keys ();
}
sub ChanMsgToggle (@) {
my $chatid = shift;
my $action = shift // undef;
my $phrase = 'Сообщения, пришедшие от имени каналов ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'chan_msg',
);
my $state = $cache->get ($chatid);
if (defined $action) {
if ($action) {
$cache->set ($chatid, 1, 'never');
$phrase .= 'не будут удаляться.';
} else {
if (defined $state && $state) {
$cache->set ($chatid, 0, 'never');
$phrase .= 'будут удаляться.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'не будут удаляться.';
}
}
} else {
if (defined $state){
if ($state) {
$cache->set ($chatid, 0, 'never');
$phrase .= 'будут удаляться.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'не будут удаляться.';
}
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'не будут удаляться.';
}
}
return $phrase;
}
sub ChanMsgStatus ($) {
my $chatid = shift;
my $phrase = 'Сообщения, пришедшие от имени каналов ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'chan_msg',
);
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state) {
$phrase .= 'не удаляются.';
} else {
$phrase .= 'удаляются.';
}
} else {
$phrase .= 'не удаляются.';
}
return $phrase;
}
sub ChanMsgEnabled ($) {
my $chatid = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'chan_msg',
);
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state) {
return 1;
} else {
return 0;
}
} else {
return 1;
}
}
sub ChanMsgToggleList () {
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'chan_msg',
);
return $cache->get_keys ();
}
sub GreetMsgToggle (@) {
my $chatid = shift;
my $action = shift // undef;
my $phrase = 'Приветствия новых участников чата ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'greet_msg',
);
if (defined $action) {
if ($action == 0) {
$cache->set ($chatid, 0, 'never');
$phrase .= 'выключены.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'включены.';
}
} else {
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state != 0) {
$cache->set ($chatid, 0, 'never');
$phrase .= 'выключены.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'включены.';
}
} else {
$cache->set ($chatid, 0, 'never');
$phrase .= 'выключены.';
}
}
return $phrase;
}
sub GreetMsgStatus ($) {
my $chatid = shift;
my $phrase = 'Приветствия новых участников чата ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'greet_msg',
);
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state) {
$phrase .= 'включено.';
} else {
$phrase .= 'выключено.';
}
} else {
$phrase .= 'включено.';
}
return $phrase;
}
sub GreetMsgEnabled ($) {
my $chatid = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'greet_msg',
);
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state) {
return 1;
} else {
return 0;
}
} else {
return 1;
}
}
sub GreetMsgToggleList () {
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'greet_msg',
);
return $cache->get_keys ();
}
sub GoodbyeMsgToggle (@) {
my $chatid = shift;
my $action = shift // undef;
my $phrase = 'Прощание с ушедшими участниками чата ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'goodbye_msg',
);
my $state = $cache->get ($chatid);
if (defined $action) {
if ($action) {
$cache->set ($chatid, 1, 'never');
$phrase .= 'включено.';
} else {
$cache->set ($chatid, 0, 'never');
$phrase .= 'выключено.';
}
} else {
if (defined $state){
if ($state) {
$cache->set ($chatid, 0, 'never');
$phrase .= 'выключено.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'включено.';
}
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'включено.';
}
}
return $phrase;
}
sub GoodbyeMsgStatus ($) {
my $chatid = shift;
my $phrase = 'Прощание с ушедшими участниками чата ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'goodbye_msg',
);
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state) {
$phrase .= 'включено.';
} else {
$phrase .= 'выключено.';
}
} else {
$phrase .= 'выключено.';
}
return $phrase;
}
sub GoodbyeMsgEnabled ($) {
my $chatid = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'goodbye_msg',
);
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
sub GoodbyeMsgToggleList () {
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'goodbye_msg',
);
return $cache->get_keys ();
}
sub PluginStatus (@) {
my $chatid = shift;
my $plugin = shift;
my $phrase = "Плагин $plugin ";
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'plugin' . '_' . utf2sha1 ($chatid),
);
my $state = $cache->get ($plugin);
if ($state) {
$phrase .= 'включён.';
} else {
unless (defined $state) {
$cache->set ($plugin, 0, 'never');
}
$phrase .= 'выключен.';
}
return $phrase;
}
sub PluginEnabled (@) {
my $chatid = shift;
my $plugin = shift;
# seems that we have point to return always true if chat is private
if ($chatid > 0) {
return 1;
}
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'plugin' . '_' . utf2sha1 ($chatid),
);
my $state = $cache->get ($plugin);
if (defined $state && $state) {
return 1;
} else {
return 0;
}
}
sub PluginToggle (@) {
my $chatid = shift;
my $plugin = shift;
my $action = shift // undef;
my $phrase = "Плагин $plugin ";
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'plugin' . '_' . utf2sha1 ($chatid),
);
my $state = $cache->get ($plugin);
if (defined $action) {
if ($action) {
$cache->set ($plugin, 1, 'never');
$phrase .= 'включён';
} else {
$cache->set ($plugin, 0, 'never');
$phrase .= 'выключен';
}
} else {
if (defined ($state) && $state) {
$cache->set ($plugin, 0, 'never');
$phrase .= 'включён';
} else {
$cache->set ($plugin, 1, 'never');
$phrase .= 'выключен';
}
}
return $phrase;
}
sub MuteByAdminToggle (@) {
my $chatid = shift;
my $action = shift // undef;
my $phrase = 'Мьют участников чата админами ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'admin_mute',
);
my $state = $cache->get ($chatid);
if (defined $action) {
if ($action) {
$cache->set ($chatid, 1, 'never');
$phrase .= 'разрешён.';
} else {
$cache->set ($chatid, 0, 'never');
$phrase .= 'запрещён.';
}
} else {
if (defined $state){
if ($state) {
$cache->set ($chatid, 0, 'never');
$phrase .= 'запрещён.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'разрешён.';
}
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'разрешён.';
}
}
return $phrase;
}
sub MuteByAdminStatus ($) {
my $chatid = shift;
my $phrase = 'Мьют админами участников чата ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'admin_mute',
);
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state) {
$phrase .= 'разрешён.';
} else {
$phrase .= 'запрещён.';
}
} else {
$phrase .= 'запрещён.';
}
return $phrase;
}
sub MuteByAdminEnabled ($) {
my $chatid = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'admin_mute',
);
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
sub MuteByAdminToggleList () {
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'admin_mute',
);
return $cache->get_keys ();
}
sub MigrateSettingsToNewChatID {
my $old_id = shift;
my $new_id = shift;
# TODO: Catch errors, if error==1, than noop
if (FortuneEnabled ($old_id)) {
FortuneToggle ($new_id, 1);
FortuneToggle ($old_id, 0);
} else {
FortuneToggle ($new_id, 0);
}
if (ChanMsgEnabled ($old_id)) {
ChanMsgToggle ($new_id, 1);
} else {
ChanMsgToggle ($new_id, 0);
}
if (GreetMsgEnabled ($old_id)) {
GreetMsgToggle ($new_id, 1);
} else {
GreetMsgToggle ($new_id, 0);
}
if (GoodbyeMsgEnabled ($old_id)) {
GoodbyeMsgToggle ($new_id, 1);
} else {
GoodbyeMsgToggle ($new_id, 0);
}
foreach my $plugin (@PluginList) {
if (PluginEnabled ($old_id, $plugin)) {
PluginToggle ($new_id, $plugin, 1);
} else {
PluginToggle ($new_id, $plugin, 0);
}
}
foreach my $ftype (@ForbiddenMessageTypes) {
if (EnabledForbidden($old_id, $ftype)) {
AddForbiddenType($new_id, $ftype);
}
# Looks like we don't need to add forbidden type for allowed types... right?
}
return;
}
sub IsCensored {
my $msg = shift;
my $forbidden = GetForbiddenTypes ($msg->chat->id);
# voice messages are special
if (defined ($msg->voice) && defined ($msg->voice->duration) && ($msg->voice->duration > 0)) {
if ($forbidden->{'voice'}) {
return 1;
}
}
foreach (keys %{$forbidden}) {
if ($forbidden->{$_} && (defined $msg->{$_})) {
return 1;
}
}
return 0;
}
sub GetSlackGreetRememberId ($) {
my $userid = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'slack_greet_remember_id',
);
my $state = $cache->get ($userid);
if (defined $state) {
if ($state) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
sub SetSlackGreetRememberId ($) {
my $userid = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'slack_greet_remember_id',
);
$cache->set ($userid, 1, 'never');
return;
}
1;
# vim: set ft=perl noet ai ts=4 sw=4 sts=4: