AnyEvent-Discord-Client
view release on metacpan or search on metacpan
lib/AnyEvent/Discord/Client.pm view on Meta::CPAN
sub new {
my ($class, %args) = @_;
my $self = {
token => delete($args{token}),
api_root => delete($args{api_root}) // 'https://discordapp.com/api',
prefix => delete($args{prefix}) // "!",
commands => delete($args{commands}) // {},
ua => LWP::UserAgent->new(),
api_useragent => "DiscordBot (https://github.com/topaz/perl-AnyEvent-Discord-Client, 0)",
user => undef,
guilds => {},
channels => {},
roles => {},
gateway => undef,
conn => undef,
websocket => undef,
heartbeat_timer => undef,
last_seq => undef,
reconnect_delay => 1,
};
die "cannot construct new $class without a token parameter" unless defined $self->{token};
die "unrecognized extra parameters were given to $class->new" if %args;
return bless $self, $class;
}
sub commands { $_[0]{commands} }
sub user { $_[0]{user} }
sub guilds { $_[0]{guilds} }
sub channels { $_[0]{channels} }
sub roles { $_[0]{roles} }
my %event_handler = (
READY => sub {
my ($self, $d) = @_;
$self->{user} = $d->{user};
print "logged in as $self->{user}{username}.\n";
print "ready!\n";
},
GUILD_CREATE => sub {
my ($self, $d) = @_;
$self->{guilds}{$d->{id}} = $d;
$self->{channels}{$_->{id}} = {%$_, guild_id=>$d->{id}} for @{$d->{channels}};
$self->{roles}{$_->{id}} = {%$_, guild_id=>$d->{id}} for @{$d->{roles}};
print "created guild $d->{id} ($d->{name})\n";
},
CHANNEL_CREATE => sub {
my ($self, $d) = @_;
$self->{channels}{$d->{id}} = $d;
push @{$self->{guilds}{$d->{guild_id}}{channels}}, $d if $d->{guild_id};
print "created channel $d->{id} ($d->{name}) of guild $d->{guild_id} ($self->{guilds}{$d->{guild_id}}{name})\n";
},
CHANNEL_UPDATE => sub {
my ($self, $d) = @_;
%{$self->{channels}{$d->{id}}} = %$d;
print "updated channel $d->{id} ($d->{name}) of guild $d->{guild_id} ($self->{guilds}{$d->{guild_id}}{name})\n";
},
CHANNEL_DELETE => sub {
my ($self, $d) = @_;
@{$self->{guilds}{$d->{guild_id}}{channels}} = grep {$_->{id} != $d->{id}} @{$self->{guilds}{$d->{guild_id}}{channels}} if $d->{guild_id};
delete $self->{channels}{$d->{id}};
print "deleted channel $d->{id} ($d->{name}) of guild $d->{guild_id} ($self->{guilds}{$d->{guild_id}}{name})\n";
},
GUILD_ROLE_CREATE => sub {
my ($self, $d) = @_;
$self->{roles}{$d->{role}{id}} = $d->{role};
push @{$self->{guilds}{$d->{guild_id}}{roles}}, $d->{role} if $d->{guild_id};
print "created role $d->{role}{id} ($d->{role}{name}) of guild $d->{guild_id} ($self->{guilds}{$d->{guild_id}}{name})\n";
},
GUILD_ROLE_UPDATE => sub {
my ($self, $d) = @_;
%{$self->{roles}{$d->{role}{id}}} = %{$d->{role}};
print "updated role $d->{role}{id} ($d->{role}{name}) of guild $d->{guild_id} ($self->{guilds}{$d->{guild_id}}{name})\n";
},
GUILD_ROLE_DELETE => sub {
my ($self, $d) = @_;
@{$self->{guilds}{$d->{guild_id}}{roles}} = grep {$_->{role}{id} != $d->{role}{id}} @{$self->{guilds}{$d->{guild_id}}{roles}} if $d->{guild_id};
delete $self->{roles}{$d->{role}{id}};
print "deleted role $d->{role}{id} ($d->{role}{name}) of guild $d->{guild_id} ($self->{guilds}{$d->{guild_id}}{name})\n";
},
TYPING_START => sub {},
MESSAGE_CREATE => sub {
my ($self, $msg) = @_;
my $channel = $self->{channels}{$msg->{channel_id}};
my $guild = $self->{guilds}{$channel->{guild_id}};
#(my $hrcontent = $msg->{content) =~ s/[\x00-\x
print "[$guild->{name} ($guild->{id}) / $channel->{name} ($channel->{id})] <$msg->{author}{username}> $msg->{content}\n";
#print STDERR join(",",unpack("U*", $msg->{content}))."\n";
return if $msg->{author}{id} == $self->{user}{id};
if ($msg->{content} =~ /^\Q$self->{prefix}\E(\S+)(?:\s+(.*?))?\s*$/ || $msg->{content} =~ /^\s*(.*?)\s*$/) {
my ($cmd, $args) = (lc $1, defined $2 ? $2 : "");
if (exists $self->{commands}{$cmd}) {
$self->{commands}{$cmd}($self, $args, $msg, $channel, $guild);
}
}
},
);
sub connect {
my ($self) = @_;
if (!defined $self->{gateway}) {
# look up gateway url
my $gateway_data = $self->api_sync(GET => "/gateway");
my $gateway = $gateway_data->{url};
die 'invalid gateway' unless $gateway =~ /^wss\:\/\//;
$gateway = new URI($gateway);
$gateway->path("/") unless length $gateway->path;
$gateway->query_form(v=>6, encoding=>"json");
$self->{gateway} = "$gateway";
}
print "Connecting to $self->{gateway}...\n";
$self->{reconnect_delay} *= 2;
$self->{reconnect_delay} = 5*60 if $self->{reconnect_delay} > 5*60;
$self->{websocket} = AnyEvent::WebSocket::Client->new(max_payload_size => 1024*1024);
$self->{websocket}->connect($self->{gateway})->cb(sub {
$self->{conn} = eval { shift->recv };
if($@) {
print "$@\n";
return;
}
print "websocket connected to $self->{gateway}.\n";
$self->{reconnect_delay} = 1;
# send "identify" op
$self->websocket_send(2, {
token => $self->{token},
( run in 1.481 second using v1.01-cache-2.11-cpan-5a3173703d6 )