App-SpreadRevolutionaryDate

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN


0.26 2019-06-08T15:16:33Z
 - Add dependency to LWP::Protocol::https

0.25 2019-06-08T10:51:03Z
 - Remove channels added by Bot::BasicBot::irc_chanjoin_state with
   different case

0.24 2019-06-04T07:47:15Z
 - Fix backward compatibility processing of --acab option
 - Fix not prompting user if --promptuser_default option is set

0.23 2019-06-03T12:37:04Z
 - Fix skipping prompt only if --promptuser_default is set
 - Decode ARGV in UTF9 if PERL_UNICODE env var does not contain 'A'
 - Remove uneffective setting or PERL_UNICODE env var in BEGIN blocks

0.22 2019-05-29T08:43:15Z
 - Do not prompt if --promptuser_default option is set
 - Add --promptuser_default option as documented
 - Add --revolutionarydate_acab option as documented

0.21 2019-05-25T10:28:36Z
 - 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

MANIFEST  view on Meta::CPAN

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
xt/author/distmeta.t
xt/author/eol.t
xt/author/no-tabs.t
xt/author/pod-coverage.t

README  view on Meta::CPAN

    
      # Prompt user for a message to spread to Mastodon
      $ spread-revolutionary-date \
          --targets=Mastodon \
          --msgmaker=UserPrompt
    
      # Spread message as command line parameter to
      # Mastodon, Bluesky, Twitter, Liberachat and Freenode
      $ spread-revolutionary-date \
          --msgmaker=UserPrompt \
          --promptuser_default
    
      # Spread message and image as command line parameter to
      # Mastodon and Bluesky
      $ spread-revolutionary-date \
          --msgmaker=UserPrompt \
          --targets=Mastodon \
          --targets=Bluesky \
          --promptuser_default \
            'This is my message to the world'
          --promptuser_img_path= \
            /my/path/to/image.png
          --promptuser_img_alt= \
            'Alternative text for image'
    
      # Spread message and image form web as command line parameter to
      # Mastodon and Bluesky
      $ spread-revolutionary-date \
          --msgmaker=UserPrompt \
          --targets=Mastodon \
          --targets=Bluesky \
          --promptuser_default \
            'This is my message to the world'
          --promptuser_img_url= \
            'https://example.com/imgs/my_image.jgp'
          --promptuser_img_alt
    
      # Spread Téléchat date of the day on Mastodon and BlueSky
      $ spread-revolutionary-date \
          --msgmaker=Telechat \
          --targets=Mastodon \
          --targets=Bluesky
    
      # Spread Gemini generating an illustrated joke on Mastodon
      # NB: usually prompts are defined in configuration file along
      # with api_key, while --gemini-process is passed on command line
      # to choose which prompt to process
      $ spread-revolutionary-date \
          --targets=Mastodon \
          --msgmaker=Gemini \
          --gemini_api_key=ApiKey \
          --gemini_process=MacronJokeColuche \
          --gemini_prompt 'MacronJokeColuche=Invente-moi une blague \
            dans le style de Coluche sur Emmanuel Macron. Pas besoin \
            de dire "D\'accord, voici une blague" ou "Bien sûr, \
            voici une blague dans le style de Coluche sur Emmanuel \
            Macron" avant la blague.' \
          --gemini_img_path "MacronJokeColuche='/my/path/to/image.png'" \
          --gemini_img_alt "MacronJokeColuche='Caricature de Coluche \
            disant : « C’est l’histoire d’un mec… » avec une caricature \
            de macron'" \
    
      # Spread Gemini searching for real time weather on Mastodon
      # NB: usually prompts are defined in configuration file along
      # with api_key, while --gemini-process is passed on command line
      # to choose which prompt to process
      $ spread-revolutionary-date \
          --targets=Mastodon \
          --msgmaker=Gemini \
          --gemini_api_key=ApiKey \
          --gemini_process=MeteoParis \
          --gemini_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.' \
          --gemini_search "MeteoParis=1"
    
      # Spread Gemini generating a list of celebrities with an url
      # prepended by an introdution on Mastodon
      # NB: usually prompts are defined in configuration file along
      # with api_key, while --gemini-process is passed on command line
      # to choose which prompt to process
      $ spread-revolutionary-date \
          --targets=Mastodon \
          --msgmaker=Gemini \
          --gemini_api_key=ApiKey \
          --gemini_process=FamousBirthday \
          --gemini_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 introduction like "Here are some famous people".' \
          --gemini_intro 'FamousBirthday=Famous people born on $month_name \
            $day for better or for worse:'

CONFIGURATION

    Once again: you have to configure spread-revolutionary-date with

README  view on Meta::CPAN


  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 RevolutionaryDate. The Value (case sensitive) of this
    option should correspond to an existing
    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

README  view on Meta::CPAN

  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

    This option can only be specified once, with a value as string. If
    default option is set, the user is not prompted and this default
    message is spread. If default option is not defined, the default
    message is 'Goodbye old world, hello revolutionary worlds' if the user
    enters nothing when prompted. The default option should be defined in
    the [PromptUser] section of the configuration file. It is only used if
    "msgmaker" option is PromptUser.

  img_path (for PromptUser)

    This option can only be specified once, with a value as string valued
    by a path to an image file on local disk. The img_path option should be
    defined in the [PromptUser] section of the configuration file. It is
    only used if "msgmaker" option is PromptUser.

