tkbautobooking.BookingSystem.java Source code

Java tutorial

Introduction

Here is the source code for tkbautobooking.BookingSystem.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package tkbautobooking;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import static java.lang.System.out;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.logging.Logger;
import org.apache.http.Header;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.AbstractHttpMessage;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 *
 * @author Jasper
 */
public class BookingSystem {

    private static final Logger logger = Logger.getLogger(BookingSystem.class.getName());

    private String userId;
    private String userPassword;

    private String LoginPageHTML;
    private String BookingPageHTML;
    private String ClassroomJSON;
    private String DateJSON;
    private String TimeJSON;
    private String BookingResultJSON;
    private String login_hidden_token;
    private String booking_hidden_token;
    private Map<String, String> cookieMap;
    private Map<String, String> classMap;
    private Map<String, String> dateMap;
    private Map<String, String> classroomMap;
    private Map<String, Map<String, String>> timeMap;

    public BookingSystem(String id, String pwd) throws Exception {
        userId = id;
        userPassword = pwd;

        getLoginPage();
        praseLoginPage();
        postLoginInfo();
        getBookingPage();
        praseBookingPage();
        praseBookingToken();
    }

    public Map<String, String> getClassMap() {
        return classMap;
    }

    public Map<String, String> getClassroomMap() {
        return classroomMap;
    }

    public Map<String, String> getDateMap() {
        return dateMap;
    }

    public Map<String, Map<String, String>> getTimeMap() {
        return timeMap;
    }

    public void chooseClass(String classValue) throws IOException {

        postClassData(classValue);
        praseClassroomJSON();
        praseDateJSON();

    }

    public void chooseClassroom(String classroomValue) throws IOException {

        timeMap = new TreeMap<>();
        for (Entry<String, String> entry : dateMap.entrySet()) {
            postClassroomData(entry.getKey(), classroomValue);
            Map<String, String> map = praseTimeJSON();
            timeMap.put(entry.getKey(), map);
        }

    }

    public List<String> checkBookingSeat(String classroomValue, String dateValue) throws IOException {

        postClassroomData(dateValue, classroomValue);
        List<String> haveSeatList = praseBookingSeat();

        return haveSeatList;
    }

    public boolean goBooking(String classValue, String classroomValue, String dateValue, String timeValue)
            throws Exception {

        getBookingPage();
        praseBookingToken();
        postBookingData(classValue, classroomValue, dateValue, timeValue);
        boolean isBookingSuccess = praseBookingResult();

        return isBookingSuccess;
    }

    public void reLogin() throws Exception {

        getLoginPage();
        praseLoginPage();
        postLoginInfo();

    }

    private void getLoginPage() throws IOException {

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(BookingParam.WEB_LOGIN_URI);
            httpGet.setConfig(BookingParam.REQUEST_PARAMS);

            try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
                //  HttpStatusCode != 200
                if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    String ErrorCode = "Response Status : " + httpResponse.getStatusLine().getStatusCode();
                    throw new IOException(ErrorCode);
                }

