App-Phoebe

 view release on metacpan or  search on metacpan

script/phoebe-ctl  view on Meta::CPAN


=item B<--log=>I<NUMBER>

This is the log level to use. 1 only prints errors; 2 also prints warnings (this
is the default); 3 prints any kind of information; 4 prints all sorts of info
the developer wanted to see as they were fixing bugs.

=back

=head2 Commands

B<phoebe-ctl help>

This is what you're reading right now.

B<phoebe-ctl update-changes>

This command looks at all the pages in the F<page> directory and generates new
entries for your changes log into F<changes.log>.

B<phoebe-ctl erase-page>

This command removes pages from the F<page> directory, removes all the kept
revisions in the F<keep> directory, and all the mentions in the F<change.log>.
Use this if spammers and vandals created page names you want to eliminate.

B<phoebe-ctl html-export> [B<--source=>F<subdirectory> ...]
[B<--target=>F<directory>] [B<--no-extension>]

This command converts all the pages in the subdirectories provided to HTML and
writes the HTML files into the target directory. The subdirectories must exist
inside your wiki data directory. The default wiki data directory is F<wiki> and
the default source subdirectory is undefined, so the actual files to be
processed are F<wiki/page/*.gmi>; if you're using virtual hosting, the
subdirectory might be your host name; if you're using spaces, those need to be
appended as well.

Example:

    phoebe-ctl html-export --wiki_dir=/home/alex/phoebe \
      --source=transjovian.org \
      --source=transjovian.org/phoebe \
      --source=transjovian.org/gemini \
      --source=transjovian.org/titan \
      --target=/home/alex/transjovian.org

This will create HTML files in F</home/alex/transjovian.org>,
F</home/alex/transjovian.org/phoebe>, F</home/alex/transjovian.org/gemini>, and
F</home/alex/transjovian.org/titan>.

Note that the I<links> in these HTML files do not include the F<.html> extension
(e.g. C</test>), so this relies on your web server doing the right thing: if a
visitor requests C</test> the web server must serve F</test.html>. If that
doesn't work, perhaps using C<--no-extension> is your best bet: the HTML files
will be written without the F<.html> extension. This should also work for local
browsing, although it does look strange, all those pages with the F<.html>
extension.

B<phoebe-ctl log hits>

If you are using L<App::Phoebe::SpeedBump>, you can find the number of blocked
requests. First, make you you are using the module in your config file:

    use App::Phoebe::DebugIpNumbers;

Make sure you start or start C<phoebe> with C<--log_level=info> or
C<--log_level=debug>. First generate a log file. Better to zip it up and analyse
it elsewhere. This can be pretty big!

    journalctl --unit=phoebe | gzip > phoebe.log.gz

Here's how to see how many requests are blocked:

    zcat phoebe.log.gz | script/phoebe-ctl log hits | head

B<phoebe-ctl log requests [IP number]>

If you are logging IP numbers, this command will offer a little summary. In your
config file, you need the following (or start C<phoebe> with
C<--log_level=debug>):

    package App::Phoebe;
    use Modern::Perl;
    our ($log);
    $log->level('debug');

And you need L<App::Phoebe::DebugIpNumbers>, of course:

    use App::Phoebe::DebugIpNumbers;

Example basic usage, feeding it the journal kept by C<systemd>, giving you the
most active IP numbers:

    journalctl --unit phoebe | phoebe-ctl log hits | head

Giving you a summary of the 20 most popular requests (Gopher selectors, Gemini
URLs, or web requests):

    journalctl --unit phoebe | phoebe-ctl log requests

The same, but limited to a particular IP number:

    journalctl --unit phoebe | phoebe-ctl log requests 201.159.58.193

=cut

package Gemini::Wiki::Control;
use Modern::Perl '2018';
use File::Slurper qw(read_dir read_text write_text);
use Encode qw(encode_utf8 decode_utf8);
use Getopt::Long;
use Pod::Text;
use File::Path qw(remove_tree);
use POSIX qw(round);
use utf8;

binmode(STDOUT, ":utf8");

my $log = 2;
my $dir = "./wiki";
my @sources;
my $target;
my $no_extension;
GetOptions (
  "log=i" => \$log,
  "wiki_dir=s" => \$dir,
  "source=s" => \@sources,
  "target=s" => \$target,
  "no-extension" => \$no_extension, );
@sources = ("") unless @sources;

my $subcommands = {

script/phoebe-ctl  view on Meta::CPAN

  my @lines;
  my $list;
  my $code;
  for (split /\n/, quote_html($text)) {
    if (/^```(?:type=([a-z]+))?/) {
      my $type = $1||"default";
      if ($code) {
	push @lines, "</pre>";
	$code = 0;
      } else {
	push @lines, "</ul>" if $list;
	$list = 0;
	push @lines, "<pre class=\"$type\">";
	$code = 1;
      }
    } elsif ($code) {
      push @lines, $_;
    } elsif (/^\* +(.*)/) {
      push @lines, "<ul>" unless $list;
      push @lines, "<li>$1";
      $list = 1;
    } elsif (my ($url, $text) = /^=&gt;\s*(\S+)\s*(.*)/) { # quoted HTML!
      push @lines, "<ul>" unless $list;
      $text ||= $url;
      push @lines, "<li><a href=\"$url\">$text</a>";
      $list = 1;
    } elsif (/^(#{1,6})\s*(.*)/) {
      push @lines, "</ul>" if $list;
      $list = 0;
      my $level = length($1);
      push @lines, "<h$level>$2</h$level>";
    } elsif (/^&gt;\s*(.*)/) { # quoted HTML!
      push @lines, "</ul>" if $list;
      $list = 0;
      push @lines, "<blockquote>$1</blockquote>";
    } else {
      push @lines, "</ul>" if $list;
      $list = 0;
      push @lines, "<p>$_";
    }
  }
  push @lines, "</pre>" if $code;
  push @lines, "</ul>" if $list;
  return join("\n", @lines);
}

sub log {
  my ($type, $filter) = @ARGV;
  if (not $type or $type ne "hits" and $type ne "requests") {
    die "No known log type (one of: hits, requests)\n";
  }
  my ($ip, %ip, %block, $n, $blocks, %request);
  while (<STDIN>) {
    if (/\[debug\] Visitor: (\S+)$/) {
      $ip = $1;
      $ip{$ip}++;
    } elsif ((not $filter or $ip and $filter eq $ip) and /\[info\] Looking at (.*)/) {
      $request{$1}++;
      $n++;
      $ip //= "anon";
    } elsif ($ip and (not $filter or $filter eq $ip) and /\[info\] (Net range (\S+) is blocked|IP is blocked)/) {
      $block{$ip}++;
      $blocks++;
    }
  }
  die("No hits (you must run the server on --log_level=info or --log_level=debug\n") unless $n;
  say("Total hits:   $n");
  say("Total blocks: $blocks");
  say("Bot level:    " . round($blocks / $n * 100) . "%") if $blocks;
  say("-" x length("Total blocks: $blocks"));
  if ($type eq "hits") {
    printf("%5s %4s%% %5s %s\n", "Hits", "Hits", "Block", "IP Number");
    for (sort { $ip{$b} <=> $ip{$a} } keys %ip) {
      printf("%5d %4d%% %4d%% %s\n", $ip{$_}, int(100*$ip{$_}/$n), exists $block{$_} ? int(100*$block{$_}/$n) : 0, $_);
    }
  } elsif ($type eq "requests") {
    printf("%5s %4s%% %s\n", "Hits", "Hits", "Request");
    for (sort { $request{$b} <=> $request{$a} } keys %request) {
      printf("%5d %4d%% %s\n", $request{$_}, int(100*$request{$_}/$n), $_);
    }
  }
}



( run in 1.041 second using v1.01-cache-2.11-cpan-97f6503c9c8 )