README  view on Meta::CPAN

  img_url (for PromptUser)

    This option can only be specified once, with a value as string valued
    by an external url to a remote image. The img_url option should be
    defined in the [PromptUser] section of the configuration file. It is
    only used if "msgmaker" option is PromptUser.

 Gemini options

    If "msgmaker" option is Gemini, instead of spreading the revolutionary
    date, requests Gemini AI to generate a text from a prompt.

  api_key

    This option can only be specified once, with a value as string: your
    Gemini API key. You have to get it following instructions on
    https://ai.google.dev/gemini-api/docs/api-key. The api_key option
    should be defined in the [Gemini] section of the configuration file. It
    is only used if "msgmaker" option is Gemini.

  process

    This option can only be specified once, with a value as string, telling
    which "prompt" and other options below should be send to Gemini AI. The
    process option should be defined in the [Gemini] section of the
    configuration file. It is only used if "msgmaker" option is Gemini.

  prompt

    This option can be specified for several prompts, each one with a key
    as a string, valued by the string configured for "process" options
    above, and a value as string valued by the prompt to send to Gemini AI.
    The prompt option should be defined in the [Gemini] section of the
    configuration file. It is only used if "msgmaker" option is Gemini.

  intro

    This option can be specified for several prompts, each one with a key
    as a string, valued by the string configured for "process" options
    above, and a value as string to prepend to Gemini answer. The intro
    option should be defined in the [Gemini] section of the configuration
    file. It is only used if "msgmaker" option is Gemini.

  search

    This option can be specified for several prompts, each one with a key
    as a string, valued by the string configured for "process" options
    above, and a true value, telling Gemini AI to use grounded sources
    (inline supporting links) and Google Search suggestions. The search
    option should be defined in the [Gemini] section of the configuration
    file. It is only used if "msgmaker" option is Gemini.

  img_path (for Gemini)

    This option can be specified for several prompts, each one with a key
    as a string, valued by the string configured for "process" options
    above, and a value as string valued by a path to an image file on local
    disk. The img_path option should be defined in the [Gemini] section of
    the configuration file. It is only used if "msgmaker" option is Gemini.

  img_alt (for Gemini)

    This option can be specified for several prompts, each one with a key
    as a string, valued by the string configured for "process" options
    above, and a value as string valued by an alternative text to an image
    file specified by img_path or img_url options. The img_alt option
    should be defined in the [Gemini] section of the configuration file. It
    is only used if "msgmaker" option is Gemini.

  img_url (for Gemini)

    This option can be specified for several prompts, each one with a key
    as a string, valued by the string configured for "process" options
    above, and a value as string valued by an external url to a remote
    image. The img_url option should be defined in the [Gemini] section of
    the configuration file. It is only used if "msgmaker" option is Gemini.

COMMAND LINE PARAMETERS

    Any command line parameter, other than the first three ones below,
    takes precedence on the corresponding option specified on the
    confiuration file, see "CONFIGURATION" above.

README  view on Meta::CPAN

  --revolutionarydate_acab | -ra

    Same as "acab" configuration option above.

  --revolutionarydate_wikipedia_link

    Same as "wikipedia_link" configuration option above.

 PromptUser parameters

  --promptuser_default <msg> | -pud <msg>

    Same as "default" configuration option above.

  --promptuser_img_path <path/to/image/file> | -pui </path/to/image/file>

    Same as "img_path (for PromptUser)" configuration option above.

  --promptuser_img_alt <alternative text> | -pua <alternative text>

    Same as "img_alt (for PromptUser)" configuration option above.

  --promptuser_img_url <img_url> | -puu <img_url>

    Same as "img_url" (for PromptUser) configuration option above.

 Gemini parameters

  --gemini_api_key <api key> | -ga <api key>

    Same as "api_key" configuration option above.

  --gemini_process <SomePrompt> | -g <SomePrompt>

    Same as "process" configuration option above.

  --gemini_prompt "<SomePrompt>=<my prompt string>" | -gp "<SomePrompt>=<my
  prompt string>"

    Same as "process" configuration option above.

  --gemini_intro "<SomePrompt>=<intro msg>" | -gi "<SomePrompt>=<intro
  msg>"

    Same as "process" configuration option above.

  --gemini_search "<SomePrompt>=1" | -gs "<SomePrompt>=1"

