diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/de/romjaki/dsbclient/DSBClient.java | 144 | ||||
-rw-r--r-- | src/main/java/de/romjaki/dsbclient/TimetableEntry.java | 95 | ||||
-rw-r--r-- | src/main/java/de/romjaki/dsbclient/UnUtil.java | 75 | ||||
-rw-r--r-- | src/test/java/Testing.java | 14 |
4 files changed, 328 insertions, 0 deletions
diff --git a/src/main/java/de/romjaki/dsbclient/DSBClient.java b/src/main/java/de/romjaki/dsbclient/DSBClient.java new file mode 100644 index 0000000..01927cd --- /dev/null +++ b/src/main/java/de/romjaki/dsbclient/DSBClient.java @@ -0,0 +1,144 @@ +package de.romjaki.dsbclient; + +import com.google.common.collect.Iterables; +import org.apache.http.HttpException; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +public class DSBClient { + private static final String BASE_URL = "https://iphone.dsbcontrol.de/iPhoneService.svc/DSB/"; + private static final String AUTH_URL = BASE_URL + "AuthID/"; + private static final String DATA_URL = BASE_URL + "timetables/"; + private static final DateFormat dateformat = new SimpleDateFormat("d.M.Y H:m"); + private final String user; + private final String pass; + private String authid; + private DefaultHttpClient client = new DefaultHttpClient(); + private Map<Long, List<TimetableEntry>> cache; + + private DSBClient(String user, String pass) { + this.user = user; + this.pass = pass; + } + + public static DSBClient buildBlocking(String user, String pass) throws HttpException, IOException, URISyntaxException, JSONException, ParseException { + DSBClient client = new DSBClient(user, pass); + client.login(); + client.receiveData(); + return client; + } + + public static DSBClient buildAsync(String user, String pass, Consumer<Exception> exceptionCallback) { + DSBClient client = new DSBClient(user, pass); + Thread t = new Thread(() -> { + try { + client.login(); + client.receiveData(); + } catch (Exception e) { + exceptionCallback.accept(e); + } + }); + return client; + } + + private void login() throws IOException, HttpException, URISyntaxException { + HttpGet get = new HttpGet(AUTH_URL + user + "/" + pass); + + HttpResponse response = client.execute(get); + + authid = EntityUtils.toString(response.getEntity()).replace("\"", ""); + } + + private void receiveData() throws URISyntaxException, IOException, HttpException, JSONException, ParseException { + HttpGet get = new HttpGet(DATA_URL + authid); + + HttpResponse response = client.execute(get); + + String str = EntityUtils.toString(response.getEntity()); + JSONArray data = new JSONArray(str); + cache = new HashMap<>(); + for (int i = 0; i < data.length(); i++) { + JSONObject o = data.getJSONObject(i); + boolean isHtml = o.getBoolean("ishtml"); + Date timetabledate = dateformat.parse(o.getString("timetabledate")); + String timetableurl = o.getString("timetableurl"); + long millis = UnUtil.sanitizeDate(UnUtil.calendarByDate(timetabledate, Locale.GERMANY)).getTimeInMillis(); + List<TimetableEntry> arrL = cache.computeIfAbsent(millis, ignored -> new ArrayList<>()); + arrL.addAll(parseEntry(isHtml, timetableurl)); + } + } + + + private List<TimetableEntry> parseEntry(boolean isHtml, String timetableurl) throws URISyntaxException, IOException, HttpException { + if (!isHtml) return Collections.emptyList(); + HttpGet get = new HttpGet(timetableurl); + HttpResponse response = client.execute(get); + Document document = Jsoup.parse(EntityUtils.toString(response.getEntity())); + Elements rows = document.getElementsByTag("tr").not(":not(:has(th))"); + List<TimetableEntry> entries = new ArrayList<>(rows.size()); + for (Element row : rows) { + entries.add(parseElement(row)); + } + return entries; + } + + private TimetableEntry parseElement(Element row) { + TimetableEntry entry = new TimetableEntry(); + entry.setKlasse(row.child(1).text()); + entry.setStunde(row.child(3).text()); + entry.setVertreter(row.child(4).text()); + entry.setFach(row.child(5).text()); + entry.setRaum(row.child(8).text()); + entry.setArt(row.child(9).text()); + entry.setText(row.child(11).text()); + if (entry.getFach() == null) { + entry.setFach(row.child(6).text()); + } + if (entry.getRaum() == null) { + entry.setRaum(row.child(7).text()); + } + if (entry.getKlasse() == null) { + entry.setKlasse(row.child(10).text()); + } + return entry; + } + + public List<TimetableEntry> byTeacher(String teacher) { + return filter(timetableEntry -> timetableEntry.getVertreter().equalsIgnoreCase(teacher)); + } + + public List<TimetableEntry> byDate(Date date) { + return cache.get(UnUtil.sanitizeDate(UnUtil.calendarByDate(date, Locale.GERMANY)).getTimeInMillis()); + } + + public List<TimetableEntry> byClass(String klasse) { + return filter(timetableEntry -> timetableEntry.getKlasse().contains(klasse) || klasse.contains(timetableEntry.getKlasse())); + } + + + public List<TimetableEntry> filter(Predicate<TimetableEntry> predicate) { + return StreamSupport.stream(Iterables.concat(cache.values()).spliterator(), false) + .filter(predicate) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/romjaki/dsbclient/TimetableEntry.java b/src/main/java/de/romjaki/dsbclient/TimetableEntry.java new file mode 100644 index 0000000..a888cfc --- /dev/null +++ b/src/main/java/de/romjaki/dsbclient/TimetableEntry.java @@ -0,0 +1,95 @@ +package de.romjaki.dsbclient; + +public class TimetableEntry { + private String klasse; + private String stunde; + private String vertreter; + private String fach; + private String raum; + private String art; + private String text; + + public String getKlasse() { + return klasse; + } + + public void setKlasse(String klasse) { + klasse = klasse.trim(); + if (klasse.isEmpty()) { + klasse = null; + } + this.klasse = klasse; + } + + public String getStunde() { + return stunde; + } + + public void setStunde(String stunde) { + stunde = stunde.trim(); + if (stunde.isEmpty()) { + stunde = null; + } + this.stunde = stunde; + } + + public String getVertreter() { + return vertreter; + } + + public void setVertreter(String vertreter) { + vertreter = vertreter.trim(); + if (vertreter.isEmpty()) { + vertreter = null; + } + this.vertreter = vertreter; + } + + public String getFach() { + return fach; + } + + public void setFach(String fach) { + fach = fach.trim(); + if (fach.isEmpty()) { + fach = null; + } + this.fach = fach; + } + + public String getRaum() { + return raum; + } + + public void setRaum(String raum) { + raum = raum.trim(); + if (raum.isEmpty()) { + raum = null; + } + this.raum = raum; + } + + public String getArt() { + return art; + } + + public void setArt(String art) { + art = art.trim(); + if (art.isEmpty()) { + art = null; + } + this.art = art; + } + + public String getText() { + return text; + } + + public void setText(String text) { + text = text.trim(); + if (text.isEmpty()) { + text = null; + } + this.text = text; + } +} diff --git a/src/main/java/de/romjaki/dsbclient/UnUtil.java b/src/main/java/de/romjaki/dsbclient/UnUtil.java new file mode 100644 index 0000000..2c3af02 --- /dev/null +++ b/src/main/java/de/romjaki/dsbclient/UnUtil.java @@ -0,0 +1,75 @@ +package de.romjaki.dsbclient; + + +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.message.BasicNameValuePair; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.*; + +import static java.util.Calendar.*; + +public class UnUtil { + + private UnUtil() { + UnUtil.singleton(UnUtil.class); + } + + public static Calendar calendarByDate(Date date, Locale germany) { + Calendar calendar = Calendar.getInstance(Locale.GERMANY); + calendar.setTime(date); + return calendar; + } + + public static Calendar sanitizeDate(Calendar temp) { + Calendar calendar = Calendar.getInstance(temp.getTimeZone()); + + calendar.set( + temp.get(YEAR), + temp.get(MONTH), + temp.get(DAY_OF_MONTH), + 0, 0, 0); + return calendar; + } + + public static void singleton(Class<UnUtil> utilClass) throws IllegalStateException { + throw new IllegalStateException("No " + utilClass.getCanonicalName() + " class instances for you :P"); + } + + public static String httpGet(String urlString, Map<String, List<String>> headers) throws IOException { + return performGeneralHttpRequest("GET", urlString, headers); + } + + public static String performGeneralHttpRequest(String method, String urlString, Map<String, List<String>> headers) throws IOException { + URL url = new URL(urlString); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod(method); + conn.getRequestProperties().putAll(headers); + + conn.setDoInput(true); + conn.setDoOutput(true); + conn.setUseCaches(false); + + InputStream stream = conn.getInputStream(); + return readFully(stream); + } + + public static UrlEncodedFormEntity createFormEntity(Map<String, String> params) { + List<NameValuePair> nameValuePairs = new ArrayList<>(); + params.forEach((name, val) -> nameValuePairs.add(new BasicNameValuePair(name, val))); + try { + return new UrlEncodedFormEntity(nameValuePairs, "UTF-8"); + } catch (UnsupportedEncodingException e) { + return null; + } + } + + public static String readFully(InputStream stream) { + return new Scanner(stream).useDelimiter("\\A").next(); + } +} diff --git a/src/test/java/Testing.java b/src/test/java/Testing.java new file mode 100644 index 0000000..b404e8d --- /dev/null +++ b/src/test/java/Testing.java @@ -0,0 +1,14 @@ +import de.romjaki.dsbclient.DSBClient; +import org.apache.http.HttpException; +import org.json.JSONException; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.text.ParseException; + +public class Testing { + public static void main(String[] args) throws URISyntaxException, IOException, HttpException, JSONException, ParseException { + DSBClient client = DSBClient.buildBlocking("166162", "Riedberg2014"); + + } +} |