Цей бот заміняє всі входження певного растрового зображення на його аналог в форматі SVG, наприклад "якесь_зображення.jpg" на "якесь_зображення.svg". Пара зображень підбирається вручну. Код програми можна побачити внизу (Я дозволю будь-кому використовувати, поширювати або змінювати його, але не отримувати від нього фінансовий прибуток). Бот написано на мові C# з використанням бібліотеки DotNetWikiBot.

Код

using System; using System.Net; using System.Threading; using System.Collections.Generic; using System.Text.RegularExpressions; using DotNetWikiBot;  class ImageReplacer:Bot {  [STAThread]  public static void Main(string[] args)  {   string username = args[0], password = args[1];   string new_img;   List<string> sites_list = new List<string>();   Dictionary<string, string> summary = new Dictionary<string, string>();   int edits, rejects;   MatchCollection mc;      summary.Add("en", "BOT: Replaced raster image with an image of format SVG.");   summary.Add("de", "BOT: Ersetzt das Rasterbild mit einem Bild des Formats SVG.");   summary.Add("pt", "BOT: Substituição de imagem raster por formato SVG.");   summary.Add("uk", "БОТ: Замінено растрове зображення на зображення в форматі SVG.");   summary.Add("ru", "БОТ: Заменено растровое изображение на изображение в формате SVG.");   summary.Add("be", "БОТ: Заменены растравы малюнак на малюнак у фармаце SVG.");   summary.Add("pl", "BOT: Zamień grafikę rastrową na obraz w formacie SVG.");   summary.Add("sr", "BOT: Zamenjena rasterska slika sa slikom u formatu SVG.");   summary.Add("hr", "BOT: Zamijenjena rasterska slika slikom u formatu SVG.");   summary.Add("hu", "BOT: Kép(ek) cseréje SVG formátumú változatra.");   summary.Add("ar", "BOT: استبدال صورة نقطية بصورة متجهية متغيرة (SVG).");   summary.Add("fa", "BOT: جایگزینی پرونده با نسخهٔ برداری SVG");   summary.Add("nv", "BÉÉSH HINÁANII: Eʼelyaaígíí łahgo áyiilaa; SVG choolʼį́.");      beginning:   edits = 0;     //USER INPUT   Console.WriteLine("Replace: ");   string old_img = args.Length>=3?args[2]:Console.ReadLine(); 	if(args.Length>=3) {Console.WriteLine(old_img);}   if(old_img.StartsWith("id="))   {    Site commons_site = new Site("https://commons.wikimedia.org/", username, password);    Page commons_page = new Page(commons_site, Int64.Parse(old_img.Substring(3)));    commons_page.Load();    old_img = commons_page.title.Substring(5);    Console.WriteLine(old_img);      mc = Regex.Matches(commons_page.text, @"\|((.)+svg)");    new_img = mc[0].Groups[1].Value;        new_img = new_img.Replace("File:", "");    if(new_img.Contains("|")) {new_img = new_img.Substring(new_img.IndexOf("|")+1);}    if(new_img.Contains("_")) {new_img = new_img.Replace("_", " ");}      Console.WriteLine("\n"+"with: \n" + new_img);   }   else   {    Console.WriteLine("\n"+"with: ");    new_img = args.Length>=4?args[3]:Console.ReadLine();    	if(args.Length>=4) {Console.WriteLine(new_img);}    if(new_img==old_img)    {Console.WriteLine("\nNew image can not be the same as the old one!\n"); goto beginning;}   }   string old_img_underlined = old_img.Replace(" ", "_");   Console.WriteLine();      //WHAT WIKIS TO PROCESS   string htmlCode;   string img_usage_list = "https://" + "commons.wikimedia.org/w/index.php?title=Special:GlobalUsage&limit=500&target=" +  	old_img.Replace(" ", "+");   bool goto_next_page = true;   sites_list.Clear();    while(goto_next_page)   {    try {using (WebClient client = new WebClient()) {htmlCode = client.DownloadString(img_usage_list);}}    catch {Console.WriteLine("No page for this image found!"); goto beginning;}       mc = Regex.Matches(htmlCode, @"\s([-\w]+\.(\w)+\.org)");    if(mc.Count==0) {Console.WriteLine("No inclusions found!"); goto beginning;}    foreach (Match m in mc)    { 	if(!sites_list.Contains(m.Groups[1].Value) && m.Groups[1].Value!="nl.wikipedia.org" && m.Groups[1].Value!="simple.wikipedia.org") 		{sites_list.Add(m.Groups[1].Value);}    }     goto_next_page = !htmlCode.Contains("| next 500)");    if(goto_next_page)    { 	mc = Regex.Matches(htmlCode, @"\|\s\<a href" + "=\"(/w/index.php" + @"\?title=Special:GlobalUsage&amp;limit=500&amp;from=" + "[^\"]+)\"");     img_usage_list = "https://" + "commons.wikimedia.org" + mc[0].Groups[1].Value.Replace("&amp;", "&");    }   }     //PROCESSING   try   {    Site wiki_site; PageList inclusions; int site_counter = 1, page_counter; string lang;    foreach (string st_f in sites_list)    {     string st = st_f;     rejects = 0;     Console.WriteLine("\n" + site_counter + ". " + st);      try_connect_again:     try {wiki_site = new Site("https://" + st, username, password);}     catch(System.Net.WebException)     {      Console.WriteLine("No internet connection or wrong sitename!");      Console.WriteLine("Check the connection and type sitename again (type 'skip' to skip):");      st = Console.ReadLine();      if(st=="skip") {continue;}      goto try_connect_again;     }     catch(DotNetWikiBot.WikiBotException)     {Console.WriteLine("Failed to login! This site will be skipped."); continue;}      inclusions = new PageList(wiki_site);     inclusions.FillFromPagesUsingImage(old_img);     Console.WriteLine("\t" + inclusions.Count() + " inclusions found" + "\n");     lang = GetLang(st);        page_counter = 1;     foreach (Page wiki_page in inclusions)     {      Console.WriteLine("\t" + page_counter + ". " + wiki_page.title); 	  	 if(st_f=="www.wikidata.org") 	 { 	  System.Windows.Forms.Clipboard.SetText(new_img); 	  System.Diagnostics.Process.Start("http://" + "www.wikidata.org/wiki/" + wiki_page.title); 	  continue; 	 }       Console.Write("\t");      wiki_page.Load();      if(wiki_page.Exists() && (wiki_page.text.Contains(old_img) || wiki_page.text.Contains(old_img_underlined)))      {       wiki_page.text = wiki_page.text.Replace(old_img, new_img);       wiki_page.text = wiki_page.text.Replace(old_img_underlined, new_img);       Console.Write("\t");       try {edits++; wiki_page.Save(summary[lang], true); if(st.StartsWith("pt.")) {Thread.Sleep(10000);}}       catch (DotNetWikiBot.WikiBotException)       {        edits--;        Console.WriteLine("\t\t" + "Site did not allow this edit");        if(++rejects > 3)        {Console.WriteLine("\t" + "To many rejects. This site will be skipped"); break;}       } 	  catch(System.Net.WebException e) 	  { 	   Console.WriteLine("\t\t" + "Network error: "); 	   Console.WriteLine("\t\t" + e.Message); 	   Console.WriteLine("\t\t" + "Waiting one minute"); 	   Thread.Sleep(60000); 	  } 	  catch(Exception e) {Console.WriteLine("\t\tUnhandled exception: " + e.GetType()); Console.WriteLine("\t\t" + e.Message);}      }      else {Console.WriteLine("\t\t" + "Image not present");}       page_counter++;     }     site_counter++;    }   }    catch(Exception e)   {    Console.WriteLine("Unhandled exception: " + e.GetType());    Console.WriteLine(e.Message);    Console.ReadKey();   }    //WRITING TO LOG   finally   {    if(edits>=3)    {     if(old_img.Length>64) {old_img = old_img.Substring(0,60) + "...";}     if(new_img.Length>64) {new_img = new_img.Substring(0,60) + "...";}      System.IO.StreamWriter outfile = new System.IO.StreamWriter("log.txt", true);     outfile.Write("\r\n" + old_img);     int tabs = (old_img.Length)/8;     tabs = 8 - tabs;     while (tabs!=0) {outfile.Write("\t"); tabs--;}      outfile.Write(new_img);     tabs = (new_img.Length)/8;     tabs = 8 - tabs;     while (tabs!=0) {outfile.Write("\t"); tabs--;}      outfile.Write(DateTime.Now.ToString("dd.MM.yyyy (HH:mm)"));     outfile.Write("\t{0,4}", edits);     outfile.Close();    }    Console.WriteLine("DONE! - " + edits + " edits done\n");   }   if(args.Length>=3) {return;}   goto beginning;  }     //CHOSING LANGUAGE OF EDIT SUMMARY  public static string GetLang(string site)  {   string[] rulangs = {"ru.", "kk.", "hy.", "uz.", "ky.", "tg.", "crh.", "gag.", "tt.", "av.",                           "kbd.", "ab.", "ba.", "bxr.", "os.", "kv.", "krc.", "mrj.", "lbe.", "lez.",                           "mdf.", "ce.", "mhr.", "koi.", "sah.", "cu.", "tyv.", "udm.", "xal.", "cv.",  			 "myv.", "ady"};   string[] delangs = {"de.", "lb.", "li.", "als.", "bar.", "ksh."};   string[] pllangs = {"pl.", "szl.", "csb.", "hsb.", "dsb."};   string[] srlangs = {"sr.", "sh.", "bs.", "mk."};    if (site.StartsWith("uk.") || site.StartsWith("rue.")) {return "uk";}   else if (site.StartsWith("be.") || site.StartsWith("be-tarask.")) {return "be";}   else if (site.StartsWith("hr.") || site.StartsWith("sl.")) {return "hr";}   else if (site.StartsWith("pt.") || site.StartsWith("es.") || site.StartsWith("gl.")) {return "pt";}   else if (site.StartsWith("hu.")) {return "hu";}   else if (site.StartsWith("ar.")) {return "ar";}   else if (site.StartsWith("fa.")) {return "fa";}   else if (site.StartsWith("nv.")) {return "nv";}   else if (Array.IndexOf(srlangs, site.Substring(0,3))>=0) {return "sr";}   else if (Array.IndexOf(pllangs, site.Substring(0,3))>=0 || Array.IndexOf(pllangs, site.Substring(0,4))>=0) {return "pl";}   else if (Array.IndexOf(delangs, site.Substring(0,3))>=0 || Array.IndexOf(delangs, site.Substring(0,4))>=0) {return "de";}   else if (Array.IndexOf(rulangs, site.Substring(0,3))>=0 || Array.IndexOf(rulangs, site.Substring(0,4))>=0) {return "ru";}   else {return "en";}  } }