App-SpreadRevolutionaryDate

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

 - 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

Changes  view on Meta::CPAN

 - 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

Changes  view on Meta::CPAN


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

Changes  view on Meta::CPAN

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

Changes  view on Meta::CPAN

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

Changes  view on Meta::CPAN

 - 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

MANIFEST  view on Meta::CPAN

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

README  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
    

README  view on Meta::CPAN

    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

README  view on Meta::CPAN

    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

README  view on Meta::CPAN

 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

README  view on Meta::CPAN

    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.

README  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 Gemini API, by
    defining the "api_key" option. For this you need to get a Gemini API
    key, by following instructions on

README  view on Meta::CPAN


    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

SIGNATURE  view on Meta::CPAN

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' );

t/config.t  view on Meta::CPAN

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');

t/config.t  view on Meta::CPAN

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');

t/locale.t  view on Meta::CPAN

}
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;



( run in 3.674 seconds using v1.01-cache-2.11-cpan-ceb78f64989 )