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 spaces in italian feast name
0.20 2019-05-14T20:59:02Z
- Update Freenode bot nick
0.19 2019-05-02T15:15:05Z
- Fix typo in French feast name
- Fix SEE ALSO sections
0.18 2019-04-10T07:07:40Z
- Defaults locale to fr for RevolutionaryDtae and en otherwise
0.17 2019-04-09T22:17:55Z
- Untranslated locale should default to fr as documented
0.16 2019-04-09T21:27:04Z
- Unset locale for PromptUser if no .mo file
0.15 2019-04-09T18:09:04Z
- Add Spanish translation of RevolutionaryDate and PromptUser msg makers
- Fix typo in USAGE
0.14 2019-04-07T21:58:42Z
- Fix errors in USAGE doc
0.13 2019-04-07T20:48:20Z
- Fix pod links with Dist::Zilla::Plugin::Test::Pod::LinkCheck
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
- Fix another typo in TODO
0.09 2019-03-27T18:52:18Z
- Fix introspection of boolean targets attributes
- Fix backward compatibility for acab option for RevolutionaryDate
MsgMaker
- Update TODO and CONTRIBUTING
- Add PromptUser massage maker with documentation and tests
- Allow to extend message crafting to something else than computing the
revolutionary date
- Move testing Mastodon and Twitter into regular tests (only
authentication needs actual params)
- Fix command line parameters in test of locales
- Fix doc for sections in command line parameters wich should be followed
by underscore, not dash
- Use IO::Handle when testing print to output for Twitter and Mastodon
- Improve readability of methods arguments
- Fix yet another typo in doc
- Fix another typo in doc
- Fix typo in doc
- Fix acab time in doc
0.08 2019-03-23T07:49:05Z
0.07 2019-03-22T15:03:21Z
- Add documentation for extending pre-defined targets
- Rename parameter of App::SpreadRevolutionaryDate::Target parameterized
role to 'worker'
- Add App::SpreadRevolutionaryDate::Target in SEE ALSO doc section
- Fix encodings and use 5.014 instead of use strict; use warnings
- Unify test for new target
- Add xtest for spreading to a new target
- Add a Moose::Role as interface for defining new targets
- Use good old shebang
- Fix locale set when computing date without acab option
- Be modern: replace eval require by Class::Load
- Update TODO
- Add test for a new target (without spread)
- Allow pre-defined targets to be easily extended
- Revert "Rename App::SpreadRevolutionaryDate::Config constructor"
- Use revolutionary quote for modules' return value
- Rename App::SpreadRevolutionaryDate::Config constructor
- Require targets classes only when needed
- Revert "Build SIGNATURE only on release stage"
- Replace targets attributes by an hashref of objects
- Revert "Explicit methods calls with parenthesis"
- Explicit methods calls with parenthesis
- Add method to compute message to spread
- Factorize get_target_arguments
- Update travis config file to run perl >= 5.14
- Update meta files
- Simplify Freenode tests by removing no_run argument
- Add test for App::SpreadRevolutionaryDate::Freenode->obj (like other
targets)
- Replace config attribute by explicit attributes in targets subclasses
- Add wikipedia link for en locale
- Delete linefeed before wikipedia link
- Add wikipedia link
- Fix computation of acab time independently of winter/summer time
- Fix link in doc
- Fix typo in doc
- Upgrade to Module::Signature 0.83
- Add CODE_OF_CONDUCT file
- Add CONTRIBUTING file
- Update TODO with nothing else than extending to other targets
- Use accessors in tests
lib/LocaleData/es/LC_MESSAGES/App-SpreadRevolutionaryDate.mo
lib/LocaleData/fr/LC_MESSAGES/App-SpreadRevolutionaryDate.mo
lib/LocaleData/it/LC_MESSAGES/App-SpreadRevolutionaryDate.mo
share/images/blanqui.png
share/images/coluche_macron.png
share/images/groucha.png
t/00-compile.t
t/bluesky.t
t/command_line.t
t/config.t
t/locale.t
t/mastodon.t
t/new_target.t
t/objects.t
t/promptuser.t
t/telechat.t
t/twitter.t
t/wikipedia.t
xt/authentication.t
xt/author/clean-namespaces.t
xt/author/critic.t
-e 'App::SpreadRevolutionaryDate->new->spread;'
# Test spreading to Mastodon only:
$ spread-revolutionary-date \
--targets=Mastodon --test
# Test spreading to Twitter only in English:
$ spread-revolutionary-date \
--targets=Twitter \
--test \
--locale en
# Spread acab time to Twitter and Liberachat
# explicit channels
$ spread-revolutionary-date \
--targets=Twitter \
--targets=Liberachat \
--liberachat_channels='#revolution' \
--liberachat_channels='#acab' \
--revolutionarydate_acab
App::SpreadRevolutionaryDate::MsgMaker::Value class consuming
App::SpreadRevolutionaryDate::MsgMaker role. Message makers values
pre-defined in this distribution are RevolutionaryDate, which spreads
the revolutionary date; PromptUser, which prompts the user for the
message to be spread (with confirmation); Telechat, which spreads the
date of the day similar to the Belgian-French TV show 'Téléchat" on the
1980's; and Gemini which prompts Gemini AI to generate a message. See
"EXTENDING TO NEW MESSAGE MAKERS" for details on using a new value for
this option.
locale
This option can only be specified once, with a value as string. Spreads
with chosen language. As of App::SpreadRevolutionaryDate 0.11 locale is
limited to 'fr', 'en', 'it' or 'es' for RevolutionaryDate and 'fr',
'en', 'it', 'es' or 'de' otherwise. Defaults to 'fr' for
RevolutionaryDate and Gemini, and to 'en' for <PromptUser>. Locale is
forced to 'fr' for Telechat since only french-spokers can understand
the TV show. To add more languages see "INTERNATIONALIZATION AND
LOCALIZATION".
test
This boolean option takes no value, either it is defined or not. If
This boolean option takes no value, either it is defined or not,
defaults to false. If defined, instead of spreading the current date
and time, pretend that decimal time is 1:31:20 (which corresponds to
03:08:56 UTC, 04:08:56 Paris winter time, or 05:08:56 Paris summer
time, in sexagesimal scale used by common Anglo-Babylonian Time).
wikipedia_link
This boolean option takes no value, either it is defined or not,
defaults to true. If defined, a link to the wikipedia page, in language
defined by the locale option, corresponding to the feast of the day, is
added to the date to be spread.
PromptUser options
If "msgmaker" option is PromptUser, instead of spreading the
revolutionary date, prompts the user (with confirmation) for the
message to be spread, with a default value (if user enters nothing when
prompted).
default
General parameters
--targets=<target> | -tg <target>
Same as "targets" configuration option above.
--msgmaker=<MsgMakerClass> | -mm <MsgMakerClass>
Same as "msgmaker" configuration option above.
--locale=<fr|en|it|es> | -l <fr|en|it|es>
Same as "locale" configuration option above.
--test | --no | -n
Same as "test" configuration option above.
Mastodon parameters
These parameters specify credentials for spread-revolutionary-date to
spread on a Mastodon account. You have to get them from your Mastodon
instance API account <https://mstdn.fr/settings/applications> with
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),
they should be defined as attributes of this class. Values for such
attributes should be set in the configuration file, inside a section
named after the message maker in lower case ([mymsgmaker]), or as
command line parameters prefixed with the name of the message maker in
lower case, followed by an underscore (--mymsgmaker_myparam).
Have a look to App::SpreadRevolutionaryDate::MsgMaker::PromptUser or
App::SpreadRevolutionaryDate::MsgMaker::Telechat classes, they show
simple examples on how to extend spread-revolutionary-date to a new
message maker.
img_alt MacronJokeColuche = 'Caricature de Coluche disant : « Câest lâhistoire dâun mec⦠» avec une caricature de macron'
prompt BlanquiRevival = 'Invente-moi un dicton révolutionnaire dans le style d\'Auguste Blanqui. Ne fais pas d\'introduction.'
img_url BlanquiRevival = 'https://example.com/imgs/my_image.jgp'
prompt MeteoParis = 'Quelle est la météo aujourd\'hui à Paris, avec la température, selon meteo-paris.com, ne devine pas, va chercher l\'information.'
search MeteoParis = 1
and, then choose the prompt to use at execution time, like:
$ spread-revolutionary-date --msgmaker=Gemini --gemini_process=FamousBirthday --locale=en
$ spread-revolutionary-date --msgmaker=Gemini --gemini_process=MacronJokeColuche
$ spread-revolutionary-date --msgmaker=Gemini --gemini_process=BlanquiRevival
$ spread-revolutionary-date --msgmaker=Gemini --gemini_process=MeteoParis
These examples show how you can tweak your message to be spread. Let's
review all these options:
First, you have to define credentials to use the Gemini API, by
defining the "api_key" option. For this you need to get a Gemini API
key, by following instructions on
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
Google for any purpose! And finally, keep in mind that each request to
Gemini AI consumes a huge amount of resources, which is detrimental to
SHA256 0d1659099f721211a2d3f3b6d92ce3a6dbc7bd9fed9a9a9a10fcf3de24a0303a lib/LocaleData/es/LC_MESSAGES/App-SpreadRevolutionaryDate.mo
SHA256 57f0e95e42b1a8e91da33f78f1297eab85a0aabd0d6f00aa2414811030c8deca lib/LocaleData/fr/LC_MESSAGES/App-SpreadRevolutionaryDate.mo
SHA256 1f40141da10af2f3acb6e75c168ab606274aa9d657c22a0c5e7eca4675fc5107 lib/LocaleData/it/LC_MESSAGES/App-SpreadRevolutionaryDate.mo
SHA256 3b6202afdb638eb807a4ddee53d1b3e46d4defa29b6440f527688067d48ef486 share/images/blanqui.png
SHA256 526bbeb3ac4598d7d26141a750ad99d5f7471b024e3020a95f618d40400af910 share/images/coluche_macron.png
SHA256 47102885766ef282deffe12bd468e596163a960b1fa1656171a902e988d365d5 share/images/groucha.png
SHA256 ed3ec364e28e79a10ac403ea47d87756eae751ba10409e293be24a404f8cfa87 t/00-compile.t
SHA256 5bdd8d62693984a7904152048e175e3d1fdb356b6c9896f87afa28d266234bc9 t/bluesky.t
SHA256 bdf0ca7f2bfd2216fae1a2c4a60f31925930d0a24551b7cfce01846640e0b2ea t/command_line.t
SHA256 2d7c00d4dc592592a7b705879957a5858e51ed5c353aa0eb5f8df4daae23fcbb t/config.t
SHA256 23fec6d51b26f654a879139c56ca67d8eb38e06c1f40f4920a1dc8b1b11f0d52 t/locale.t
SHA256 58913ef0354246be4289c61d238a57f32c95556a5579ee770540021c4ff47eb9 t/mastodon.t
SHA256 115371bb2369438a0c11f11e798eb0bd98a0c4bf341d33d3c8e807ffd59f98c1 t/new_target.t
SHA256 21dcedfebfb6f99d618ca6dc0960e5860a685ddc1a0181b1d1aef446e517275c t/objects.t
SHA256 a5f2dc6aa4e3196e0669ddf284ca8b817331d8370f4d846a09254e2dc4c1e166 t/promptuser.t
SHA256 71b57d81a38a4fa94aa21c8faad2efc3284ba53c2f02e0ac4c5d992dc4977cc0 t/telechat.t
SHA256 55982028df94718329e2f5cf0ffee472f7f9a892ed958668cece0b546496a226 t/twitter.t
SHA256 ad757d3982248c0516a133cf1cf6ea2d4a481c50e35612d4ec379c634ccf422e t/wikipedia.t
SHA256 a2c8558be357f5da776b7231432d5d45594f947ec16ac146e56dd02d33cae674 xt/authentication.t
SHA256 5ef831669a93639062c1ec526619f41830e1eeb907ce190742729242d57066c7 xt/author/clean-namespaces.t
SHA256 37e82e5ceaf9091effb6eccb9f6f56ab1336c7ffeca9f5f24e05ad0142ff712b xt/author/critic.t
bin/spread-revolutionary-date view on Meta::CPAN
-e 'App::SpreadRevolutionaryDate->new->spread;'
# Test spreading to Mastodon only:
$ spread-revolutionary-date \
--targets=Mastodon --test
# Test spreading to Twitter only in English:
$ spread-revolutionary-date \
--targets=Twitter \
--test \
--locale en
# Spread acab time to Twitter and Liberachat
# explicit channels
$ spread-revolutionary-date \
--targets=Twitter \
--targets=Liberachat \
--liberachat_channels='#revolution' \
--liberachat_channels='#acab' \
--revolutionarydate_acab
bin/spread-revolutionary-date view on Meta::CPAN
These options should appear outside of any section of the configuration file.
=head3 targets
This option can be specified multiple times, with values as strings. It explicitly defines targets where the revolutionary date should be spread to. Any value set for this option should be a valid target: any of the five default targets (C<Mastodon>,...
=head3 msgmaker
This option can only be specified once, with a value as string. Spreads a message computed by the class defined by the value of this option, defaults to C<RevolutionaryDate>. The C<Value> (case sensitive) of this option should correspond to an existi...
=head3 locale
This option can only be specified once, with a value as string. Spreads with chosen language. As of L<App::SpreadRevolutionaryDate> 0.11 locale is limited to C<'fr'>, C<'en'>, C<'it'> or C<'es'> for C<RevolutionaryDate> and C<'fr'>, C<'en'>, C<'it'>,...
=head3 test
This boolean option takes no value, either it is defined or not. If defined, do not actually spread the revolutionary date, just print it on standard output for C<Mastodon>, C<Bluesky> and C<Twitter>, and send it on configured test channels for C<Lib...
=head2 Mastodon options
These options are credentials for C<spread-revolutionary-date> to spread on a Mastodon account. You have to get them from your L<Mastodon instance API account|https://mstdn.fr/settings/applications> with C<write> scope. Note that Mastodon is a decent...
=head3 instance
bin/spread-revolutionary-date view on Meta::CPAN
=head2 RevolutionaryDate options
These options change the way revolutionary date is computed when L</msgmaker> option is C<RevolutionaryDate>. They should be defined in the C<[revolutionarydate]> section of the configuration file.
=head3 acab
This boolean option takes no value, either it is defined or not, defaults to C<false>. If defined, instead of spreading the current date and time, pretend that decimal time is 1:31:20 (which corresponds to 03:08:56 UTC, 04:08:56 Paris winter time, or...
=head3 wikipedia_link
This boolean option takes no value, either it is defined or not, defaults to C<true>. If defined, a link to the wikipedia page, in language defined by the L<locale> option, corresponding to the feast of the day, is added to the date to be spread.
=head2 PromptUser options
If L</msgmaker> option is C<PromptUser>, instead of spreading the revolutionary date, prompts the user (with confirmation) for the message to be spread, with a default value (if user enters nothing when prompted).
=head3 default
This option can only be specified once, with a value as string. If C<default> option is set, the user is not prompted and this default message is spread. If C<default> option is not defined, the default message is C<'Goodbye old world, hello revoluti...
=head3 img_path (for PromptUser)
bin/spread-revolutionary-date view on Meta::CPAN
=head2 General parameters
=head3 --targets=<target> | -tg <target>
Same as L</targets> configuration option above.
=head3 --msgmaker=<MsgMakerClass> | -mm <MsgMakerClass>
Same as L</msgmaker> configuration option above.
=head3 --locale=<fr|en|it|es> | -l <fr|en|it|es>
Same as L</locale> configuration option above.
=head3 --test | --no | -n
Same as L</test> configuration option above.
=head2 Mastodon parameters
These parameters specify credentials for C<spread-revolutionary-date> to spread on a Mastodon account. You have to get them from your L<Mastodon instance API account|https://mstdn.fr/settings/applications> with C<write> scope. Note that Mastodon is a...
=head3 --mastodon_instance=<instance> | -mi <instance>
bin/spread-revolutionary-date view on Meta::CPAN
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:
[Gemini]
bin/spread-revolutionary-date view on Meta::CPAN
img_alt MacronJokeColuche = 'Caricature de Coluche disant : « Câest lâhistoire dâun mecâ¦Â » avec une caricature de macron'
prompt BlanquiRevival = 'Invente-moi un dicton révolutionnaire dans le style d\'Auguste Blanqui. Ne fais pas d\'introduction.'
img_url BlanquiRevival = 'https://example.com/imgs/my_image.jgp'
prompt MeteoParis = 'Quelle est la météo aujourd\'hui à Paris, avec la température, selon meteo-paris.com, ne devine pas, va chercher l\'information.'
search MeteoParis = 1
and, then choose the prompt to use at execution time, like:
$ spread-revolutionary-date --msgmaker=Gemini --gemini_process=FamousBirthday --locale=en
$ spread-revolutionary-date --msgmaker=Gemini --gemini_process=MacronJokeColuche
$ spread-revolutionary-date --msgmaker=Gemini --gemini_process=BlanquiRevival
$ spread-revolutionary-date --msgmaker=Gemini --gemini_process=MeteoParis
These examples show how you can tweak your message to be spread. Let's review all these options:
First, you have to define credentials to use the I<Gemini API>, by defining the L</api_key> option. For this you need to get a I<Gemini API key>, by following instructions on L<https://ai.google.dev/gemini-api/docs/api-key>.
Then for each prompt, you have to choose an identifier, which is one word in camel case, like C<FamousBirthday>, C<MacronJokeColuche>, C<BlanquiRevival> or C<MeteoParis>. This prompt identifier should be the value of the C<< --gemini_process <ThisPro...
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...
etc/sample-spread-revolutionary-date.conf view on Meta::CPAN
test
locale = 'en'
[bluesky]
# Get these values from https://bsky.app/
identifier = 'Identifier'
password = 'Password'
[twitter]
# Get these values from https://apps.twitter.com/
consumer_key = 'ConsumerKey'
consumer_secret = 'ConsumerSecret'
lib/App/SpreadRevolutionaryDate.pm view on Meta::CPAN
if ($config->special_birthday_name && $config->special_birthday_day && $config->special_birthday_month) {
$special_birthday_args{special_birthday_name} = $config->special_birthday_name;
$special_birthday_args{special_birthday_day} = $config->special_birthday_day;
$special_birthday_args{special_birthday_month} = $config->special_birthday_month;
$special_birthday_args{special_birthday_url} = $config->special_birthday_url if $config->special_birthday_url;
$special_birthday_args{special_birthday_gemini} = $config->special_birthday_gemini if $config->special_birthday_gemini;
$special_birthday_args{special_birthday_prefix} = $config->special_birthday_prefix if $config->special_birthday_prefix;
$special_birthday_args{special_birthday_plural} = $config->special_birthday_plural if $config->special_birthday_plural;
$special_birthday_args{special_birthday_gender} = $config->special_birthday_gender if $config->special_birthday_gender;
}
my $msgmaker = $msgmaker_class->new(locale => $config->locale, %msgmaker_args, %special_birthday_args);
return $class->$orig(config => $config, targets => {}, msgmaker => $msgmaker);
};
sub BUILD {
my $self = shift;
foreach my $target (@{$self->config->targets}) {
my $target_class = 'App::SpreadRevolutionaryDate::Target::' . ucfirst(lc($target));
lib/App/SpreadRevolutionaryDate/Config.pm view on Meta::CPAN
$file_start = tell $filename if $filename && ref($filename);
# Find targets
my $config_targets = AppConfig::new($class, {CREATE => 1, ERROR => sub {}},
'conf' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'c'},
'version' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'v'},
'help' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'h|?'},
'targets' => {ARGCOUNT => ARGCOUNT_LIST, ALIAS => 'tg'},
'msgmaker' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'mm'},
'test' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'no|n'},
'locale' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'l'},
'acab' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'a'},
'bluesky' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'b'},
'twitter' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 't'},
'mastodon' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'm'},
'freenode' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'f'},
'liberachat' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'lt'});
# Rewind command line arguments and process them
@ARGV = @orig_argv;
$config_targets->parse_file($filename);
lib/App/SpreadRevolutionaryDate/Config.pm view on Meta::CPAN
$config_targets->parse_command_line;
# Add targets defined with targets option
my @targets = @{$config_targets->targets};
# For backward compatibility, add targets defined directly
my %potential_targets = $config_targets->varlist(".");
foreach my $potential_target (keys %potential_targets) {
next unless $potential_targets{$potential_target};
next if $potential_target =~ /_/;
if ($potential_target !~ /^(?:acab|test|locale|targets|msgmaker|conf|version|help)$/) {
push @targets, $potential_target;
}
}
# Set default targets if no target specified
if (!$config_targets->bluesky && !$config_targets->twitter && !$config_targets->mastodon && !$config_targets->freenode && !$config_targets->liberachat && !scalar(@targets)) {
push @targets, 'bluesky', 'twitter', 'mastodon', 'freenode', 'liberachat';
$config_targets->targets(@targets);
$config_targets->bluesky(1);
$config_targets->twitter(1);
lib/App/SpreadRevolutionaryDate/Config.pm view on Meta::CPAN
my %msgmaker_attributes;
my $msgmaker = $config_targets->msgmaker || 'RevolutionaryDate';
my $msgmaker_class = 'App::SpreadRevolutionaryDate::MsgMaker::' . $msgmaker;
my $msgmaker_meta;
try_load_class($msgmaker_class)
or die "Cannot found msgmaker class $msgmaker_class for msgmaker $msgmaker\n";
load_class($msgmaker_class);
eval { $msgmaker_meta = $msgmaker_class->meta; };
die "Cannot found msgmaker meta class $msgmaker_class for msgmaker $msgmaker: $@\n" if $@;
foreach my $msgmaker_meta_attribute ($msgmaker_meta->get_all_attributes) {
next if $msgmaker_meta_attribute->name eq 'locale';
my $msgmaker_meta_attribute_type = $msgmaker_meta_attribute->type_constraint;
my $msgmaker_meta_attribute_argcount = $msgmaker_meta_attribute_type =~ /ArrayRef/ ? ARGCOUNT_LIST : $msgmaker_meta_attribute_type =~ /HashRef/ ? ARGCOUNT_HASH : $msgmaker_meta_attribute_type =~ /Bool/ ? ARGCOUNT_NONE : ARGCOUNT_ONE;
$msgmaker_attributes{lc($msgmaker) . '_' . $msgmaker_meta_attribute->name} = { ARGCOUNT => $msgmaker_meta_attribute_argcount };
$msgmaker_attributes{lc($msgmaker)} = { ARGCOUNT => ARGCOUNT_NONE };
if ($msgmaker_meta_attribute->has_default) {
$msgmaker_attributes{lc($msgmaker) . '_' . $msgmaker_meta_attribute->name}{DEFAULT} = $msgmaker_meta_attribute->default;
}
}
lib/App/SpreadRevolutionaryDate/Config.pm view on Meta::CPAN
# Build actual instance
my $self = AppConfig::new($class,
%target_attributes,
%msgmaker_attributes,
'conf' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'c'},
'version' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'v'},
'help' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'h|?'},
'targets' => {ARGCOUNT => ARGCOUNT_LIST, ALIAS => 'tg'},
'msgmaker' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'mm', default => 'RevolutionaryDate'},
'test' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'no|n'},
'locale' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'l', default => 'fr'},
'acab' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'a'},
# Overwrite found attributes for default targets
# for backward compatibility with aliases
'bluesky' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'b'},
'twitter' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 't'},
'mastodon' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'm'},
'freenode' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'f'},
'liberachat' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'lt'},
'bluesky_identifier' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'bi'},
'bluesky_password' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'bp'},
lib/App/SpreadRevolutionaryDate/Config.pm view on Meta::CPAN
}
# Add targets defined with targets option
@targets = @{$self->targets};
# For backward compatibility, add targets defined directly
my %confvars = $self->varlist(".");
foreach my $potential_target (keys %confvars) {
next unless $confvars{$potential_target};
next if $potential_target =~ /_/;
if ($potential_target !~ /^(?:acab|test|locale|targets|msgmaker|conf|version|help)$/) {
push @targets, $potential_target;
$self->targets($potential_target);
}
}
# Set default targets if no target specified
if (!$self->bluesky && !$self->twitter && !$self->mastodon && !$self->freenode && !$self->liberachat && !scalar(@targets)) {
push @targets, 'bluesky', 'twitter', 'mastodon', 'freenode', 'liberachat';
map { $self->targets($_); } @targets;
$self->bluesky(1);
lib/App/SpreadRevolutionaryDate/Config.pm view on Meta::CPAN
sub usage {
print << "USAGE";
Usage: $0 <OPTIONS>
with <OPTIONS>:
--conf|-c <file>: path to configuration file (default: ~/.config/spread-revolutionary-date/spread-revolutionary-date.conf or ~/.spread-revolutionary-date.conf)'
--version|-v': print out version
--help|-h|-?': print out this help
--targets|-tg <target_1> [--targets|-tg <target_2> [â¦--targets|-tg <target_n>]]': define targets (default: mastodon, bluesky, twitter, liberachat, freenode)
--msgmaker|-mm <MsgMakerClass>: define message maker (default: RevolutionaryDate)
--locale|-l <fr|en|it|es>: define locale (default: fr for msgmaker=RevolutionaryDate, en otherwise)
--test|--no|-n: do not spread, just print out message or spread to test channels for Freenode or Liberachat
--mastodon_instance|-mi <instance>: define Mastodon instance
--mastodon_client_id|-mci <id>: define Mastodon client id
--mastodon_client_secret|-mcs <secret>: define Mastodon client secret
--mastodon_access_token|-mat <token>: define Mastodon access token
--bluesky_identifier|-bi <key>: define Bluesky identifier
--bluesky_password|-bp <key>: define Bluesky password
--twitter_consumer_key|-tck <key>: define Twitter consumer key
--twitter_consumer_secret|-tcs <secret>: define Twitter consumer secret
--twitter_access_token|-tat <token>: define Twitter access token
lib/App/SpreadRevolutionaryDate/MsgMaker.pm view on Meta::CPAN
#
# The GNU General Public License, Version 3, June 2007
#
use 5.014;
use utf8;
package App::SpreadRevolutionaryDate::MsgMaker;
$App::SpreadRevolutionaryDate::MsgMaker::VERSION = '0.54';
# ABSTRACT: Role providing interface for crafting a message to be spread by L<App::SpreadRevolutionaryDate>.
use Moose::Role;
use Locale::Util qw(set_locale);
use Locale::Messages qw(LC_ALL nl_putenv);
use Locale::TextDomain 'App-SpreadRevolutionaryDate';
use namespace::autoclean;
has locale => (
is => 'ro',
isa => 'Str',
required => 1,
default => 'en',
trigger => sub {
# Set locale to $val, see https://metacpan.org/pod/Locale::TextDomain::FAQ#How-do-I-switch-languages-or-force-a-certain-language-independently-from-user-settings-read-from-the-environment?
my ( $self, $val, $old_val ) = @_;
if ($val) {
Locale::Messages->select_package('gettext_pp');
set_locale(LC_ALL, $val, undef, 'utf-8');
nl_putenv("LANGUAGE=$val");
nl_putenv("LANG=$val");
nl_putenv("OUTPUT_CHARSET=utf-8");
}
},
);
has special_birthday_name => (
is => 'ro',
isa => 'Str',
lib/App/SpreadRevolutionaryDate/MsgMaker.pm view on Meta::CPAN
=head1 VERSION
version 0.54
=head1 DESCRIPTION
This role defines the interface for any class that makes a message to be spread by L<App::SpreadRevolutionaryDate>.
Any class consuming this role is required to implement a C<compute> method, which is called with no parameters, and should return an array with the message to be spread as a string, and optionally a hash with C<path> key valued by the path to an imag...
This role provides a C<locale> required attribute (defaults to C<'fr'>), which holds the language, defined in language code of L<ISO 639-1 alpha-2|https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes>. Consuming classes are then free to use this C<l...
=head1 SEE ALSO
=over
=item L<spread-revolutionary-date>
=item L<App::SpreadRevolutionaryDate>
=item L<App::SpreadRevolutionaryDate::Config>
lib/App/SpreadRevolutionaryDate/MsgMaker/Gemini.pm view on Meta::CPAN
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 $url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-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/PromptUser.pm view on Meta::CPAN
has 'img_url' => (
is => 'rw',
isa => 'Maybe[Str]',
default => '',
);
around BUILDARGS => sub {
my ($orig, $class, %args) = @_;
if ($args{locale}) {
# Get sure locale has .mo file
my ($volume, $directory, $file) = File::Spec->splitpath(__FILE__);
my $locale_mo = File::Spec->catfile($directory, '..', '..', '..', 'LocaleData', $args{locale}, 'LC_MESSAGES', 'App-SpreadRevolutionaryDate.mo');
$args{locale} = 'en' unless -f $locale_mo;
}
# Do not pass default => undef to force default in attribute definition
delete $args{default}
if exists $args{default} && !defined $args{default};
return $class->$orig(%args);
};
sub compute {
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate.pm view on Meta::CPAN
# ABSTRACT: MsgMaker class for L<App::SpreadRevolutionaryDate> to build message with revolutionary date
use Moose;
with 'App::SpreadRevolutionaryDate::MsgMaker';
use App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Calendar;
use Locale::TextDomain 'App-SpreadRevolutionaryDate';
use namespace::autoclean;
has '+locale' => (
default => 'fr',
);
has 'acab' => (
is => 'ro',
isa => 'Bool',
required => 1,
default => 0,
);
has 'wikipedia_link' => (
is => 'ro',
isa => 'Bool',
required => 1,
default => 1,
);
around BUILDARGS => sub {
my ($orig, $class, %args) = @_;
$args{locale} = 'fr'
unless $args{locale}
&& grep { $args{locale} eq $_ } ('en', 'it', 'es');
return $class->$orig(%args);
};
sub compute {
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,
feast_long => $feast_long,
time => $revolutionary->hms,
);
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 && $self->special_birthday_url) {
$msg .= ' ' . $self->special_birthday_url;
} elsif ($self->wikipedia_link) {
use URI::Escape;
my $entry = $revolutionary->locale->wikipedia_redirect($revolutionary->month, $revolutionary->feast_short);
$msg .= ' https://' . $self->locale . '.wikipedia.org/wiki/' . uri_escape_utf8($entry);
}
return ($msg, undef);
}
no Moose;
__PACKAGE__->meta->make_immutable;
# A module must return a true value. Traditionally, a module returns 1.
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Calendar.pm view on Meta::CPAN
extends 'DateTime::Calendar::FrenchRevolutionary';
use Class::Load ':all';
use namespace::autoclean;
sub set {
my $self = shift;
my %args = @_;
my $locale_arg = delete $args{locale};
my $locale_class;
if ($locale_arg) {
die "only 'fr', 'en', 'it' and 'es' possible"
unless $locale_arg =~ /^(?:en|fr|it|es)$/;
$locale_class = 'App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Locale::' . $locale_arg;
}
$self = $self->SUPER::set(%args);
if ($locale_class) {
try_load_class($locale_class)
or die "Cannot import locale class $locale_class\n";
load_class($locale_class);
$self->{locale} = $locale_class->new();
}
return $self;
}
no Moose;
__PACKAGE__->meta->make_immutable;
# A module must return a true value. Traditionally, a module returns 1.
lib/App/SpreadRevolutionaryDate/MsgMaker/RevolutionaryDate/Calendar.pm view on Meta::CPAN
App::SpreadRevolutionaryDate::MsgMaker::RevolutionaryDate::Calendar - Subclass overloading L<DateTime::Calendar::FrenchRevolutionary> to allow language extension
=head1 VERSION
version 0.54
=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/Telechat.pm view on Meta::CPAN
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',
);
around BUILDARGS => sub {
my ($orig, $class, %args) = @_;
$args{locale} = 'fr';
return $class->$orig(%args);
};
sub compute {
my $self = shift;
my %telechat_calendars = (
'0tvtime' => {
'0101' => ['flaque d\'eau', 'flaques d\'eau', 'f'],
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;
t/command_line.t view on Meta::CPAN
use Test::More tests => 32;
use Test::NoWarnings;
use Test::Trap;
use App::SpreadRevolutionaryDate;
use FindBin;
my $conf_file = $FindBin::Bin . '/../etc/sample-spread-revolutionary-date.conf';
@ARGV = ('--locale', 'fr', '-c', $conf_file);
my $spread_revolutionary_date = App::SpreadRevolutionaryDate->new();
is($spread_revolutionary_date->config->conf, $conf_file, 'Conf option value');
is($spread_revolutionary_date->config->test, 1, 'Test option set');
is($spread_revolutionary_date->config->locale, 'fr', 'Locale option value');
is_deeply($spread_revolutionary_date->config->targets, ['bluesky', 'twitter', 'mastodon', 'freenode', 'liberachat'], 'Default targets options set by default');
ok($spread_revolutionary_date->config->twitter, 'Twitter option set by default');
ok($spread_revolutionary_date->config->mastodon, 'Mastodon option set by default');
ok($spread_revolutionary_date->config->freenode, 'Freenode option set by default');
ok($spread_revolutionary_date->config->liberachat, 'Liberachat option set by default');
is($spread_revolutionary_date->config->twitter_consumer_key, 'ConsumerKey', 'Twitter consumer_key value');
is($spread_revolutionary_date->config->twitter_consumer_secret, 'ConsumerSecret', 'Twitter consumer_secret value');
t/command_line.t view on Meta::CPAN
is($spread_revolutionary_date->config->freenode_password, 'Password', 'Freenode password value');
is_deeply($spread_revolutionary_date->config->freenode_test_channels, ['#TestChannel1', '#TestChannel2'], 'Freenode test_channels values');
is_deeply($spread_revolutionary_date->config->freenode_channels, ['#Channel1', '#Channel2', '#Channel3'], 'Freenode channels values');
is($spread_revolutionary_date->config->liberachat_nickname, 'NickName', 'Liberachat nickname value');
is($spread_revolutionary_date->config->liberachat_password, 'Password', 'Liberachat password value');
is_deeply($spread_revolutionary_date->config->liberachat_test_channels, ['#TestChannel1', '#TestChannel2'], 'Liberachat test_channels values');
is_deeply($spread_revolutionary_date->config->liberachat_channels, ['#Channel1', '#Channel2', '#Channel3'], 'Liberachat channels values');
is($spread_revolutionary_date->config->msgmaker, 'RevolutionaryDate', 'MsgMaker option default value');
is($spread_revolutionary_date->config->locale, 'fr', 'MsgMaker locale option value');
ok(!$spread_revolutionary_date->config->acab, 'MsgMaker acab option value');
@ARGV = ('--version', '--test');
trap { App::SpreadRevolutionaryDate->new };
is($trap->exit, 0, 'Version exit code' );
is($trap->stdout, $App::SpreadRevolutionaryDate::VERSION . "\n", 'Version value' );
@ARGV = ('-?', '-n');
trap { App::SpreadRevolutionaryDate->new };
is($trap->exit, 0, 'Help exit code' );
use App::SpreadRevolutionaryDate;
@ARGV = ('--test');
my $data_start = tell DATA;
my $spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
isa_ok($spread_revolutionary_date, 'App::SpreadRevolutionaryDate', 'Base class constructor');
isa_ok($spread_revolutionary_date->config, 'App::SpreadRevolutionaryDate::Config', 'Config class constructor');
is($spread_revolutionary_date->config->test, 1, 'Test option set');
is($spread_revolutionary_date->config->locale, 'fr', 'Locale option value');
is_deeply($spread_revolutionary_date->config->targets, ['bluesky', 'twitter', 'mastodon', 'freenode', 'liberachat'], 'Default targets options set by default');
ok($spread_revolutionary_date->config->bluesky, 'Bluesky option set by default');
ok($spread_revolutionary_date->config->twitter, 'Twitter option set by default');
ok($spread_revolutionary_date->config->mastodon, 'Mastodon option set by default');
ok($spread_revolutionary_date->config->freenode, 'Freenode option set by default');
is($spread_revolutionary_date->config->bluesky_identifier, 'Identifier', 'Bluesky identifier value');
is($spread_revolutionary_date->config->bluesky_password, 'Password', 'Bluesky password value');
is($spread_revolutionary_date->config->mastodon_client_id, 'ClientId', 'Mastodon client_id value');
is($spread_revolutionary_date->config->mastodon_client_secret, 'ClientSecret', 'Mastodon client_secret value');
is($spread_revolutionary_date->config->mastodon_access_token, 'AccessToken', 'Mastodon access_token value');
is($spread_revolutionary_date->config->freenode_nickname, 'NickName', 'Freenode nickname value');
is($spread_revolutionary_date->config->freenode_password, 'Password', 'Freenode password value');
is_deeply($spread_revolutionary_date->config->freenode_test_channels, ['#TestChannel1', '#TestChannel2'], 'Freenode test_channels values');
is_deeply($spread_revolutionary_date->config->freenode_channels, ['#Channel1', '#Channel2', '#Channel3'], 'Freenode channels values');
is($spread_revolutionary_date->config->msgmaker, 'RevolutionaryDate', 'MsgMaker option default value');
is($spread_revolutionary_date->config->locale, 'fr', 'MsgMaker locale option value');
ok(!$spread_revolutionary_date->config->acab, 'MsgMaker acab option value');
@ARGV = ('--twitter', '--test');
seek DATA, $data_start, 0;
my $spread_only_to_twitter = App::SpreadRevolutionaryDate->new(\*DATA);
is_deeply($spread_only_to_twitter->config->targets, ['twitter'], 'Targets options set');
ok($spread_only_to_twitter->config->twitter, 'Twitter option explicitely set');
ok(!$spread_only_to_twitter->config->mastodon, 'Mastodon option not explicitely set');
ok(!$spread_only_to_twitter->config->freenode, 'Freenode option not explicitely set');
}
use open qw(:std :encoding(UTF-8));
binmode(DATA, ":encoding(UTF-8)");
use Test::More tests => 6;
use Test::Output;
use Test::NoWarnings;
use App::SpreadRevolutionaryDate;
@ARGV = ('--locale', 'fr');
my $data_start = tell DATA;
my $fr_spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
stdout_like { $fr_spread_revolutionary_date->spread } qr/Diffusé sur Twitter : Nous sommes le/, 'Spread on Twitter in French';
@ARGV = ('--locale', 'en');
seek DATA, $data_start, 0;
my $en_spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
stdout_like { $en_spread_revolutionary_date->spread } qr/Spread on Twitter: We are/, 'Spread on Twitter in English';
@ARGV = ('--locale', 'it');
seek DATA, $data_start, 0;
my $it_spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
stdout_like { $it_spread_revolutionary_date->spread } qr/Diffondi su Twitter : Ã/, 'Spread on Twitter in Italian';
@ARGV = ('--locale', 'es');
seek DATA, $data_start, 0;
my $es_spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
stdout_like { $es_spread_revolutionary_date->spread } qr/Difundido en Twitter: ¡Estamos el/, 'Spread on Twitter in French not Spanish';
@ARGV = ('--locale', 'tlh');
seek DATA, $data_start, 0;
my $klingon_spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
stdout_like { $klingon_spread_revolutionary_date->spread } qr/Diffusé sur Twitter : Nous sommes le/, 'Spread on Twitter in Klingon';
__DATA__
test
twitter
[twitter]
t/new_target.t view on Meta::CPAN
use App::SpreadRevolutionaryDate;
my $spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
is_deeply($spread_revolutionary_date->config->targets, ['ezln'], 'EZLN target option set');
is($spread_revolutionary_date->config->ezln_land, 'Chiapas', 'EZLN land value');
is_deeply($spread_revolutionary_date->config->ezln_subcomandantes, ['Marcos', 'Moisés', 'Galeano'], 'EZLN subcomandantes values');
stdout_like {$spread_revolutionary_date->spread } qr/^From Chiapas\nWe are .+\nSubcomandantes Marcos, Moisés, Galeano\n$/u, 'Spread to Ezln';
__DATA__
targets = 'ezln'
locale = 'en'
[ezln]
subcomandantes = 'Marcos'
subcomandantes = 'Moisés'
subcomandantes = 'Galeano'
land = 'Chiapas'
t/promptuser.t view on Meta::CPAN
binmode(DATA, ":encoding(UTF-8)");
use Test::More tests => 7;
use Test::NoWarnings;
use Test::Output;
use File::HomeDir;
use App::SpreadRevolutionaryDate;
@ARGV = ('--test', '--twitter', '--locale', 'en');
my $data_start = tell DATA;
my $spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
# Default message
stdout_like { $spread_revolutionary_date->spread } qr/Spread on Twitter: Goodbye old world, hello revolutionary worlds$/, 'Spread default on Twitter';
# Set message
@ARGV = ('--test', '--twitter', '--promptuser_default', 'Thinking, attacking, building â such is our fabulous agenda.');
seek DATA, $data_start, 0;
$spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
stdout_like { $spread_revolutionary_date->spread } qr/Diffusé sur Twitter : Thinking, attacking, building â such is our fabulous agenda\.$/, 'Spread message on Twitter';
# Default message in Italian
@ARGV = ('--test', '--twitter', '--locale', 'it');
seek DATA, $data_start, 0;
$spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
stdout_like { $spread_revolutionary_date->spread } qr/Diffondi su Twitter : Goodbye old world, hello revolutionary worlds$/, 'Spread in Italian';
# Default message in Spanish
@ARGV = ('--test', '--twitter', '--locale', 'es');
seek DATA, $data_start, 0;
$spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
stdout_like { $spread_revolutionary_date->spread } qr/Difundido en Twitter: Goodbye old world, hello revolutionary worlds$/, 'Spread in Italian';
# Use locale oustide of languages allowed by RevolutionaryDate
@ARGV = ('--test', '--twitter', '--locale', 'de');
seek DATA, $data_start, 0;
$spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
stdout_like { $spread_revolutionary_date->spread } qr/Ãberträgt auf Twitter: Goodbye old world, hello revolutionary worlds$/, 'Spread in German';
# Default message in French for untranslated locale
@ARGV = ('--test', '--twitter', '--locale', 'tlh');
seek DATA, $data_start, 0;
$spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
stdout_like { $spread_revolutionary_date->spread } qr/Spread on Twitter: Goodbye old world, hello revolutionary worlds$/, 'Spread in Klingon';
__DATA__
msgmaker = 'PromptUser'
[twitter]
# Get these values from https://apps.twitter.com/
t/telechat.t view on Meta::CPAN
binmode(DATA, ":encoding(UTF-8)");
use Test::More tests => 2;
use Test::NoWarnings;
use Test::Output;
use File::HomeDir;
use App::SpreadRevolutionaryDate;
@ARGV = ('--test', '--mastodon', '--locale', 'en');
my $data_start = tell DATA;
my $spread_revolutionary_date = App::SpreadRevolutionaryDate->new(\*DATA);
# Default message
stdout_like { $spread_revolutionary_date->spread } qr/^(?:Message 1: )?Diffusé sur Mastodon : Chalut ! Aujourd'hui, (?:Lourdi|Pardi|Morquidi|Jourdi|Dendrevi|Sordi|Mitanche) \d+, c'est la Sainte?-[^.]+\..+Bonne.+fête.+à .+tou(?:te)?s.+les.+ !.+wi...
__DATA__
msgmaker = 'Telechat'
xt/author/eol.t view on Meta::CPAN
'lib/App/SpreadRevolutionaryDate/Target/Freenode.pm',
'lib/App/SpreadRevolutionaryDate/Target/Freenode/Bot.pm',
'lib/App/SpreadRevolutionaryDate/Target/Liberachat.pm',
'lib/App/SpreadRevolutionaryDate/Target/Liberachat/Bot.pm',
'lib/App/SpreadRevolutionaryDate/Target/Mastodon.pm',
'lib/App/SpreadRevolutionaryDate/Target/Twitter.pm',
't/00-compile.t',
't/bluesky.t',
't/command_line.t',
't/config.t',
't/locale.t',
't/mastodon.t',
't/new_target.t',
't/objects.t',
't/promptuser.t',
't/telechat.t',
't/twitter.t',
't/wikipedia.t'
);
eol_unix_ok($_, { trailing_whitespace => 1 }) foreach @files;
xt/author/no-tabs.t view on Meta::CPAN
'lib/App/SpreadRevolutionaryDate/Target/Freenode.pm',
'lib/App/SpreadRevolutionaryDate/Target/Freenode/Bot.pm',
'lib/App/SpreadRevolutionaryDate/Target/Liberachat.pm',
'lib/App/SpreadRevolutionaryDate/Target/Liberachat/Bot.pm',
'lib/App/SpreadRevolutionaryDate/Target/Mastodon.pm',
'lib/App/SpreadRevolutionaryDate/Target/Twitter.pm',
't/00-compile.t',
't/bluesky.t',
't/command_line.t',
't/config.t',
't/locale.t',
't/mastodon.t',
't/new_target.t',
't/objects.t',
't/promptuser.t',
't/telechat.t',
't/twitter.t',
't/wikipedia.t'
);
notabs_ok($_) foreach @files;