<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wikimirror.piraten.tools/wiki/index.php?action=history&amp;feed=atom&amp;title=Benutzer%3ADrahflow%27s_Bot%2FSource</id>
	<title>Benutzer:Drahflow's Bot/Source - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wikimirror.piraten.tools/wiki/index.php?action=history&amp;feed=atom&amp;title=Benutzer%3ADrahflow%27s_Bot%2FSource"/>
	<link rel="alternate" type="text/html" href="https://wikimirror.piraten.tools/wiki/index.php?title=Benutzer:Drahflow%27s_Bot/Source&amp;action=history"/>
	<updated>2026-06-01T13:04:52Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Piratenwiki Mirror</subtitle>
	<generator>MediaWiki 1.35.14</generator>
	<entry>
		<id>https://wikimirror.piraten.tools/wiki/index.php?title=Benutzer:Drahflow%27s_Bot/Source&amp;diff=55639822&amp;oldid=prev</id>
		<title>imported&gt;Drahflow's Bot: Mich selbst hochladen</title>
		<link rel="alternate" type="text/html" href="https://wikimirror.piraten.tools/wiki/index.php?title=Benutzer:Drahflow%27s_Bot/Source&amp;diff=55639822&amp;oldid=prev"/>
		<updated>2011-02-04T00:03:38Z</updated>

		<summary type="html">&lt;p&gt;&lt;a href=&quot;/Benutzer:Drahflow%27s_Bot&quot; title=&quot;Benutzer:Drahflow&amp;#039;s Bot&quot;&gt;Mich selbst&lt;/a&gt; hochladen&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;  &amp;lt;nowiki&amp;gt;#!/usr/bin/perl&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
