User:TLULbot/jBot/WikiSession.java

/* * jBot - Java bot framework, for editing a wiki powered by MediaWiki. * Copyright (c) 2009-2010 The last username left and others. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;. * * This framework was based on AmauriceBot, created by Maurice Abraham. * * Contributors: * The last username left - Task framework, GUI * Maurice Abraham - Core utilities *--*/

package jBot;

import java.io.IOException; import java.net.URLEncoder; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.SortedSet; import java.util.TimeZone; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern;

/** * Class to handle the wiki session * @author Maurice Abraham (modified by The last username left) */ public class WikiSession {   private String API_URL = "http://community.wikia.com/api.php";

private HashMap&lt;String,String&gt; m_cookies = new HashMap&lt;String,String&gt;;

private boolean m_loggedIn = false;

private String m_lastGetTitle = null; private String m_lastGetEditToken = null; private String m_lastGetTimestamp = null;

private Pattern m_substPattern = Pattern.compile("&lt;expandtemplates[^&gt;]*&gt;(.*)&lt;/expandtemplates&gt;", Pattern.DOTALL); private Pattern m_getTextPattern = Pattern.compile("&lt;rev [^&gt;]*&gt;(.*)&lt;/rev&gt;", Pattern.DOTALL); private Pattern m_loginTokenPattern = Pattern.compile(" token=\"([^\"]*)\"");   private Pattern m_editTokenPattern = Pattern.compile(" edittoken=\"([^\"]*)\""); private Pattern m_timestampPattern = Pattern.compile(" timestamp=\"([^\"]*)\"");   private Pattern m_allPagesPattern = Pattern.compile(" title=\"([^\"]*)\""); private Pattern m_apFromPattern = Pattern.compile(" apfrom=\"([^\"]*)\"");   private String m_loggedInUser = null;

private DateFormat m_tsFmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); public Core.Printer p = null; private int lastStopCheck = 10;

public WikiSession(Core.Printer printer) {       m_tsFmt.setTimeZone(TimeZone.getTimeZone("UTC")); p = printer; }

private String doCmd(String cmd) throws IOException {       return Utils.getInternetPage(API_URL, cmd + "&amp;format=xml", m_cookies, p); }

