At
view release on metacpan or search on metacpan
method did() {
$self->session->{did};
}
method session() {
$session //= $self->get('com.atproto.server.getSession');
$session;
}
## Internals
sub now { Time::Moment->now }
sub _percent ( $limit, $remaining ) { $remaining && $limit ? ( ( $limit / $remaining ) * 100 ) : 0 }
sub _plural( $count, $word ) { $count ? sprintf '%d %s%s', $count, $word, $count == 1 ? '' : 's' : () }
sub _duration ($seconds) {
$seconds || return '0 seconds';
$seconds = abs $seconds; # just in case
my ( $time, @times ) = reverse grep {defined} _plural( int( $seconds / 31536000 ), 'year' ), # assume 365 days and no leap seconds
_plural( int( ( $seconds % 31536000 ) / 604800 ), 'week' ), _plural( int( ( $seconds % 604800 ) / 86400 ), 'day' ),
_plural( int( ( $seconds % 86400 ) / 3600 ), 'hour' ), _plural( int( ( $seconds % 3600 ) / 60 ), 'minute' ),
_plural( $seconds % 60, 'second' );
join ' and ', @times ? join( ', ', reverse @times ) : (), $time;
#
method ratelimit_ ( $rate, $type, $meta //= () ) { #~ https://docs.bsky.app/docs/advanced-guides/rate-limits
defined $meta ? $ratelimits{$type}{$meta} = $rate : $ratelimits{$type} = $rate;
}
method _ratecheck( $type, $meta //= () ) {
my $rate = defined $meta ? $ratelimits{$type}{$meta} : $ratelimits{$type};
$rate->{reset} // return;
return warnings::warnif( At => sprintf 'Exceeded %s rate limit. Try again in %s', $type, _duration( $rate->{reset} - time ) )
if defined $rate->{reset} && $rate->{remaining} == 0 && $rate->{reset} > time;
my $percent = _percent( $rate->{remaining}, $rate->{limit} );
warnings::warnif(
At => sprintf '%.2f%% of %s rate limit remaining (%d of %d). Slow down or try again in %s',
$percent, $type, $rate->{remaining}, $rate->{limit}, _duration( $rate->{reset} - time )
) if $percent <= 5;
}
# Init
{
our %capture;
sub namespace2package ($fqdn) {
my $namespace = $fqdn =~ s[[#\.]][::]gr;
'At::Lexicon::' . $namespace;
}
lib/At/Protocol/DID.pm view on Meta::CPAN
}
#~ Taken from https://github.com/bluesky-social/atproto/blob/main/packages/syntax/src/did.ts
#~ Human-readable constraints:
#~ - valid W3C DID (https://www.w3.org/TR/did-core/#did-syntax)
#~ - entire URI is ASCII: [a-zA-Z0-9._:%-]
#~ - always starts "did:" (lower-case)
#~ - method name is one or more lower-case letters, followed by ":"
#~ - remaining identifier can have any of the above chars, but can not end in ":"
#~ - it seems that a bunch of ":" can be included, and don't need spaces between
#~ - "%" is used only for "percent encoding" and must be followed by two hex characters (and thus can't end in "%")
#~ - query ("?") and fragment ("#") stuff is defined for "DID URIs", but not as part of identifier itself
#~ - "The current specification does not take a position on the maximum length of a DID"
#~ - in current atproto, only allowing did:plc and did:web. But not *forcing* this at lexicon layer
#~ - hard length limit of 8KBytes
#~ - not going to validate "percent encoding" here
sub ensureValidDid ($did) {
# check that all chars are boring ASCII
throw InvalidDidError('Disallowed characters in DID (ASCII letters, digits, and a couple other characters only)')
unless $did =~ /^[a-zA-Z0-9._:%-]*$/;
#
my @parts = split ':', $did, -1; # negative limit, ftw
throw InvalidDidError('DID requires prefix, method, and method-specific content') if @parts < 3;
#
throw InvalidDidError('DID requires "did:" prefix') if $parts[0] ne 'did';
lib/At/Protocol/URI.pm view on Meta::CPAN
#~ Validation utils from https://github.com/bluesky-social/atproto/blob/main/packages/syntax/src/aturi_validation.ts
#~ Human-readable constraints on ATURI:
#~ - following regular URLs, a 8KByte hard total length limit
#~ - follows ATURI docs on website
#~ - all ASCII characters, no whitespace. non-ASCII could be URL-encoded
#~ - starts "at://"
#~ - "authority" is a valid DID or a valid handle
#~ - optionally, follow "authority" with "/" and valid NSID as start of path
#~ - optionally, if NSID given, follow that with "/" and rkey
#~ - rkey path component can include URL-encoded ("percent encoded"), or:
#~ ALPHA / DIGIT / "-" / "." / "_" / "~" / ":" / "@" / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
#~ [a-zA-Z0-9._~:@!$&'\(\)*+,;=-]
#~ - rkey must have at least one char
#~ - regardless of path component, a fragment can follow as "#" and then a JSON pointer (RFC-6901)
sub ensureValidAtUri($uri) {
my $fragmentPart;
my @uriParts = split '#', $uri, -1; # negative limit, ftw
throw InvalidAtUriError('ATURI can have at most one "#", separating fragment out') if scalar @uriParts > 2;
$fragmentPart = $uriParts[1];
$uri = $uriParts[0];
( run in 0.328 second using v1.01-cache-2.11-cpan-709fd43a63f )