Discord-Client

 view release on metacpan or  search on metacpan

lib/Discord/Client/Interaction.pm  view on Meta::CPAN

    if ( my $initial = $self->{initial_operation} ) {
        $initial->fail( $failed->failure ) unless $initial->is_ready;
    }

    # Cancel outstanding delivery after publishing the deadline failure.
    if ( my $source = delete $self->{initial_source} ) {
        $source->cancel unless $source->is_ready;
    }
}

sub _message {
    my ( $self, $message, %options ) = @_;

    # Copy caller data before adding SDK-controlled visibility flags.
    croak 'Message must be a string or hash reference'
        unless defined($message)
        && ( !ref($message) || ref($message) eq 'HASH' );
    my $data = ref($message) ? {%$message} : { content => "$message" };
    if ( $options{ephemeral} ) {
        croak 'Invalid message flags'
            if defined( $data->{flags} )
            && ( ref( $data->{flags} ) || $data->{flags} !~ /\A\d+\z/ );
        $data->{flags} = ( $data->{flags} // 0 ) | 64;
    }
    return $data;
}

sub reply {
    my ( $self, $message, %options ) = @_;
    return $self->_failed( 'Autocomplete interactions require choices', 'state' ) if $self->{type} == 4;
    my $data = eval { $self->_message( $message, %options ) };
    return $self->_failed( 'Invalid interaction message', 'request' ) if $@;

    # Complete a confirmed deferral by editing its original message exactly once.
    if ( $self->{state} eq 'deferred' || $self->{state} eq 'deferred_update' ) {
        return $self->_failed( 'Deferred response visibility is already fixed', 'request' )
            if exists $options{ephemeral};
        $self->{state} = 'completing';
        my $future = $self->_webhook( 'PATCH', '/messages/@original', json => $data );
        $future->on_ready( sub { $self->{state} = $future->is_done ? 'replied' : 'failed' } );
        return $future;
    }
    return $self->_initial( 4, $data, 'replied' );
}

sub defer {
    my ( $self, %options ) = @_;
    return $self->_failed( 'Autocomplete cannot be deferred', 'state' ) if $self->{type} == 4;

    # Message updates and new deferred replies have different visibility rules.
    if ( $options{update} ) {
        return $self->_failed( 'Update deferral requires a message component', 'state' ) unless $self->_can_update;
        return $self->_failed( 'Update deferral cannot set ephemeral visibility', 'request' ) if $options{ephemeral};
        return $self->_initial( 6, undef, 'deferred_update' );
    }
    return $self->_initial( 5, $options{ephemeral} ? { flags => 64 } : undef, 'deferred' );
}

sub _can_update { $_[0]->{type} == 3 || ( $_[0]->{type} == 5 && ref( $_[0]->{raw}{message} ) eq 'HASH' ) }

sub update {
    my ( $self, $message ) = @_;
    return $self->_failed( 'Update requires a message component', 'state' ) unless $self->_can_update;
    my $data = eval { $self->_message($message) };
    return $self->_failed( 'Invalid interaction message', 'request' ) if $@;
    return $self->_initial( 7, $data, 'replied' );
}

sub autocomplete {
    my ( $self, $choices ) = @_;
    return $self->_failed( 'Choices require an autocomplete interaction', 'state' ) unless $self->{type} == 4;
    return $self->_failed( 'Invalid autocomplete choices', 'request' )
        unless ref($choices) eq 'ARRAY' && @$choices <= 25;

    # Validate each suggestion against the focused option and normalize JSON value types.
    my @wire;
    for my $choice (@$choices) {
        return $self->_failed( 'Invalid autocomplete choice', 'request' )
            unless ref($choice) eq 'HASH'
            && defined( $choice->{name} )
            && !ref( $choice->{name} )
            && length( $choice->{name} ) >= 1
            && length( $choice->{name} ) <= 100
            && defined( $choice->{value} )
            && !ref( $choice->{value} );
        my $type = $self->{focused}{type};
        if ( $type == 3 ) {
            return $self->_failed( 'Invalid autocomplete choice value', 'request' )
                if length( $choice->{value} ) > 100;
        }
        else {
            return $self->_failed( 'Invalid autocomplete choice value', 'request' )
                if !looks_like_number( $choice->{value} )
                || abs( $choice->{value} ) > 9007199254740992
                || ( $type == 4
                    && ( $choice->{value} != int( $choice->{value} ) || abs( $choice->{value} ) >= 9007199254740992 ) );
        }
        push @wire, { %$choice, value => $type == 3 ? "$choice->{value}" : 0 + $choice->{value} };
    }
    return $self->_initial( 8, { choices => \@wire }, 'replied' );
}

sub modal {
    my ( $self, $data ) = @_;

    # A modal opens only from a command or message component, never a modal submission.
    return $self->_failed( 'Modal response is invalid for this interaction', 'state' )
        unless $self->{type} == 2 || $self->{type} == 3;
    return $self->_failed( 'Invalid modal response', 'request' )
        unless ref($data) eq 'HASH'
        && defined( $data->{custom_id} )
        && !ref( $data->{custom_id} )
        && length( $data->{custom_id} ) <= 100
        && length( $data->{custom_id} ) > 0
        && defined( $data->{title} )
        && !ref( $data->{title} )
        && length( $data->{title} ) > 0
        && length( $data->{title} ) <= 45
        && ref( $data->{components} ) eq 'ARRAY';
    return $self->_initial( 9, $data, 'replied' );
}



( run in 0.712 second using v1.01-cache-2.11-cpan-1236ad508bc )