public void login(String user, String passwd) throws IOException {       String cmd = "action=login&amp;lgname=" + user + "&amp;lgpassword=" + passwd; String result = doCmd(cmd); if (result.matches(".*result=\"[Nn]eed[Tt]oken\".*")) {           //MediaWiki 1.15.3 or later so need to send again with token String[] toks = Utils.extract(m_loginTokenPattern, result); if (toks != null) {               cmd = cmd + "&amp;lgtoken=" + Utils.decodeEntities(toks[1]); result = doCmd(cmd); }       }        if (!result.matches(".*result=\"[Ss]uccess\".*")) throw new IOException("Login failed"); m_loggedIn = true; m_loggedInUser = user; }   private String fullWikiURL(String wikiName) {       if (wikiName.contains("/") || wikiName.contains("\\")) return wikiName; else if (wikiName.contains(".")) return "http://" + wikiName + "/api.php"; else return "http://" + wikiName + ".wikia.com/api.php"; }   public void setWiki(String wikiName) {       API_URL = fullWikiURL(wikiName); }   public boolean isCurrentWiki(String wikiName) {       if (fullWikiURL(wikiName) == API_URL) return true; return false; }   public String getCurrentUser throws IOException {       if(m_loggedInUser != null &amp;&amp; m_loggedIn) return m_loggedInUser; else throw new IOException("Not logged in/Null username"); }   public boolean isLoggedIn {       return m_loggedIn; }

public void logout throws IOException, Core.jBotException {       updateLog; String cmd = "action=logout"; doCmd(cmd); m_loggedIn = false; m_loggedInUser = null; }

public String subst(String str) throws IOException {       String cmd = "action=expandtemplates&amp;text=" + URLEncoder.encode(str,"utf-8"); String result = doCmd(cmd);

String[] toks = Utils.extract(m_substPattern, result); if (toks != null) return Utils.decodeEntities(toks[1]);

return null; }

public String getText(String title) throws IOException {       String cmd = "action=query&amp;prop=info|revisions&amp;intoken=edit&amp;titles=" + URLEncoder.encode(title,"utf-8") + "&amp;rvprop=timestamp|content"; String result = doCmd(cmd);

m_lastGetTitle = title;

String[] toks = Utils.extract(m_editTokenPattern, result); m_lastGetEditToken = (toks != null ? toks[1] : null);

toks = Utils.extract(m_timestampPattern, result); m_lastGetTimestamp = (toks != null ? toks[1] : null);

toks = Utils.extract(m_getTextPattern, result); if (toks != null) return Utils.decodeEntities(toks[1]);

return title; }

public Date getLastTimestamp {       if (m_lastGetTimestamp == null) return null;

try {           return (Date)m_tsFmt.parse(m_lastGetTimestamp); }       catch (Exception e)        { return null; }   }

public boolean editText(String title, String text, String comment, boolean allowCreate) throws IOException, Core.jBotException {       if (!title.equals(m_lastGetTitle)) {           p.errString("Edit failed: title != lastTitle"); return false; }       String cmd = "action=edit" + "&amp;bot=true" + "&amp;title=" + URLEncoder.encode(title, "utf-8") + "&amp;summary=" + URLEncoder.encode(comment, "utf-8") + "&amp;text=" + URLEncoder.encode(text, "utf-8") + (allowCreate ? "" : "&amp;nocreate=1") + "&amp;token=" + URLEncoder.encode("" + m_lastGetEditToken, "utf-8") + "&amp;basetimestamp=" + URLEncoder.encode("" + m_lastGetTimestamp, "utf-8"); String result = doCmd(cmd);

if (lastStopCheck++ &gt;= 10) {           String t = getText("User:" + getCurrentUser + "/Control"); if (t == null) editText("User:" + getCurrentUser + "/Control", "Control page for TLULbot", "TLULbot control page - for when TLULbot edits on this account.", true); else if (t.contains("PAUSE")) {               Utils.log("Stopped by control page, after editing " + title); throw new Core.jBotException("Stopped by control page!"); }           lastStopCheck = 0; }

if (result.matches(".*result=\"[Ss]uccess\".*")) return true; else {           p.errString("Edit failed: " + result); return false; }   }    public boolean protectPage(String text, String comment) {       p.errString("Protect page functionality not coded. Suggested fix: Yell at the developper for procrastinating."); return false; }

public SortedSet&lt;String&gt; getAllPages(int namespace, String from, int limit) throws IOException {       String cmd = "action=query&amp;list=allpages&amp;apnamespace=" + namespace + "&amp;apfilterredir=nonredirects&amp;aplimit=" + (limit &lt; 500? limit : 500); if (from != null) cmd += "&amp;apfrom=" + URLEncoder.encode(from,"utf-8"); String result = doCmd(cmd);

SortedSet&lt;String&gt; allTitles = new TreeSet&lt;String&gt;; while (allTitles.size &lt; limit) {           Matcher titleMatcher = m_allPagesPattern.matcher(result); while (titleMatcher.find) {               String title = titleMatcher.group(1); allTitles.add(Utils.decodeEntities(title)); }

String[] toks = Utils.extract(m_apFromPattern, result); if (toks == null) break; // no more

String contCmd = cmd + "&amp;apfrom=" + toks[1]; result = doCmd(contCmd); }       return allTitles; }   public void updateLog throws IOException, Core.jBotException {       if (isLoggedIn == false) {           p.outString("Unable to log - not logged in"); return; //Cannot log as an IP       } if (Utils.getLogList.size == 0) return; // nothing to log

String wikiLog = "User:" + getCurrentUser + "/Log"; StringBuffer textBuf = new StringBuffer(getText(wikiLog)); textBuf.append("\n");

textBuf.append("==== ").append((new Date).toString).append(" ====\n"); for (String msg : Utils.getLogList) textBuf.append("* ").append(msg).append("\n");

if (!editText(wikiLog, textBuf.toString, "Adding logging", true)) p.errString("Failed to add to " + wikiLog); }

@Override protected void finalize throws Throwable {       try {           if (m_loggedIn) logout; }       finally {           super.finalize; }   }

}