README  view on Meta::CPAN

    App::SpreadRevolutionaryDate::MsgMaker::Telechat classes, they show
    simple examples on how to extend spread-revolutionary-date to a new
    message maker.

 Gemini message maker

    From version 0.45, a new message maker is included which requests
    Gemini AI. This allows to extend spread-revolutionary-date just by
    configuring a few options. The most practical way to configure these
    options is to prepare everything by setting all "Gemini options" in the
    configuration file, except "process" to pickup the prompt at execution
    time by using the --gemini_process <ThisPrompt> command line parameter.

    This way, you can setup different prompts in your configuration file.
    Here is an example with 4 different prompts configured:

      [Gemini]
      # See https://ai.google.dev/gemini-api/docs/api-key
      api_key                      = 'GEMINI_API_KEY'
      prompt   FamousBirthday      = 'Which famous people have their birthday on $month_name $day? Give a list of up to 6 people, then after the list give the unformatted URL of the Wikipedia page of only one of them, no comments and no need for an i...
      intro    FamousBirthday      = 'FamousBirthday=Famous people born on $month_name $day for better or for worse:'
    
      prompt   MacronJokeColuche   = 'Invente-moi une blague dans le style de Coluche sur Emmanuel Macron. Pas besoin de dire "D\'accord, voici une blague" ou "Bien sûr, voici une blague dans le style de Coluche sur Emmanuel Macron" avant la blague....
      img_path MacronJokeColuche   = '/usr/local/share/perl/5.32.1/auto/share/dist/App-SpreadRevolutionaryDate/images/coluche_macron.png'
      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
    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 FamousBirthday, MacronJokeColuche,
    BlanquiRevival or MeteoParis. This prompt identifier should be the
    value of the --gemini_process <ThisPrompt> command line parameter.

    All other options are relative to one particular prompt, and therefore
    prefixed with the corresponding identifier. Under the hood, these
    options are hashes keyed with prompt identifiers:

    "prompt"

      This is the option where you can define your prompt. It is advised to
      test this prompt to have Gemini answer as you wish. For instance,
      Gemini often start its answers to your prompt by: “Sure, here is
      ‘what you've asked for’, and you wouldn't want to spread this
      introduction in your message. In this case, you should write your
      prompt instructing Gemini to not include any introduction.

      You can test your prompt with interactive form to Gemini at
      https://gemini.google.com/app or with spread-revolutionary-date with
      options --test and --targets=Mastodon for example.

      The spread message will be Gemini answer, optionally prepended with a
      configured introduction (see bellow), and ending with hashtags
      #IAGenerated #PromptIdentifier.

      Prompts often need to mention informations relative to today, such as
      the FamousBirthday example below, or it could be that you wanna ask
      Gemni for today's weather, or traffic jams occuring the same day of
      the week as today, etc. As a syntactic sugar, you can insert in
      "prompt" option, any variable prefixed with a dollar sign ($) which
      correspond to a method of DateTime module applied to DateTime-now()>
      object, and it will be replaced by the result of this method in the
      prompt sent to Gemini. For example, in the FamousBirthday example
      below, if run on June 21st, the prompt sent to Gemini would be:

        'Which famous people have their birthday on June 21? Give a list of up to 6 people, then after the list give the unformatted URL of the Wikipedia page of only one of them, no comments and no need for an introduction like "Here are some famous...

      You should be careful that such variables are not interpreted by the
      Shell before calling spread-revolutionary-date, specially if
      specified as command line parameters. You can prevent such
      intepretation by the Shell by enclosing the option in single quotes,
      like the examples above.

    "intro"

README  view on Meta::CPAN


      This option specifies an alternative text to an image added on the
      spread message. If unset, the alternative text will be the name of
      the file specified in "img_path" or "img_url" options.

    "img_url"

      This option allows to add a remote image on the spread message.

    Finally, one word of localization: you don't need it, since 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 i...

    The only place where you should be concerned by localization is when
    you define an introduction to be prepended to Gemini answer. Since it
    is a configured static string, it should be written in the desired
    language, like:

      intro    FamousBirthday      = 'FamousBirthday=Berühmte Personen, die am $day $month_name geboren wurden, im Guten wie im Schlechten:'

    Also, if you use some syntactic sugars relative to methods of DateTime
    module that are localizable, like month_name, you should use the

SIGNATURE  view on Meta::CPAN

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
SHA256 58584c538a460abcb90873f001732356f63761b025b374f0d51142c99d08d938 xt/author/distmeta.t
SHA256 d2bc940493145b3da1e4bf7ac091cd2553dea27364a870868d7984ba3d08fd58 xt/author/eol.t
SHA256 9a33f52d99d271d2fa6a6e49b32648567b81d053e7be3e9d099938d8ea72d38a xt/author/no-tabs.t
SHA256 fb4f17037e9be1f1341245abfd6328425fe644afe21c0865095baefdd0dd8c0b xt/author/pod-coverage.t

TODO  view on Meta::CPAN

  use gettext system.

* Add some new languages.

* Add some new targets to spread to.

* Add some new message makers.

* Add message maker from Gemini

* Allow to configure hash variable to select which prompt to use for Gemini message maker

