GuildWiki

GuildWiki has been locked down: anonymous editing and account creation are disabled. Current registered users are unaffected. Leave any comments on the Community Portal.

READ MORE

GuildWiki
Advertisement

Description[]

This script rewrites orphaned links to the old Build: namespace articles, pointing them instead to the appropriate article on the PvX Wiki.

  • Language: Perl
  • Throttle: 360 edits/hour (10 seconds between edits)
  • Status: Complete. There are a few build-related pages left in Special:Wantedpages, but most have less than 5 links and can be handled manually.

Process[]

  1. Scans Special:Wantedpages for links to builds, which are identified by beginning with "Team" or a profession abbreviation followed by a slash, such as "W/".
  2. Checks a correspondence file (to be compiled by Ereanor) for the new name of the build on PvX Wiki.
  3. For each build redlink found, scans Special:Whatlinkshere for that link and gets a list of the articles containing that specific redlink.
  4. For each article containing a build redlink, edits the article to rewrite the link as follows:
    [[Old Build Name]] → [[PvX:Build:New Build Name|]]

Code[]

#!/usr/bin/perl
use strict;

use Perlwikipedia;

# Read the correspondence file (namespace is included in new name)
my %corr;
open (IFP, "build-corr.txt") or die "can't open file: $!\n";
while (<IFP>) {
	chomp;
	my ($old, $new) = split /;/;
	($corr{$old} = $new) =~ s/_/ /g;
}
close (IFP);
print "Read corr file.\n";

# Log file
open (OFP, ">>$0.log") or die "can't open log file: $!\n";
my $ofh = select(OFP);
$| = 1;
select($ofh);
print OFP "\n", "="x20, "\n";
{ # These brackets are just to block off the time variables so I don't have to worry about multiple declarations
	my ($sec, $min, $hour, $day, $mon, $year) = (localtime)[0,1,2,3,4,5];
	printf OFP "$0 starting at %2d:%02d:%02d %4d-%02d-%02d\n", $hour, $min, $sec, $year+1900, $mon+1, $day;
}
$| = 1;
# Create a Perlwikipedia object
my $user = 'Bot ishmael'; my $pass = $ARGV[0];
my $editor = Perlwikipedia->new($user);

# Turn debugging on, to see what the bot is doing
$editor->{debug} = 1;

# Login to guildwiki
$editor->set_wiki('guildwars.wikia.com','');
my $status = $editor->login($user, $pass);
if ($status) { die $editor->{errstr}; }

# Editing options
my $is_minor = 1;
my $edit_summary='Builds redlinks rewrite';

# Pull all build redlinks from Special:Wantedpages
my @builds = builds_from_wantedpages(); # Custom function not from Perlwikipedia; see below

