Utilisateur:MisterMatt Bot/Classes
Ceci n'est pas le code source dans son intégralité. J'ai enlevé quelques passages pour ne pas trop surcharger la page. Le code source complet est disponible sur demande.
Class Article
modifierC'est la classe la plus importante. Quand un nouvel objet est créé (un article), on se loggue si ce n'est pas déjà fait dans la langue correspondante à l'article. Ensuite, on récupère le code wiki de l'article pour remplir automatiquement certaines variables :
- @articleName : nom de l'article
- @lang : langue de l'article
- @source : source wiki de l'article
- @interwikis : liste des interwikis
- @cat : liste des catégories
- @wlh : liste des pages liées (variable récupérée sur demande car demande une nouvelle connection)
Le code pour modifier un article ressemble à cela :
bot = Article.new("Utilisateur:MisterMatt/Test1","fr") bot.source = wiki # 'wiki' étant la source wiki de l'article modifié bot.update("MisterMat Bot : Modification automatisée")
initialize(articleName,lang)
modifierTout ce qui est là est exécuté lors de la création d'un nouvel objet Article.
def initialize(articleName,lang) @articleName = articleName @lang = lang if (@@login[@lang] != true) then self.login() end self.getWikiSource() self.getInterwikis() self.getCat() end
login()
modifierMéthode permettant de s'identifier à la Wikipédia courante
def login() loginfo = { "wpName" => @@user[@lang], "wpPassword" => @@password[@lang], "wpLoginattempt" => "Identification", "wpRemember" => "1" } @post_login = loginfo.keys.map{ |k| "#{k}=#{CGI.escape(loginfo[k].to_s)}" }.join("&") puts @post_login if LOG Net::HTTP.start(@lang+@@DOMAINE, 80) do |log| response = log.post(@@LOGIN, @post_login, @@headers) case response when Net::HTTPRedirection print " * Identification..." if TEST else print " * Identification (pas de redirection)..." if TEST end location = response['location'] if location puts " * Login to #{@lang}.wikipedia.org ..." # + " (#{location}.)" p response.to_hash if LOG p response['set-cookie'] if LOG @@cookie = response['set-cookie']#.slice(/([a-z0-9]){32}/) puts " * cookie : " + @@cookie if TEST else puts " ERREUR : le compte #{@user[lang]} n'existe pas !" @@stopped = true end end @@login[@lang] = true end
getPageSource(url)
modifierRécupère le code source HTML d'une page
def getPageSource(url) @reconnecter = true # Connexion à la page courante et modification @@headers['cookie'] = @@cookie url.gsub!(' ', '_') url = CGI.escape(url) url.gsub!('%3A', ':') url.gsub!('%2F', '/') url.gsub!('%3F', '?') url.gsub!('%3D', '=') url.gsub!('%26', '&') begin Net::HTTP.start("#{@lang + @@DOMAINE}", 80) do |page| @source = page.get(url, @@headers) #puts url #puts @source.body end rescue SocketError, RuntimeError if @reconnecter @reconnecter = false retry else $stderr.puts "* Connexion impossible ! Page non traitée." @error = true end end return @source.body end
getWikiSource()
modifierRécupère le code wiki d'un article à partir du code HTML.
def getWikiSource() @reecrire = true @source = getPageSource("/w/index.php?title=#{@articleName}&action=edit") @error = false # Sauvegarde de la source pour rexml begin s = File.open("source", "w") s.write(@source) rescue SystemCallError if @reecrire @reecrire = false retry else $stderr.puts "#{@articleName} n'a pu être enregistrée. Page non traitée." @error = true end else #print " * #{@articleName} en cours...\n" @reecrire = false ensure s.close unless s.nil? end # parsing de la source if not @error @doc = Document.new File.new("source") # Ne pas traiter les pages bloquées if @doc.elements["html/body/div/div/div/div/form/textarea"] == nil if @doc.elements["html/body/div/div/div/div/textarea"] != nil puts "Page bloquée par un administrateur. Page non traitée." else puts "Page inaccessible bien que non bloquée. Page non traitée." end @error = true break else @data = @doc.elements["html/body/div/div/div/div/form/textarea"].text @doc.elements.each("html/body/div/div/div/div/form/input") do |e| @wpEdittime = e.attributes["value"] if e.attributes["name"] == "wpEdittime" @wpEditToken = e.attributes["value"] if e.attributes["name"] == "wpEditToken" end end end @source = @data end
getWhatLinksHere()
modifierRécupère les pages liées à l'article et les stocke dans le tableau @wlh
def getWhatLinksHere() @reconnecter = true @reecrire = true @name = @articleName @name.gsub!(' ', '_') @name = CGI.escape(@name) @name.gsub!('%3A', ':') @name.gsub!('%2F', '/') @name.gsub!('%3F', '?') @name.gsub!('%3D', '=') @name.gsub!('%26', '&') @wlhURL = "http://#{@lang+@@DOMAINE}/w/index.php?title=Special:Whatlinkshere&target=#{CGI.escape(@name)}" begin # Connexion à l'url wlh wiki = Net::HTTP.get_response(URI.parse(@wlhURL)) @status = wiki.code @reponse = wiki.message puts " * url : #{@wlh} (#{@status} #{@reponse})" if TEST rescue SocketError, RuntimeError if @reconnecter @reconnecter = false retry else # Sauvegarde du couple anciennePage - nouvellePage dans tobedone puts "-------- Erreur ---------" $stderr.puts " * Connexion impossible : " + $! +"." puts " * Arrêt du bot." begin f = File.open("tobebone", "a") f.write(page + "|" + @nouvellePage + "\r") rescue SystemCallError if @reecrire @reecrire = false retry else $stderr.puts " * #{@articleName} n'a pu être ajoutée à la liste des pages à traiter plus tard." @@stopped = true end else puts " * La page #{@articleName} a été ajoutée à la liste des pages à traiter plus tard." ensure f.close unless f.nil? end puts "-------------------------" end end # Parsing de wlh if @reponse == "OK" and not @@stopped catch(@status) do throw @status unless @status == "200" puts " * #{@articleName} est disponible." puts " * Construction de la liste des pages liées..." (wiki.body.scan(/<li><a href="(.+)" title="(.+)">(.+)<\/a><\/li>/)).each do |page| page[2].gsub!(' ', '_') page[2].each do |lien| page[2] = CGI.escape(lien) end @liste << page[2] end p @liste if LOG if @liste.nitems == 0 puts " * Aucune page liée à #{@articleName}." @@stopped = true else puts " * Construction de la liste achevée avec succès :" #@liste.each do |page| puts " - #{CGI.unescape(page)}" end #puts end end end @wlh = @liste end
reOrganizeCatAndInterwikis()
modifierRéordonne la structure interne du code wiki de l'article en plaçant les interwikis et les catégories en haut.
def reOrganizeCatAndInterwikis() @data = @source @interwiki = ["en", "de", "ja", "fr", "pl", "nl", "sv", "it", "es", "zh", "pt", "he", "no", "fi", "eo", "da", "ru", "bg", "sl", "ca", "et", "hu", "cs", "sr", "nn", "id", "ro", "uk", "ko", "tt", "sk", "gl", "lt", "ms", "simple", "hr", "lb", "is", "vi", "bs", "th", "ar", "af", "su", "la", "io", "hy", "el", "tr", "wa", "cy", "nds", "fa", "ast", "be", "ia", "fy", "ku", "ka", "zh-min-nan", "lv", "ta", "li", "ang", "ga", "hi", "scn", "als", "tl", "eu", "ur", "sq", "sa", "kw", "mk", "gd", "mi", "kn", "jv", "br", "an", "mt", "oc", "sh", "ks", "fo", "tokipona", "csb", "qu", "se", "mn", "mr", "te", "tpi", "gu", "co", "ml", "nah", "ne", "jbo", "sw", "mo", "bn", "ie", "vo", "tlh", "rm", "az", "ln", "mg", "ht", "yi", "sc", "roa-rup", "na", "ps", "cv", "bo", "tum", "haw", "ug", "tk", "ky", "so", "bi", "nv", "iu", "km", "yo", "bm", "gn", "uz", "got", "ce", "ab", "gv", "sn", "nb"] @interwiki = @interwiki.sort @interwiki = @interwiki.reverse if ((@data =~ /\[\[Catégorie:(.*?)\]\]/i) != nil) then @data = "\n"+@data #puts " - - - - - Catégorie présente - - - - -" espace = false (@data.scan(/\[\[Catégorie:(.*?)\]\]/i)).reverse.each do |cat| @data.gsub!(/(\n){0,1}\[\[Catégorie:#{Regexp.escape(cat[0])}\]\]( )*/i, "") if espace then @data = "[[Catégorie:" + cat[0] + "]] " + @data else @data = "[[Catégorie:" + cat[0] + "]]" + @data # @firstCat = cat[0] espace = true end end end sauteLigne = true espace = false @interwiki.each do |codeInterwiki| if ((@data =~ /\[\[#{codeInterwiki}:(.*?)\]\]/i) != nil) then if sauteLigne then @data = "\n"+@data sauteLigne = false end #puts " - - - - - Interwiki #{codeInterwiki} présent - - - - -" (@data.scan(/\[\[#{codeInterwiki}:(.*?)\]\]/i)).reverse.each do |interwikilien| @data.gsub!(/(\n){0,1}\[\[#{codeInterwiki}:#{Regexp.escape(interwikilien[0])}\]\]( )*/i, "") if espace then @data = "[[" + codeInterwiki + ":" + interwikilien[0] + "]] " + @data else @data = "[[" + codeInterwiki + ":" + interwikilien[0] + "]]" + @data espace = true end end end end @source = @data end
getInterwikis()
modifierRécupère les interwikis et les stocke dans le tableau @interwikis.
def getInterwikis() @interwikis = {} @data = @source @interwiki = ["en", "de", "ja", "fr", "pl", "nl", "sv", "it", "es", "zh", "pt", "he", "no", "fi", "eo", "da", "ru", "bg", "sl", "ca", "et", "hu", "cs", "sr", "nn", "id", "ro", "uk", "ko", "tt", "sk", "gl", "lt", "ms", "simple", "hr", "lb", "is", "vi", "bs", "th", "ar", "af", "su", "la", "io", "hy", "el", "tr", "wa", "cy", "nds", "fa", "ast", "be", "ia", "fy", "ku", "ka", "zh-min-nan", "lv", "ta", "li", "ang", "ga", "hi", "scn", "als", "tl", "eu", "ur", "sq", "sa", "kw", "mk", "gd", "mi", "kn", "jv", "br", "an", "mt", "oc", "sh", "ks", "fo", "tokipona", "csb", "qu", "se", "mn", "mr", "te", "tpi", "gu", "co", "ml", "nah", "ne", "jbo", "sw", "mo", "bn", "ie", "vo", "tlh", "rm", "az", "ln", "mg", "ht", "yi", "sc", "roa-rup", "na", "ps", "cv", "bo", "tum", "haw", "ug", "tk", "ky", "so", "bi", "nv", "iu", "km", "yo", "bm", "gn", "uz", "got", "ce", "ab", "gv", "sn", "nb"] @interwiki = @interwiki.sort @interwiki = @interwiki.reverse sauteLigne = true espace = false @interwiki.each do |codeInterwiki| if ((@data =~ /\[\[#{codeInterwiki}:(.*?)\]\]/i) != nil) then (@data.scan(/\[\[#{codeInterwiki}:(.*?)\]\]/i)).reverse.each do |interwikilien| @interwikis["#{codeInterwiki}"] = interwikilien[0] end end end end
addInterwikis(newInterwikis,lang)
modifierAjoute facilement un interwiki.
def addInterwikis(newInterwikis,lang) @data = @source if ((@data =~ /\[\[#{lang}:#{newInterwikis}\]\]/i) == nil) then @data = @data + "[[#{lang}:#{newInterwikis}]]" end @source = @data reOrganizeCatAndInterwikis() getInterwikis() end
getCat()
modifierRécupère les catégories auxquelles l'article appartient et les stocke dans le tableau @cat.
def getCat() @cat = [] @data = @source if ((@data =~ /\[\[Catégorie:(.*?)\]\]/i) != nil) then (@data.scan(/\[\[Catégorie:(.*?)\]\]/i)).reverse.each do |cat| cat = cat[0].split("|") @cat << cat[0] end end end
addCat(newCat)
modifierAjoute une catégorie.
def addCat(newCat) @data = @source if ((@data =~ /\[\[Catégorie:.?#{newCat}\]\]/i) == nil) then @data = @data + "[[Catégorie:#{newCat}]]" end @source = @data reOrganizeCatAndInterwikis() getCat() end
update(summary)
modifierEnvoie la nouvelle version de la page sur le serveur avec 'summary' comme commentaire de la modification.
def update(summary) @reecrire = true @reconnecter = true donnees = { 'wpTextbox1' => @source, 'wpSummary' => summary, 'wpEdittime' => @wpEdittime, 'wpSave' => 'Sauvegarder', 'wpSection' => '', 'wpMinoredit' => '1', 'wpWatchthis' => 'on', 'wpEditToken' => @wpEditToken } @name = @articleName @name.gsub!(' ', '_') @name = CGI.escape(@name) @name.gsub!('%3A', ':') @name.gsub!('%2F', '/') @name.gsub!('%3F', '?') @name.gsub!('%3D', '=') @name.gsub!('%26', '&') @@headers['cookie'] = @@cookie @post_uri = "/w/index.php?title=#{@name}&action=submit" puts @post_uri @post_donnees = donnees.keys.map{ |k| "#{k}=#{CGI.escape(donnees[k].to_s)}" }.join("&") puts " * données : #{post_donnees}" if TEST puts " * sur : #{@lang+@@DOMAINE}/w/index.php?title=#{@name}&action=submit" if TEST begin Net::HTTP.start("#{@lang+@@DOMAINE}", 80) do |modifier| modification = modifier.post(@post_uri, @post_donnees, @@headers) case modification when Net::HTTPRedirection print "sauvegarde... " else print "sauvegarde (pas de redirection !) " end location = modification['location'] if location puts "OK." else puts "ERREUR (#{location}) :" puts " - body :" puts modification.body puts " - code/message :" puts modification.code puts modification.message end # Sauvegarde de la pageCourante pour mémoire begin l = File.open("done", "a") l.write(@name + "\r") rescue SystemCallError if @reecrire @reecrire = false retry else $stderr.puts "#{@name} n'a pu être ajoutée au log." if TEST @error = true end else puts " * #{@name} ajoutée au log." if TEST @reecrire = false ensure l.close unless l.nil? end end rescue SocketError, RuntimeError if @reconnecter @reconnecter = false print " (2) " retry else puts "* Modification impossible. Page non traitée." end end sleep @PAUSE end
class Category<Article
modifierCette classe hérite de la superclasse Article. En gros, elle garde les mêmes caractéristiques que la classe Article, mais on va lui attribuer de nouvelles méthodes comme lister les articles à l'intérieur d'une catégorie.
Variables accessibles en dehors de la classe :
- @articlesList
- @subCatList
- @imagesList
- @subCatArbo
listArticles()
modifierListe les articles appartenant à la catégorie et les rassemble dans le tableau @articlesList.
def listArticles() @articlesList = [] @sourceURL = getPageSource("/wiki/#{@articleName}") (@sourceURL.scan(/<li><a href="(.*?)" title="(.*?)">(.*?)<\/a><\/li>/)).each do |page| # On coupe en deux pour voir si c'est une catégorie ou pas titre = page[1].split(":") titre[0].each do |lien| titre[0] = CGI.escape(lien) end # On ne prends pas les catégories if titre[0]!="Cat%C3%A9gorie" then page[2].gsub!(' ', '_') page[2].each do |lien| page[2] = CGI.escape(lien) end @articlesList << page[2] end end p @articlesList if LOG if @articlesList.nitems == 0 then puts " * Aucune article disponible" puts " * Arrêt du bot." @stopped = true else puts " * Construction de la liste achevée avec succès :" @articlesList.each do |page| puts " - #{page}" end puts end end
listSubCat()
modifierListe les sous-catégories appartenant à la catégorie et les rassemble dans le tableau @subCatList.
def listSubCat() @subCatList = [] @sourceURL = getPageSource("/wiki/#{@articleName}") (@sourceURL.scan(/<li><a href="(.*?)" title="(.*?)">(.*?)<\/a><\/li>/)).each do |page| # On coupe en deux pour voir si c'est une catégorie ou pas titre = page[1].split(":") titre[0].each do |lien| titre[0] = CGI.escape(lien) end # On prends les catégories if titre[0]=="Cat%C3%A9gorie" then page[2].gsub!(' ', '_') page[2].each do |lien| page[2] = CGI.escape(lien) end @subCatList << page[2] end end p @subCatList if LOG if @subCatList.nitems == 0 then # puts " * Aucune article disponible" # puts " * Arrêt du bot." @stopped = true else # puts " * Construction de la liste achevée avec succès :" # @subCatList.each do |page| puts " - #{page}" end # puts end end
listImages()
modifierListe les imagess appartenant à la catégorie et les rassemble dans le tableau @imagesList.
def listImages() @imagesList = [] @sourceURL = getPageSource("/wiki/#{@articleName}") (@sourceURL.scan(/<a href="\/wiki\/Image:(.*?)" title="Image:(.*?)"><img src="(.*?)<\/a>/)).each do |image| @name = image[1] @name.gsub!(' ', '_') @name = CGI.escape(@name) @name.gsub!('%3A', ':') @name.gsub!('%2F', '/') @name.gsub!('%3F', '?') @name.gsub!('%3D', '=') @name.gsub!('%26', '&') @imagesList << @name end p @imagesList if LOG if @imagesList.nitems == 0 then puts " * Aucune image disponible" puts " * Arrêt du bot." @stopped = true else puts " * Construction de la liste achevée avec succès :" @imagesList.each do |page| puts " - #{page}" end puts end end
findSubCat()
modifierGénère la liste indentée des sous-catégories, sous-sous-catégories... de la catégorie. Cette liste à cette forme :
- Cat
- SubCat1
- SubSubCat1
- SubSubcat2
- SubCat2
- SubCat3
- SubCat1
def findSubCat() self.findSubCat2(@articleName,0) @subCatArbo = $wiki end # Fonction récursive pour trouver toutes les sous-catégories def findSubCat2(cat,n) if n==0 then $wiki = "" end cat2 = cat cat2.gsub!('_', ' ') n += 1 donnees = "*"*n + "[[:Catégorie:"+CGI.unescape(cat2)+"|"+CGI.unescape(cat2)+"]]\n" $wiki = $wiki + donnees #puts $wiki cat = Category.new("Catégorie:"+CGI.unescape(cat),"fr") cat.listSubCat() cat.subCatList.each do |subCatName| findSubCat2(subCatName,n) end n -= 1 end protected :findSubCat2