bin/spread-revolutionary-date  view on Meta::CPAN


  # Prompt user for a message to spread to Mastodon
  $ spread-revolutionary-date \
      --targets=Mastodon \
      --msgmaker=UserPrompt

  # Spread message as command line parameter to
  # Mastodon, Bluesky, Twitter, Liberachat and Freenode
  $ spread-revolutionary-date \
      --msgmaker=UserPrompt \
      --promptuser_default

  # Spread message and image as command line parameter to
  # Mastodon and Bluesky
  $ spread-revolutionary-date \
      --msgmaker=UserPrompt \
      --targets=Mastodon \
      --targets=Bluesky \
      --promptuser_default \
        'This is my message to the world'
      --promptuser_img_path= \
        /my/path/to/image.png
      --promptuser_img_alt= \
        'Alternative text for image'

  # Spread message and image form web as command line parameter to
  # Mastodon and Bluesky
  $ spread-revolutionary-date \
      --msgmaker=UserPrompt \
      --targets=Mastodon \
      --targets=Bluesky \
      --promptuser_default \
        'This is my message to the world'
      --promptuser_img_url= \
        'https://example.com/imgs/my_image.jgp'
      --promptuser_img_alt

  # Spread Téléchat date of the day on Mastodon and BlueSky
  $ spread-revolutionary-date \
      --msgmaker=Telechat \
      --targets=Mastodon \
      --targets=Bluesky

  # Spread Gemini generating an illustrated joke on Mastodon
  # NB: usually prompts are defined in configuration file along
  # with api_key, while --gemini-process is passed on command line
  # to choose which prompt to process
  $ spread-revolutionary-date \
      --targets=Mastodon \
      --msgmaker=Gemini \
      --gemini_api_key=ApiKey \
      --gemini_process=MacronJokeColuche \
      --gemini_prompt 'MacronJokeColuche=Invente-moi une blague \
        dans le style de Coluche sur Emmanuel Macron. Pas besoin \
        de dire "D\'accord, voici une blague" ou "Bien sûr, \
        voici une blague dans le style de Coluche sur Emmanuel \
        Macron" avant la blague.' \
      --gemini_img_path "MacronJokeColuche='/my/path/to/image.png'" \
      --gemini_img_alt "MacronJokeColuche='Caricature de Coluche \
        disant : « C’est l’histoire d’un mec… » avec une caricature \
        de macron'" \

  # Spread Gemini searching for real time weather on Mastodon
  # NB: usually prompts are defined in configuration file along
  # with api_key, while --gemini-process is passed on command line
  # to choose which prompt to process
  $ spread-revolutionary-date \
      --targets=Mastodon \
      --msgmaker=Gemini \
      --gemini_api_key=ApiKey \
      --gemini_process=MeteoParis \
      --gemini_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.' \
      --gemini_search "MeteoParis=1"

  # Spread Gemini generating a list of celebrities with an url
  # prepended by an introdution on Mastodon
  # NB: usually prompts are defined in configuration file along
  # with api_key, while --gemini-process is passed on command line
  # to choose which prompt to process
  $ spread-revolutionary-date \
      --targets=Mastodon \
      --msgmaker=Gemini \
      --gemini_api_key=ApiKey \
      --gemini_process=FamousBirthday \
      --gemini_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 introduction like "Here are some famous people".' \
      --gemini_intro 'FamousBirthday=Famous people born on $month_name \
        $day for better or for worse:'

=head1 CONFIGURATION

Once again: you B<have to> configure C<spread-revolutionary-date> with credentials for registered account on each of the desired targets and also for I<Gemini> message maker, so it can spread the revolutionary date or an IA generated message on behal...

bin/spread-revolutionary-date  view on Meta::CPAN

=head2 General options

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

bin/spread-revolutionary-date  view on Meta::CPAN

=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)

This option can only be specified once, with a value as string valued by a path to an image file on local disk. The C<img_path> option should be defined in the C<[PromptUser]> section of the configuration file. It is only used if L</msgmaker> option ...

=head3 img_alt (for PromptUser)

This option can only be specified once, with a value as string valued by an alternative text to an image file specified by C<img_path> or C<img_url> options. The C<img_alt> option should be defined in the C<[PromptUser]> section of the configuration ...

=head3 img_url (for PromptUser)

This option can only be specified once, with a value as string valued by an external url to a remote image. The C<img_url> option should be defined in the C<[PromptUser]> section of the configuration file. It is only used if L</msgmaker> option is C<...

=head2 Gemini options

If L</msgmaker> option is C<Gemini>, instead of spreading the revolutionary date, requests I<Gemini> AI to generate a text from a prompt.

=head3 api_key

This option can only be specified once, with a value as string: your I<Gemini> API key. You have to get it following instructions on L<https://ai.google.dev/gemini-api/docs/api-key>. The C<api_key> option should be defined in the C<[Gemini]> section ...

=head3 process

This option can only be specified once, with a value as string, telling which L</prompt> and other options below should be send to I<Gemini> AI. The C<process> option should be defined in the C<[Gemini]> section of the configuration file. It is only ...

=head3 prompt

This option can be specified for several prompts, each one with a key as a string, valued by the string configured for L</process> options above, and a value as string valued by the prompt to send to I<Gemini> AI. The C<prompt> option should be defin...

=head3 intro