foreach my $build (@builds) {
	my $buildname = $build->{title};
	my $count = $build->{count};

	# Get the new buildname
	my $new_buildname = $corr{$buildname};
	
	# Get the list of articles linking to this build
	my @what_links_here = $editor->what_links_here($buildname);
	$buildname =~ s/\(/\\\(/g;
	$buildname =~ s/\)/\\\)/g;
	
	foreach my $article (@what_links_here) {
		# Get the text of the article
		my $text = $editor->get_text($article->{title});
		if ($text == 1) { die "Error getting page $article->{title}\n"; }
		
		# Rewrite the links
		if ($count < 10 || !defined($new_buildname)) {
			$text =~ s!\[\[$buildname(.*?)\]\]!\{\{DeletedLink\|$buildname$1\}\}!gi;
			$buildname =~ s/_/ /g; # Links can use underscores or spaces, do this and match again to cover both possibilities
			$text =~ s!\[\[$buildname(.*?)\]\]!\{\{DeletedLink\|$buildname$1\}\}!gi;
		} else {
			$text =~ s!\[\[$buildname([\|#](.*?)|)\]\]!\[\[PvX:$new_buildname\|$2\]\]!gi;
			$buildname =~ s/_/ /g;
			$text =~ s!\[\[$buildname([\|#](.*?)|)\]\]!\[\[PvX:$new_buildname\|$2\]\]!gi;
		}
		
		# Save the article
		my $res = $editor->edit($article->{title}, $text, $edit_summary, $is_minor);
		if ($res == 1) { die "Error saving page $article->{title}\n"; }
		my ($sec, $min, $hour, $day, $mon, $year) = (localtime)[0,1,2,3,4,5];
		printf OFP "%2d:%02d:%02d %4d-%02d-%02d\t%s\t%s", $hour, $min, $sec, $year+1900, $mon+1, $day, $article->{title}, $buildname;
		if ($res->decoded_content =~ /The page you wanted to save was blocked by the spam filter\./) {
			print OFP "\tSPAM ERROR\n";
		} else { 
			print OFP "\n";
			# Wait 10 seconds before making another edit
			print "sleeping...\n";
			sleep 10;
		}
	}
}
{ # These brackets are just to block off the time variables so I don't have to worry about multiple declarations
	my ($sec, $min, $hour, $day, $mon, $year) = (localtime)[0,1,2,3,4,5];
	printf OFP "\n$0 finishing at %2d:%02d:%02d %4d-%02d-%02d\n", $hour, $min, $sec, $year+1900, $mon+1, $day;
}
close (OFP);

#=========

sub builds_from_wantedpages {
	my @links;

	my $res = $editor->_get( 'Special:Wantedpages', 'view', "&limit=1000" );
	unless ($res) { return 1; }
	my $content = $res->decoded_content;
	while ( $content =~ m{<li><a href="/index.php\?title=(.*?)&action=edit".+?>(\d+) links}g ) {
		my $full_title = $1;
		my $count = $2;
		(my $title = $full_title) =~ s/^Build://;
		$full_title =~ s/\%27/'/g;
		$full_title =~ s/\%28/\(/g;
		$full_title =~ s/\%29/\)/g;

		# Only pass through titles that look like build articles
		if ( 
			$title =~ m{^Team} 
			|| $title =~ m{^(W|R|Mo|Me|N|E|A|Rt|P|D)/(W|R|Mo|Me|N|E|A|Rt|P|D|any)} 
			|| $title =~ m{^Build talk:}
			)
		{
			push @links, { title => $full_title, count => $count };
		}
    }

	return @links;
}

Correspondence list of old/new build names[]

Any build names not listed here either have less than 10 links according to Special:Wantedpages or were deleted from PvX. The namespace is included in the new name because some Build:s were turned into Guide:s.

  • Mo/any_55hp_Solo_Monk;Build:Mo/any_55hp_Solo_Monk
  • N/Me_SS_Nuker;Build:N/Me_SS_Nuker
  • Team_-_Barrage/Pet_%28Tomb_Ruins%29;Build:Team_-_Barrage/Pet
  • E/Me_Terra_Tank;Build:E/Me_Terra_Tank
  • D/E_Obsidian_Dervish;Build:D/E_Obsidian_Dervish
  • A/R_Critical_Barrager;Build:A/R_Critical_Barrager
  • A/E_Solo_Green_Farmer;Build:A/E_Solo_Green_Farmer
  • Team_-_Underworld_trapping;Guide:Underworld_Trapping
  • R/N_Touch_Ranger;Build:R/N_Touch_Ranger
  • Mo/Me_Barrier_Bond_Monk;Build:Mo/Me_Barrier_Bond_Monk
  • Mo/E_SoA_Sliver;Build:Mo/E_SoA_Sliver
  • E/Me_Heavy_Nuker;Build:E/any_Renewal_Nuker
  • R/any_General_Barrager;Build:R/any_Barrage_Ranger
  • Team_-_55/SS_FoW;Build:Team_-_55/SS_FoW
  • W/Mo_Vermin_Farmer;Build:W/Mo_Triple_Chop_Farmer
  • N/any_Minion_Master;Build:N/any_Minion_Master
  • R/any_General_Interrupter;Build:R/any_General_Interrupter
  • A/any_Chkkr_Locust_Lord_Farmer;Build:A/any_Chkkr_Farmer
  • Mo/any_SoA_Monk;Build:Mo/any_SoA_55_Monk
  • Team_-_Underworld_Speed_Trap_Duo;Build:Team_-_Underworld_Speed_Trap_Duo
  • W/Mo_Bold_Forge_Runner;Build:W/Mo_Bold_Forge_Runner
  • W/any_Fissure_Spider_Farmer;Build:W/any_Fissure_Spider_Farmer
  • N/Mo_Boss_Farmer;Build:N/Mo_Boss_Farmer
  • Mo/any_Spirit_Bonder;Build:Mo/any_Spirit_Bonder
  • W/Mo_Regeneration_IDS_Farmer;Build:W/Mo_Regeneration_IDS_Farmer
  • N/any_BiP_Necro;Build:N/any_BiP_Necro
  • Team_-_55/SS;Build:Team_-_55/SS
  • E/A_Solo_Green_Farmer;Build:E/A_Solo_Green_Farmer
  • Mo/Me_PvE_WoH_Monk;Build:Mo/Me_PvE_WoH_Monk
  • E/A_Gloom_Farmer;Build:E/A_Gloom_Farmer
  • Mo/Me_Boon_Prot;Build:Mo/Me_Boon_Prot
  • E/Me_Echo_Nuker;Build:E/Me_Echo_Nuker
  • Mo/A_Blessed_Escaper;Build:Mo/A_Blessed_Escaper
  • Build:W/Me_Enduring_Visage_UW_Solo;Build:W/Me_Enduring_Visage_UW_Solo
  • E/A_DoA_Solo_Gloom_Farmer;Build:E/A_Gloom_Farmer
  • E/any_Searing_Flames_Elementalist;Build:E/any_Searing_Flames_Elementalist
  • W/E_Obsidian_Tank;Build:W/E_Obsidian_Tank
  • R/Me_Underworld_Speed_Trap_Solo;Build:R/Me_Underworld_Speed_Trap_Solo
  • A/W_Berserking_Shadow;Build:A/W_Shadow_Prison_Assassin
  • Rt/Me_Vengeful_Farmer;Build:Rt/Me_Vengeful_Farmer
  • R/Mo_Basic_Ranger_Runner;Build:R/Mo_Basic_Ranger_Runner
  • R/any_Tank_Master;Build:R/any_Tank_Master
  • W/R_Melandru%27s_Resilience_Totem_Axe_Farmer;Build:W/R_Melandru%27s_Resilience_Totem_Axe_Farmer
  • Build:W/Me_UW_Solo;Build:W/Me_UW_Solo
  • Mo/any_Canthan_Bonder;Build:Mo/any_Boon_Signet_Bonder
  • A/any_Deadly_Promise;Build:A/R_Assassin's_Promise_LR_Spiker
  • R/W_Bold_Forge_Runner;Build:R/W_Bold_Forge_Runner
  • W/Me_Raging_IDS_Farmer;Build:W/Me_Raging_IDS_Farmer
  • E/Me_Mist_Form_Farmer;Build:E/Me_Mist_Form_Farmer
  • Rt/any_Ritual_Lord;Build:Rt/any_Ritual_Lord
  • N/Mo_Minion_Master;Build:N/any_Minion_Master
  • Rt/N_Explosive_Creation;Build:Rt/N_Explosive_Growth_Minion_Bomber
  • N/Mo_55hp_Solo_Necromancer;Build:N/Mo_Solo_SS_Necromancer
  • N/Mo_Tombs_OOV;Build:Team_-_Barrage/Pet#N/Mo_Orders_Necromancer
  • N/Mo_Solo_SS_Necromancer;Build:N/Mo_Solo_SS_Necromancer
  • Team_-_Dual_UW_Smite;Build:Team_-_600/Smite
  • N/Me_Midnight_Solo;Build:N/Me_Midnight_Solo
  • A/R_Solo_Rajazan%27s_Fervor_Farmer;Build:A/R_Solo_Rajazan%27s_Fervor_Farmer
  • W/E_Shock_Axe;Build:W/E_Shock_Axe
  • Build:Mo/any_SoA_Monk;Build:Mo/any_SoA_Monk
  • Rt/any_Spirit_Nuker;Build:Rt/any_Spirit_Nuker
  • Me/W_Illusion_Slasher;Build:Me/W_Illusion_Slasher
  • E/any_Air_Spiker;Build:E/any_Air_Spiker
  • R/Me_Fissure_Forest_Farmer;Build:R/Me_Fissure_Forest_Farmer
  • Me/E_Flashfire;Build:Me/E_Fast_Casting_Nuker
  • A/D_Disciple_of_Death;Build:A/D_CS_Scythe_Assassin
  • Mo/D_Monk_Vermin_Farmer;Build:Mo/D_Monk_Vermin_Farmer
  • Build:Mo/any_55hp_Solo_Monk;Build:Mo/any_55hp_Solo_Monk
  • Mo/Me_Blessed_Light_Bond_Monk;Build:Mo/Me_Blessed_Light_Bond_Monk
  • D/A_Dark_Silence_Runner;Build:D/A_Dark_Silence_Runner
  • W/A_Lone_Ganksman;Build:W/A_Lone_Ganksman
  • Mo/E_Glyph_Boon_Healer;Build:Mo/E_GoLE_Healer's_Boon_Healer
  • W/Mo_Full_Vigor_Paladin;Build:W/Mo_Full_Vigor_Paladin
  • A/E_UW_Farmer;Build:A/E_UW_Farmer
  • Mo/any_Invincible_Monk;Guide:Invinci-Monk_Guide
  • E/Me_Underworld_Tank;Build:E/Me_Underworld_Tank
  • R/Me_Cripshot_Ranger;Build:R/Me_Cripshot_Ranger
  • W/E_Sliver_Vermin;Build:W/E_Sliver_Vermin
  • W/any_Triple_Chop_PvE_Tank;Build:W/any_Triple_Chop_Warrior
  • R/D_Enchanted_Forge_Runner;Build:R/D_Enchanted_Forge_Runner
  • E/any_Shockwave_Vermin_Farmer;Build:E/any_Shockwave_Vermin_Farmer
  • Rt/any_Continual_Channeler;Build:Rt/any_Continual_Channeler
  • E/any_Renewal_Nuker;Build:E/any_Renewal_Nuker
  • Team_-_55/Famine_Redux;Build:Team_-_55/Famine_Redux
  • N/any_Aura_of_the_Lich_MM;Build:N/any_Aura_of_the_Lich_MM
  • N/any_IV_Transfusion;Build:N/any_IV_Transfusion
  • N/any_Icy_Blighter;Build:N/any_Icy_Veins_PvE
  • Mo/E_Glyph_Shield_of_Regen;Build:Mo/E_GoLE_Shield_of_Regeneration
  • N/Mo_Boss_Farmer/Boss_strategies;Build:N/Mo_Boss_Farmer/Boss_strategies
  • N/Me_FoC_Spiker;Build:N/Me_FoC_Necro
  • R/Me_Feverish_Archer;Build:R/Me_Fevered_Dreams_Ranger
  • Mo/any_Word_of_Healing_Monk;Build:Mo/any_Word_of_Healing_Monk
  • Mo/N_Boon_Prot;Build:Mo/N_Boon_Prot
  • A/any_Impaler;Build:A/any_Impaler
  • W/any_Flailing_Dragon;Build:W/any_PvE_Dragon_Slash
  • P/W_ParaThumper;Build:P/W_ParaThumper
  • E/Mo_Savannah_Heat_Farmer;Build:E/Mo_Savannah_Heat_Farmer
  • W/Mo_Paladin;Build:W/Mo_Paladin
  • Rt/any_Attuned_Restorer;Build:Rt/any_Attuned_was_Songkai_Healer
  • Me/any_PvE_Domination_Mesmer;Build:Me/any_PvE_Domination_Mesmer
  • W/any_Fierce_Hammer;Build:W/any_Devastating_Hammer_Warrior
  • Team_-_IWAY;Build:Team_-_IWAY
  • A/E_Falling_Shocker;Build:A/E_AoD_Shock_Sin
  • A/E_Gloom_Farmer;Build:A/E_Gloom_Farmer
  • W/Me_UW_Solo;Build:W/Me_UW_Solo
  • W/any_Cleave_PvE_Soldier;Build:W/any_Cleave_PvE_Soldier
  • Build:Mo/E_SoA_Sliver;Build:Mo/E_SoA_Sliver
  • Build:E/A_Solo_Green_Farmer;Build:E/A_Solo_Green_Farmer
  • R/Me_Chkkr_Thousand_Tail_Farmer;Build:R/Me_Chkkr_Thousand_Tail_Farmer
  • Mo/Me_Zealous_Prot;Build:Mo/Me_Hex_Breaker_ZB_Monk
  • Mo/Me_Inspiration_Boon_Healer;Build:Mo/Me_Inspiration_Magic_Healer's_Boon_Healer
  • W/any_Axe_Rune_Farmer;Build:W/any_Axe_Rune_Farmer
  • Me/A_Neutral_IW;Build:Me/A_Neutral_IW
  • P/any_Commanding_Support;Build:P/any_Commanding_Support
  • A/Me_Solo_Sin;Build:A/Me_Solo_Sin
  • E/any_Dual_Attunement_Air_Spiker;Build:E/any_Dual_Attunement_Air_Spiker
  • W/Rt_UW_solo;Build:W/Rt_VWK_farmer
  • Me/any_E-Surge_Mesmer;Build:Me/any_E-Surge_Mesmer
  • W/any_Steady_Warrior;Build:W/any_Steady_Warrior
  • Rt/R_Nightmare_Marksman;Build:Rt/R_Nightmare_Marksman
  • A/any_Shadow_Blossom;Build:A/any_Shadow_Blossom
  • Rt/Me_Painful_Echo;Build:Rt/Me_Painful_Echo
  • W/any_Basic_PvE_Hammer;Build:W/any_Basic_PvE_Hammer
  • Mo/Me_Elona%27s_Bonder;Build:Mo/Me_Elona%27s_Bonder
Advertisement