view release on metacpan or search on metacpan
- Configuration file should be opened in UTF-8, pass filehandle to
AppConfig
0.46 2025-03-20T23:48:51Z
- Improve splitting of messages according to max_length
- Fix missing used module
- Add some images to use with Gemini
0.45 2025-03-20T21:08:22Z
- Add documentation for Gemini
- Use locale attribute to build DateTime
- Add Gemini options in help message
- Fix PromptUser options in help message
- Missing mandatory parameters that have a default value should not
trigger an error
- Add missing config option for Gemini msgmaker
- Add configuration sample for Gemini msgmaker config options
- Use Camel case for configuration section, like msgmaker module name
- Add tests for Gemini msgmaker config options
- Add config options for Gemini msgmaker
- Add Gemini msgmaker
- Fix errors in USAGE doc
0.11 2019-04-07T14:26:45Z
- Add German localization of PromptUser msgmaker
- Add documentation for i18n/l10n
- Let multivalued options be overridden by command line arguments
- Add App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale
role and moosify consuming classes
- Add localization template
- Add Italian localization
- Overload DateTime::Calendar::FrenchRevolutionary to extend defaults
fr/en locales
- Add localization with Locale::TextDomain
0.10 2019-03-30T20:59:56Z
- Add --conf, --version and --help command line parameters
- Fix and improve doc
- Add default value when defined for options guessed from Target and
MsgWriter consuming classes
- Add wikipedia_link option to revolutionarydate msgmaker
- Process wikipedia ambiguous links
"Test::Vars" : "0",
"strict" : "0",
"warnings" : "0"
}
},
"runtime" : {
"requires" : {
"AppConfig" : "0",
"Bot::BasicBot" : "0",
"Class::Load" : "0",
"DateTime" : "0",
"DateTime::Calendar::FrenchRevolutionary" : "0",
"Encode" : "0",
"File::Basename" : "0",
"File::HomeDir" : "0",
"File::ShareDir" : "0",
"File::Spec" : "0",
"File::Temp" : "0",
"File::Type" : "0",
"Getopt::Long" : "0",
"IO::Handle" : "0",
"IO::Prompt::Hooked" : "0",
App::SpreadRevolutionaryDate::Target::Mastodon:
file: lib/App/SpreadRevolutionaryDate/Target/Mastodon.pm
version: '0.51'
App::SpreadRevolutionaryDate::Target::Twitter:
file: lib/App/SpreadRevolutionaryDate/Target/Twitter.pm
version: '0.51'
requires:
AppConfig: '0'
Bot::BasicBot: '0'
Class::Load: '0'
DateTime: '0'
DateTime::Calendar::FrenchRevolutionary: '0'
Encode: '0'
File::Basename: '0'
File::HomeDir: '0'
File::ShareDir: '0'
File::Spec: '0'
File::Temp: '0'
File::Type: '0'
Getopt::Long: '0'
IO::Handle: '0'
IO::Prompt::Hooked: '0'
Makefile.PL view on Meta::CPAN
"EXE_FILES" => [
"bin/spread-revolutionary-date"
],
"LICENSE" => "gpl",
"MIN_PERL_VERSION" => "5.014",
"NAME" => "App::SpreadRevolutionaryDate",
"PREREQ_PM" => {
"AppConfig" => 0,
"Bot::BasicBot" => 0,
"Class::Load" => 0,
"DateTime" => 0,
"DateTime::Calendar::FrenchRevolutionary" => 0,
"Encode" => 0,
"File::Basename" => 0,
"File::HomeDir" => 0,
"File::ShareDir" => 0,
"File::Spec" => 0,
"File::Temp" => 0,
"File::Type" => 0,
"Getopt::Long" => 0,
"IO::Handle" => 0,
"IO::Prompt::Hooked" => 0,
Makefile.PL view on Meta::CPAN
"test" => {
"TESTS" => "t/*.t"
}
);
my %FallbackPrereqs = (
"AppConfig" => 0,
"Bot::BasicBot" => 0,
"Class::Load" => 0,
"DateTime" => 0,
"DateTime::Calendar::FrenchRevolutionary" => 0,
"Encode" => 0,
"File::Basename" => 0,
"File::HomeDir" => 0,
"File::ShareDir" => 0,
"File::Spec" => 0,
"File::Temp" => 0,
"File::Type" => 0,
"FindBin" => 0,
"Getopt::Long" => 0,
"IO::Handle" => 0,
100 minutes; and minutes into 100 seconds.
You must have a registered account on each of the targets you want to
spread the revolutionary date. And you must get credentials for
spread-revolutionary-date to post on Mastodon, Bluesky and Twitter, and
also for IA generated messages with Gemini message maker. Finally, you
have to configure spread-revolutionary-date to use these credentials,
see "CONFIGURATION" and "COMMAND LINE PARAMETERS" below.
The revolutionary date and time is computed thanks to the
DateTime::Calendar::FrenchRevolutionary Perl module, by Jean Forget.
USAGE
# Just execute the script in your shell
# to spread current date to configured accounts
# to Bluesky, Twitter, Mastodon, Freenode and Liberachat:
$ spread-revolutionary-date
# Or, since this script does nothing but calling
# the L<App::SpreadRevolutionaryDate> Perl module,
App::SpreadRevolutionaryDate::MsgMaker for a comprehensive description
of this role.
The name of the message maker should be set as a value of the
"msgmaker" option.
Such a message maker class is actually just a wrapper. Usually a
message maker has to use an existing specific module (which can be a
Moose class or not) to craft the message.
App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate uses
DateTime::Calendar::FrenchRevolutionary, while
App::SpreadRevolutionaryDate::MsgMaker::PromptUser is based on
IO::Prompt::Hooked and App::SpreadRevolutionaryDate::MsgMaker::Gemini
just uses LWP to request Gemini server. You may need for example LWP to
extract the message from a fetched web page or service, or XML::Feed to
build it from a RSS <https://en.wikipedia.org/wiki/RSS> feed, or DBI to
retrieve it from a database, or nothing at all to spread a fixed
message, etc.
If your new message maker class needs specific parameters (other than
locale, which comes with App::SpreadRevolutionaryDate::MsgMaker role),
The spread message will be Gemini answer, optionally prepended with a
configured introduction (see bellow), and ending with hashtags
#IAGenerated #PromptIdentifier.
Prompts often need to mention informations relative to today, such as
the FamousBirthday example below, or it could be that you wanna ask
Gemni for today's weather, or traffic jams occuring the same day of
the week as today, etc. As a syntactic sugar, you can insert in
"prompt" option, any variable prefixed with a dollar sign ($) which
correspond to a method of DateTime module applied to DateTime-now()>
object, and it will be replaced by the result of this method in the
prompt sent to Gemini. For example, in the FamousBirthday example
below, if run on June 21st, the prompt sent to Gemini would be:
'Which famous people have their birthday on June 21? Give a list of up to 6 people, then after the list give the unformatted URL of the Wikipedia page of only one of them, no comments and no need for an introduction like "Here are some famous...
You should be careful that such variables are not interpreted by the
Shell before calling spread-revolutionary-date, specially if
specified as command line parameters. You can prevent such
intepretation by the Shell by enclosing the option in single quotes,
like the examples above.
"intro"
You may want that the spread message to start with your own
introducing words before displaying Gemini answer. You can specify
this with the "intro" option.
Likewise, this option use the same syntactic sugar relative to
methods of DateTime module. For example, the message spread on June
21st by the FamousBirthday example bellow, would be something like
Famous people born on June 21 for better or for worse:
First Name
Second Name
Third Name
Fourth Name
Fifth Name
Sixth Name
prompt FamousBirthday = 'Which famous people have their birthday on $month_name $day? Give a list of up to 6 people, then after the list give the unformatted URL of the Wikipedia page of only one of them, no comments and no need for an i...
The only place where you should be concerned by localization is when
you define an introduction to be prepended to Gemini answer. Since it
is a configured static string, it should be written in the desired
language, like:
intro FamousBirthday = 'FamousBirthday=Berühmte Personen, die am $day $month_name geboren wurden, im Guten wie im Schlechten:'
Also, if you use some syntactic sugars relative to methods of DateTime
module that are localizable, like month_name, you should use the
"locale" option to have it translated in the desired language.
And now you are ready to spread whatever your like, with just some
configuration tweaks!
Be aware that Gemini, like any other AI, has no concept of truth. It
can only give formally probable answers, based on its training data. So
do not ask somehing where truth matters⦠Also, all data you're sending
to Gemini are assumed to not be private anymore and could be used by
msgid "or {abort} to abort"
msgstr "oder {abort}, um abzubrechen"
And that's it! As of version 0.11 of spread-revolutionary-date, there
is only about a dozen of strings to translate, mainly for PromptUser
message maker. But with the possibility to extend to other message
makers, you may need more and more strings to be translated.
Translating days, months and feasts used in the RevolutionaryDate
message maker do not use the gettext system. Mainly because it uses
DateTime::Calendar::FrenchRevolutionary which proposes French and
English translations in dedicated Perl modules.
spread-revolutionary-date keeps the same way for translating
expressions used in the French revolutionary calendar, but, thanks to
Moose::Role
App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale,
translatable nominal groups have been isolated from other Perl code.
Their translations lie in a consuming class in the
App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::
namespace for each translated language. These classes are named after
the two-letter (ISO 639-1 <https://en.wikipedia.org/wiki/ISO_639-1>) or
days. But for consistency reasons, I'd rather group all these
translations used in the French Revolutionary Calendar in the same
translation class. Nevertheless, I'm open to find solutions if you
think it would be easier to translate everything with the gettext
system.
SEE ALSO
App::SpreadRevolutionaryDate
DateTime::Calendar::FrenchRevolutionary
AppConfig
App::SpreadRevolutionaryDate::BlueskyLite
Twitter::API
Mastodon::Client
Bot::BasicBot
bin/spread-revolutionary-date view on Meta::CPAN
=head1 DESCRIPTION
C<spread-revolutionary-date> is a L<Free Software|https://www.gnu.org/philosophy/free-sw.html> that spreads the current date, expressed in the L<French Revolutionary calendar|https://en.wikipedia.org/wiki/French_Republican_calendar>, to various socia...
Moreover, you can easily extend these defaults targets with any desired one, see L</"EXTENDING TO NEW TARGETS">, and even spread something else than the revolutionary date, see L</msgmaker> option and L</"EXTENDING TO NEW MESSAGE MAKERS">.
The French Revolutionary calendar, also called Republican calendar, was introduced during the L<French Revolution|https://en.wikipedia.org/wiki/French_Revolution>, and used from late 1793 to 1805, and also during the L<Paris Commune|https://en.wikipe...
You B<must> have a registered account on each of the targets you want to spread the revolutionary date. And you must get credentials for C<spread-revolutionary-date> to post on C<Mastodon>, C<Bluesky> and C<Twitter>, and also for IA generated message...
The revolutionary date and time is computed thanks to the L<DateTime::Calendar::FrenchRevolutionary> Perl module, by Jean Forget.
=head1 USAGE
# Just execute the script in your shell
# to spread current date to configured accounts
# to Bluesky, Twitter, Mastodon, Freenode and Liberachat:
$ spread-revolutionary-date
# Or, since this script does nothing but calling
# the L<App::SpreadRevolutionaryDate> Perl module,
bin/spread-revolutionary-date view on Meta::CPAN
Also, we do not plan to extend this feature to C<Twitter> target, since we recommand to not use this social network for political reasons.
Starting from version 0.45, C<Mastodon> and C<Bluesky> classes have a C<max_lenght> attribute (set to 300 for C<Mastodon> and set to 250 for C<Bluesky>), which is used to split a longer message into a thread of multiple posts. Again, we do not plan t...
=head1 EXTENDING TO NEW MESSAGE MAKERS
It is even easier to spread whatever you want instead of the revolutionary date. You should write a new class in the C<App::SpreadRevolutionaryDate::MsgMaker::> namespace (that is: the class should be C<App::SpreadRevolutionaryDate::MsgMaker::MyMsgMa...
The name of the message maker should be set as a value of the L</msgmaker> option.
Such a message maker class is actually just a wrapper. Usually a message maker has to use an existing specific module (which can be a C<Moose> class or not) to craft the message. L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate> uses L<Dat...
If your new message maker class needs specific parameters (other than C<locale>, which comes with L<App::SpreadRevolutionaryDate::MsgMaker> role), they should be defined as attributes of this class. Values for such attributes should be set in the L<...
Have a look to L<App::SpreadRevolutionaryDate::MsgMaker::PromptUser> or L<App::SpreadRevolutionaryDate::MsgMaker::Telechat> classes, they show simple examples on how to extend C<spread-revolutionary-date> to a new message maker.
=head2 Gemini message maker
From version 0.45, a new message maker is included which requests I<Gemini> AI. This allows to extend C<spread-revolutionary-date> just by configuring a few options. The most practical way to configure these options is to prepare everything by settin...
This way, you can setup different prompts in your configuration file. Here is an example with 4 different prompts configured:
bin/spread-revolutionary-date view on Meta::CPAN
=over
=item L</prompt>
This is the option where you can define your prompt. It is advised to test this prompt to have I<Gemini> answer as you wish. For instance, I<Gemini> often start its answers to your prompt by: âSure, here is âwhat you've asked forâ, and you woul...
You can test your prompt with interactive form to I<Gemini> at L<https://gemini.google.com/app> or with C<spread-revolutionary-date> with options C<--test> and C<--targets=Mastodon> for example.
The spread message will be I<Gemini> answer, optionally prepended with a configured introduction (see bellow), and ending with hashtags C<#IAGenerated> C<#PromptIdentifier>.
Prompts often need to mention informations relative to today, such as the C<FamousBirthday> example below, or it could be that you wanna ask I<Gemni> for today's weather, or traffic jams occuring the same day of the week as today, etc. As a syntactic...
'Which famous people have their birthday on June 21? Give a list of up to 6 people, then after the list give the unformatted URL of the Wikipedia page of only one of them, no comments and no need for an introduction like "Here are some famous peopl...
You should be careful that such variables are not interpreted by the C<Shell> before calling C<spread-revolutionary-date>, specially if specified as command line parameters. You can prevent such intepretation by the C<Shell> by enclosing the option i...
=item L</intro>
You may want that the spread message to start with your own introducing words before displaying I<Gemini> answer. You can specify this with the L</intro> option.
Likewise, this option use the same syntactic sugar relative to methods of L<DateTime> module. For example, the message spread on June 21st by the C<FamousBirthday> example bellow, would be something like
Famous people born on June 21 for better or for worse:
First Name
Second Name
Third Name
Fourth Name
Fifth Name
Sixth Name
https://en.wikipedia.org/wiki/Third_Name
bin/spread-revolutionary-date view on Meta::CPAN
=back
Finally, one word of localization: you don't need it, since I<Gemini> will answer in the language you've used in your prompt. Or you can ask in your prompt to be answered in another language, like:
prompt FamousBirthday = 'Which famous people have their birthday on $month_name $day? Give a list of up to 6 people, then after the list give the unformatted URL of the Wikipedia page of only one of them, no comments and no need for an intro...
The only place where you should be concerned by localization is when you define an introduction to be prepended to I<Gemini> answer. Since it is a configured static string, it should be written in the desired language, like:
intro FamousBirthday = 'FamousBirthday=Berühmte Personen, die am $day $month_name geboren wurden, im Guten wie im Schlechten:'
Also, if you use some syntactic sugars relative to methods of L<DateTime> module that are localizable, like C<month_name>, you should use the L</locale> option to have it translated in the desired language.
And now you are ready to spread whatever your like, with just some configuration tweaks!
Be aware that I<Gemini>, like any other AI, has no concept of truth. It can only give formally probable answers, based on its training data. So do not ask somehing where truth matters⦠Also, all data you're sending to I<Gemini> are assumed to not b...
=head1 INTERNATIONALIZATION AND LOCALIZATION
Starting from version 0.11, this distribution uses the widespread internationalization and localization system L<gettext|https://en.wikipedia.org/wiki/Gettext>, commonly used for writing multilingual programs. See L<GNU gettext documentation|https://...
Translators can find a portable object template C<po/App-SpreadRevolutionaryDate.pot> which includes all translatable strings used by C<spread-revolutionary-date> (but not translations of days, months, feasts used in the French Revolutionary Calendar...
bin/spread-revolutionary-date view on Meta::CPAN
msgstr "Bitte geben Sie die Nachricht zu verbreiten ein"
When the string to be translated includes some words in curly braces, these words are actually named variables and should be left as is in the translation. E.g.:
msgid "or {abort} to abort"
msgstr "oder {abort}, um abzubrechen"
And that's it! As of version 0.11 of C<spread-revolutionary-date>, there is only about a dozen of strings to translate, mainly for C<PromptUser> message maker. But with the possibility to extend to other message makers, you may need more and more str...
Translating days, months and feasts used in the C<RevolutionaryDate> message maker do not use the C<gettext> system. Mainly because it uses L<DateTime::Calendar::FrenchRevolutionary> which proposes French and English translations in dedicated Perl mo...
Just copy the French class (from C<lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale/fr.pm> file) into the desired language, change the name of the class and replace every French string. E.g.: the names of the months should be replace...
has '+months' => (
default => sub {[
'Vendémiaire', 'Brumaire', 'Frimaire',
'Nivôse', 'Pluviôse', 'Ventôse',
'Germinal', 'Floréal', 'Prairial',
'Messidor', 'Thermidor', 'Fructidor',
'jour complémentaire',
bin/spread-revolutionary-date view on Meta::CPAN
);
Because of the trick on prefix and suffix for feasts and the needed mapping for wikipedia entries, using the C<gettext> system would be quite difficult. It wouldn't be an issue for translating names of months or days. But for consistency reasons, I'd...
=head1 SEE ALSO
=over
=item L<App::SpreadRevolutionaryDate>
=item L<DateTime::Calendar::FrenchRevolutionary>
=item L<AppConfig>
=item L<App::SpreadRevolutionaryDate::BlueskyLite>
=item L<Twitter::API>
=item L<Mastodon::Client>
=item L<Bot::BasicBot>
lib/App/SpreadRevolutionaryDate.pm view on Meta::CPAN
$self->targets->{$target}->spread($msg, $self->config->test, $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
lib/App/SpreadRevolutionaryDate/BlueskyLite.pm view on Meta::CPAN
#
# The GNU General Public License, Version 3, June 2007
#
use 5.014;
use utf8;
package App::SpreadRevolutionaryDate::BlueskyLite;
$App::SpreadRevolutionaryDate::BlueskyLite::VERSION = '0.51';
# ABSTRACT: Simple Class to post status to BlueSky.
use LWP::UserAgent;
use DateTime;
use JSON qw(encode_json decode_json);
use URI;
use Encode qw(decode_utf8);
use File::Type;
use File::Basename;
use namespace::autoclean;
sub _fetch_embed_url_card {
my $self = shift;
lib/App/SpreadRevolutionaryDate/BlueskyLite.pm view on Meta::CPAN
my $payload = {
repo => $self->{did},
collection => 'app.bsky.feed.post',
record => {
text => $text,
facets => $facets,
($embed ?
(embed => $embed)
: ()
),
createdAt => DateTime->now->iso8601 . 'Z',
},
};
if ($img) {
$img = {path => $img} unless ref($img) && ref($img) eq 'HASH' && $img->{path};
my $ft = File::Type->new();
my $mime_type = $ft->mime_type($img->{path});
my $img_alt = $img->{alt} // ucfirst(fileparse($img->{path}, qr/\.[^.]*/));
lib/App/SpreadRevolutionaryDate/BlueskyLite.pm view on Meta::CPAN
if ($response->is_success) {
return decode_json($response->decoded_content);
} else {
return $response;
}
}
# 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
lib/App/SpreadRevolutionaryDate/Config.pm view on Meta::CPAN
USAGE
exit 0;
}
no Moose;
__PACKAGE__->meta->make_immutable(inline_constructor => 0);
# 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
lib/App/SpreadRevolutionaryDate/MsgMaker.pm view on Meta::CPAN
is => 'ro',
isa => 'Str',
default => 'f',
);
requires 'compute';
# 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
lib/App/SpreadRevolutionaryDate/MsgMaker/Gemini.pm view on Meta::CPAN
#
use 5.014;
use utf8;
package App::SpreadRevolutionaryDate::MsgMaker::Gemini;
$App::SpreadRevolutionaryDate::MsgMaker::Gemini::VERSION = '0.51';
# ABSTRACT: MsgMaker class for L<App::SpreadRevolutionaryDate> to build message with Gemini prompt
use Moose;
with 'App::SpreadRevolutionaryDate::MsgMaker';
use DateTime;
use File::ShareDir ':ALL';
use LWP::UserAgent;
use JSON;
use Locale::TextDomain 'App-SpreadRevolutionaryDate';
use namespace::autoclean;
has 'api_key' => (
is => 'ro',
isa => 'Str',
lib/App/SpreadRevolutionaryDate/MsgMaker/Gemini.pm view on Meta::CPAN
return $class->$orig(%args);
};
sub compute {
my $self = shift;
my $url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key= ' . $self->api_key;
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 => [
lib/App/SpreadRevolutionaryDate/MsgMaker/Gemini.pm view on Meta::CPAN
$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
lib/App/SpreadRevolutionaryDate/MsgMaker/PromptUser.pm view on Meta::CPAN
return ($msg, undef);
}
}
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
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate.pm view on Meta::CPAN
my $self = shift;
# As of App::SpreadRevolutionaryDate 0.11
# locale is limited to 'fr', 'en', 'it' or 'es', defaults to 'fr'
# forced to 'fr' for any other value
my $revolutionary = $self->acab ?
App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Calendar->now->set(hour => 1, minute => 31, second => 20, locale => $self->locale)
: App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Calendar->now->set(locale => $self->locale);
my $feast_long = $revolutionary->feast_long;
my $today = DateTime->today;
if ($self->special_birthday_day && $self->special_birthday_month && $self->special_birthday_name && $today->day == $self->special_birthday_day && $today->month == $self->special_birthday_month) {
$feast_long = $revolutionary->locale->prefixes->[$self->special_birthday_prefix] . $self->special_birthday_name . $revolutionary->locale->suffix;
}
my $msg = __x("We are {day_name}, {day} {month} of Revolution year {roman_year} ({year}), {feast_long}, it is {time}!",
day_name => $revolutionary->day_name,
day => $revolutionary->day,
month => $revolutionary->month_name,
roman_year => $revolutionary->strftime("%EY"),
year => $revolutionary->year,
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate.pm view on Meta::CPAN
return ($msg, undef);
}
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
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Calendar.pm view on Meta::CPAN
# 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;
package App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Calendar;
$App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Calendar::VERSION = '0.51';
# ABSTRACT: Subclass overloading L<DateTime::Calendar::FrenchRevolutionary> to allow language extension
use Moose;
use MooseX::NonMoose;
extends 'DateTime::Calendar::FrenchRevolutionary';
use Class::Load ':all';
use namespace::autoclean;
sub set {
my $self = shift;
my %args = @_;
my $locale_arg = delete $args{locale};
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Calendar.pm view on Meta::CPAN
return $self;
}
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::RevolutionaryDate::Calendar - Subclass overloading L<DateTime::Calendar::FrenchRevolutionary> to allow language extension
=head1 VERSION
version 0.51
=head1 METHODS
=head2 set
Overloads L<DateTime::Calendar::FrenchRevolutionary> to allow setting locale, extending 'fr' and 'en'.
=head1 SEE ALSO
=over
=item L<spread-revolutionary-date>
=item L<App::SpreadRevolutionaryDate>
=item L<App::SpreadRevolutionaryDate::Config>
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale.pm view on Meta::CPAN
# The GNU General Public License, Version 3, June 2007
#
use 5.014;
use utf8;
package App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale;
$App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::VERSION = '0.51';
# ABSTRACT: Role providing interface for localization of revolutionary date built by L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate>.
use Moose::Role;
use DateTime::Calendar::FrenchRevolutionary;
use Locale::TextDomain 'App-SpreadRevolutionaryDate';
use namespace::autoclean;
has months => (
is => 'ro',
isa => 'ArrayRef[Str]',
required => 1,
);
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale.pm view on Meta::CPAN
my ($self, $month, $entry) = @_;
$entry = $self->wikipedia_entries->{$month}->{$entry}
if exists $self->wikipedia_entries->{$month}
&& exists $self->wikipedia_entries->{$month}->{$entry};
return $entry;
}
# 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
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale.pm view on Meta::CPAN
App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale - Role providing interface for localization of revolutionary date built by L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate>.
=head1 VERSION
version 0.51
=head1 DESCRIPTION
This role defines the localization interface for L<App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate>.
It provides some methods copied from L<DateTime::Calendar::FrenchRevolutionary::Locale::fr>.
Any class consuming this role is required to overload every mandatory attribute with a default in the language of that class:
=over
=item months
Default for this attribute should be a sorted array reference of 13 strings, each of them translating the name of each month (C<'Vendémiaire'>, C<'Brumaire'>, C<'Frimaire'>, C<'Nivôse'>, C<'Pluviôse'>, C<'Ventôse'>, C<'Germinal'>, C<'Floréal'>,...
has '+months' => (
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale.pm view on Meta::CPAN
},
}},
);
=back
=head1 METHODS
=head2 month_name
Returns the name of the month. Takes a L<DateTime::Calendar::FrenchRevolutionary> object as mandatory parameter.
=head2 day_name
Returns the name of the day. Takes a L<DateTime::Calendar::FrenchRevolutionary> object as mandatory parameter.
=head2 feast_short
Returns the feast of the day. Takes a L<DateTime::Calendar::FrenchRevolutionary> object as mandatory parameter.
=head2 feast_long
Returns the feast of the day in long format (I<day of E<lt>xxxE<gt>>). Takes a L<DateTime::Calendar::FrenchRevolutionary> object as mandatory parameter.
=head2 wikipedia_redirect
Returns the wikipedia entry (the end of the wikipedia url) corresponding to the feast of the day. Takes two mandatory parameters: the month as integer from 1 to 13 (13 is used for complementary days, also called "sans-culottides"), and the search ent...
=head1 SEE ALSO
=over
=item L<spread-revolutionary-date>
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale/en.pm view on Meta::CPAN
# 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;
package App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::en;
$App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::en::VERSION = '0.51';
# ABSTRACT: English localization of (part of) L<DateTime::Calendar::FrenchRevolutionary::Locale::en>
use Moose;
with 'App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale';
use Locale::TextDomain 'App-SpreadRevolutionaryDate';
use namespace::autoclean;
has '+months' => (
default => sub {[
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale/en.pm view on Meta::CPAN
},
}},
);
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::RevolutionaryDate::Locale::en - English localization of (part of) L<DateTime::Calendar::FrenchRevolutionary::Locale::en>
=head1 VERSION
version 0.51
=head1 DESCRIPTION
This modules copies and fixes some of the English translations of L<DateTime::Calendar::FrenchRevolutionary::Locale::en>, which bases its translation on:
=over
=item [Carlyle]
"The French Revolution: A History", Thomas Carlyle, 1837, Ed. K. J. Fielding and David Sorensen, The Worldâs Classics, Oxford, New York, Oxford University Press, 1989.
=item [Taylor]
Alan Taylor's web site: L<http://www.kokogiak.com/frc/default.asp>.
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale/en.pm view on Meta::CPAN
Jonathan Badger's French Revolutionary Calendar module written in Ruby
L<https://github.com/jhbadger/FrenchRevCal-ruby>.
=item [Wikipedia]
L<http://en.wikipedia.org/wiki/French_Republican_Calendar>.
=back
When L<DateTime::Calendar::FrenchRevolutionary::Locale::en> leaves some translations as doubtful, they are fixed here based on Wikipedia.
=head1 SEE ALSO
=over
=item L<spread-revolutionary-date>
=item L<App::SpreadRevolutionaryDate>
=item L<App::SpreadRevolutionaryDate::Config>
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale/es.pm view on Meta::CPAN
# 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;
package App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::es;
$App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::es::VERSION = '0.51';
# ABSTRACT: Spanish localization of (part of) L<DateTime::Calendar::FrenchRevolutionary::Locale::fr>
use Moose;
with 'App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale';
use Locale::TextDomain 'App-SpreadRevolutionaryDate';
use namespace::autoclean;
has '+months' => (
default => sub {[
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale/es.pm view on Meta::CPAN
},
}},
);
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::RevolutionaryDate::Locale::es - Spanish localization of (part of) L<DateTime::Calendar::FrenchRevolutionary::Locale::fr>
=head1 VERSION
version 0.51
=head1 DESCRIPTION
This modules adds Spanish translations to L<DateTime::Calendar::FrenchRevolutionary>, based on Wikipedia: L<https://es.wikipedia.org/wiki/Calendario_republicano_franc%C3%A9s>.
=head1 SEE ALSO
=over
=item L<spread-revolutionary-date>
=item L<App::SpreadRevolutionaryDate>
=item L<App::SpreadRevolutionaryDate::Config>
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale/fr.pm view on Meta::CPAN
# 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;
package App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::fr;
$App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::fr::VERSION = '0.51';
# ABSTRACT: French localization of (part of) L<DateTime::Calendar::FrenchRevolutionary::Locale::fr>
use Moose;
with 'App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale';
use Locale::TextDomain 'App-SpreadRevolutionaryDate';
use namespace::autoclean;
has '+months' => (
default => sub {[
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale/fr.pm view on Meta::CPAN
},
}},
);
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::RevolutionaryDate::Locale::fr - French localization of (part of) L<DateTime::Calendar::FrenchRevolutionary::Locale::fr>
=head1 VERSION
version 0.51
=head1 DESCRIPTION
This modules copies and fixes some of the French translations of L<DateTime::Calendar::FrenchRevolutionary::Locale::fr>.
Sources:
=over
=item [Décret]
"Annuaire ou calendrier pour la seconde année de la République française, annexe du décret du 4 frimaire, an II (24 novembre 1793) sur l'ère, le commencement et l'organisation de l'année et sur les noms des jours et des mois" ; in J. Madival an...
=item [Fabre]
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale/it.pm view on Meta::CPAN
# 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;
package App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::it;
$App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::it::VERSION = '0.51';
# ABSTRACT: Italian localization of (part of) L<DateTime::Calendar::FrenchRevolutionary>
use Moose;
with 'App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale';
use Locale::TextDomain 'App-SpreadRevolutionaryDate';
use namespace::autoclean;
has '+months' => (
default => sub {[
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Locale/it.pm view on Meta::CPAN
},
}},
);
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::RevolutionaryDate::Locale::it - Italian localization of (part of) L<DateTime::Calendar::FrenchRevolutionary>
=head1 VERSION
version 0.51
=head1 DESCRIPTION
This modules adds Italian translations to L<DateTime::Calendar::FrenchRevolutionary>, based on Wikipedia: L<https://it.wikipedia.org/wiki/Calendario_rivoluzionario_francese>.
=head1 SEE ALSO
=over
=item L<spread-revolutionary-date>
=item L<App::SpreadRevolutionaryDate>
=item L<App::SpreadRevolutionaryDate::Config>
lib/App/SpreadRevolutionaryDate/MsgMaker/Telechat.pm view on Meta::CPAN
#
use 5.014;
use utf8;
package App::SpreadRevolutionaryDate::MsgMaker::Telechat;
$App::SpreadRevolutionaryDate::MsgMaker::Telechat::VERSION = '0.51';
# ABSTRACT: MsgMaker class for L<App::SpreadRevolutionaryDate> to build message with Téléchat date
use Moose;
with 'App::SpreadRevolutionaryDate::MsgMaker';
use DateTime;
use File::ShareDir ':ALL';
use App::SpreadRevolutionaryDate;
use Locale::TextDomain 'App-SpreadRevolutionaryDate';
use namespace::autoclean;
has '+locale' => (
default => 'fr',
);
lib/App/SpreadRevolutionaryDate/MsgMaker/Telechat.pm view on Meta::CPAN
'1227' => ['pyréolophore', 'pyréolophores', 'm'],
'1228' => ['soubassophone', 'soubassophones', 'm'],
'1229' => ['vastringue', 'vastringues', 'm'],
'1230' => ['vocifération sportive', 'vociférations sportives', 'f'],
'1231' => ['connotation de proximité temporelle', 'connotations de proximité temporelle', 'f'],
},
);
my @telechat_days = ('Lourdi', 'Pardi', 'Morquidi', 'Jourdi', 'Dendrevi', 'Sordi', 'Mitanche');
my $today = DateTime->now(locale => $self->locale);
my $day_name = $telechat_days[$today->day_of_week_0];
my @calendars = sort keys %telechat_calendars;
my $calendar_key = sprintf("%02d", $today->month).sprintf("%02d", $today->day);
shift @calendars unless $telechat_calendars{'0tvtime'}->{$calendar_key};
my $chosen_calendar = @calendars[rand @calendars];
my $feast = $telechat_calendars{$chosen_calendar}->{$calendar_key};
my $feast_gender = $feast->[2] eq 'm' ? 'Saint' : 'Sainte';
my $feast_singular = $feast->[0];
$feast_singular =~ s/\b(\w)/\U$1/g;
lib/App/SpreadRevolutionaryDate/MsgMaker/Telechat.pm view on Meta::CPAN
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
lib/App/SpreadRevolutionaryDate/Target.pm view on Meta::CPAN
my $str = substr $text, 0, $loc, '';
push @msgs, $str;
substr $text, 0, 1, '';
}
return @msgs;
}
# 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
lib/App/SpreadRevolutionaryDate/Target/Bluesky.pm view on Meta::CPAN
}
}
}
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
lib/App/SpreadRevolutionaryDate/Target/Freenode.pm view on Meta::CPAN
$self->obj->run;
POE::Kernel->run();
}
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
lib/App/SpreadRevolutionaryDate/Target/Freenode/Bot.pm view on Meta::CPAN
return;
}
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
lib/App/SpreadRevolutionaryDate/Target/Liberachat.pm view on Meta::CPAN
$self->obj->run;
POE::Kernel->run();
}
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
lib/App/SpreadRevolutionaryDate/Target/Liberachat/Bot.pm view on Meta::CPAN
return;
}
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
lib/App/SpreadRevolutionaryDate/Target/Mastodon.pm view on Meta::CPAN
}
}
}
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
lib/App/SpreadRevolutionaryDate/Target/Twitter.pm view on Meta::CPAN
$self->obj->post('tweets', {'-to_json' => {"text" => $msg}});
}
}
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