This option can be specified for several prompts, each one with a key as a string, valued by the string configured for L</process> options above, and a value as string to prepend to I<Gemini> answer. The C<intro> option should be defined in the C<[Ge...

=head3 search

This option can be specified for several prompts, each one with a key as a string, valued by the string configured for L</process> options above, and a true value, telling I<Gemini> AI to use grounded sources (inline supporting links) and I<Google Se...

=head3 img_path (for Gemini)

This option can be specified for several prompts, each one with a key as a string, valued by the string configured for L</process> options above, and a value as string valued by a path to an image file on local disk. The C<img_path> option should be ...

=head3 img_alt (for Gemini)

This option can be specified for several prompts, each one with a key as a string, valued by the string configured for L</process> options above, and a value as string valued by an alternative text to an image file specified by C<img_path> or C<img_u...

=head3 img_url (for Gemini)

This option can be specified for several prompts, each one with a key as a string, valued by the string configured for L</process> options above, and a value as string valued by an external url to a remote image. The C<img_url> option should be defin...

=head1 COMMAND LINE PARAMETERS

Any command line parameter, other than the first three ones below, takes precedence on the corresponding option specified on the confiuration file, see L</CONFIGURATION> above.

=head2 Command line only parameters

=head3 --conf=<file> | -c <file>

Use C<E<lt>fileE<gt>> path as configuration file, instead of the default ones, see L</CONFIGURATION> above.

bin/spread-revolutionary-date  view on Meta::CPAN

=head3 --revolutionarydate_acab | -ra

Same as L</acab> configuration option above.

=head3 --revolutionarydate_wikipedia_link

Same as L</wikipedia_link> configuration option above.

=head2 PromptUser parameters

=head3 --promptuser_default <msg> | -pud <msg>

Same as L</default> configuration option above.

=head3 --promptuser_img_path <path/to/image/file> | -pui </path/to/image/file>

Same as L</img_path (for PromptUser)> configuration option above.

=head3 --promptuser_img_alt <alternative text> | -pua <alternative text>

Same as L</img_alt (for PromptUser)> configuration option above.

=head3 --promptuser_img_url <img_url> | -puu <img_url>

Same as L</img_url> (for PromptUser) configuration option above.

=head2 Gemini parameters

=head3 --gemini_api_key <api key> | -ga <api key>

Same as L</api_key> configuration option above.

=head3 --gemini_process <SomePrompt> | -g <SomePrompt>

Same as L</process> configuration option above.

=head3 --gemini_prompt "<SomePrompt>=<my prompt string>" | -gp "<SomePrompt>=<my prompt string>"

Same as L</process> configuration option above.

=head3 --gemini_intro "<SomePrompt>=<intro msg>" | -gi "<SomePrompt>=<intro msg>"

Same as L</process> configuration option above.

=head3 --gemini_search "<SomePrompt>=1" | -gs "<SomePrompt>=1"

Same as L</process> configuration option above.

bin/spread-revolutionary-date  view on Meta::CPAN

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]
  # See https://ai.google.dev/gemini-api/docs/api-key
  api_key                      = 'GEMINI_API_KEY'
  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...
  intro    FamousBirthday      = 'FamousBirthday=Famous people born on $month_name $day for better or for worse:'

  prompt   MacronJokeColuche   = 'Invente-moi une blague dans le style de Coluche sur Emmanuel Macron. Pas besoin de dire "D\'accord, voici une blague" ou "Bien sûr, voici une blague dans le style de Coluche sur Emmanuel Macron" avant la blague.'
  img_path MacronJokeColuche   = '/usr/local/share/perl/5.32.1/auto/share/dist/App-SpreadRevolutionaryDate/images/coluche_macron.png'
  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...

All other options are relative to one particular prompt, and therefore prefixed with the corresponding identifier. Under the hood, these options are hashes keyed with prompt identifiers:

=over

=item L</prompt>

This is the option where you can define your prompt. It is advised to test this prompt to have I<Gemini> answer as you wish. For instance, I<Gemini> often start its answers to your prompt by: “Sure, here is ‘what you've asked for’, and you woul...

You can test your prompt with interactive form to I<Gemini> at L<https://gemini.google.com/app> or with C<spread-revolutionary-date> with options C<--test> and C<--targets=Mastodon> for example.

The spread message will be I<Gemini> answer, optionally prepended with a configured introduction (see bellow), and ending with hashtags C<#IAGenerated> C<#PromptIdentifier>.

Prompts often need to mention informations relative to today, such as the C<FamousBirthday> example below, or it could be that you wanna ask I<Gemni> for today's weather, or traffic jams occuring the same day of the week as today, etc. As a syntactic...

  'Which famous people have their birthday on June 21? Give a list of up to 6 people, then after the list give the unformatted URL of the Wikipedia page of only one of them, no comments and no need for an introduction like "Here are some famous peopl...

You should be careful that such variables are not interpreted by the C<Shell> before calling C<spread-revolutionary-date>, specially if specified as command line parameters. You can prevent such intepretation by the C<Shell> by enclosing the option i...

=item L</intro>

You may want that the spread message to start with your own introducing words before displaying I<Gemini> answer. You can specify this with the L</intro> option.

Likewise, this option use the same syntactic sugar relative to methods of L<DateTime> module. For example, the message spread on June 21st by the C<FamousBirthday> example bellow, would be something like

bin/spread-revolutionary-date  view on Meta::CPAN

=item L</img_alt>

This option specifies an alternative text to an image added on the spread message. If unset, the alternative text will be the name of the file specified in L</img_path> or L</img_url> options.

=item L</img_url>

This option allows to add a remote image on the spread message.

=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...

etc/sample-spread-revolutionary-date.conf  view on Meta::CPAN

channels      = '#Channel1'
channels      = '#Channel2'
channels      = '#Channel3'

[RevolutionaryDate]
acab

