Skip to content

Instantly share code, notes, and snippets.

@rjbs
Created October 16, 2024 20:14
Show Gist options
  • Save rjbs/8fda2c11161e33aa4c17de8d6241899a to your computer and use it in GitHub Desktop.
Save rjbs/8fda2c11161e33aa4c17de8d6241899a to your computer and use it in GitHub Desktop.
#!/home/rjbs/.plenv/versions/5.32.0/bin/perl5.32.0
use v5.32.0;
use warnings;
use utf8;
use Data::Printer;
use IO::Async;
use IO::Async::Loop;
use JMAP::Tester;
use JSON::MaybeXS;
use MIME::Base64;
use Net::Async::HTTP;
use Path::Tiny;
use Prometheus::Tiny;
use WebService::RTM::CamelMilk;
my $Loop = IO::Async::Loop->new;
my $http = Net::Async::HTTP->new;
$Loop->add($http);
my $config = decode_json( path("/home/rjbs/.rtm.config/config.json")->slurp );
my $tokens = decode_json( path("/home/rjbs/.rtm.config/tokens.json")->slurp );
my $token = (values %$tokens)[0]->{token};
my $rtm = WebService::RTM::CamelMilk->new({
api_key => $config->{api_key},
api_secret => $config->{api_secret},
http_client => $http,
});
my $tl = $rtm->api_call('rtm.timelines.create' => { auth_token => $token })
->get
->get('timeline');
sub get_rtm_metrics {
my ($prom) = @_;
for my $type_pair (
[
overdue => [
'dueBefore:today',
'status:incomplete',
'NOT listContains:๐Ÿ“’',
'NOT startAfter:today',
],
],
[
upcoming => [
'dueWithin:"1 week"',
'status:incomplete',
'NOT listContains:๐Ÿ“’',
'NOT startAfter:today',
],
],
) {
my $rsp_f = $rtm->api_call('rtm.tasks.getList' => {
auth_token => $token,
filter => join(q{ AND }, $type_pair->[1]->@*),
});
my $rsp = $rsp_f->get;
unless ($rsp->is_success) {
use Data::Dumper; warn Dumper($rsp);
warn sprintf "failed to cope with a request for milk: %s", $rsp->_response;
return;
}
my $count = 0;
for my $list ($rsp->get('tasks')->{list}->@*) {
for my $tseries ($list->{taskseries}->@*) {
my @tasks = $tseries->{task}->@*;
$count += @tasks;
}
}
$prom->set(todo_tasks => $count, { type => $type_pair->[0] });
}
return 1;
}
my %fm_accounts = (
manxome => {
token => '...',
},
work => {
token => '...',
},
);
sub get_fm_metrics {
my ($prom) = @_;
for my $account (keys %fm_accounts) {
my $credentials = $fm_accounts{$account};
my $ok = eval {
my $tester = JMAP::Tester->new({
authentication_uri => 'https://api.fastmail.com/.well-known/jmap',
default_using => [ qw(
urn:ietf:params:jmap:core
urn:ietf:params:jmap:mail
) ],
});
$tester->ua->set_default_header(Authorization => "Bearer $credentials->{token}");
$tester->update_client_session;
my $mailbox_res = $tester->request([
[
'Mailbox/get',
{
accountId => $tester->primary_account_for('urn:ietf:params:jmap:mail'),
properties => [ qw( name role totalThreads ) ],
}
]
]);
my @todoboxes = grep {; ($_->{role}//'') eq 'inbox'
|| ($_->{role}//'') eq 'drafts'
|| $_->{name} =~ /\A@/
|| $_->{name} =~ /\A@/
} $mailbox_res->single_sentence('Mailbox/get')->arguments->{list}->@*;
for (@todoboxes) {
$prom->set(
todo_messages => $_->{totalThreads},
{
label => $_->{name},
account => $account,
},
);
}
1;
};
unless ($ok) {
warn "failed: $@";
return;
}
}
return 1;
}
return sub {
my $env = shift;
my $prom = Prometheus::Tiny->new;
$prom->declare(
'todo_messages',
help => "messages pending action",
type => "gauge",
);
my $ok = 1;
$ok = $ok && get_rtm_metrics($prom);
$ok = $ok && get_fm_metrics($prom);
unless ($ok) {
return [
500,
[ 'Content-Type' => 'text/plain' ],
[ "something went wrong\n" ]
];
}
return [
200,
[ 'Content-Type' => 'text/plain' ],
[ $prom->format ],
];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment