QISPOSParser [Part 2]
continuous-integration/drone/push Build is passing Details

* parse grades and store them in a HashMap per semester
This commit is contained in:
Jannik 2020-08-14 15:08:42 +02:00
parent ff0c4ad1a7
commit 8ecfe8f120
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
3 changed files with 100 additions and 8 deletions

View File

@ -179,7 +179,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
EncryptedPreferences.load(this) EncryptedPreferences.load(this)
val parser = QISPOSParser() val parser = QISPOSParser()
parser.test(applicationContext) parser.parseGrades(applicationContext)
} }
Log.i(className, "startup completed in $startupTime ms") Log.i(className, "startup completed in $startupTime ms")

View File

@ -6,8 +6,10 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.mosad.seil0.projectlaogai.R import org.mosad.seil0.projectlaogai.R
import org.mosad.seil0.projectlaogai.controller.preferences.EncryptedPreferences import org.mosad.seil0.projectlaogai.controller.preferences.EncryptedPreferences
import org.mosad.seil0.projectlaogai.util.gradeSubject
import java.security.KeyStore import java.security.KeyStore
import java.security.cert.CertificateFactory import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate import java.security.cert.X509Certificate
@ -15,20 +17,75 @@ import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManagerFactory import javax.net.ssl.TrustManagerFactory
/**
* TODO context in constructor?
*/
class QISPOSParser { class QISPOSParser {
private val className = this.javaClass.name private val className = this.javaClass.name
private val baseURL = "https://notenverwaltung.hs-offenburg.de" 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 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<String, ArrayList<gradeSubject>>()
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 credentials = EncryptedPreferences.readCredentials(context)
val username = credentials.first.substringBefore("@") val username = credentials.first.substringBefore("@")
val password = credentials.second val password = credentials.second
runBlocking { return runBlocking {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
try { try {
println("querying qispos ...") println("querying qispos ...")
@ -56,14 +113,46 @@ class QISPOSParser {
println("cookies: $loginCookies") println("cookies: $loginCookies")
println("status is: ${res.statusMessage()}: ${res.statusCode()}") println("status is: ${res.statusMessage()}: ${res.statusCode()}")
println(res.body())
// grades url // grades root document and url
val test = Jsoup.parse(res.body()).select("li.menueListStyle").select("a.auflistung").last() val rootHtml =Jsoup.parse(res.body())
println(test) 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) { } catch (ex: Exception) {
Log.e(className, "could not load qispos", ex) Log.e(className, "could not load qispos", ex)
null
} }
} }
} }

View File

@ -108,6 +108,9 @@ data class TimetableDay(val timeslots: Array<ArrayList<Lesson>> = Array(6) { Arr
data class TimetableWeek(val weekIndex: Int = 0, val weekNumberYear: Int = 0, val days: Array<TimetableDay> = Array(6) { TimetableDay() }) data class TimetableWeek(val weekIndex: Int = 0, val weekNumberYear: Int = 0, val days: Array<TimetableDay> = 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 // TCoR
data class TimetableWeekTCoR(val days: Array<TimetableDay> = Array(6) { TimetableDay() }) data class TimetableWeekTCoR(val days: Array<TimetableDay> = Array(6) { TimetableDay() })