Usuário:SandroHcBot/Código Fonte/AdvlogTask

De RuneScape Wiki
Ir para: navegação, pesquisa

Atualiza a informação na página do diário de aventuras dos utilizadores.

/*--------------------------------------------------------
 * AmauriceBot - RuneScape Wikia update task robot
 * Copyright (c) 2009-2012  Maurice Abraham.
 *
 * 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 <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *   None
 *------------------------------------------------------*/

package amauricebot;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Description(summary = "Atualiza a informação na página do diário de aventuras dos utilizadores.")
public class AdvlogTask implements BotTask {
	private WikiSession m_wiki = null;
	private DateFormat m_dateFmt = null;
	private DateFormat m_pubDateFmt = null;
	private DateFormat m_eventDateFmt = null;

	private String m_badRecord = null;
	private TreeSet<String> m_badReqPages = new TreeSet<String>();
	private boolean m_fatalError = false;

	private final static int DEFAULT_ITEMS = 10;
	private final static int AL_DELAY = 70 * 1000; // Jagex allows max 1 per minute
	private final static int MAX_FAIL_DAYS = 7;

	private final Pattern m_templatePattern = Pattern.compile("\\@\\@Advlog autoupdate(.*?)\\$\\$");	// Advlog atualizar
	private final Pattern m_playerPattern = Pattern.compile("\\|\\s*player\\s*=\\s*([^|\\n]*)");
	private final Pattern m_pagePattern = Pattern.compile("\\|\\s*page\\s*=\\s*([^|\\n]*)");
	private final Pattern m_intervalPattern = Pattern.compile("\\|\\s*interval\\s*=\\s*(\\d+)");
	private final Pattern m_itemsPattern = Pattern.compile("\\|\\s*items\\s*=\\s*(\\d+)");
	private final Pattern m_datePattern = Pattern.compile("\\|\\s*date\\s*=\\s*([^|\\n]*)");
	private final Pattern m_formatPattern = Pattern.compile("\\|\\s*format\\s*=\\s*([^|\\n]*)");

	private final Pattern m_itemPattern = Pattern.compile("<item>(.*?)</item>");
	private final Pattern m_titlePattern = Pattern.compile("<title>(.*?)</title>");
	private final Pattern m_descPattern = Pattern.compile("<description>(.*?)</description>");
	private final Pattern m_pubDatePattern = Pattern.compile("<pubDate>(.*?)</pubDate>");

	private final static String AL_URL = "http://services.runescape.com/m=adventurers-log/l=3/rssfeed?searchName=";

	private final static String[] m_eventMaps = {
			"(Aumentei meu nível de ) (\\w+).*(agora sou nível  \\d+) =>; '''$1''' {{ícone|$2}} &amp;mdash; $3",
			"(Missão cumprida: )(.*?)---.* =>; '''$1[[$2]]'''",
			"(.*?)---.* =>; '''$1'''" };

	public AdvlogTask(WikiSession wiki) {
		m_wiki = wiki;
		
		Locale locale = new java.util.Locale("pt","PT");

		m_dateFmt = new SimpleDateFormat("yyyyMMddHHmmss", Locale.UK);
		m_dateFmt.setTimeZone(TimeZone.getTimeZone("UTC"));

		m_pubDateFmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", locale);
		m_pubDateFmt.setTimeZone(TimeZone.getTimeZone("UTC"));

		m_eventDateFmt = new SimpleDateFormat("d MMMM, yyyy", locale);
		m_eventDateFmt.setTimeZone(TimeZone.getTimeZone("UTC"));

		String loginUser = m_wiki.getLoginUser();
		if (loginUser != null)
			m_badRecord = "Utilizador:" + loginUser + "/MausDiários";
	}

	public void perform() throws IOException {
		if (m_badRecord == null)
			return;

		String badList = m_wiki.getText(m_badRecord);
		if (badList == null)
			badList = "";
		for (String line : badList.split("\\r?\\n")) {
			if (line.startsWith("*"))
				m_badReqPages.add(line.substring(1));
		}

		int updated = 0;
		for (String reqPage : m_wiki.getEmbeddedUsages("Predefinição:Advlog atualizar", 2, 500)) {
			if (m_badReqPages.contains(reqPage))
				continue;

			String text = m_wiki.subst("{{" + reqPage + "}}");
			if (text == null) {
				Utils.log("Falha ao obter a página do diário de aventuras " + reqPage);
				m_wiki.getText(reqPage);
				if (m_wiki.getLastAgeDays() >= MAX_FAIL_DAYS)
					m_badReqPages.add(reqPage);
				continue;
			}

			String[] toks = Utils.extract(m_templatePattern, text);
			if (toks == null) {
				Utils.log("Falha ao obter a predefinição do diário de aventuras de " + reqPage);
				m_wiki.getText(reqPage);
				if (m_wiki.getLastAgeDays() >= MAX_FAIL_DAYS)
					m_badReqPages.add(reqPage);
				continue;
			}
			text = toks[1];

			toks = Utils.extract(m_playerPattern, text);
			if (toks == null) {
				Utils.log("O nome do jogador está em falta em " + reqPage);
				m_wiki.getText(reqPage);
				if (m_wiki.getLastAgeDays() >= MAX_FAIL_DAYS)
					m_badReqPages.add(reqPage);
				continue;
			}
			String player = toks[1];

			toks = Utils.extract(m_pagePattern, text);
			if (toks == null) {
				Utils.log("O nome da página está em falta em " + reqPage);
				m_wiki.getText(reqPage);
				if (m_wiki.getLastAgeDays() >= MAX_FAIL_DAYS)
					m_badReqPages.add(reqPage);
				continue;
			}
			String dataPage = toks[1];

			String lcUser = reqPage.toLowerCase().replaceFirst("/.*", "");
			dataPage = dataPage.replace('_', ' ');
			if (dataPage.toLowerCase().equals(reqPage.toLowerCase()) || !dataPage.toLowerCase().startsWith(lcUser + "/")) {
				Utils.log("O nome da página está incorreto em " + reqPage);
				m_wiki.getText(reqPage);
				if (m_wiki.getLastAgeDays() >= MAX_FAIL_DAYS)
					m_badReqPages.add(reqPage);
				continue;
			}

			toks = Utils.extract(m_intervalPattern, text);
			long interval = (toks != null ? Utils.parseNum(toks[1], null, 1) : 1);
			if (interval < 1)
				interval = 1;

			toks = Utils.extract(m_itemsPattern, text);
			long maxItems = (toks != null ? Utils.parseNum(toks[1], null, 1) : 10);
			if (maxItems < 1)
				maxItems = DEFAULT_ITEMS;

			toks = Utils.extract(m_datePattern, text);
			String withDate = (toks != null ? toks[1] : "yes");

			toks = Utils.extract(m_formatPattern, text);
			String format = (toks != null ? toks[1] : "list");

			if (updateAdvlogData(reqPage, player, dataPage, interval, maxItems,
					!withDate.toLowerCase().equals("no"), format.toLowerCase()))
				updated++;

			if (m_fatalError)
				return;
		}

		if (updated > 0) {
			Utils.log(updated + " páginas de entradas do diário de aventuras atualizadas");

			StringBuilder newList = new StringBuilder();
			newList.append("== Lista Negra de Diários de Aventuras ==\n");
			for (String reqPage : m_badReqPages)
				newList.append("*").append(reqPage).append("\n");
			m_wiki.getText(m_badRecord);
			m_wiki.editText(m_badRecord, newList.toString(), "Atualizada a lista negra", true);
		}
	}

