The Perl Advent Calendar needs more articles for 2022. Submit your idea today!


App::Phoebe::Oracle - an anonymous question asking game


By default, Phoebe creates a wiki editable by all. With this extension, the /oracle space turns into a special site: if you have a client certificate, you can pose questions and get answers.

When you ask a question, you can delete any answers on it, and the question itself. Once it has gotten three answers, it is hidden from view and only you can decide wether to delete it, or whether to publish it. If the question is no longer waiting for answers, deleting every answer deletes the question, too.

You can only answer questions not your own. You can answer every question just once (even if you or the question asker deletes your answer, there is no going back). You can delete your answer. If the question is no longer waiting for answers, deleting the last answer deletes the question, too.

Simply add it to your config file. If you are virtual hosting, name the host or hosts for your capsules.

    package App::Phoebe::Oracle;
    use Modern::Perl;
    our @oracle_hosts = qw(;
    use App::Phoebe::Oracle;

If you don't want to use /oracle for the game, you can change it:

    our $oracle_space = 'truth';

If you want to change the maximu number of answers that a question may have:

    our $max_answers = 5;

If you want to notify Antenna whenever a new question has been asked:

    use App::Phoebe qw($log);
    use IO::Socket::SSL;
    # a very simple Gemini client
    sub query {
      my $url = shift;
      my($scheme, $authority, $path, $query, $fragment) =
        $url =~ m|(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(\S*))?|;
      my ($host, $port) = split(/:/, $authority);
      my $socket = IO::Socket::SSL->new(
        PeerHost => $host, PeerPort => $port||1965,
        # don't verify the server certificate
        SSL_verify_mode => SSL_VERIFY_NONE, );
      local $/ = undef; # slurp
      return <$socket>;
    # wrap the save_data sub in our own code
    *old_save_oracle_data = \&App::Phoebe::Oracle::save_data;
    *App::Phoebe::Oracle::save_data = \&new_save_oracle_data;
    # call Antenna after saving
    sub new_save_oracle_data {
      my $gemlog = "gemini://";
      my $res = query("gemini://$gemlog");
      my ($code) = $res =~ /^(\d+)/;
      $log->info("Antenna: $code");