[Gemini]
# See https://ai.google.dev/gemini-api/docs/api-key
api_key                      = 'api_key'
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 introducti...
intro    FamousBirthday  = 'FamousBirthday=Famous people born on $month_name $day for better or for worse:'

prompt   MacronJokeColuche   = 'Invente-moi une blague dans le style de Coluche sur Emmanuel Macron. Pas besoin de dire "D\'accord, voici une blague" ou "Bien sûr, voici une blague dans le style de Coluche sur Emmanuel Macron" avant la blague.'
img_path MacronJokeColuche   = '/usr/local/share/perl/5.32.1/auto/share/dist/App-SpreadRevolutionaryDate/images/coluche_macron.png'
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

lib/App/SpreadRevolutionaryDate/Config.pm  view on Meta::CPAN

    'mastodon_access_token' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'mat'},
    'freenode_nickname' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'fn'},
    'freenode_password' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'fp'},
    'freenode_test_channels' => {ARGCOUNT => ARGCOUNT_LIST, ALIAS => 'ftc'},
    'freenode_channels' => {ARGCOUNT => ARGCOUNT_LIST, ALIAS => 'fc'},
    'liberachat_nickname' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'ln'},
    'liberachat_password' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'lp'},
    'liberachat_test_channels' => {ARGCOUNT => ARGCOUNT_LIST, ALIAS => 'ltc'},
    'liberachat_channels' => {ARGCOUNT => ARGCOUNT_LIST, ALIAS => 'lc'},
    'revolutionarydate_acab' => {ARGCOUNT => ARGCOUNT_NONE, ALIAS => 'ra'},
    'promptuser_default' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'pud'},
    'promptuser_img_path' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'pui'},
    'promptuser_img_alt' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'pua'},
    'promptuser_img_url' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'puu'},
    'gemini_api_key' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'ga'},
    'gemini_process' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'g'},
    'gemini_prompt' => {ARGCOUNT => ARGCOUNT_HASH, ALIAS => 'gp'},
    'gemini_intro' => {ARGCOUNT => ARGCOUNT_HASH, ALIAS => 'gi'},
    'gemini_search' => {ARGCOUNT => ARGCOUNT_HASH, ALIAS => 'gs'},
    'gemini_img_path' => {ARGCOUNT => ARGCOUNT_HASH, ALIAS => 'gip'},
    'gemini_img_alt' => {ARGCOUNT => ARGCOUNT_HASH, ALIAS => 'gia'},
    'gemini_img_url' => {ARGCOUNT => ARGCOUNT_HASH, ALIAS => 'giu'},
    'special_birthday_name' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'bn'},
    'special_birthday_day' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'bd'},
    'special_birthday_month' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'bm'},
    'special_birthday_url' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'bu'},
    'special_birthday_gemini' => {ARGCOUNT => ARGCOUNT_ONE, ALIAS => 'bg'},

lib/App/SpreadRevolutionaryDate/Config.pm  view on Meta::CPAN

  $msgmaker = lc($msgmaker);

  my %msgmaker_args = $self->varlist("^${msgmaker}_", 1);

  # Add acab option for RevolutionaryDate for backward compatibility
  $msgmaker_args{acab} = $self->acab
    if  $msgmaker eq 'revolutionarydate'
        && !$msgmaker_args{acab}
        && $self->acab;

  # Do not prompt if PromptUser default is set
  if ($msgmaker eq 'promptuser') {
    require App::SpreadRevolutionaryDate::MsgMaker::PromptUser;
    if ($msgmaker_args{default} && $msgmaker_args{default} ne App::SpreadRevolutionaryDate::MsgMaker::PromptUser->meta->get_attribute('default')->default) {
      $ENV{PERL_MM_USE_DEFAULT} = 1
    }
  }

  return %msgmaker_args;
}


lib/App/SpreadRevolutionaryDate/Config.pm  view on Meta::CPAN

    --twitter_access_token_secret|tats <token_secret>: define Twitter access token secret
    --liberachat_nickname|-ln <nick>: define Liberachat nickname
    --liberachat_password|-lp <passwd>: define Liberachat password
    --liberachat_test_channels|-ltc <channel_1>  [--liberachat_test_channels|-ltc <channel_2> […--liberachat_test_channels|-ltc <channel_n>]]: define Liberachat channels
    --liberachat_channels|-lc <channel_1>  [--liberachat_channels|-lc <channel_2> […--liberachat_channels|-lc <channel_n>]]: define Liberachat test channels
    --freenode_nickname|-fn <nick>: define Freenode nickname
    --freenode_password|-fp <passwd>: define Freenode password
    --freenode_test_channels|-ftc <channel_1>  [--freenode_test_channels|-ftc <channel_2> […--freenode_test_channels|-ftc <channel_n>]]: define Freenode channels
    --freenode_channels|-fc <channel_1>  [--freenode_channels|-fc <channel_2> […--freenode_channels|-fc <channel_n>]]: define Freenode test channels
    --revolutionarydate_acab | -ra: pretend it is 01:31:20 (default: false)
    --promptuser_default|-pud <msg>: define default message when --msgmaker=PromptUser (default: 'Goodbye old world, hello revolutionary worlds')
    --promptuser_img_path|-pui <path/to/image/file>: define image file path when --msgmaker=PromptUser
    --promptuser_img_alt|-pua <alternative text>: define image alternative text when --msgmaker=PromptUser
    --promptuser_img_url|-puu <https://example.com/imgs/my_image.jgp>: define image external url when --msgmaker=PromptUser
    --gemini_api_key|-ga <msg>: define default message when --msgmaker=PromptUser (default: 'Goodbye old world, hello revolutionary worlds')
    --gemini_process|-g <SomePrompt>: tell which prompt to process --msgmaker=Gemini
    --gemini_prompt|-gp "<SomePrompt>=<my prompt string>": define prompt to request for when --msgmaker=Gemini
    --gemini_intro|-gi "<SomePrompt>=<intro msg>": define introduction message to preprend to response when --msgmaker=Gemini
    --gemini_search|-gs "<SomePrompt>=1": use grounding search results when --msgmaker=Gemini
    --gemini_img_path|-gip "<SomePrompt>=<path/to/image/file>": define image file path when --msgmaker=Gemini
    --gemini_img_alt|-gia "<SomePrompt>=<alternative text>": define image alternative text when --msgmaker=Gemini
    --gemini_img_url|-giu "<SomePrompt>=<https://example.com/imgs/my_image.jgp>": define image external url when --msgmaker=Gemini
