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

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

Atualiza a informação na página de recordes 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.Pattern;

@Description(summary = "Atualiza a informação na página de recordes dos utilizadores.")
public class HighscoresTask implements BotTask
{
    private WikiSession m_wiki = null;
    private DateFormat m_dateFmt = null;

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

    private final static int MAX_HISTORY = 14;
    private final static int HS_DELAY = 2*1000;

    private final static int MAX_FAIL_DAYS = 7;

    private final Pattern m_templatePattern = Pattern.compile("\\@\\@Hiscore autoupdate(.*?)\\$\\$");	// Recordes 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_historyPattern = Pattern.compile("\\|\\s*history\\s*=\\s*(\\d+)");

    private final Pattern m_timePattern[];
    private final Pattern m_dataPattern[];

    private final static String HS_URL = "http://hiscore.runescape.com/index_lite.ws?player=";

	public HighscoresTask(WikiSession wiki) {
		m_wiki = wiki;
		m_dateFmt = new SimpleDateFormat("yyyyMMddHHmmss", Locale.UK);
		m_dateFmt.setTimeZone(TimeZone.getTimeZone("UTC"));

		m_timePattern = new Pattern[MAX_HISTORY + 1];
		m_dataPattern = new Pattern[MAX_HISTORY + 1];
		for (int i = 0; i <= MAX_HISTORY; i++) {
			m_timePattern[i] = Pattern.compile("\\| *time" + i + "\\b[^=}]*= *([^<|}]+)");
			m_dataPattern[i] = Pattern.compile("\\| *data" + i + "\\b[^=}]*= *([^<|}]+)");
		}

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

	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:Recordes 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 de recordes " + 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 de recordes " + 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("'Jogador' em falta encontrado 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("'Página' em falta encontrada 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("'Página' inválida encontrada 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_historyPattern, text);
			long history = (toks != null ? Utils.parseNum(toks[1], null, 1) : 1);
			if (history > MAX_HISTORY)
				interval = MAX_HISTORY;
			if (history < 1)
				interval = 1;

			if (updateHighscoreData(reqPage, player, dataPage, interval,
					history))
				updated++;

			if (m_fatalError)
				return;
		}

    	if (updated > 0)
    	{
    		Utils.log(updated + " páginas de recordes de utilizadores atualizadas");

    		StringBuilder newList = new StringBuilder();
    		newList.append("== Lista Negra de Recordes ==\n");
    		for (String reqPage : m_badReqPages)
    			newList.append("*").append(reqPage).append("\n");
    		m_wiki.getText(m_badRecord);
    		m_wiki.editText(m_badRecord, newList.toString(), "Lista negra atualizada", true);
    	}
    }

	private boolean updateHighscoreData(String reqPage, String player, String dataPage,
										long interval, long history)
            throws IOException
    {
		String text = m_wiki.getText(dataPage);

        if (text == null)
            text = "";

        // get time of last update entry
        Date lastUpdate = null;
        String[] toks = Utils.extract(m_timePattern[0], text);
        if (toks != null)
        {
            try
            {
                lastUpdate = m_dateFmt.parse(toks[1]);
            }
            catch (Exception ex)
            {
                // ignore
            }
        }
        if (lastUpdate == null)
            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(HS_DELAY);

            newData = Utils.getInternetPage(HS_URL + player.replace(' ','+'),
                                            null, null);
        }
        catch (Exception ex)
        {
            if (!ex.toString().contains("Error 404"))
            {
                Utils.log("ERRO: Erro fatal ao obter os recordes de "
                        + player + "' e pedido em [[" + reqPage + "]]");
                m_fatalError = true;
                return false;
            }

            if (updateDay > MAX_FAIL_DAYS)
            	m_badReqPages.add(reqPage);
            String failText = "Falha ao obter recordes para '"
                    + player + "' como pedido em [[" + reqPage + "]]";
            if (lastUpdate == null)
                m_wiki.editText(dataPage, failText, "Recordes de utilizador atualizados, 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|}}}}}");
        for (int i = 1; i <= history; i ++)
        {
            toks = Utils.extract(m_timePattern[i-1], text);
            if (toks == null)
                break;
            String histTime = toks[1];

            toks = Utils.extract(m_dataPattern[i-1], text);
            if (toks == null)
                break;
            String histData = toks[1];

            newText.append("|time").append(i).append("=").append(histTime);
            newText.append("|data").append(i).append("=").append(histData);
        }
        newText.append("|time|time0=").append(newTime);
        newText.append("|data|data0|#default=").append(newData);
        newText.append("}}");

        if (!m_wiki.editText(dataPage, newText.toString(),
                "Recordes de utilizadores atualizados, pedido de " + reqPage, true))
        {
            Utils.log("AVISO: Falha ao atualizar [[" + dataPage + "]] (possível conflicto)");
            return false;
        }
        
        return true;
    }
}