diff --git a/app/src/main/java/org/mosad/seil0/projectlaogai/MainActivity.kt b/app/src/main/java/org/mosad/seil0/projectlaogai/MainActivity.kt index 54f0afe..dbab618 100644 --- a/app/src/main/java/org/mosad/seil0/projectlaogai/MainActivity.kt +++ b/app/src/main/java/org/mosad/seil0/projectlaogai/MainActivity.kt @@ -179,7 +179,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte EncryptedPreferences.load(this) val parser = QISPOSParser() - parser.test(applicationContext) + parser.parseGrades(applicationContext) } Log.i(className, "startup completed in $startupTime ms") diff --git a/app/src/main/java/org/mosad/seil0/projectlaogai/controller/QISPOSParser.kt b/app/src/main/java/org/mosad/seil0/projectlaogai/controller/QISPOSParser.kt index 28b7d1a..3e4d546 100644 --- a/app/src/main/java/org/mosad/seil0/projectlaogai/controller/QISPOSParser.kt +++ b/app/src/main/java/org/mosad/seil0/projectlaogai/controller/QISPOSParser.kt @@ -6,8 +6,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import org.jsoup.Jsoup +import org.jsoup.nodes.Element import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.controller.preferences.EncryptedPreferences +import org.mosad.seil0.projectlaogai.util.gradeSubject import java.security.KeyStore import java.security.cert.CertificateFactory import java.security.cert.X509Certificate @@ -15,20 +17,75 @@ import javax.net.ssl.SSLContext import javax.net.ssl.SSLSocketFactory import javax.net.ssl.TrustManagerFactory +/** + * TODO context in constructor? + */ class QISPOSParser { private val className = this.javaClass.name private val baseURL = "https://notenverwaltung.hs-offenburg.de" private val loginPath = "/qispos/rds?state=user&type=1&category=auth.login&startpage=portal.vm&breadCrumbSource=portal" - private val rootPath = "/qispos/rds?state=change&type=1&moduleParameter=studyPOSMenu&nextdir=change&next=menu.vm&subdir=applications&xml=menu&purge=y&navigationPosition=functions%2CstudyPOSMenu&breadcrumb=studyPOSMenu&topitem=functions&subitem=studyPOSMenu" + //private val rootPath = "/qispos/rds?state=change&type=1&moduleParameter=studyPOSMenu&nextdir=change&next=menu.vm&subdir=applications&xml=menu&purge=y&navigationPosition=functions%2CstudyPOSMenu&breadcrumb=studyPOSMenu&topitem=functions&subitem=studyPOSMenu" - fun test(context: Context) { + + fun parseGrades(context: Context) { + val gradesMap = HashMap>() + val gradesListHtml = readGrades(context) + + gradesListHtml?.select("table > tbody > tr")?.forEach { + val row = it.select("td.qis_konto") + + //println("-----------------------------------------------------------") + //println(it.select("td.qis_konto")) + + if(row.size >= 6) { + val subject = gradeSubject( + id = row[0].text(), + name = row[1].text(), + semester = row[2].text(), + grade = row[3].text(), + credits = row[5].text() + ) + + if (gradesMap.containsKey(subject.semester)) { + gradesMap[subject.semester]!!.add(subject) + println(subject.name) + } else { + gradesMap[subject.semester] = arrayListOf(subject) + println(subject.name) + } + + println("ID: ${row[0].text()}") + println("Subject Name: ${row[1].text()}") + println("Semester: ${row[2].text()}") + println("Grade: ${row[3].text()}") + println("Credits: ${row[5].text()}") + println("------------------------------------------------------") + + } + + } + println(gradesMap) + gradesMap.forEach { + println("${it.key}: ${it.value}") + } + + // TODO sort + + println("finished parsing!") + } + + /** + * read the grades html from qispos + * @return the grades list as html element or null + */ + private fun readGrades(context: Context): Element?{ val credentials = EncryptedPreferences.readCredentials(context) val username = credentials.first.substringBefore("@") val password = credentials.second - runBlocking { + return runBlocking { withContext(Dispatchers.IO) { try { println("querying qispos ...") @@ -56,14 +113,46 @@ class QISPOSParser { println("cookies: $loginCookies") println("status is: ${res.statusMessage()}: ${res.statusCode()}") - println(res.body()) - // grades url - val test = Jsoup.parse(res.body()).select("li.menueListStyle").select("a.auflistung").last() - println(test) + // grades root document and url + val rootHtml =Jsoup.parse(res.body()) + val gradesRootLink = rootHtml.select("li.menueListStyle > a.auflistung").last().attr("abs:href") + println(gradesRootLink) + // parse grades url + val gradesHtml = Jsoup.connect(gradesRootLink) + .sslSocketFactory(socketFactory) + .followRedirects(true) + .cookies(loginCookies) + .referrer("https://notenverwaltung.hs-offenburg.de/qispos/rds?state=user&type=0") + .get() + + val gradesNextLink = gradesHtml.select("li.treelist > a.regular").attr("abs:href") + println(gradesNextLink) + + val gradesNextHtml = Jsoup.connect(gradesNextLink) + .sslSocketFactory(socketFactory) + .followRedirects(true) + .cookies(loginCookies) + .referrer("https://notenverwaltung.hs-offenburg.de/qispos/rds?state=user&type=0") + .get() + + val gradesListLink = gradesNextHtml.selectFirst("li.treelist > ul > li").selectFirst("a").attr("abs:href") + println(gradesListLink) + + // get the grades list + val gradesListHtml = Jsoup.connect(gradesListLink) + .sslSocketFactory(socketFactory) + .followRedirects(true) + .cookies(loginCookies) + .referrer("https://notenverwaltung.hs-offenburg.de/qispos/rds?state=user&type=0") + .get() + + //println(gradesListHtml.body()) + gradesListHtml.body() } catch (ex: Exception) { Log.e(className, "could not load qispos", ex) + null } } } diff --git a/app/src/main/java/org/mosad/seil0/projectlaogai/util/DataTypes.kt b/app/src/main/java/org/mosad/seil0/projectlaogai/util/DataTypes.kt index ac3c615..4e96851 100644 --- a/app/src/main/java/org/mosad/seil0/projectlaogai/util/DataTypes.kt +++ b/app/src/main/java/org/mosad/seil0/projectlaogai/util/DataTypes.kt @@ -108,6 +108,9 @@ data class TimetableDay(val timeslots: Array> = Array(6) { Arr data class TimetableWeek(val weekIndex: Int = 0, val weekNumberYear: Int = 0, val days: Array = Array(6) { TimetableDay() }) +// data classes for the qispos part +data class gradeSubject(val id: String = "", val name: String = "", val semester: String = "", val grade: String = "", val credits: String = "") + // TCoR data class TimetableWeekTCoR(val days: Array = Array(6) { TimetableDay() })