USAGE
 exit 0;
}


lib/App/SpreadRevolutionaryDate/MsgMaker/Gemini.pm  view on Meta::CPAN

# This software is Copyright (c) 2019-2026 by Gérald Sédrati.
#
# This is free software, licensed under:
#
#   The GNU General Public License, Version 3, June 2007
#
use 5.014;
use utf8;
package App::SpreadRevolutionaryDate::MsgMaker::Gemini;
$App::SpreadRevolutionaryDate::MsgMaker::Gemini::VERSION = '0.54';
# ABSTRACT: MsgMaker class for L<App::SpreadRevolutionaryDate> to build message with Gemini prompt

use Moose;
with 'App::SpreadRevolutionaryDate::MsgMaker';

use DateTime;
use File::ShareDir ':ALL';
use LWP::UserAgent;
use JSON;

use Locale::TextDomain 'App-SpreadRevolutionaryDate';

lib/App/SpreadRevolutionaryDate/MsgMaker/Gemini.pm  view on Meta::CPAN

  isa => 'Str',
  required => 1,
);

has 'process' => (
  is  => 'ro',
  isa => 'Str',
  required => 1,
);

has 'prompt' => (
  is  => 'ro',
  isa => 'HashRef[Str]',
  required => 1,
);

has 'search' => (
  is  => 'ro',
  isa => 'HashRef[Bool]',
);