use MediaWiki::Bot;&lt;br /&gt;
use Data::Dumper;&lt;br /&gt;
use LWP;&lt;br /&gt;
use LWP::UserAgent;&lt;br /&gt;
use Encode;&lt;br /&gt;
use URI::Escape;&lt;br /&gt;
use Storable qw(nstore retrieve);&lt;br /&gt;
use Carp;&lt;br /&gt;
&lt;br /&gt;
$SIG{__DIE__} = sub { confess; };&lt;br /&gt;
&lt;br /&gt;
use encoding 'utf8';&lt;br /&gt;
&lt;br /&gt;
my $wiki;&lt;br /&gt;
my $lwp;&lt;br /&gt;
&lt;br /&gt;
my $WIKINAME = $ARGV[0] or die &amp;quot;usage: ./bot.pl &amp;lt;Wiki&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
my $conf;&lt;br /&gt;
&lt;br /&gt;
if($WIKINAME eq &amp;quot;AK&amp;quot;) {&lt;br /&gt;
  $conf = {&lt;br /&gt;
    'wiki' =&amp;gt; { 'host' =&amp;gt; 'wiki.vorratsdatenspeicherung.de', 'path' =&amp;gt; '/' },&lt;br /&gt;
    'bot' =&amp;gt; { 'user' =&amp;gt; 'Drahflow\'s Bot', 'pass' =&amp;gt; 'geheim' },&lt;br /&gt;
  };&lt;br /&gt;
} elsif($WIKINAME eq &amp;quot;Piraten&amp;quot;) {&lt;br /&gt;
  $conf = {&lt;br /&gt;
    'wiki' =&amp;gt; { 'host' =&amp;gt; 'wiki.piratenpartei.de', 'path' =&amp;gt; 'wiki/' },&lt;br /&gt;
    'bot' =&amp;gt; { 'user' =&amp;gt; 'Drahflow\'s Bot', 'pass' =&amp;gt; 'geheim' },&lt;br /&gt;
  };&lt;br /&gt;
} else {&lt;br /&gt;
  die &amp;quot;Unknown wiki: $WIKINAME&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub cycleConnection {&lt;br /&gt;
  $wiki-&amp;gt;logout() if($wiki);&lt;br /&gt;
&lt;br /&gt;
  $wiki = MediaWiki::Bot-&amp;gt;new({&lt;br /&gt;
    'assert' =&amp;gt; 'user',&lt;br /&gt;
    'agent' =&amp;gt; &amp;quot;Drahflow's Wiki Bot&amp;quot;,&lt;br /&gt;
    'protocol' =&amp;gt; 'http',&lt;br /&gt;
    'host' =&amp;gt; $conf-&amp;gt;{'wiki'}-&amp;gt;{'host'},&lt;br /&gt;
    'path' =&amp;gt; $conf-&amp;gt;{'wiki'}-&amp;gt;{'path'},&lt;br /&gt;
    'login_data' =&amp;gt; {&lt;br /&gt;
      'username' =&amp;gt; $conf-&amp;gt;{'bot'}-&amp;gt;{'user'},&lt;br /&gt;
      'password' =&amp;gt; $conf-&amp;gt;{'bot'}-&amp;gt;{'pass'}&lt;br /&gt;
    },&lt;br /&gt;
    'debug' =&amp;gt; 1000,&lt;br /&gt;
  }) or die &amp;quot;Wiki init failed&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  $lwp = LWP::UserAgent-&amp;gt;new();&lt;br /&gt;
  $lwp-&amp;gt;agent(&amp;quot;Drahflow's Wiki Bot&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
cycleConnection();&lt;br /&gt;
&lt;br /&gt;
while(my $command = &amp;lt;STDIN&amp;gt;) {&lt;br /&gt;
  chomp $command;&lt;br /&gt;
  last if($command eq &amp;quot;q&amp;quot; or $command eq &amp;quot;quit&amp;quot;);&lt;br /&gt;
  print &amp;quot;len: &amp;quot; . length($command) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  my $force = 0;&lt;br /&gt;
  if ($command =~ /^!(.*)/) {&lt;br /&gt;
    $force = 1;&lt;br /&gt;
    $command = $1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $error;&lt;br /&gt;
  do {&lt;br /&gt;
    print &amp;quot;executing: $command\n&amp;quot;;&lt;br /&gt;
    eval {&lt;br /&gt;
      dumpContent($1) if($command =~ /^DUMP ([^|]*)$/);&lt;br /&gt;
      execTest() if($command eq 'TEST');&lt;br /&gt;
      uploadSource() if($command eq 'CUPLOAD');&lt;br /&gt;
      cleanupRedirect($1, $2, $3? 1: 0) if($command =~ /^CREDIR ([^|]*)\|?((?:del)?)\|?((?:auto)?)$/);&lt;br /&gt;
      cleanupDoubleRedirect() if($command =~ /^CDBLREDIR$/);&lt;br /&gt;
      checkout($1) if($command =~ /^MVOUT ([^|]*)$/);&lt;br /&gt;
      checkin($1, $2) if($command =~ /^MVIN ([^|]*)\|?([^|]*)$/);&lt;br /&gt;
      syncin($1, $2, $3) if($command =~ /^MVSYN ([^|]*)\|?([^|]*)\|?([^|]*)$/);&lt;br /&gt;
      storein($1, $2) if($command =~ /^MVSTORE ([^|]*)\|([^|]*)$/);&lt;br /&gt;
      copyout($1) if($command =~ /^GET ([^|]*)$/);&lt;br /&gt;
      masscopyout($1,$2) if($command =~ /^MGET ([^|]*)\|?((?:follow)?)$/);&lt;br /&gt;
      fetchCategoryMatrix($1, $2) if($command =~ /^GETC ([^|]*)\|(.*)$/);&lt;br /&gt;
      checkToDoUsage() if($command =~ /^QTODO$/);&lt;br /&gt;
      checkLanguageSync() if($command =~ /^QLANG$/);&lt;br /&gt;
      moveCategory($1, $2) if($command =~ /^CMV ([^|]*)\|?([^|]*)$/);&lt;br /&gt;
      addCategories($1, $2) if($command =~ /^CADD (.*)\|\|(.*)$/);&lt;br /&gt;
      putCategoryMatrix($1, $2, $3) if($command =~ /^CPUT ([^|]*)(?:\|([^|]+))?(?:\|(auto|ask))?$/);&lt;br /&gt;
      pirateBoardUpdate() if($command =~ /^CPP$/);&lt;br /&gt;
    };&lt;br /&gt;
    $error = $@;&lt;br /&gt;
    print $error if $error&lt;br /&gt;
  } while ($error and $force);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$wiki-&amp;gt;logout();&lt;br /&gt;
&lt;br /&gt;
sub loadSure {&lt;br /&gt;
  my ($name, $mode) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no mode given&amp;quot; unless $mode;&lt;br /&gt;
&lt;br /&gt;
  my $content = $wiki-&amp;gt;get_text($name);&lt;br /&gt;
  unless(defined $content) {&lt;br /&gt;
    die &amp;quot;could not load $name&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Page $name loaded.\n&amp;quot;;&lt;br /&gt;
  return $content;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub loadCategorySure {&lt;br /&gt;
  my ($name) = @_;&lt;br /&gt;
&lt;br /&gt;
  unless($name =~ /Kategorie:|Category:/) {&lt;br /&gt;
    die &amp;quot;category name must be given with prefix&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $req = HTTP::Request-&amp;gt;new(&lt;br /&gt;
    'GET' =&amp;gt; 'http://' . $conf-&amp;gt;{'wiki'}-&amp;gt;{'host'} . '/' . $name . '?redirect=no');&lt;br /&gt;
  my $res = $lwp-&amp;gt;request($req);&lt;br /&gt;
&lt;br /&gt;
  if(not $res-&amp;gt;is_success()) {&lt;br /&gt;
    die &amp;quot;could not load $name&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my ($subcatsPart) = $res-&amp;gt;content() =~ /\n&amp;lt;h2&amp;gt;Unterkategorien(.*?)\n&amp;lt;h2/s;&lt;br /&gt;
  my ($articlesPart) = $res-&amp;gt;content() =~ /\n&amp;lt;h2&amp;gt;Seiten in der Kategorie(.*?)\nVon/s;&lt;br /&gt;
&lt;br /&gt;
  my $subcats = [];&lt;br /&gt;
  my $articles = [];&lt;br /&gt;
&lt;br /&gt;
  while(defined $subcatsPart and $subcatsPart =~ s/.*?&amp;lt;a href=&amp;quot;\/([^&amp;quot;]+)&amp;quot; title=&amp;quot;([^&amp;quot;]+)&amp;quot;&amp;gt;//) {&lt;br /&gt;
    push @$subcats, $2;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while(defined $articlesPart and $articlesPart =~ s/.*?&amp;lt;a href=&amp;quot;\/([^&amp;quot;]+)&amp;quot; title=&amp;quot;([^&amp;quot;]+)&amp;quot;&amp;gt;//) {&lt;br /&gt;
    push @$articles, $2;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Category $name loaded.\n&amp;quot;;&lt;br /&gt;
  return $articles, $subcats;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub looksOffLimit {&lt;br /&gt;
  my ($name) = @_;&lt;br /&gt;
&lt;br /&gt;
  my $result = (&lt;br /&gt;
    $name =~ /Ortsgruppe/ or&lt;br /&gt;
    $name =~ /^Benutzer/ or&lt;br /&gt;
    $name =~ /^Presse:/&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub saveSure {&lt;br /&gt;
  my ($name, $text, $summary, $minor) = @_;&lt;br /&gt;
&lt;br /&gt;
  if(looksOffLimit($name)) {&lt;br /&gt;
    askConfirmation(&amp;quot;Page &amp;quot; . $name . &amp;quot; looks like it should be left alone&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no summary given&amp;quot; unless $summary;&lt;br /&gt;
&lt;br /&gt;
  $wiki-&amp;gt;edit({&lt;br /&gt;
      'page' =&amp;gt; $name,&lt;br /&gt;
      'text' =&amp;gt; $text,&lt;br /&gt;
      'summary' =&amp;gt; $summary,&lt;br /&gt;
      'is_minor' =&amp;gt; $minor? 1: 0,&lt;br /&gt;
  }) or die &amp;quot;could not save &amp;quot; . $name;&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Page &amp;quot; . $name . &amp;quot; saved.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub askConfirmation {&lt;br /&gt;
  my ($message) = @_;&lt;br /&gt;
&lt;br /&gt;
  while(1) {&lt;br /&gt;
    print &amp;quot;==&amp;gt; $message, continue [N/y]\n&amp;quot;;&lt;br /&gt;
    my $answer = &amp;lt;STDIN&amp;gt;;&lt;br /&gt;
    chomp $answer;&lt;br /&gt;
    if($answer eq '' or $answer eq 'n') {&lt;br /&gt;
      die &amp;quot;User confirmation failed.&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    if($answer eq 'y') {&lt;br /&gt;
      last;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub dumpContent {&lt;br /&gt;
  my ($name) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no name given&amp;quot; unless $name;&lt;br /&gt;
&lt;br /&gt;
  my $text = loadSure($name, &amp;quot;r&amp;quot;);&lt;br /&gt;
  print Dumper($text);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub execTest {&lt;br /&gt;
  my $text = loadSure('Benutzer:Drahflow/Sandkasten', &amp;quot;rw&amp;quot;);&lt;br /&gt;
  print Dumper($text);&lt;br /&gt;
  saveSure(&lt;br /&gt;
    'Benutzer:Drahflow/Sandkasten',&lt;br /&gt;
    $text . 'Minimaler Testlauf',&lt;br /&gt;
    'Testing [[Benutzer:Drahflow]]\'s Bot',&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub uploadSource {&lt;br /&gt;
  open SRC, '&amp;lt;', 'bot.pl' or die &amp;quot;cannot open bot.pl: $!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  my $text = '  &amp;lt;no' . 'wiki&amp;gt;' .&lt;br /&gt;
    (join '', map { s/'pass' =&amp;gt; 'geheim']*'/'pass' =&amp;gt; 'geheim'/; $_ } &amp;lt;SRC&amp;gt;) .&lt;br /&gt;
  '&amp;lt;/no' . 'wiki&amp;gt;';&lt;br /&gt;
  close SRC;&lt;br /&gt;
&lt;br /&gt;
  saveSure(&lt;br /&gt;
    'Benutzer:Drahflow\'s Bot/Source',&lt;br /&gt;
    $text,&lt;br /&gt;
    '[[Benutzer:Drahflow\'s Bot|Mich selbst]] hochladen'&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub fetchIncoming {&lt;br /&gt;
  my ($name) = @_;&lt;br /&gt;
&lt;br /&gt;
  my @incoming = map { $_-&amp;gt;{'title'} } $wiki-&amp;gt;what_links_here($name);&lt;br /&gt;
&lt;br /&gt;
  print Dumper(\@incoming);&lt;br /&gt;
&lt;br /&gt;
  return @incoming;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub cleanupRedirect {&lt;br /&gt;
  my ($name, $del, $auto) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no name given&amp;quot; unless $name;&lt;br /&gt;
&lt;br /&gt;
  my $content = loadSure($name, &amp;quot;r&amp;quot;);&lt;br /&gt;
  $content =~ m!#(?:redirect|weiterleitung):? ?\[\[([^\]|]+)( ?\|([^\]]+))?\]\]!i or die &amp;quot;could not find redirect&amp;quot;;&lt;br /&gt;
  my ($redirect, undef, $redirectDisplay) = ($1, $2, $3);&lt;br /&gt;
  $redirectDisplay = $name unless defined $redirectDisplay;&lt;br /&gt;
  $redirectDisplay =~ s/_/ /g;&lt;br /&gt;
  print &amp;quot;Redirect to: $redirect, Display: $redirectDisplay\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  my $fix = sub {&lt;br /&gt;
    my ($in) = @_;&lt;br /&gt;
&lt;br /&gt;
    return if($auto and looksOffLimit($in));&lt;br /&gt;
&lt;br /&gt;
    my $content = loadSure($in, &amp;quot;rw&amp;quot;);&lt;br /&gt;
    my $any = 0;&lt;br /&gt;
    my $mask = $name;&lt;br /&gt;
    $mask =~ s/[ _]/[ _]/g;&lt;br /&gt;
    $mask =~ s/\(/\\(/g;&lt;br /&gt;
    $mask =~ s/\)/\\)/g;&lt;br /&gt;
    $mask =~ s/\\/\\\\/g;&lt;br /&gt;
    while($content =~ m!\[\[$mask(#[^ ]*)?( ?\|([^\]]+))?\]\]!s) {&lt;br /&gt;
      my ($anchor, undef, $display) = ($1, $2, $3);&lt;br /&gt;
      if(not defined $anchor) {&lt;br /&gt;
        $anchor = '';&lt;br /&gt;
      }&lt;br /&gt;
      if(not defined $display) {&lt;br /&gt;
        $display = $redirectDisplay;&lt;br /&gt;
      }&lt;br /&gt;
      print &amp;quot;Displayname: $display\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
      $content =~ s!\[\[$mask(#[^ ]*)?( ?(\|[^\]]+)?)\]\]![[$redirect$anchor\|$display]]!;&lt;br /&gt;
      print &amp;quot;Link on $in fixed.\n&amp;quot;;&lt;br /&gt;
      ++$any;&lt;br /&gt;
    }&lt;br /&gt;
    if($any) {&lt;br /&gt;
      unless($auto) {&lt;br /&gt;
        askConfirmation(&amp;quot;Page $in will be saved&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      saveSure(&lt;br /&gt;
        $in,&lt;br /&gt;
        $content,&lt;br /&gt;
        &amp;quot;Weiterleitungs-Cleanup, Link von $name auf $redirect verbogen&amp;quot;&lt;br /&gt;
      );&lt;br /&gt;
    } else {&lt;br /&gt;
      if($auto) {&lt;br /&gt;
        warn &amp;quot;incoming link not found&amp;quot; if(not $any);&lt;br /&gt;
      } else {&lt;br /&gt;
        die &amp;quot;incoming link not found&amp;quot; if(not $any);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  my @incoming = fetchIncoming($name);&lt;br /&gt;
  my $templateFixed = 0;&lt;br /&gt;
  foreach my $in (&lt;br /&gt;
      sort { looksOffLimit($a) &amp;lt;=&amp;gt; looksOffLimit($b) }&lt;br /&gt;
      grep { $_ =~ /^Vorlage:/ }&lt;br /&gt;
      @incoming) {&lt;br /&gt;
    &amp;amp;$fix($in);&lt;br /&gt;
    $templateFixed = 1;&lt;br /&gt;
  }&lt;br /&gt;
  if($templateFixed) {&lt;br /&gt;
    cycleConnection();&lt;br /&gt;
    @incoming = fetchIncoming($name);&lt;br /&gt;
  }&lt;br /&gt;
  foreach my $in (&lt;br /&gt;
      sort { looksOffLimit($a) &amp;lt;=&amp;gt; looksOffLimit($b) }&lt;br /&gt;
      grep { $_ !~ /^Vorlage:/ }&lt;br /&gt;
      @incoming) {&lt;br /&gt;
    &amp;amp;$fix($in);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if($del) {&lt;br /&gt;
    $content = loadSure($name, &amp;quot;rw&amp;quot;);&lt;br /&gt;
    if($content =~ m!^#redirect ?\[\[$redirect\]\]$!si) {&lt;br /&gt;
      $content .= &amp;quot;\n{{Vorlage:Drahflow/Löschen/Weiterleitung}}&amp;quot;;&lt;br /&gt;
      print &amp;quot;Inserted deletion remark.\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    askConfirmation(&amp;quot;Page $name will be saved&amp;quot;);&lt;br /&gt;
    saveSure(&lt;br /&gt;
      $name,&lt;br /&gt;
      $content,&lt;br /&gt;
      &amp;quot;Weiterleitungs-Cleanup, Weiterleitung zum Löschen eingetragen&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub cleanupDoubleRedirect {&lt;br /&gt;
  my $req = HTTP::Request-&amp;gt;new(&lt;br /&gt;
    'GET' =&amp;gt; 'http://' . $conf-&amp;gt;{'wiki'}-&amp;gt;{'host'} . '/Spezial:Doppelte_Weiterleitungen');&lt;br /&gt;
  my $res = $lwp-&amp;gt;request($req);&lt;br /&gt;
&lt;br /&gt;
  if(not $res-&amp;gt;is_success()) {&lt;br /&gt;
    die &amp;quot;could not load Spezial:Doppelte_Weiterleitungen&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
  my @names =&lt;br /&gt;
    map { uri_unescape($_) }&lt;br /&gt;
    map { $_ =~ qr{.*&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;/index\.php\?title=([^&amp;quot;]+)&amp;amp;amp;redirect=no&amp;quot;.*?→.*?&amp;lt;a href=&amp;quot;/index\.php\?title=([^&amp;quot;]+)&amp;amp;amp;redirect=no&amp;quot;.*}; ($1, $2) }&lt;br /&gt;
    grep { /^&amp;lt;li&amp;gt;/ }&lt;br /&gt;
    split /\n/, $res-&amp;gt;content();&lt;br /&gt;
&lt;br /&gt;
  for(my $i = 0; $i &amp;lt; @names; ++$i) {&lt;br /&gt;
    eval {&lt;br /&gt;
      cleanupRedirect($names[$i], 0, 1);&lt;br /&gt;
    };&lt;br /&gt;
    warn if($@);&lt;br /&gt;
    print &amp;quot;($i / &amp;quot; . scalar(@names) . &amp;quot;)\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub sanitizeFilename {&lt;br /&gt;
  my ($name) = @_;&lt;br /&gt;
&lt;br /&gt;
  $name =~ s/-/--/g;&lt;br /&gt;
  $name =~ s!/!-+!g;&lt;br /&gt;
  return &amp;quot;checkout/$name&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub checkout {&lt;br /&gt;
  my ($name) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no name given&amp;quot; unless $name;&lt;br /&gt;
&lt;br /&gt;
  my $content = loadSure($name, &amp;quot;rw&amp;quot;);&lt;br /&gt;
  if($content =~ /{{ *InArbeit/ or&lt;br /&gt;
    $content =~ /{{ *Vorlage: *InArbeit/) {&lt;br /&gt;
    askConfirmation(&amp;quot;Page $name is tagged with {{Vorlage:InArbeit}}&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $origContent = $content;&lt;br /&gt;
  $content =&lt;br /&gt;
    &amp;quot;{{Vorlage:InArbeit|[[Benutzer:Drahflow]]}}\n&amp;quot; . $content;&lt;br /&gt;
  saveSure($name, $content, &amp;quot;{{:Vorlage:InArbeit}} gesetzt&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
  my $filename = sanitizeFilename($name);&lt;br /&gt;
  open PAGE, '&amp;gt;:utf8', $filename or die &amp;quot;cannot open $filename: $!&amp;quot;;&lt;br /&gt;
  print PAGE $origContent;&lt;br /&gt;
  close PAGE;&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub copyout {&lt;br /&gt;
  my ($name) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no name given&amp;quot; unless $name;&lt;br /&gt;
&lt;br /&gt;
  my $content = loadSure($name, &amp;quot;rw&amp;quot;);&lt;br /&gt;
  my $filename = sanitizeFilename($name);&lt;br /&gt;
  open PAGE, '&amp;gt;:utf8', $filename or die &amp;quot;cannot open $filename: $!&amp;quot;;&lt;br /&gt;
  print PAGE $content;&lt;br /&gt;
  close PAGE;&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub masscopyout {&lt;br /&gt;
  my ($filename,$follow) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no filename given&amp;quot; unless $filename;&lt;br /&gt;
  my @failures;&lt;br /&gt;
&lt;br /&gt;
  open LIST, '&amp;lt;:utf8', $filename or die &amp;quot;cannot open $filename: $!&amp;quot;;&lt;br /&gt;
  my $i = 0;&lt;br /&gt;
  while(my $name = &amp;lt;LIST&amp;gt;) {&lt;br /&gt;
    chomp $name;&lt;br /&gt;
&lt;br /&gt;
    if($name =~ /%/) {&lt;br /&gt;
      $name = decode('utf8', encode('utf8', uri_unescape(encode('utf8', $name))));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    eval {&lt;br /&gt;
      my $content = loadSure($name, &amp;quot;r&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      if($follow and $content =~ m!#(?:redirect|weiterleitung):? ?\[\[([^\]|]+)( ?\|([^\]]+))?\]\]!i) {&lt;br /&gt;
        $name = $1;&lt;br /&gt;
&lt;br /&gt;
        if($name =~ /%/) {&lt;br /&gt;
          $name = decode('utf8', encode('utf8', uri_unescape(encode('utf8', $name))));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $content = loadSure($name, &amp;quot;r&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $filename = sanitizeFilename(sprintf(&amp;quot;%06d&amp;quot;, $i));&lt;br /&gt;
      open PAGE, '&amp;gt;:utf8', $filename or die &amp;quot;cannot open $filename: $!&amp;quot;;&lt;br /&gt;
      print PAGE $content;&lt;br /&gt;
      close PAGE;&lt;br /&gt;
    };&lt;br /&gt;
    if($@) {&lt;br /&gt;
      push @failures, [$i, $name];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $i++;&lt;br /&gt;
    sleep 3;&lt;br /&gt;
  }&lt;br /&gt;
  close LIST;&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Failures:\n&amp;quot;;&lt;br /&gt;
  foreach my $fail (@failures) {&lt;br /&gt;
    printf &amp;quot;%06d: %s\n&amp;quot;, @$fail;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub checkin {&lt;br /&gt;
  my ($name, $reason) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no name given&amp;quot; unless $name;&lt;br /&gt;
  die &amp;quot;no reason given&amp;quot; unless $reason;&lt;br /&gt;
&lt;br /&gt;
  my $filename = sanitizeFilename($name);&lt;br /&gt;
  open PAGE, '&amp;lt;:utf8', $filename or die &amp;quot;cannot open $filename: $!&amp;quot;;&lt;br /&gt;
  my $origContent = join('', &amp;lt;PAGE&amp;gt;);&lt;br /&gt;
  close PAGE;&lt;br /&gt;
&lt;br /&gt;
  my $content = loadSure($name, &amp;quot;rw&amp;quot;);&lt;br /&gt;
  if($content !~ /^{{Vorlage:InArbeit|\[\[Benutzer:Drahflow\]\]}}/s) {&lt;br /&gt;
    askConfirmation(&amp;quot;Page $name is not tagged as being edited by you&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  saveSure($name, $origContent, $reason);&lt;br /&gt;
&lt;br /&gt;
  unlink $filename;&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub syncin {&lt;br /&gt;
  my ($filename, $name, $reason) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no file given&amp;quot; unless $filename;&lt;br /&gt;
  die &amp;quot;no name given&amp;quot; unless $name;&lt;br /&gt;
  die &amp;quot;no reason given&amp;quot; unless $reason;&lt;br /&gt;
&lt;br /&gt;
  while(1) {&lt;br /&gt;
    eval {&lt;br /&gt;
      open PAGE, '&amp;lt;:utf8', $filename or die &amp;quot;cannot open $filename: $!&amp;quot;;&lt;br /&gt;
      my $origContent = join('', &amp;lt;PAGE&amp;gt;);&lt;br /&gt;
      close PAGE;&lt;br /&gt;
&lt;br /&gt;
      saveSure($name, $origContent, $reason);&lt;br /&gt;
      print &amp;quot;Synced.\n&amp;quot;;&lt;br /&gt;
    };&lt;br /&gt;
    if($@) {&lt;br /&gt;
      print $@;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    sleep 15;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub storein {&lt;br /&gt;
  my ($filename, $reason) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no file given&amp;quot; unless $filename;&lt;br /&gt;
  die &amp;quot;no reason given&amp;quot; unless $reason;&lt;br /&gt;
&lt;br /&gt;
  my $data = retrieve($filename) or die &amp;quot;could not retrieve from $filename: $!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  foreach my $d (@$data) {&lt;br /&gt;
    eval {&lt;br /&gt;
      saveSure($d-&amp;gt;{'wiki_location'}, $d-&amp;gt;{'wiki_content'}, $reason);&lt;br /&gt;
      print &amp;quot;Stored &amp;quot; . $d-&amp;gt;{'wiki_location'} . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    };&lt;br /&gt;
    if($@) {&lt;br /&gt;
      print $@;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub getTemplateUsers {&lt;br /&gt;
  my ($name) = @_;&lt;br /&gt;
&lt;br /&gt;
  return map { $_-&amp;gt;{'title'} } $wiki-&amp;gt;list_transclusions($name);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub checkToDoUsage {&lt;br /&gt;
  my @users = getTemplateUsers(&amp;quot;Vorlage:ToDo&amp;quot;);&lt;br /&gt;
  my @problems;&lt;br /&gt;
&lt;br /&gt;
  foreach my $user (@users) {&lt;br /&gt;
    my $content = loadSure($user, &amp;quot;r&amp;quot;);&lt;br /&gt;
    if($content =~ /{{Vorlage: *ToDo/) {&lt;br /&gt;
      push @problems, $user;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  foreach my $user (@problems) {&lt;br /&gt;
    print &amp;quot;Problematic usage: $user\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub moveCategory {&lt;br /&gt;
  my ($from, $to) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no from category given&amp;quot; unless $from;&lt;br /&gt;
  die &amp;quot;no to category given&amp;quot; unless $to;&lt;br /&gt;
&lt;br /&gt;
  my ($articles, $subcats) = loadCategorySure($from);&lt;br /&gt;
&lt;br /&gt;
  my @problems;&lt;br /&gt;
  foreach my $entry (@$articles, @$subcats) {&lt;br /&gt;
    my $content = loadSure($entry, &amp;quot;rw&amp;quot;);&lt;br /&gt;
    my $success = 0;&lt;br /&gt;
&lt;br /&gt;
    if($content =~ /\[\[$to(?:\|[^\]|]*)?\]\]/) {&lt;br /&gt;
      if($content =~ s/\[\[$from(?:\|[^\]|]*)?\]\]//) {&lt;br /&gt;
        $success = 1;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if($content =~ s/\[\[$from((?:\|[^\]|]*)?)\]\]/[[$to$1]]/) {&lt;br /&gt;
        $success = 1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if($success) {&lt;br /&gt;
      saveSure(&lt;br /&gt;
        $entry,&lt;br /&gt;
        $content,&lt;br /&gt;
        &amp;quot;Kategorie-Umbenennung, von $from nach $to&amp;quot;);&lt;br /&gt;
    } else {&lt;br /&gt;
      push @problems, $entry;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  foreach my $entry (@problems) {&lt;br /&gt;
    print &amp;quot;Problematic usage: $entry\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub fetchCategoryMatrix {&lt;br /&gt;
  my ($name, $categories) = @_;&lt;br /&gt;
&lt;br /&gt;
  my @categories = split /\|/, $categories;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no category given&amp;quot; unless @categories;&lt;br /&gt;
&lt;br /&gt;
  my %articles;&lt;br /&gt;
&lt;br /&gt;
  my $filename = sanitizeFilename($name);&lt;br /&gt;
  open OUTPUT, '&amp;gt;:utf8', $filename or die &amp;quot;cannot open $filename: $!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  foreach my $cat (@categories) {&lt;br /&gt;
    my ($articles, $subcats) = loadCategorySure($cat);&lt;br /&gt;
&lt;br /&gt;
    print OUTPUT &amp;quot;$cat\n&amp;quot;;&lt;br /&gt;
    foreach my $article (@$articles, @$subcats) {&lt;br /&gt;
      $articles{$article}-&amp;gt;{$cat} = 1;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  print OUTPUT &amp;quot;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  foreach my $article (sort keys %articles) {&lt;br /&gt;
    foreach my $cat (@categories) {&lt;br /&gt;
      print OUTPUT $articles{$article}-&amp;gt;{$cat}? &amp;quot;x &amp;quot;: &amp;quot;  &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    print OUTPUT &amp;quot; &amp;quot; . $article . &amp;quot;\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
  close OUTPUT;&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub putCategoryMatrix {&lt;br /&gt;
  my ($name, $reason, $mode) = @_;&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no reason has been given&amp;quot; unless $reason;&lt;br /&gt;
&lt;br /&gt;
  my $filename = sanitizeFilename($name);&lt;br /&gt;
&lt;br /&gt;
  my @categories;&lt;br /&gt;
&lt;br /&gt;
  open INPUT, '&amp;lt;:utf8', $filename or die &amp;quot;cannot open $filename: $!&amp;quot;;&lt;br /&gt;
  while(my $line = &amp;lt;INPUT&amp;gt;) {&lt;br /&gt;
    chomp $line;&lt;br /&gt;
    last if($line eq &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    push @categories, $line;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my %articlesNew;&lt;br /&gt;
&lt;br /&gt;
  while(my $line = &amp;lt;INPUT&amp;gt;) {&lt;br /&gt;
    chomp $line;&lt;br /&gt;
    my $article = substr($line, 1 + 2 * @categories);&lt;br /&gt;
    &lt;br /&gt;
    my $i = 0;&lt;br /&gt;
    foreach my $cat (@categories) {&lt;br /&gt;
      $articlesNew{$article}-&amp;gt;{$cat} = (substr($line, $i, 1) eq 'x');&lt;br /&gt;
      $i += 2;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  close INPUT;&lt;br /&gt;
&lt;br /&gt;
  my %articlesCurrent;&lt;br /&gt;
  foreach my $cat (@categories) {&lt;br /&gt;
    my ($articles, $subcats) = loadCategorySure($cat);&lt;br /&gt;
&lt;br /&gt;
    foreach my $article (@$articles, @$subcats) {&lt;br /&gt;
      $articlesCurrent{$article}-&amp;gt;{$cat} = 1;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my @problems;&lt;br /&gt;
&lt;br /&gt;
  # only articles mentioned in the file are touched&lt;br /&gt;
  foreach my $article (sort keys %articlesNew) {&lt;br /&gt;
    my @toInsert;&lt;br /&gt;
    my @toDelete;&lt;br /&gt;
&lt;br /&gt;
    # only categories mentioned in the file are touched&lt;br /&gt;
    foreach my $newCat (@categories) {&lt;br /&gt;
      next unless $articlesNew{$article}-&amp;gt;{$newCat};&lt;br /&gt;
      push @toInsert, $newCat unless $articlesCurrent{$article}-&amp;gt;{$newCat};&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # only categories mentioned in the file are touched&lt;br /&gt;
    foreach my $curCat (@categories) {&lt;br /&gt;
      unless($articlesCurrent{$article}-&amp;gt;{$curCat}) {&lt;br /&gt;
        next;&lt;br /&gt;
      }&lt;br /&gt;
      push @toDelete, $curCat unless $articlesNew{$article}-&amp;gt;{$curCat};&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(@toInsert or @toDelete) {&lt;br /&gt;
      print &amp;quot;Modifying $article\n&amp;quot; .&lt;br /&gt;
            &amp;quot; Insert: @toInsert\n&amp;quot; .&lt;br /&gt;
            &amp;quot; Delete: @toDelete\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
      if(defined $mode) {&lt;br /&gt;
        if($mode eq 'ask') {&lt;br /&gt;
          askConfirmation(&amp;quot;$article will be changed as above&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        my $content = loadSure($article, &amp;quot;rw&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        my $success = 1;&lt;br /&gt;
        my $catDisplay = undef;&lt;br /&gt;
        foreach my $cat (@toDelete) {&lt;br /&gt;
          my $catRegex = $cat;&lt;br /&gt;
          $catRegex =~ s/ /[ _]/g;&lt;br /&gt;
&lt;br /&gt;
          if($content =~ s/\n\[\[$catRegex((?:\|[^\]|]*)?)\]\]\n/\n/s) {&lt;br /&gt;
            $catDisplay = substr($1, 1);&lt;br /&gt;
          } elsif ($content =~ s/\[\[$catRegex((?:\|[^\]|]*)?)\]\]//) {&lt;br /&gt;
            $catDisplay = substr($1, 1);&lt;br /&gt;
          } else {&lt;br /&gt;
            push @problems, &amp;quot;$article &amp;lt;-&amp;gt; $cat\n&amp;quot;;&lt;br /&gt;
            $success = 0;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        foreach my $cat (@toInsert) {&lt;br /&gt;
          unless($content =~ /\[\[$cat((?:\|[^\]|]*)?)\]\]/) {&lt;br /&gt;
            unless($content =~ /\n$/s) {&lt;br /&gt;
              $content .= &amp;quot;\n&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            if(defined $catDisplay) {&lt;br /&gt;
              $content .= &amp;quot;[[$cat|$catDisplay]]&amp;quot;;&lt;br /&gt;
            } else {&lt;br /&gt;
              $content .= &amp;quot;[[$cat]]&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if($success) {&lt;br /&gt;
          saveSure($article, $content, &amp;quot;Kategorie-Zuordnungs-Upload, $reason&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  foreach my $entry (@problems) {&lt;br /&gt;
    print &amp;quot;Problematic usage: $entry\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub checkLanguageSync {&lt;br /&gt;
  my %users = map { ($_, $_) } getTemplateUsers(&amp;quot;Vorlage:Mehrsprachig&amp;quot;);&lt;br /&gt;
  my @problems;&lt;br /&gt;
&lt;br /&gt;
  while(%users) {&lt;br /&gt;
    my ($first) = keys %users;&lt;br /&gt;
&lt;br /&gt;
    my $content = loadSure($first, &amp;quot;r&amp;quot;);&lt;br /&gt;
    unless($content =~ /{{(Vorlage:)? *Mehrsprachig\b(.*)}}/s) {&lt;br /&gt;
      delete $users{$first};&lt;br /&gt;
      push @problems, &amp;quot;Could not find template call: $first&amp;quot;;&lt;br /&gt;
      next;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    my $parameters = $2;&lt;br /&gt;
    unless($parameters =~ /\bsynchronisiert *= *1/) {&lt;br /&gt;
      delete $users{$first};&lt;br /&gt;
      next;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    my @otherPages;&lt;br /&gt;
    push @otherPages, $1 if($parameters =~ /\bde *= *([^|{}]*)/s);&lt;br /&gt;
    push @otherPages, $1 if($parameters =~ /\ben *= *([^|{}]*)/s);&lt;br /&gt;
&lt;br /&gt;
    @otherPages = grep { $_ ne $first } map { chomp; $_ } @otherPages;&lt;br /&gt;
&lt;br /&gt;
    if(@otherPages &amp;lt; 1) {&lt;br /&gt;
      delete $users{$first};&lt;br /&gt;
      push @problems, &amp;quot;Synchronization group of less than 2 on $first&amp;quot;;&lt;br /&gt;
      next;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    OTHERS: foreach my $other (@otherPages) {&lt;br /&gt;
      my @firstLines = split /\n/, $content;&lt;br /&gt;
&lt;br /&gt;
      my $otherContent = loadSure($other, &amp;quot;r&amp;quot;);&lt;br /&gt;
      unless($otherContent =~ /{{(Vorlage:)? *Mehrsprachig\b(.*)}}/s) {&lt;br /&gt;
        push @problems, &amp;quot;Could not find template call: $other&amp;quot;;&lt;br /&gt;
        next;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my $parameters = $2;&lt;br /&gt;
      unless($parameters =~ /\bsynchronisiert *= *1/) {&lt;br /&gt;
        next;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      my @otherLines = split /\n/, $otherContent;&lt;br /&gt;
&lt;br /&gt;
      if(@firstLines != @otherLines) {&lt;br /&gt;
        push @problems, &amp;quot;Line counts differ between $first and $other&amp;quot;;&lt;br /&gt;
        last OTHERS;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      @firstLines = map { length($_)? 1: 0; } @firstLines;&lt;br /&gt;
      @otherLines = map { length($_)? 1: 0; } @otherLines;&lt;br /&gt;
&lt;br /&gt;
      for(my $i = 0; $i &amp;lt; @firstLines; ++$i) {&lt;br /&gt;
        if($firstLines[$i] ne $otherLines[$i]) {&lt;br /&gt;
          push @problems, &amp;quot;Line &amp;quot; . ($i + 1) .&lt;br /&gt;
            &amp;quot; differs between $first and $other&amp;quot;;&lt;br /&gt;
          last OTHERS;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    delete $users{$first};&lt;br /&gt;
    foreach my $name (@otherPages) {&lt;br /&gt;
      delete $users{$name};&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  foreach my $entry (@problems) {&lt;br /&gt;
    print &amp;quot;$entry\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub addCategories {&lt;br /&gt;
  my ($categories, $names) = @_;&lt;br /&gt;
&lt;br /&gt;
  my @categories = split(/\|/, $categories);&lt;br /&gt;
  my @names = split(/\|/, $names);&lt;br /&gt;
&lt;br /&gt;
  die &amp;quot;no categories given&amp;quot; unless @categories;&lt;br /&gt;
  die &amp;quot;no pages given&amp;quot; unless @names;&lt;br /&gt;
&lt;br /&gt;
  my %pagesInCat;&lt;br /&gt;
&lt;br /&gt;
  foreach my $cat (@categories) {&lt;br /&gt;
    my $correctPages = loadCategorySure($cat);&lt;br /&gt;
    $pagesInCat{$cat} = $correctPages;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  foreach my $name (@names) {&lt;br /&gt;
    my $content = loadSure($name, &amp;quot;rw&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    my $changes = 0;&lt;br /&gt;
    foreach my $cat (@categories) {&lt;br /&gt;
      next if(grep { $_ eq $name } @{$pagesInCat{$cat}});&lt;br /&gt;
&lt;br /&gt;
      $content .= &amp;quot;\n[[$cat]]&amp;quot;;&lt;br /&gt;
      print &amp;quot;$cat added.\n&amp;quot;;&lt;br /&gt;
      $changes = 1;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if($changes) {&lt;br /&gt;
      saveSure(&lt;br /&gt;
        $name,&lt;br /&gt;
        $content,&lt;br /&gt;
        &amp;quot;Kategorie hinzugefügt&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub pirateBoardUpdate {&lt;br /&gt;
  my @files = glob(&amp;quot;/home/drahflow/piraten/vorstand/*-protokoll&amp;quot;);&lt;br /&gt;
  my %decisions;&lt;br /&gt;
  foreach my $file (@files) {&lt;br /&gt;
    open FILE, '&amp;lt;:utf8', $file or die &amp;quot;cannot read $file: $!&amp;quot;;&lt;br /&gt;
    my $lastLine;&lt;br /&gt;
    while(my $line = &amp;lt;FILE&amp;gt;) {&lt;br /&gt;
      chomp $line;&lt;br /&gt;
      if($line =~ /(#\d\d\d\d-\d\d-\d\d.\d+)/) {&lt;br /&gt;
        my $decision = $1;&lt;br /&gt;
        if(length($line) &amp;lt; 80) {&lt;br /&gt;
          $line = $lastLine . $line;&lt;br /&gt;
        }&lt;br /&gt;
        $line =~ s/$decision//g;&lt;br /&gt;
        $decisions{$decision} = $line;&lt;br /&gt;
        print $line, &amp;quot;\n&amp;quot;;&lt;br /&gt;
      }&lt;br /&gt;
      $lastLine = $line;&lt;br /&gt;
    }&lt;br /&gt;
    close FILE;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $content = loadSure(&amp;quot;Landesverband_Niedersachsen/Vorstand/Beschlüsse&amp;quot;, &amp;quot;rw&amp;quot;);&lt;br /&gt;
  foreach my $decision (sort keys %decisions) {&lt;br /&gt;
    next if($content =~ $decision);&lt;br /&gt;
&lt;br /&gt;
    $content .= &amp;lt;&amp;lt;EOWIKI;&lt;br /&gt;
'''$decision''': ''Unkategorisiert'': $decisions{$decision}&lt;br /&gt;
&lt;br /&gt;
EOWIKI&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  saveSure(&lt;br /&gt;
    &amp;quot;Landesverband_Niedersachsen/Vorstand/Beschlüsse&amp;quot;,&lt;br /&gt;
    $content,&lt;br /&gt;
    &amp;quot;Update der Vorstandsbeschlüsse&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  $content = &amp;lt;&amp;lt;EOWIKI;&lt;br /&gt;
[[Kategorie:Landesverband Niedersachsen]]&lt;br /&gt;
&lt;br /&gt;
'''Achtung''': Die Inhalte dieser Seite halte [[Benutzer:Drahflow|ich]] auf&lt;br /&gt;
meinem eigenen Rechner autorativ. Änderungen werden nach der nächsten&lt;br /&gt;
Vorstandstelko unbesehen gelöscht.&lt;br /&gt;
&lt;br /&gt;
EOWIKI&lt;br /&gt;
&lt;br /&gt;
  my $name;&lt;br /&gt;
  open FILE, '&amp;lt;:utf8', '/home/drahflow/piraten/vorstand/todo' or die &amp;quot;open fail: ~/piraten/vorstand/todo: $!&amp;quot;;&lt;br /&gt;
  while(my $line = &amp;lt;FILE&amp;gt;) {&lt;br /&gt;
    chomp $line;&lt;br /&gt;
    if($line =~ /^([A-Z].*)$/) {&lt;br /&gt;
      if(defined $name) {&lt;br /&gt;
        $content .= &amp;quot;}}\n&amp;quot;;&lt;br /&gt;
      }&lt;br /&gt;
      $name = $1;&lt;br /&gt;
      $content .= &amp;quot;{{Kasten grau|$name|\n&amp;quot;;&lt;br /&gt;
    } elsif($line =~ /^ +(.*)$/) {&lt;br /&gt;
      my $task = $1;&lt;br /&gt;
      $content .= &amp;quot;* $task\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(defined $name) {&lt;br /&gt;
    $content .= &amp;quot;}}\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
  close FILE;&lt;br /&gt;
&lt;br /&gt;
  saveSure(&lt;br /&gt;
    &amp;quot;Landesverband_Niedersachsen/Vorstand/TODO&amp;quot;,&lt;br /&gt;
    $content,&lt;br /&gt;
    &amp;quot;Update der VorstandsTODOs&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  print &amp;quot;Done.\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#TODO: Something within a directory which is also a name of a category should&lt;br /&gt;
#      belong to said category&lt;br /&gt;
#TODO: Nothing should belong to a category and also directly to some category&lt;br /&gt;
#      above it.&lt;br /&gt;
#TODO: Everything should have a category&lt;br /&gt;
#TODO: Categories should not be cyclic&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>imported&gt;Drahflow's Bot</name></author>
	</entry>
</feed>