The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

—
#
# This file is part of App-SpreadRevolutionaryDate
#
# This software is Copyright (c) 2019-2025 by Gérald Sédrati.
#
# This is free software, licensed under:
#
# The GNU General Public License, Version 3, June 2007
#
use 5.014;
use utf8;
$App::SpreadRevolutionaryDate::MsgMaker::Gemini::VERSION = '0.47';
# ABSTRACT: MsgMaker class for L<App::SpreadRevolutionaryDate> to build message with Gemini prompt
use Moose;
use File::ShareDir ':ALL';
use JSON;
use Locale::TextDomain 'App-SpreadRevolutionaryDate';
has 'api_key' => (
is => 'ro',
isa => 'Str',
required => 1,
);
has 'process' => (
is => 'ro',
isa => 'Str',
required => 1,
);
has 'prompt' => (
is => 'ro',
isa => 'HashRef[Str]',
required => 1,
);
has 'search' => (
is => 'ro',
isa => 'HashRef[Bool]',
);
has 'intro' => (
is => 'ro',
isa => 'HashRef[Str]',
);
has 'img_path' => (
is => 'ro',
isa => 'HashRef[Str]',
);
has 'img_url' => (
is => 'ro',
isa => 'HashRef[Str]',
);
has 'img_alt' => (
is => 'ro',
isa => 'HashRef[Str]',
);
has '+locale' => (
default => 'fr',
);
around BUILDARGS => sub {
my ($orig, $class, %args) = @_;
if ($args{process}) {
die "Process $args{process} has no prompt\n" unless $args{prompt}->{$args{process}};
}
return $class->$orig(%args);
};
sub compute {
my $self = shift;
my $today = DateTime->now(locale => $self->locale);
my $prompt = $self->prompt->{$self->process};
my @vars = $self->prompt->{$self->process} =~ /\$(\w+)/g;
foreach my $var (@vars) {
$prompt =~ s/\$$var/$today->$var/e;
}
my $payload = {
contents => [
{
parts => [
{
text => $prompt,
}
],
}
],
};
if ($self->search && $self->search->{$self->process}) {
$payload->{tools} = [
{
google_search => {},
},
];
}
my $json = JSON->new->utf8;
my $args_json = $json->encode($payload);
my $ua = LWP::UserAgent->new(env_proxy => 1, timeout => 10, agent =>'App::SpreadRevolutionaryDate bot');
$ua->default_header('Accept' => 'application/json');
$ua->default_header('Content-Type' => 'application/json');
my $req = HTTP::Request->new('POST', $url);
$req->content($args_json);
my $resp = $ua->request($req);
my $msg;
if ($resp && $resp->is_success) {
my $content;
eval { $content = $json->decode($resp->content) };
unless ($@) {
if ($content->{candidates} && scalar(@{$content->{candidates}}) == 1 && $content->{candidates}->[0]->{content} && $content->{candidates}->[0]->{content}->{parts} && scalar(@{$content->{candidates}->[0]->{content}->{parts}}) >= 1 && $content->{candidates}->[0]->{content}->{parts}->[0]->{text}) {
$msg = $content->{candidates}->[0]->{content}->{parts}->[0]->{text};
$msg =~ s/\s+$//;
$msg .= "\n#IAGenerated #" . $self->process;
}
}
}
if ($self->intro && $self->intro->{$self->process}) {
my $intro = $self->intro->{$self->process};
my @intro_vars = $self->intro->{$self->process} =~ /\$(\w+)/g;
foreach my $intro_var (@intro_vars) {
$intro =~ s/\$$intro_var/$today->$intro_var/e;
}
$msg = $intro . "\n" . $msg;
}
my $img;
$img->{path} = $self->img_path->{$self->process} if $self->img_path && $self->img_path->{$self->process};
$img->{url} = $self->img_url->{$self->process} if $self->img_url && $self->img_url->{$self->process};
$img->{alt} = $self->img_alt->{$self->process} if $self->img_alt && $self->img_alt->{$self->process};
return ($msg, $img);
}
no Moose;
__PACKAGE__->meta->make_immutable;
# A module must return a true value. Traditionally, a module returns 1.
# But this module is a revolutionary one, so it discards all old traditions.
# Idea borrowed from Jean Forget's DateTime::Calendar::FrenchRevolutionary.
"Quand le gouvernement viole les droits du peuple,
l'insurrection est pour le peuple le plus sacré
et le plus indispensable des devoirs";
__END__
=pod
=encoding UTF-8
=head1 NAME
App::SpreadRevolutionaryDate::MsgMaker::Gemini - MsgMaker class for L<App::SpreadRevolutionaryDate> to build message with Gemini prompt
=head1 VERSION
version 0.47
=head1 METHODS
=head2 compute
Computes replies by Gemini AI given a prompt.
=head1 SEE ALSO
=over
=item L<spread-revolutionary-date>
=item L<App::SpreadRevolutionaryDate>
=item L<App::SpreadRevolutionaryDate::Config>
=item L<App::SpreadRevolutionaryDate::BlueskyLite>
=item L<App::SpreadRevolutionaryDate::Target>
=item L<App::SpreadRevolutionaryDate::Target::Bluesky>
=item L<App::SpreadRevolutionaryDate::Target::Twitter>
=item L<App::SpreadRevolutionaryDate::Target::Mastodon>
=item L<App::SpreadRevolutionaryDate::Target::Freenode>
=item L<App::SpreadRevolutionaryDate::Target::Freenode::Bot>
=item L<App::SpreadRevolutionaryDate::Target::Liberachat>
=item L<App::SpreadRevolutionaryDate::Target::Liberachat::Bot>
=item L<App::SpreadRevolutionaryDate::MsgMaker>
=item L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate>
=item L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Calendar>
=item L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale>
=item L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::fr>
=item L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::en>
=item L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::it>
=item L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::es>
=item L<App::SpreadRevolutionaryDate::MsgMaker::PromptUser>
=item L<App::SpreadRevolutionaryDate::MsgMaker::Telechat>
=back
=head1 AUTHOR
Gérald Sédrati <gibus@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is Copyright (c) 2019-2025 by Gérald Sédrati.
This is free software, licensed under:
The GNU General Public License, Version 3, June 2007
=cut