Archived
Added measures to make sure the user logs into their schedule before fetching can commence
This commit is contained in:
@@ -13,6 +13,7 @@ import com.denizk0461.weserplaner.data.showErrorSnackBar
|
|||||||
import com.denizk0461.weserplaner.data.showSnackBar
|
import com.denizk0461.weserplaner.data.showSnackBar
|
||||||
import com.denizk0461.weserplaner.data.showToast
|
import com.denizk0461.weserplaner.data.showToast
|
||||||
import com.denizk0461.weserplaner.databinding.ActivityFetcherBinding
|
import com.denizk0461.weserplaner.databinding.ActivityFetcherBinding
|
||||||
|
import com.denizk0461.weserplaner.exception.NotLoggedInException
|
||||||
import com.denizk0461.weserplaner.model.TextSheetContentId
|
import com.denizk0461.weserplaner.model.TextSheetContentId
|
||||||
import com.denizk0461.weserplaner.sheet.TextSheet
|
import com.denizk0461.weserplaner.sheet.TextSheet
|
||||||
import com.denizk0461.weserplaner.viewmodel.FetcherViewModel
|
import com.denizk0461.weserplaner.viewmodel.FetcherViewModel
|
||||||
@@ -58,9 +59,7 @@ class FetcherActivity : FragmentActivity() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Enabling JavaScript. See comment above lint suppression for reason why this is done.
|
// Enabling JavaScript. See comment above lint suppression for reason why this is done.
|
||||||
binding.webview.settings.apply {
|
binding.webview.settings.javaScriptEnabled = true
|
||||||
javaScriptEnabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.webview.webViewClient = object : WebViewClient() {
|
binding.webview.webViewClient = object : WebViewClient() {
|
||||||
// Disallow redirecting to prevent the app from launching Chrome after the user logs in
|
// Disallow redirecting to prevent the app from launching Chrome after the user logs in
|
||||||
@@ -125,9 +124,7 @@ class FetcherActivity : FragmentActivity() {
|
|||||||
|
|
||||||
binding.fab.setOnClickListener {
|
binding.fab.setOnClickListener {
|
||||||
|
|
||||||
if (binding.webview.url?.contains(
|
if (binding.webview.url?.contains(scheduleUrl) == true) {
|
||||||
scheduleUrl
|
|
||||||
) == true) {
|
|
||||||
/*
|
/*
|
||||||
* Retrieve encoded HTML via JavaScript function. Encoding is done as otherwise not all
|
* Retrieve encoded HTML via JavaScript function. Encoding is done as otherwise not all
|
||||||
* symbols will be accurately fetched.
|
* symbols will be accurately fetched.
|
||||||
@@ -143,15 +140,27 @@ class FetcherActivity : FragmentActivity() {
|
|||||||
* Notify the user that the fetch was successful, and tell the user how many
|
* Notify the user that the fetch was successful, and tell the user how many
|
||||||
* items could not be fetched.
|
* items could not be fetched.
|
||||||
*/
|
*/
|
||||||
showToast(this, when (elementsNotFetched) {
|
showToast(
|
||||||
0 -> getString(R.string.toast_fetch_finished_zero)
|
this, when (elementsNotFetched) {
|
||||||
1 -> getString(R.string.toast_fetch_finished_one)
|
0 -> getString(R.string.toast_fetch_finished_zero)
|
||||||
else -> getString(R.string.toast_fetch_finished_other, elementsNotFetched)
|
1 -> getString(R.string.toast_fetch_finished_one)
|
||||||
})
|
else -> getString(
|
||||||
|
R.string.toast_fetch_finished_other,
|
||||||
|
elementsNotFetched
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Close the activity
|
// Close the activity
|
||||||
finish()
|
finish()
|
||||||
|
|
||||||
|
} catch (e: NotLoggedInException) {
|
||||||
|
// Let the user know that they need to log in
|
||||||
|
theme.showErrorSnackBar(
|
||||||
|
binding.coordinatorLayout,
|
||||||
|
getString(R.string.fetch_error_login_snack),
|
||||||
|
binding.bottomAppBar,
|
||||||
|
)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
// Let the user know that an error occurred
|
// Let the user know that an error occurred
|
||||||
theme.showErrorSnackBar(
|
theme.showErrorSnackBar(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.denizk0461.weserplaner.data
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.denizk0461.weserplaner.db.AppRepository
|
import com.denizk0461.weserplaner.db.AppRepository
|
||||||
|
import com.denizk0461.weserplaner.exception.NotLoggedInException
|
||||||
import com.denizk0461.weserplaner.model.StudIPEvent
|
import com.denizk0461.weserplaner.model.StudIPEvent
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
@@ -20,10 +21,11 @@ class StudIPParser(application: Application) {
|
|||||||
* Parse a given HTML string. HTML must be of a Stud.IP timetable. May skip elements that don't
|
* Parse a given HTML string. HTML must be of a Stud.IP timetable. May skip elements that don't
|
||||||
* provide full information on an event (title, timeslot, lecturers, room).
|
* provide full information on an event (title, timeslot, lecturers, room).
|
||||||
*
|
*
|
||||||
* @param html website content of the Stud.IP timetable
|
* @param html website content of the Stud.IP timetable
|
||||||
* @throws IOException when an error in fetching or the database transaction occurs
|
* @throws NotLoggedInException if the user has not logged in before starting the fetch
|
||||||
|
* @throws IOException when an error in fetching or the database transaction occurs
|
||||||
*/
|
*/
|
||||||
@Throws(IOException::class)
|
@Throws(NotLoggedInException::class, IOException::class)
|
||||||
fun parse(html: String): Int {
|
fun parse(html: String): Int {
|
||||||
// Counts how many elements could not be successfully fetched
|
// Counts how many elements could not be successfully fetched
|
||||||
var elementsNotFetched = 0
|
var elementsNotFetched = 0
|
||||||
@@ -31,6 +33,11 @@ class StudIPParser(application: Application) {
|
|||||||
// Parse the HTML using Jsoup to traverse the document
|
// Parse the HTML using Jsoup to traverse the document
|
||||||
val doc = Jsoup.parse(html)
|
val doc = Jsoup.parse(html)
|
||||||
|
|
||||||
|
// Check if the user has logged in by checking the ID of the body tag
|
||||||
|
if (doc.body().id() != "calendar-schedule-index") {
|
||||||
|
throw NotLoggedInException()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the list that all events will be added to temporarily before saving them to
|
* Create the list that all events will be added to temporarily before saving them to
|
||||||
* persistent storage.
|
* persistent storage.
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
package com.denizk0461.weserplaner.exception
|
|
||||||
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
class InvalidContentIdException : IOException()
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.denizk0461.weserplaner.exception
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception used to let the user know that they need to log in in order to download their schedule.
|
||||||
|
*/
|
||||||
|
class NotLoggedInException : IOException()
|
||||||
@@ -2,4 +2,7 @@ package com.denizk0461.weserplaner.exception
|
|||||||
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exception is fired whenever a parcel is not transmitted properly.
|
||||||
|
*/
|
||||||
class ParcelNotFoundException : IOException()
|
class ParcelNotFoundException : IOException()
|
||||||
@@ -2,6 +2,7 @@ package com.denizk0461.weserplaner.viewmodel
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.denizk0461.weserplaner.data.StudIPParser
|
import com.denizk0461.weserplaner.data.StudIPParser
|
||||||
|
import com.denizk0461.weserplaner.exception.NotLoggedInException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import kotlin.jvm.Throws
|
import kotlin.jvm.Throws
|
||||||
|
|
||||||
@@ -20,9 +21,11 @@ class FetcherViewModel(app: Application) : AppViewModel(app) {
|
|||||||
/**
|
/**
|
||||||
* Fetches and parses the user's Stud.IP schedule.
|
* Fetches and parses the user's Stud.IP schedule.
|
||||||
*
|
*
|
||||||
* @param html source code of the schedule website
|
* @param html source code of the schedule website
|
||||||
|
* @throws NotLoggedInException if the user has not logged in before starting the fetch
|
||||||
|
* @throws IOException when an error in fetching or the database transaction occurs
|
||||||
*/
|
*/
|
||||||
@Throws(IOException::class)
|
@Throws(NotLoggedInException::class, IOException::class)
|
||||||
fun parse(html: String): Int =
|
fun parse(html: String): Int =
|
||||||
returnBlocking {
|
returnBlocking {
|
||||||
parser.parse(html)
|
parser.parse(html)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
<string name="fetch_error_snack">Ein Fehler ist aufgetreten!</string>
|
<string name="fetch_error_snack">Ein Fehler ist aufgetreten!</string>
|
||||||
<string name="fetch_error_webpage_snack">Du musst deinen Stundenplan öffnen!</string>
|
<string name="fetch_error_webpage_snack">Du musst deinen Stundenplan öffnen!</string>
|
||||||
|
<string name="fetch_error_login_snack">Du musst dich zuerst einloggen!</string>
|
||||||
<string name="canteen_fetch_error">Mensaplan konnte nicht heruntergeladen werden!</string>
|
<string name="canteen_fetch_error">Mensaplan konnte nicht heruntergeladen werden!</string>
|
||||||
|
|
||||||
<string name="canteen_item_difference_text_one">Ein Angebot aufgrund deiner Präferenzen versteckt.</string>
|
<string name="canteen_item_difference_text_one">Ein Angebot aufgrund deiner Präferenzen versteckt.</string>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
<string name="fetch_error_snack">Something went wrong!</string>
|
<string name="fetch_error_snack">Something went wrong!</string>
|
||||||
<string name="fetch_error_webpage_snack">You must navigate to your schedule!</string>
|
<string name="fetch_error_webpage_snack">You must navigate to your schedule!</string>
|
||||||
|
<string name="fetch_error_login_snack">You must log in first!</string>
|
||||||
<string name="canteen_fetch_error">Couldn\'t retrieve the canteen plan!</string>
|
<string name="canteen_fetch_error">Couldn\'t retrieve the canteen plan!</string>
|
||||||
|
|
||||||
<string name="canteen_item_difference_text_one">One offer hidden due to your preferences.</string>
|
<string name="canteen_item_difference_text_one">One offer hidden due to your preferences.</string>
|
||||||
|
|||||||
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
|
#Sun May 21 09:09:07 CEST 2023
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
Reference in New Issue
Block a user