Java tutorial
package bkampfbot; /* Copyright (C) 2011 georf@georf.de This file is part of BKampfBot. BKampfBot 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 2 of the License, or 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/>. */ import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; import json.JSONException; import json.JSONObject; import json.JSONTokener; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; import org.apache.http.NameValuePair; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.CookiePolicy; import org.apache.http.conn.params.ConnRoutePNames; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import bkampfbot.exceptions.FatalError; import bkampfbot.exceptions.LocationChangedException; import bkampfbot.exceptions.RestartLater; import bkampfbot.modes.Gluecksrad; import bkampfbot.modes.Jagd; import bkampfbot.modes.Lottery; import bkampfbot.modes.Pins; import bkampfbot.modes.Quiz; import bkampfbot.modes.ScratchTicket; import bkampfbot.modes.Tagesspiel; import bkampfbot.modes.TestProxy; import bkampfbot.modes.Wein; import bkampfbot.output.Output; import bkampfbot.plan.PlanAngriff; import bkampfbot.plan.PlanArbeiten; import bkampfbot.plan.PlanBoeseBeute; import bkampfbot.plan.PlanBoeseKrieg; import bkampfbot.plan.PlanBoeseRespekt; import bkampfbot.state.Config; import bkampfbot.state.User; import bkampfbot.utils.Aussendienst; public final class Instance { /** * for debugging */ public String lastResponse = null; public enum Daily { quiz, scratchTicket, glueck, wein, spiel, jagd, spielZwerg } public enum Modus { normal, daily, help, lottery, pins, testproxy } // Configuration from file public int additionalService = 0; public boolean lookAhead = false; // Modes private Modus modus = Modus.normal; private Daily[] daily; // Instance public DefaultHttpClient httpclient; /** * Parst die Parameter und liest die Konfigurationsdatei aus. * * @param args * @throws FatalError * @throws IOException * @throws RestartLater */ public Instance(String[] args) throws FatalError, IOException { // configure plans PlanBoeseBeute.initiate(); PlanBoeseKrieg.initiate(); PlanBoeseRespekt.initiate(); PlanAngriff.initiate(); // reset config new Config(); // reset user new User(); this.parseArguments(args); if (this.modus.equals(Modus.help)) { Output.help(); } // read config file try { File f = new File(Config.getConfigFile()); FileInputStream fstream = new FileInputStream(f.getAbsoluteFile()); DataInputStream in = new DataInputStream(fstream); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String strLine, configString = ""; // Read File Line By Line while ((strLine = br.readLine()) != null) { // Kommentare werden ausgelassen if (strLine.length() > 0 && strLine.substring(0, 1).equals("#")) { configString += "\n"; continue; } configString += strLine + "\n"; } // Close the input stream in.close(); try { JSONObject config = new JSONObject(new JSONTokener(configString)); Config.parseJsonConfig(config); } catch (JSONException e) { int lines = configString.substring(0, e.getIndex()).replaceAll("[^\n]", "").length(); throw new FatalError( "Die Struktur der Konfigurationsdatei " + "stimmt nicht. Versuche den Inhalt der " + "Datei mit einem externen Werkzeug zu " + "reparieren. Dafr gibt es Webseiten, " + "die JSON-Objekte validieren knnen. Vermutlich in der Zeile " + lines + "." + "\n\nAls Hinweis hier noch die Fehlerausgabe:\n" + e.getMessage() + "\n\nEingabe war:\n" + e.getInputString()); } } catch (FileNotFoundException e) { throw new FatalError("Die Konfigurationsdatei konnte nicht gefunden/geffnet werden.\n Datei: " + Config.getConfigFile() + "\n Fehler: " + e.getMessage()); } if (Config.getUserName() == null || Config.getUserPassword() == null || Config.getHost() == null) { throw new FatalError("Die Konfigurationsdatei ist nicht vollstndig. " + "Es wird mindestens der Benutzername, das " + "Passwort und der Hostname bentigt."); } } private final boolean finishOldWork() throws FatalError { Output.printClockLn("Versuche alte Aufgaben zu beenden.", 2); boolean returnValue = false; switch (User.getStatus()) { case work: returnValue = PlanArbeiten.finish(); break; case service: returnValue = Aussendienst.finish(); break; case training: Output.printTabLn("Versuche das Training zu beenden.", 1); Utils.visit("training"); returnValue = true; break; case nothing: default: returnValue = true; break; } this.getCharacter(); return returnValue; } public final String getCharacter() throws FatalError { return this.getCharacter(false); } /** * Sammelt Informationen ber Benutzer * * @param login * gibt an, ob es der Aufruf nach dem Login ist */ private final String getCharacter(boolean login) throws FatalError { HttpGet httpget = new HttpGet(Config.getHost() + "characters"); httpget.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); httpget.addHeader("Accept-Language", "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"); // httpget.addHeader("Accept-Encoding","deflate"); httpget.addHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7"); httpget.addHeader("Keep-Alive", "300"); if (login) { httpget.addHeader("Referer", Config.getHost() + "signups/login"); } String s = ""; try { // Create a response handler HttpResponse response = this.httpclient.execute(httpget); HttpEntity entity = response.getEntity(); if (entity != null) { s = EntityUtils.toString(entity); this.testStatus(s); int navi2 = s.indexOf("flashvars"); int lineFront = s.indexOf('{', navi2); int lineEnd = s.indexOf(';', lineFront + 1); String s2 = s.substring(lineFront + 1, lineEnd + 1); s2 = "{" + s2; JSONTokener tk = new JSONTokener(s2); JSONObject character = new JSONObject(tk); User.setLevel(Integer.parseInt(character.getString("lvl"))); User.setMaxLivePoints(Integer.parseInt(character.getString("max_lp"))); User.setCurrentLivePoints(Integer.parseInt(character.getString("lp"))); User.setGold(Integer.parseInt(character.getString("water"))); // try to find race s2 = "<b>Bundesland:</b> </span><br/><span style=\"color:#000000; font-size:12px;\">"; lineFront = s.indexOf(s2); lineEnd = s.indexOf('<', lineFront + 1 + s2.length()); User.setRace(s.substring(lineFront + s2.length() + 1, lineEnd - 1)); // Output.user(user); } } catch (JSONException e) { if (s.contains("form action=\"/signups/login\" method=\"post\"")) { throw new FatalError("Login fehlgeschlagen. " + "Vermutlich sind die Benutzerdaten nicht korrekt."); } String message = "Get an error at initiation\n"; if (login) { message += "Reason 1: Login failed\n" + "Reason 2: Something on server side changed.\n"; } else { message += "Possible reason: Something on server side changed.\n"; } message += "\n" + "If you want to report a bug, please post this:\n\n" + e.getMessage() + "\n"; StackTraceElement[] trace = e.getStackTrace(); for (StackTraceElement elem : trace) { message += elem.toString() + "\n"; } throw new FatalError(message + "\nResponse was:\n" + s); } catch (IOException e) { Output.error(e); throw new FatalError("Es gab einen Verbindungsfehler."); } return s; } /** * Fhrt den Login durch */ private final void login() throws FatalError { try { Output.printClockLn("Login (" + Config.getUserName() + ")", 1); // create post data HttpPost httppost = new HttpPost(Config.getHost() + "signups/login/"); List<NameValuePair> nvps = new ArrayList<NameValuePair>(); nvps.add(new BasicNameValuePair("data[Signup][name]", Config.getUserName())); nvps.add(new BasicNameValuePair("data[Signup][pass]", Config.getUserPassword())); nvps.add(new BasicNameValuePair("Einloggen.x", "67")); nvps.add(new BasicNameValuePair("Einloggen.y", "18")); httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); httppost.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); httppost.addHeader("Accept-Language", "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"); httppost.addHeader("Accept-Encoding", "gzip,deflate"); httppost.addHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7"); httppost.addHeader("Keep-Alive", "300"); httppost.addHeader("Referer", Config.getHost() + "signups/login"); // send post HttpResponse response = this.httpclient.execute(httppost); HttpEntity entity = response.getEntity(); if (entity != null) { entity.consumeContent(); } this.getCharacter(true); // Ist User im Verein? try { Utils.getString("verein/buendnisse", "verein/index"); User.setGuildMember(true); } catch (LocationChangedException e) { User.setGuildMember(false); } } catch (IOException e) { Output.println(e.getMessage(), 0); throw new FatalError(e.getMessage()); } } /** * Fhrt das Logout durch */ public final void logout() { Output.printClockLn("Logout", 1); Utils.visit("signups/logout"); } /** * Prft bergebene Argumente * * @param args */ private final void parseArguments(String[] args) { this.daily = new Daily[args.length]; int dailyCount = 0; for (String arg : args) { if (arg.startsWith("quiz") && (this.modus.equals(Modus.normal) || this.modus.equals(Modus.daily)) && (arg.equals("quiz") || arg.matches("^quiz=[1-9]$"))) { if (arg.matches("^quiz=[1-9]$")) { Quiz.wrongAnswerCount = Integer.parseInt(arg.replaceAll("[^1-9]", "")); } this.modus = Modus.daily; this.daily[dailyCount] = Daily.quiz; dailyCount++; continue; } if (arg.equals("los") && (this.modus.equals(Modus.normal) || this.modus.equals(Modus.daily))) { this.modus = Modus.daily; this.daily[dailyCount] = Daily.scratchTicket; dailyCount++; continue; } if (arg.startsWith("lotto") && this.modus.equals(Modus.normal)) { if (arg.equals("lotto")) { this.modus = Modus.lottery; continue; } else if (arg.matches("^lotto=(([1-9]|([1-4][0-9])),){4}([1-9]|([1-4][0-9]))$")) { this.modus = Modus.lottery; String[] numbers = arg.replaceAll("[^0-9,]+", "").split(","); if (numbers.length != 5) { Output.println("Lottozahlen sind ungltig", Output.ERROR); } for (int i = 0; i < 5; i++) { Lottery.numbers[i] = Integer.parseInt(numbers[i]); } Lottery.random = false; continue; } } if (arg.length() > 5 && arg.substring(0, 5).equalsIgnoreCase("pins=") && this.modus.equals(Modus.normal)) { Pins.in = arg.substring(5); this.modus = Modus.pins; continue; } if (arg.equals("glueck") && (this.modus.equals(Modus.normal) || this.modus.equals(Modus.daily))) { this.modus = Modus.daily; this.daily[dailyCount] = Daily.glueck; dailyCount++; continue; } if (arg.equals("wein") && (this.modus.equals(Modus.normal) || this.modus.equals(Modus.daily))) { this.modus = Modus.daily; this.daily[dailyCount] = Daily.wein; dailyCount++; continue; } if (arg.equals("spiel") && (this.modus.equals(Modus.normal) || this.modus.equals(Modus.daily))) { this.modus = Modus.daily; this.daily[dailyCount] = Daily.spiel; dailyCount++; continue; } if (arg.equals("spielmitzwerg") && (this.modus.equals(Modus.normal) || this.modus.equals(Modus.daily))) { this.modus = Modus.daily; this.daily[dailyCount] = Daily.spielZwerg; dailyCount++; continue; } if (arg.equals("jagd") && (this.modus.equals(Modus.normal) || this.modus.equals(Modus.daily))) { this.modus = Modus.daily; this.daily[dailyCount] = Daily.jagd; dailyCount++; continue; } if (arg.length() > 9 && arg.substring(0, 9).equalsIgnoreCase("--config=")) { Config.setConfigFile(arg.substring(9)); continue; } if (arg.equals("--help") || args.equals("-h")) { this.modus = Modus.help; continue; } if (arg.equals("testproxy") && this.modus.equals(Modus.normal)) { this.modus = Modus.testproxy; continue; } // Argument passt nicht Output.println("Argument \"" + arg + "\" nicht gltig", Output.ERROR); System.exit(1); } } /** * Fhrt die aktuelle Instans aus * * @throws ClientProtocolException * @throws IOException * @throws FatalError * @throws JSONException * @throws RestartLater * @throws NoSuchAlgorithmException */ public final void run() throws FatalError, RestartLater { // initialization HTTP client this.httpclient = new DefaultHttpClient(); final HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setUseExpectContinue(params, false); HttpProtocolParams.setUserAgent(params, Config.getUserAgent()); this.httpclient.setParams(params); if (Config.getProxyHost() != null && Config.getProxyPort() != 0) { if (Config.getProxyUsername() != null && Config.getProxyPassword() != null) { httpclient.getCredentialsProvider().setCredentials( new AuthScope(Config.getProxyHost(), Config.getProxyPort()), new UsernamePasswordCredentials(Config.getProxyUsername(), Config.getProxyPassword())); } HttpHost proxy = new HttpHost(Config.getProxyHost(), Config.getProxyPort()); httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); } this.httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY); switch (this.modus) { // default: do nothing default: break; // call help case help: Output.help(); System.exit(0); break; // call proxy test case testproxy: new TestProxy(); System.exit(0); break; } // login this.login(); this.switchToSpeedHost(); switch (this.modus) { // for things without login case help: case testproxy: break; case daily: for (Daily d : this.daily) { if (d == null) break; switch (d) { // call "Rubbellos" case scratchTicket: ScratchTicket.getInstance().run(); break; // call "Tagesquiz" case quiz: Quiz.getInstance().run(); break; // call "Lotto" case glueck: Gluecksrad.getInstance().run(); break; // call "Weinfsser" case wein: Wein.getInstance().run(); break; // call "Tagesspiel" case spiel: Tagesspiel.getInstance().run(); break; // call "Tagesspiel" case spielZwerg: Tagesspiel.getInstance(true).run(); break; // call "Wrterjagd" case jagd: Jagd.getInstance().run(); break; } } Control.safeExit(); break; // call "Lotto" case lottery: Lottery.getInstance().run(); Control.safeExit(); break; // call "Pins" case pins: Pins.getInstance().run(); Control.safeExit(); break; // call "Plan" default: case normal: if (Config.getPlan0() == null && Config.getPlan1() == null) { Output.printTabLn("Beide Plne sind leer. " + "Bitte berprfen Sie die Konfiguration.", 0); System.exit(1); } Calendar lastCall = null; while (true) { Calendar now = new GregorianCalendar(); now.setTime(Config.getDate()); now.add(Calendar.MINUTE, -2); if (lastCall != null && lastCall.after(now)) { Output.println("Der Bot war bei der Abarbeitung der Plne zu schnell. " + "Vermutlich trat ein Fehler auf. Damit wir nicht auffallen, " + "warten wir 5 Minuten.", 1); Control.sleep(3000); } lastCall = new GregorianCalendar(); this.runPlans(); Control.sleep(5); this.getCharacter(); Control.sleep(5); } } } private void switchToSpeedHost() throws FatalError { if (Config.getSpeedHost() != null) { try { String page = Utils.getString("speed/index"); int pos = page.indexOf("speedlink"); if (pos < 0) throw new NotFound(); page = page.substring(pos); pos = page.indexOf("\""); if (pos < 0) throw new NotFound(); page = page.substring(pos + 1); pos = page.indexOf("\""); if (pos < 0) throw new NotFound(); page = page.substring(0, pos); page = page.substring(Config.getSpeedHost().length()); Config.setHost(Config.getSpeedHost()); Utils.getString(page); getCharacter(); } catch (NotFound e) { } } } /** * Durchluft beide Plne genau ein mal * * @throws FatalError * @throws RestartLater * wird von Plnen geworfen */ private final void runPlans() throws FatalError, RestartLater { // first check for old not finished task if (!User.getStatus().equals(User.Status.nothing)) { for (int i = 0; i < 3 && !this.finishOldWork(); i++) { Control.sleep(3600); } if (!User.getStatus().equals(User.Status.nothing)) { throw new FatalError("Konnte die alte Aufgabe nicht beenden."); } } // Ab Version 1.0.beta11 muss plan0 nicht gesetzt sein if (Config.getPlan0() != null) { Config.getPlan0().run(); } // Ab Version 1.0.beta11 muss plan1 nicht gesetzt sein if (Config.getPlan1() != null) { Config.getPlan1().run(); } } /** * berprft das Ergebniss der Profilseite auf Hinweise zur aktuellen * Ttigkeit. * * @param HTML */ private final void testStatus(String s) { if (s.indexOf("/Bilderx/arbeiten.jpg") != -1) { User.setStatus(User.Status.work); Output.printTabLn("Du bist gerade am Arbeiten", 2); } else if (s.indexOf("/Bilderx/train.jpg") != -1) { User.setStatus(User.Status.training); Output.printTabLn("Du bist gerade am Trainieren", 2); } else if (s.indexOf("/Bilderx/dienst.jpg") != -1) { User.setStatus(User.Status.service); Output.printTabLn("Du bist im Auendienst", 2); } else { User.setStatus(User.Status.nothing); } } /** * Wartet bis das Leben aufgefllt ist. * * @throws FatalError * @throws IOException * @throws ClientProtocolException * * @throws ClientProtocolException * @throws IOException * @throws FatalError */ public final void waitForStatus() throws FatalError { getCharacter(); while (User.getCurrentLivePoints() != User.getMaxLivePoints()) { Output.printTabLn("Warte bis Leben aufgefllt ist.", 2); Control.sleep(300, 2); getCharacter(); } } public class NotFound extends Exception { private static final long serialVersionUID = -7987563389035661007L; } }