Updated code for some format edge cases unnoticed

Builds with maven for testing. Work on new methods for different documents.
This commit is contained in:
Claudio Maggioni 2018-01-22 19:27:15 +01:00
parent c17330f504
commit 52571565e5
11 changed files with 308 additions and 52 deletions

55
.gitignore vendored Normal file
View file

@ -0,0 +1,55 @@
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
cmake-build-release/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Custom
.idea/libraries
/*.jar
target

18
.idea/compiler.xml Normal file
View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="ProvaArgo" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
<module name="ProvaArgo" target="1.8" />
<module name="ProvaArgo_main" target="1.5" />
<module name="ProvaArgo_test" target="1.5" />
</bytecodeTargetLevel>
</component>
</project>

25
.idea/misc.xml Normal file
View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="PreferredVcsStorage">
<preferredVcsName>ApexVCS</preferredVcsName>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
<component name="SbtLocalSettings">
<option name="modificationStamps">
<map>
<entry key="$PROJECT_DIR$/../provaPlay/provaplay" value="1482616563139" />
<entry key="$USER_HOME$/Progetti/FirstScalaJS" value="1477318418808" />
</map>
</option>
<option name="externalProjectsViewState">
<projects_view />
</option>
</component>
</project>

8
.idea/modules.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/ProvaArgo.iml" filepath="$PROJECT_DIR$/ProvaArgo.iml" group="ProvaArgo" />
</modules>
</component>
</project>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/../../target/classes" />
<output-test url="file://$MODULE_DIR$/../../target/test-classes" />
<content url="file://$MODULE_DIR$/../..">
<sourceFolder url="file://$MODULE_DIR$/../../src/android" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../www" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/../../.gradle" />
<excludeFolder url="file://$MODULE_DIR$/../../build" />
<excludeFolder url="file://$MODULE_DIR$/../../out" />
<excludeFolder url="file://$MODULE_DIR$/../../target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.jsoup:jsoup:1.11.2" level="project" />
<orderEntry type="library" name="Maven: org.json:json:20171018" level="project" />
<orderEntry type="module-library">
<library name="Maven: cordova:org.apache:7.0.0">
<CLASSES>
<root url="jar://$MODULE_DIR$/../../org.apache.cordova-7.0.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

View file

@ -1,25 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> <module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5"> <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" /> <output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" /> <output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/android" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/android" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/libraries" /> <sourceFolder url="file://$MODULE_DIR$/www" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.jsoup:jsoup:1.11.2" level="project" /> <orderEntry type="library" name="Maven: org.jsoup:jsoup:1.11.2" level="project" />
<orderEntry type="library" name="Maven: org.json:json:20171018" level="project" />
<orderEntry type="module-library"> <orderEntry type="module-library">
<library name="Maven: org.apache:cordova:2.4.0"> <library name="Maven: cordova:org.apache:7.0.0">
<CLASSES> <CLASSES>
<root url="jar://$MODULE_DIR$/libraries/cordova-2.4.0.jar!/" /> <root url="jar://$MODULE_DIR$/org.apache.cordova-7.0.0.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES /> <SOURCES />
</library> </library>
</orderEntry> </orderEntry>
<orderEntry type="library" scope="PROVIDED" name="Maven: org.json:json:20171018" level="project" /> <orderEntry type="library" name="Maven: com.google.android:android:4.1.1.4" level="project" />
<orderEntry type="library" name="Maven: commons-logging:commons-logging:1.1.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.0.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.0.1" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.3" level="project" />
<orderEntry type="library" name="Maven: org.khronos:opengl-api:gl1.1-android-2.1_r1" level="project" />
<orderEntry type="library" name="Maven: xerces:xmlParserAPIs:2.6.2" level="project" />
<orderEntry type="library" name="Maven: xpp3:xpp3:1.1.4c" level="project" />
</component> </component>
</module> </module>

41
pom.xml Normal file
View file

@ -0,0 +1,41 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>xyz.maggioni</groupId>
<artifactId>ProvaArgo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<modelVersion>4.0.0</modelVersion>
<dependencies>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.2</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20171018</version>
</dependency>
<dependency>
<groupId>cordova</groupId>
<artifactId>org.apache</artifactId>
<version>7.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/org.apache.cordova-7.0.0.jar</systemPath>
</dependency>
</dependencies>
</project>

View file

@ -22,7 +22,6 @@ import org.jsoup.Connection.*;
import org.jsoup.Connection; import org.jsoup.Connection;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.apache.cordova.LOG;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
@ -32,13 +31,13 @@ class ArgoAPI {
private ArgoAPI() { private ArgoAPI() {
} }
private static void logResponse(Response res) throws IOException { private static void logResponse(Response res) {
LOG.i("ArgoAPI", "Response URL: " + res.url()); PluginLOG.i("ArgoAPI", "Response URL: " + res.url());
LOG.i("ArgoAPI","Response code: " + res.statusCode()); PluginLOG.i("ArgoAPI", "Response code: " + res.statusCode());
LOG.i("ArgoAPI","Response status: " + res.statusMessage()); PluginLOG.i("ArgoAPI", "Response status: " + res.statusMessage());
for (Map.Entry<String, String> entry : res.cookies().entrySet()) { for (Map.Entry<String, String> entry : res.cookies().entrySet()) {
LOG.i("ArgoAPI","Response cookie: " + entry.getKey() + "=" + entry.getValue()); PluginLOG.i("ArgoAPI", "Response cookie: " + entry.getKey() + "=" + entry.getValue());
} }
} }
@ -48,12 +47,23 @@ class ArgoAPI {
} }
} }
static Document getMarksDocument(Map<String, String> cookies) { enum ArgoDocument {
MARKS("[evt=menu-servizialunno:vot|event|custom]"),
HOMEWORK("[evt=menu-serviziclasse:_idJsp25|event|submit]"),
LESSONS("[evt=menu-serviziclasse:_idJsp27|event|submit]");
private String backbaseDelta;
ArgoDocument(String s) {
backbaseDelta = s;
}
}
static Document getDocument(Map<String, String> cookies, ArgoDocument d) {
try { try {
Response markRes = Jsoup.connect("https://www.portaleargo.it/argoweb/famiglia/index.jsf") Response markRes = Jsoup.connect("https://www.portaleargo.it/argoweb/famiglia/index.jsf")
.cookies(cookies) .cookies(cookies)
.referrer("https://www.portaleargo.it/argoweb/famiglia/index.jsf") .referrer("https://www.portaleargo.it/argoweb/famiglia/index.jsf")
.data("BackbaseClientDelta", "[evt=menu-servizialunno:vot|event|custom]") .data("BackbaseClientDelta", d.backbaseDelta)
.followRedirects(true) .followRedirects(true)
.method(Connection.Method.POST) .method(Connection.Method.POST)
.execute(); .execute();
@ -62,7 +72,7 @@ class ArgoAPI {
logResponse(markRes); logResponse(markRes);
return Jsoup.parse(markRes.body().replaceAll("Â", "")); return Jsoup.parse(markRes.body().replaceAll("Â", ""));
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); PluginLOG.e("ArgoAPI", e.getLocalizedMessage(), e);
return null; return null;
} }
} }
@ -77,9 +87,9 @@ class ArgoAPI {
updateCookies(cookies, initRes.cookies()); updateCookies(cookies, initRes.cookies());
logResponse(initRes); logResponse(initRes);
LOG.i("ArgoAPI","Cookie init complete"); PluginLOG.i("ArgoAPI", "Cookie init complete");
Map<String, String> params = new HashMap<String, String>(); Map<String, String> params = new HashMap<>();
params.put("utente", user.getUsername()); params.put("utente", user.getUsername());
params.put("j_password", user.getPassword()); params.put("j_password", user.getPassword());
params.put("j_username", user.getUsername() + "#" + user.getSchoolCode()); params.put("j_username", user.getUsername() + "#" + user.getSchoolCode());
@ -96,14 +106,14 @@ class ArgoAPI {
updateCookies(cookies, loginRes.cookies()); updateCookies(cookies, loginRes.cookies());
logResponse(loginRes); logResponse(loginRes);
LOG.i("ArgoAPI","login complete"); PluginLOG.i("ArgoAPI", "login complete");
Document d = loginRes.parse(); Document d = loginRes.parse();
return !d.select("html > head > title").isEmpty() return !d.select("html > head > title").isEmpty()
&& "Argo - Famiglia".equalsIgnoreCase(d.select("html > head > title").first().text()); && "Argo - Famiglia".equalsIgnoreCase(d.select("html > head > title").first().text());
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); PluginLOG.e("ArgoAPI", e.getLocalizedMessage(), e);
return false; return false;
} }
} }
@ -121,7 +131,7 @@ class ArgoAPI {
updateCookies(cookies, loginRes.cookies()); updateCookies(cookies, loginRes.cookies());
logResponse(loginRes); logResponse(loginRes);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); PluginLOG.e("ArgoAPI", e.getLocalizedMessage(), e);
} }
} }
} }

View file

@ -18,16 +18,13 @@
package xyz.maggioni.ProvaArgo; package xyz.maggioni.ProvaArgo;
import org.apache.cordova.CordovaPlugin; import org.apache.cordova.*;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.LOG;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.HashMap; import java.util.HashMap;
@ -37,15 +34,38 @@ import java.util.regex.Pattern;
public class ArgoAPIPlugin extends CordovaPlugin { public class ArgoAPIPlugin extends CordovaPlugin {
public static void main(String... args) {
PluginLOG.useCordova = false;
JSONArray arr = new JSONArray();
JSONObject obj = new JSONObject();
obj.put("username", "maggioni");
obj.put("password", "huuu273j");
obj.put("schoolCode", "SG26426");
arr.put(obj);
ArgoAPIPlugin a = new ArgoAPIPlugin();
try {
System.out.println(a.getMarks(arr).toString(2));
} catch (ArgoException | JSONException e) {
e.printStackTrace();
}
}
@Override @Override
public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException { public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
if (action.equals("getMarks")) { if (action.equals("getMarks")) {
final ArgoAPIPlugin this__ = this; final ArgoAPIPlugin this__ = this;
new Thread(new Runnable() { new Thread(() -> {
public void run() { try {
this__.getMarks(args, callbackContext); this__.getMarks(args);
} catch (ArgoException e) {
callbackContext.error(e.getResponse());
} catch (JSONException e1) {
callbackContext.error(e1.getLocalizedMessage());
} }
}).start(); }).start();
@ -54,7 +74,7 @@ public class ArgoAPIPlugin extends CordovaPlugin {
return false; return false;
} }
private void getMarks(JSONArray args, CallbackContext c) { private JSONObject getMarks(JSONArray args) throws JSONException, ArgoException {
JSONObject response = new JSONObject(); JSONObject response = new JSONObject();
JSONArray subjects = new JSONArray(); JSONArray subjects = new JSONArray();
@ -69,13 +89,13 @@ public class ArgoAPIPlugin extends CordovaPlugin {
jsonObject.getString("password"), jsonObject.getString("password"),
jsonObject.getString("schoolCode")); jsonObject.getString("schoolCode"));
Map<String, String> cookies = new HashMap<String, String>(); Map<String, String> cookies = new HashMap<>();
if (!ArgoAPI.login(cookies, user)) { if (!ArgoAPI.login(cookies, user)) {
throw new IllegalStateException("Login on Argo failed"); throw new IllegalStateException("Login on Argo failed");
} }
Document marksDocument = ArgoAPI.getMarksDocument(cookies); Document marksDocument = ArgoAPI.getDocument(cookies, ArgoAPI.ArgoDocument.MARKS);
if (marksDocument == null) { if (marksDocument == null) {
throw new IllegalStateException("Failed to get marks document"); throw new IllegalStateException("Failed to get marks document");
} }
@ -89,24 +109,26 @@ public class ArgoAPIPlugin extends CordovaPlugin {
subject.put("name", el.select("legend").first().text()); subject.put("name", el.select("legend").first().text());
subject.put("marks", marks); subject.put("marks", marks);
String lastDate = null;
for (Element el2 : el.select("table > tbody > tr")) { for (Element el2 : el.select("table > tbody > tr")) {
Elements cells = el2.select("td");
Element[] cellsArr = cells.toArray(new Element[3]);
JSONObject mark = new JSONObject(); JSONObject mark = new JSONObject();
mark.put("date", new SimpleDateFormat("yyyy-MM-dd").parse(cellsArr[1].text()));
String markStr = cellsArr[2].text(); Pattern p = Pattern.compile("\\d\\d\\d\\d-\\d\\d-\\d\\d");
Matcher m2 = p.matcher(el2.text());
Pattern regMark = Pattern.compile("Voto ((?:[Ss]critto)|(?:[Oo]rale)|(?:[Pp]ratico)) .*\\(([0-9.]+)\\)"); if (!m2.find()) {
Matcher m = regMark.matcher(markStr); if (lastDate == null) throw new IllegalStateException("Date not found in: \"" + el2.text() + "\"");
// if date has not been written, assume the date is equal to the last known date
if (m.find()) { // (already in last date)
mark.put("type", m.group(1));
mark.put("value", Double.parseDouble(m.group(2)));
} else { } else {
throw new IllegalStateException("Regex for mark does not match with markStr \"" + markStr + "\""); lastDate = m2.group(0);
} }
mark.put("date", new SimpleDateFormat("yyyy-MM-dd").parse(lastDate));
Pattern regMark = Pattern.compile("((?:[Ss]critto)|(?:[Oo]rale)|(?:[Pp]ratico)).*\\(([0-9.]+)\\)");
Matcher m = regMark.matcher(el2.text());
if (!m.find()) throw new IllegalStateException("Mark not found in: \"" + mark + "\"");
mark.put("type", m.group(1));
mark.put("value", Double.parseDouble(m.group(2)));
marks.put(mark); marks.put(mark);
} }
@ -117,26 +139,27 @@ public class ArgoAPIPlugin extends CordovaPlugin {
ArgoAPI.logout(cookies); ArgoAPI.logout(cookies);
} catch (Exception e) { } catch (Exception e) {
LOG.e("ArgoAPIPlugin", e.getMessage(), e); PluginLOG.e("ArgoAPIPlugin", e.getMessage(), e);
try { try {
response.put("success", false); response.put("success", false);
response.put("subjects", new JSONArray()); response.put("subjects", new JSONArray());
response.put("message", e.getLocalizedMessage()); response.put("message", e.getLocalizedMessage());
} catch (JSONException e1) { } catch (JSONException e1) {
LOG.e("ArgoAPIPlugin", e1.getMessage(), e1); PluginLOG.e("ArgoAPIPlugin", e1.getMessage(), e1);
c.error(e1.getMessage()); throw e1;
} }
} }
try { try {
if (response.get("success").equals(true)) { if (response.get("success").equals(true)) {
c.success(response); return response;
} else { } else {
c.error(response); throw new ArgoException(response);
} }
} catch (JSONException e) { } catch (JSONException | ArgoException e) {
LOG.e("ArgoAPIPlugin", e.getMessage(), e); PluginLOG.e("ArgoAPIPlugin", e.getMessage(), e);
c.error(e.getMessage()); throw e;
} }
} }
} }

View file

@ -0,0 +1,20 @@
package xyz.maggioni.ProvaArgo;
import org.json.JSONObject;
public class ArgoException extends Exception {
private JSONObject response;
ArgoException(JSONObject response) {
this.response = response;
}
public JSONObject getResponse() {
return response;
}
@Override
public String getMessage() {
return "Marks fetch failed with the following data: "+response.toString();
}
}

View file

@ -0,0 +1,20 @@
package xyz.maggioni.ProvaArgo;
import org.apache.cordova.LOG;
public class PluginLOG {
public static boolean useCordova = true;
public static void i(String tag, String message) {
if (useCordova) LOG.i(tag, message);
else System.out.println("INFO (" + tag + "): " + message);
}
public static void e(String tag, String s, Throwable e) {
if (useCordova) LOG.e(tag, s, e);
else {
System.err.println("ERROR (" + tag + "): " + s);
e.printStackTrace(System.err);
}
}
}