From 8a66c4ef785ba4e72f320f4023718148854e6ac1 Mon Sep 17 00:00:00 2001 From: Gianni Ceccarelli Date: Wed, 22 Feb 2023 11:56:10 +0000 Subject: misskey client --- cpanfile | 1 + lib/Dakkar/Misskey.pm | 86 ++++++++++++++++++++++++++++++++++++++++++++++ lib/Dakkar/NotesArchive.pm | 45 ++++++++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 lib/Dakkar/Misskey.pm create mode 100644 lib/Dakkar/NotesArchive.pm diff --git a/cpanfile b/cpanfile index 9abf9e9..66ba8c6 100644 --- a/cpanfile +++ b/cpanfile @@ -12,3 +12,4 @@ requires 'namespace::clean'; requires 'Net::Twitter'; requires 'Path::Tiny'; requires 'Types::Standard'; +requires 'List::Util'; diff --git a/lib/Dakkar/Misskey.pm b/lib/Dakkar/Misskey.pm new file mode 100644 index 0000000..8d6dd5e --- /dev/null +++ b/lib/Dakkar/Misskey.pm @@ -0,0 +1,86 @@ +package Dakkar::Misskey; +use v5.36; +use Moo; +use JSON::MaybeXS; +use LWP::UserAgent; +use Types::Standard qw(Str); +use Types::URI qw(Uri); +use List::Util qw(minstr); +use URI; +use namespace::clean; + +has _json => ( is => 'lazy', builder => sub { JSON::MaybeXS->new(utf8=>1,relaxed=>1, pretty=>0) } ); +has _ua => ( is => 'lazy', builder => sub { LWP::UserAgent->new(agent=>'Dakkar::Misskey') } ); + +has token => ( is => 'ro', required => 1 ); +has base_url => ( is => 'ro', required => 1, isa => Uri, coerce => 1 ); + +sub _request($self, $endpoint, $payload) { + my $payload_json = $self->_json->encode({ + $payload->%*, + i => $self->token, + }); + + my $uri = URI->new($endpoint)->abs($self->base_url); + + my $response = $self->_ua->post( + $uri, + 'Content-type' => 'application/json', + Content => $payload_json, + ); + + if ($response->is_success) { + return( + $self->_json->decode( + $response->decoded_content(charset=>'none') + ), + undef, + ); + } + + return( undef, $response->status_line ); +} + +sub _paged_request($self, $endpoint, $payload) { + my @all_results; + + my $page_payload = { + limit => 100, + $payload->%*, + }; + + while (1) { + my ($result, $error) = $self->_request($endpoint, $page_payload); + return (\@all_results, $error) if $error; + + last unless $result->@*; + + push @all_results, $result->@*; + $page_payload->{untilId} = minstr(map { $_->{id} } $result->@* ); + } + + return (\@all_results, undef); +} + +sub timeline($self,$options) { + return $self->_paged_request( + 'api/notes/timeline', + $options, + ); +} + +sub followers($self,$user_id) { + return $self->_paged_request( + 'api/users/followers', + { userId => $user_id }, + ); +} + +sub following($self,$user_id) { + return $self->_paged_request( + 'api/users/following', + { userId => $user_id }, + ); +} + +1; diff --git a/lib/Dakkar/NotesArchive.pm b/lib/Dakkar/NotesArchive.pm new file mode 100644 index 0000000..5571419 --- /dev/null +++ b/lib/Dakkar/NotesArchive.pm @@ -0,0 +1,45 @@ +package Dakkar::NotesArchive; +use v5.36; +use Moo; +use experimental 'builtin'; +use Dakkar::Misskey; +use Types::Standard qw(Str InstanceOf); +use namespace::clean; + +has [qw(base_url token user_id)] => ( + is => 'ro', + required => 1, + isa => Str, +); + +has client => ( + is => 'lazy', + isa => InstanceOf['Dakkar::Misskey'], +); + + +sub _build_client($self) { + my $nt = Dakkar::Misskey->new({ + base_url => $self->base_url, + token => $self->token, + }); +} + +sub timeline($self, $since_id) { + return $self->client->timeline({ + sinceId => $since_id, + includeMyRenotes => \1, + includeLocalRenotes => \1, + includeRenotedMyNotes => \0, + }); +} + +sub following($self) { + return $self->client->following($self->user_id); +} + +sub followers($self) { + return $self->client->followers($self->user_id); +} + +1; -- cgit v1.2.3