	private boolean updateAdvlogData(String reqPage, String player,
			String dataPage, long interval, long maxItems, boolean withDate,
			String format) throws IOException {
		String oldText = m_wiki.getText(dataPage);
		if (oldText == null)
			oldText = "";
		if (oldText.contains("<rss>"))
			return false; // already using <rss> instead

		Date lastUpdate = m_wiki.getLastTimestamp();

		long updateDay = 0;
		if (lastUpdate != null) {
			updateDay = Utils.ageDays(lastUpdate) - interval;
			if (updateDay < 0)
				return false;
		}

		String newData;
		try {
			Thread.sleep(AL_DELAY);

			newData = Utils.getInternetPage(AL_URL + player.replace(' ', '+'),
					null, null);
		} catch (Exception ex) {
			if (!ex.toString().contains("Error 404")) {
				Utils.log("ERRO: Ocorreu um erro ao obter as entradas de aventuras de " + player + "' como pedido em [[" + reqPage + "]]");
				m_fatalError = true;
				return false;
			}

			if (updateDay > MAX_FAIL_DAYS)
				m_badReqPages.add(reqPage);
			String failText = "Ocorreu um erro ao obter as entradas de aventuras de '" + player + "' como pedido em [[" + reqPage + "]]";
			if (lastUpdate == null)
				m_wiki.editText(dataPage, failText, "Entradas do Diário de Aventuras atualizadas, pedido por " + reqPage, true);
			return false;
		}

		newData = newData.replaceAll("\\s+", " ");
		String newTime = m_dateFmt.format(new Date());
		StringBuilder newText = new StringBuilder();
		newText.append("{{#switch:{{lc:{{{1|}}}}}|time=").append(newTime)
				.append("|data|#default=");

		Matcher itemMatcher = m_itemPattern.matcher(newData);
		long numItems = 0;
		while (numItems < maxItems && itemMatcher.find()) {
			String itemText = itemMatcher.group(1);

			// get main event text from rss title field
			String[] toks = Utils.extract(m_titlePattern, itemText);
			if (toks == null)
				break;
			String event = toks[1].trim();

			// append description text to event text for now
			toks = Utils.extract(m_descPattern, itemText);
			if (toks == null)
				break;
			event = event + "---" + toks[1].trim();
			event = Utils.decodeEntities(event);

			// now map event text to appropriate strings
			for (int i = 0; i < m_eventMaps.length; i++) {
				String[] map = m_eventMaps[i].split(" =>; ", 2);
				event = event.replaceFirst(map[0], map[1]);
			}

			// get event date from the rss pubDate field
			toks = Utils.extract(m_pubDatePattern, itemText);
			if (toks == null)
				break;
			String pubDate = toks[1];
			try {
				Date tmpDate = m_pubDateFmt.parse(pubDate);
				pubDate = m_eventDateFmt.format(tmpDate);
			} catch (Exception ex) {
				// ignore
			}

			if (format.equals("table")) {
				newText.append("\n<tr>");
				if (withDate)
					newText.append("<td style=\"text-align:center;\">")
							.append(pubDate).append("</td>");
				newText.append("<td>").append(event)
						.append("</td></tr>");
			} else {
				newText.append("\n*");
				if (withDate)
					newText.append(pubDate).append(": ");
				newText.append(event);
			}
			numItems++;
		}
		newText.append("}}");
		if (numItems == 0) {
			Utils.log("AVISO: Falha ao obter qualquer entrada do diário de aventuras para '" + player + "', pedido por [[" + reqPage + "]]");
			return false;
		}

		if (!m_wiki.editText(dataPage, newText.toString(), "Entradas do Diário de Aventuras atualizadas, pedido por " + reqPage, true)) {
			Utils.log("AVISO: Falha ao atualizar [[" + dataPage + "]] (possível conflicto)");
			return false;
		}

		return true;
	}
}