                try (InputStreamReader isr = new InputStreamReader(httpResponse.getEntity().getContent(),
                        StandardCharsets.UTF_8); BufferedReader reader = new BufferedReader(isr)) {

                    cookieMap = new TreeMap<>();
                    for (Header header : httpResponse.getHeaders("Set-Cookie")) {
                        //out.println(header);
                        String hstr = header.getValue().split(";")[0];
                        cookieMap.put(hstr.split("=", 2)[0], hstr.split("=", 2)[1]);
                    }

                    String line;
                    StringBuilder builder = new StringBuilder();

                    while ((line = reader.readLine()) != null) {
                        builder.append(line);
                        builder.append("\n");
                    }
                    LoginPageHTML = builder.toString();
                }
            }
        }
    }

    private void praseLoginPage() throws Exception {

        Document doc = Jsoup.parse(LoginPageHTML);
        Elements token_elm = doc.getElementsByAttributeValue("name", "access_token");

        if (token_elm.isEmpty() || token_elm.size() > 1 || !token_elm.first().hasAttr("value"))
            throw new Exception("Prase Login Page fail !");

        login_hidden_token = token_elm.first().attr("value");

    }

    private void postLoginInfo() throws IOException {

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(BookingParam.WEB_LOGIN_POST_URI);
            httpPost.setConfig(BookingParam.REQUEST_PARAMS);
            httpPost.addHeader("Referer", BookingParam.WEB_LOGIN_URI);

            setCookieData(httpPost);

            //  ??
            List<NameValuePair> nvps = new ArrayList<>();
            nvps.add(new BasicNameValuePair("id", userId));
            nvps.add(new BasicNameValuePair("pwd", userPassword));
            nvps.add(new BasicNameValuePair("access_token", login_hidden_token));
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));

            try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
                //  HttpStatusCode != 302
                if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_MOVED_TEMPORARILY) {
                    String ErrorCode = "Response Status : " + httpResponse.getStatusLine().getStatusCode() + "\n";
                    ErrorCode += "";
                    throw new IOException(ErrorCode);
                }
                /*
                try ( InputStreamReader isr = new InputStreamReader(httpResponse.getEntity().getContent(), StandardCharsets.UTF_8);
                    BufferedReader reader = new BufferedReader(isr) ) {
                String line;
                StringBuilder builder = new StringBuilder();
                    
                while ( (line = reader.readLine()) != null ) {
                    builder.append(line);
                    builder.append("\n");
                }
                }*/
            }
        }

    }

    private void getBookingPage() throws IOException {

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(BookingParam.WEB_BOOKING_URI);
            httpGet.setConfig(BookingParam.REQUEST_PARAMS);
            httpGet.addHeader("Referer", BookingParam.WEB_LOGIN_POST_URI);

            setCookieData(httpGet);

            try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
                //  HttpStatusCode != 200
                if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    String ErrorCode = "Response Status : " + httpResponse.getStatusLine().getStatusCode();
                    throw new IOException(ErrorCode);
                }

                try (InputStreamReader isr = new InputStreamReader(httpResponse.getEntity().getContent(),
                        StandardCharsets.UTF_8); BufferedReader reader = new BufferedReader(isr)) {

                    String line;
                    StringBuilder builder = new StringBuilder();

                    while ((line = reader.readLine()) != null) {
                        builder.append(line);
                        builder.append("\n");
                    }
                    BookingPageHTML = builder.toString();
                }
            }
        }
    }

    private void praseBookingPage() throws Exception {

        Document doc = Jsoup.parse(BookingPageHTML);
        Element class_selector = doc.getElementById("class_selector");

        if (class_selector == null)
            throw new Exception("Prase Booking Page fail !");

        classMap = new TreeMap<>();
        for (Element option : class_selector.getElementsByTag("option")) {
            if (option.attr("value").equals(""))
                continue;

            classMap.put(option.attr("value"), option.text().replace("", " "));
        }
    }

    private void praseBookingToken() throws Exception {

        Document doc = Jsoup.parse(BookingPageHTML);
        Element script = doc.getElementsByTag("script").last();

        String str = script.toString().substring(script.toString().indexOf("access_token"));
        str = str.substring(str.indexOf("\"") + 1);
        str = str.substring(0, str.indexOf("\""));

        booking_hidden_token = str;
    }

    private void postClassData(String classValue) throws IOException {

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(BookingParam.WEB_BOOKING_CLASSROOM_URI);
            httpPost.setConfig(BookingParam.REQUEST_PARAMS);
            httpPost.addHeader("Referer", BookingParam.WEB_BOOKING_URI);

            setCookieData(httpPost);

            List<NameValuePair> nvps = new ArrayList<>();
            nvps.add(new BasicNameValuePair("class_data", classValue));
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));

            try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
                //  HttpStatusCode != 200
                if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    String ErrorCode = "Response Status : " + httpResponse.getStatusLine().getStatusCode();
                    throw new IOException(ErrorCode);
                }

                try (InputStreamReader isr = new InputStreamReader(httpResponse.getEntity().getContent(),
                        StandardCharsets.UTF_8); BufferedReader reader = new BufferedReader(isr)) {
                    String line;
                    StringBuilder builder = new StringBuilder();

                    while ((line = reader.readLine()) != null) {
                        builder.append(line);
                        builder.append("\n");
                    }
                    ClassroomJSON = builder.toString();
                }
            }
        }

        JSONObject json = new JSONArray(ClassroomJSON).getJSONObject(0);

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(BookingParam.WEB_BOOKING_DATE_URI);
            httpPost.setConfig(BookingParam.REQUEST_PARAMS);
            httpPost.addHeader("Referer", BookingParam.WEB_BOOKING_URI);

            setCookieData(httpPost);

            List<NameValuePair> nvps = new ArrayList<>();
            nvps.add(new BasicNameValuePair("effectiveDate", json.getString("EFFECTIVE_DATE")));
            nvps.add(new BasicNameValuePair("class_data", classValue));
            nvps.add(new BasicNameValuePair("class_status", json.getString("CLASS_STATUS")));
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));

            try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
                //  HttpStatusCode != 200
                if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    String ErrorCode = "Response Status : " + httpResponse.getStatusLine().getStatusCode();
                    throw new IOException(ErrorCode);
                }

                try (InputStreamReader isr = new InputStreamReader(httpResponse.getEntity().getContent(),
                        StandardCharsets.UTF_8); BufferedReader reader = new BufferedReader(isr)) {
                    String line;
                    StringBuilder builder = new StringBuilder();

                    while ((line = reader.readLine()) != null) {
                        builder.append(line);
                        builder.append("\n");
                    }
                    DateJSON = builder.toString();
                }
            }
        }
    }

    private void praseClassroomJSON() {
        JSONArray jsonArray = new JSONArray(ClassroomJSON);
        classroomMap = new TreeMap<>();

        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject json = jsonArray.getJSONObject(i);
            classroomMap.put(json.getString("LOCATION"), json.getString("BRANCH_NAME"));
        }
    }

    private void praseDateJSON() {
        JSONArray jsonArray = new JSONArray(DateJSON);
        dateMap = new TreeMap<>();

        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject json = jsonArray.getJSONObject(i);
            dateMap.put(json.getString("DATE_VALUE"), json.getString("DATE_STRING"));
        }
    }

    private void postClassroomData(String dateValue, String classroomValue) throws IOException {

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(BookingParam.WEB_BOOKING_TIME_URI);
            httpPost.setConfig(BookingParam.REQUEST_PARAMS);
            httpPost.addHeader("Referer", BookingParam.WEB_BOOKING_URI);

            setCookieData(httpPost);

            List<NameValuePair> nvps = new ArrayList<>();
            nvps.add(new BasicNameValuePair("date", dateValue));
            nvps.add(new BasicNameValuePair("branch_no", classroomValue));
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));

            try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
                //  HttpStatusCode != 200
                if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    String ErrorCode = "Response Status : " + httpResponse.getStatusLine().getStatusCode();
                    throw new IOException(ErrorCode);
                }

                try (InputStreamReader isr = new InputStreamReader(httpResponse.getEntity().getContent(),
                        StandardCharsets.UTF_8); BufferedReader reader = new BufferedReader(isr)) {
                    String line;
                    StringBuilder builder = new StringBuilder();

                    while ((line = reader.readLine()) != null) {
                        builder.append(line);
                        builder.append("\n");
                    }
                    TimeJSON = builder.toString();
                }
            }
        }
    }

    private Map<String, String> praseTimeJSON() {
        JSONArray jsonArray = new JSONArray(TimeJSON);
        Map<String, String> map = new TreeMap<>();

        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject json = jsonArray.getJSONObject(i);

            String timeData = json.getString("INIT_TIME") + " ~ " + json.getString("END_TIME");

            if (!json.getString("HASCLASS").equals("0"))
                timeData += " ?";
            else if (json.getString("SEATNUM").equals("0"))
                timeData += " ";
            else if (!json.getString("OFFCLASS").equals("0"))
                timeData += " ?";
            else
                timeData += " ? : " + json.getString("SEATNUM");

            map.put(json.getString("SEGMENT"), timeData);
        }

        return map;
    }

    private List<String> praseBookingSeat() {
        JSONArray jsonArray = new JSONArray(TimeJSON);
        List<String> haveSeatList = new ArrayList<>();

        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject json = jsonArray.getJSONObject(i);

            if (json.getString("HASCLASS").equals("0") && json.getString("OFFCLASS").equals("0")) {
                int seatNum = Integer.parseInt(json.getString("SEATNUM"));
                if (seatNum > 0)
                    haveSeatList.add(json.getString("SEGMENT"));
            }
        }

        return haveSeatList;
    }

    private void postBookingData(String classValue, String classroomValue, String dateValue, String timeValue)
            throws IOException {

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(BookingParam.WEB_POST_BOOKING_URI);
            httpPost.setConfig(BookingParam.REQUEST_PARAMS);
            httpPost.addHeader("Referer", BookingParam.WEB_BOOKING_URI);

            setCookieData(httpPost);

            List<NameValuePair> nvps = new ArrayList<>();
            nvps.add(new BasicNameValuePair("class_data", classValue));
            nvps.add(new BasicNameValuePair("date", dateValue));
            nvps.add(new BasicNameValuePair("branch_no", classroomValue));
            nvps.add(new BasicNameValuePair("session_time[]", timeValue));
            nvps.add(new BasicNameValuePair("access_token", booking_hidden_token));

            httpPost.setEntity(new UrlEncodedFormEntity(nvps));

            try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
                //  HttpStatusCode != 200
                if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    String ErrorCode = "Response Status : " + httpResponse.getStatusLine().getStatusCode();
                    throw new IOException(ErrorCode);
                }

                try (InputStreamReader isr = new InputStreamReader(httpResponse.getEntity().getContent(),
                        StandardCharsets.UTF_8); BufferedReader reader = new BufferedReader(isr)) {
                    String line;
                    StringBuilder builder = new StringBuilder();

                    while ((line = reader.readLine()) != null) {
                        builder.append(line);
                        builder.append("\n");
                    }
                    BookingResultJSON = builder.toString();
                }
            }
        }
    }

    private boolean praseBookingResult() {
        JSONObject json = new JSONObject(BookingResultJSON);

        return json.getString("MESSAGE").contains("??");
    }

    private void setCookieData(AbstractHttpMessage httpMessage) {
        StringBuilder CookieBuilder = new StringBuilder();

        cookieMap.forEach((key, value) -> {
            CookieBuilder.append("; ").append(key).append("=").append(value);
        });

        if (CookieBuilder.length() > 2)
            httpMessage.setHeader("Cookie", CookieBuilder.substring(2));
    }

}