lib/App/SpreadRevolutionaryDate/MsgMaker/Gemini.pm  view on Meta::CPAN

);

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 => [
          {
            text => $prompt,
          }
        ],
      }
    ],
  };

  if ($self->search && $self->search->{$self->process}) {
    $payload->{tools} = [
      {
        google_search => {},

lib/App/SpreadRevolutionaryDate/MsgMaker/Gemini.pm  view on Meta::CPAN

et le plus indispensable des devoirs";

__END__

=pod

=encoding UTF-8

=head1 NAME

App::SpreadRevolutionaryDate::MsgMaker::Gemini - MsgMaker class for L<App::SpreadRevolutionaryDate> to build message with Gemini prompt

=head1 VERSION

version 0.54

=head1 METHODS

=head2 compute

Computes replies by Gemini AI given a prompt.

=head1 SEE ALSO

=over

=item L<spread-revolutionary-date>

=item L<App::SpreadRevolutionaryDate>

=item L<App::SpreadRevolutionaryDate::Config>

lib/App/SpreadRevolutionaryDate/MsgMaker/PromptUser.pm  view on Meta::CPAN

# This software is Copyright (c) 2019-2026 by Gérald Sédrati.
#
# This is free software, licensed under:
#
#   The GNU General Public License, Version 3, June 2007
#
use 5.014;
use utf8;
package App::SpreadRevolutionaryDate::MsgMaker::PromptUser;
$App::SpreadRevolutionaryDate::MsgMaker::PromptUser::VERSION = '0.54';
# ABSTRACT: MsgMaker class for L<App::SpreadRevolutionaryDate> to build message by prompting user

use Moose;
with 'App::SpreadRevolutionaryDate::MsgMaker';

use open qw(:std :encoding(UTF-8));
use IO::Prompt::Hooked;
use File::Spec;
use File::Basename;
use File::Temp qw/tempfile/;
use LWP::UserAgent;

lib/App/SpreadRevolutionaryDate/MsgMaker/PromptUser.pm  view on Meta::CPAN

    $self->img_alt(ucfirst(fileparse($self->img_path, qr/\.[^.]*/))) unless $self->img_alt;
    $confirm_question =  __x("with image file"). ' ' . $self->{img_path} . ' (alt:' . $self->img_alt . '), ' . $confirm_question;
  } elsif ($self->img_url) {
    $self->img_alt(ucfirst(fileparse($self->img_url, qr/\.[^.]*/))) unless $self->img_alt;
    $confirm_question =  __x("with image from url:"). ' ' . $self->{img_url} . ' (alt:' . $self->img_alt . '), ' . $confirm_question;
  }

  my $confirm = $confirm_nok;
  my $msg;
  while (defined $confirm && $confirm !~ qr($confirm_ok)) {
    $msg = prompt($question, $self->default);
    $confirm = prompt(
      message  => $confirm_intro . ' "' . $msg . '", ' . $confirm_question,
      default  => $confirm_ok,
      validate => qr/^[$confirm_ok$confirm_nok]$/i,
      escape   => qr/^$confirm_abort$/,
      error    => $confirm_error,
      tries    => 2,
    );
  }
  die "$abort\n" unless defined $confirm && $confirm =~ qr($confirm_ok);

lib/App/SpreadRevolutionaryDate/MsgMaker/PromptUser.pm  view on Meta::CPAN

et le plus indispensable des devoirs";

__END__

=pod

=encoding UTF-8

=head1 NAME

App::SpreadRevolutionaryDate::MsgMaker::PromptUser - MsgMaker class for L<App::SpreadRevolutionaryDate> to build message by prompting user

=head1 VERSION

version 0.54

=head1 METHODS

=head2 compute

Prompts user for the message to be spread. Takes no argument. Returns message as string, ready to be spread.

t/config.t  view on Meta::CPAN



@ARGV  = ('--msgmaker=Gemini', '--test');
seek DATA, $data_start, 0;
eval { my $spread_gemini_no_process = App::SpreadRevolutionaryDate->new(\*DATA); };
chomp $@;
like($@, qr/Attribute \(process\) does not pass the type constraint because: Validation failed for 'Str' with value undef at constructor App::SpreadRevolutionaryDate::MsgMaker::Gemini::new/, 'Gemini without process option');

@ARGV  = ('--msgmaker=Gemini', '--test', '--gemini_process=NoPrompt');
seek DATA, $data_start, 0;
eval { my $spread_gemini_no_prompt = App::SpreadRevolutionaryDate->new(\*DATA); };
chomp $@;
like($@, qr/Process NoPrompt has no prompt/, 'Gemini without process option');

@ARGV  = ('--msgmaker=Gemini', '--test', '--gemini_process=AnniversairePeople');
seek DATA, $data_start, 0;
my $spread_gemini = App::SpreadRevolutionaryDate->new(\*DATA);
is($spread_gemini->config->gemini_process, 'AnniversairePeople', 'Gemini process option value');
my @gemini_prompt_keys = sort keys %{$spread_gemini->config->gemini_prompt};
is_deeply(\@gemini_prompt_keys, ['AnniversairePeople', 'MacronJokeColuche'], 'Gemini prompt option keys');
like($spread_gemini->config->gemini_prompt->{AnniversairePeople}, qr/^Quelles sont les personalit.s ayant leurs anniversaire le /, 'Gemini promt option value');
ok($spread_gemini->config->gemini_search->{MacronJokeColuche}, 'Gemini search set');
ok(!$spread_gemini->config->gemini_search->{AnniversairePeople}, 'Gemini search unset');
is($spread_gemini->config->gemini_img_path->{MacronJokeColuche}, '~/Images/coluche_macron.png', 'Gemini img path');
is($spread_gemini->config->gemini_img_url->{MacronJokeColuche}, 'https://upload.wikimedia.org/wikipedia/commons/3/38/Emmanuel_Macron_-_Caricature_%2840366024295%29.jpg', 'Gemini img url');
is($spread_gemini->config->gemini_img_alt->{MacronJokeColuche}, 'Caricature de Coluche disant : « C’est l’histoire d’un mec… » avec une caricature de macron', 'Gemini img alt');
__DATA__

[bluesky]
# Get these values from https://bsky.app/
identifier = 'Identifier'

t/config.t  view on Meta::CPAN

nickname      = 'NickName'
password      = 'Password'
test_channels = '#TestChannel1'
test_channels = '#TestChannel2'
channels      = '#Channel1'
channels      = '#Channel2'
channels      = '#Channel3'

[Gemini]
api_key                    = APIKEY
prompt AnniversairePeople  = "Quelles sont les personalités ayant leurs anniversaire le $day $month ? Donne une liste d'au maximum 6 personnes, puis après la liste donne l'URL sans formattage de la fiche wikipédia d'une seule d'entre elles, ne com...
prompt MacronJokeColuche   = "Je veux envoyer chaque jour une blague différente sur les réseaux sociaux Mastodon et Bluesky. La blague doit être chaque fois suffisamment différente, toujours dans le style de Coluche et toujours sur Emmanuel Macro...
search MacronJokeColuche   = 1
img_path MacronJokeColuche = '~/Images/coluche_macron.png'
img_url MacronJokeColuche  = 'https://upload.wikimedia.org/wikipedia/commons/3/38/Emmanuel_Macron_-_Caricature_%2840366024295%29.jpg'
img_alt MacronJokeColuche  = 'Caricature de Coluche disant : « C’est l’histoire d’un mec… » avec une caricature de macron'

t/promptuser.t  view on Meta::CPAN

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

xt/author/eol.t  view on Meta::CPAN

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

xt/author/no-tabs.t  view on Meta::CPAN

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



( run in 0.782 second using v1.01-cache-2.11-cpan-0b5f733616e )