diff --git a/.idea/misc.xml b/.idea/misc.xml index 0ad17cb..2904b84 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,11 @@ + + + + + + diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 27e25b0..5e5bffb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -32,8 +32,8 @@ android { applicationId = "ru.n08i40k.polytechnic.next" minSdk = 26 targetSdk = 35 - versionCode = 2 - versionName = "1.1" + versionCode = 3 + versionName = "1.2" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/data/schedule/impl/RemoteScheduleRepository.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/data/schedule/impl/RemoteScheduleRepository.kt index f460137..3134a6a 100644 --- a/app/src/main/java/ru/n08i40k/polytechnic/next/data/schedule/impl/RemoteScheduleRepository.kt +++ b/app/src/main/java/ru/n08i40k/polytechnic/next/data/schedule/impl/RemoteScheduleRepository.kt @@ -1,7 +1,10 @@ package ru.n08i40k.polytechnic.next.data.schedule.impl import android.content.Context +import com.android.volley.Request +import com.android.volley.ServerError import com.android.volley.toolbox.RequestFuture +import com.android.volley.toolbox.StringRequest import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map @@ -10,14 +13,67 @@ import kotlinx.coroutines.withContext import ru.n08i40k.polytechnic.next.data.MyResult import ru.n08i40k.polytechnic.next.data.schedule.ScheduleRepository import ru.n08i40k.polytechnic.next.model.Group +import ru.n08i40k.polytechnic.next.network.NetworkConnection import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetRequest import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetRequestData import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleGetResponse +import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleUpdateRequest +import ru.n08i40k.polytechnic.next.network.data.schedule.ScheduleUpdateRequestData import ru.n08i40k.polytechnic.next.settings.settingsDataStore +import java.util.logging.Logger +import kotlin.io.encoding.Base64 +import kotlin.io.encoding.ExperimentalEncodingApi class RemoteScheduleRepository(private val context: Context) : ScheduleRepository { + @OptIn(ExperimentalEncodingApi::class) + suspend fun getMainPage(): MyResult { + return withContext(Dispatchers.IO) { + val mainPageFuture = RequestFuture.newFuture() + val request = StringRequest( + Request.Method.GET, + "https://politehnikum-eng.ru/index/raspisanie_zanjatij/0-409", + mainPageFuture, + mainPageFuture + ) + NetworkConnection.getInstance(context).addToRequestQueue(request) + + try { + val encodedMainPage = + Base64.Default.encode(mainPageFuture.get().encodeToByteArray()) + MyResult.Success(encodedMainPage) + } catch (exception: Exception) { + MyResult.Failure(exception) + } + } + } + + suspend fun updateMainPage(): MyResult { + return withContext(Dispatchers.IO) { + val mainPage = getMainPage() + + if (mainPage is MyResult.Failure) + return@withContext mainPage + + val updateFuture = RequestFuture.newFuture() + ScheduleUpdateRequest( + ScheduleUpdateRequestData((mainPage as MyResult.Success).data), + context, + updateFuture, + updateFuture + ).send() + + try { + MyResult.Success(updateFuture.get()) + } catch (exception: Exception) { + MyResult.Failure(exception) + } + } + } + override suspend fun getGroup(): MyResult { return withContext(Dispatchers.IO) { + val logger = Logger.getLogger("RemoteScheduleRepository") + val groupName = runBlocking { context.settingsDataStore.data.map { settings -> settings.group }.first() } @@ -25,16 +81,49 @@ class RemoteScheduleRepository(private val context: Context) : ScheduleRepositor if (groupName.isEmpty()) return@withContext MyResult.Failure(IllegalArgumentException("No group name provided!")) - val responseFuture = RequestFuture.newFuture() + val firstPassFuture = RequestFuture.newFuture() ScheduleGetRequest( ScheduleGetRequestData(groupName), context, - responseFuture, - responseFuture + firstPassFuture, + firstPassFuture + ).send() + + var firstPassResponse: ScheduleGetResponse? = null + + try { + firstPassResponse = firstPassFuture.get() + if (!firstPassResponse.updateRequired) { + logger.info("Successfully get group schedule!") + return@withContext MyResult.Success(firstPassFuture.get().group) + } + logger.info("Successfully get group schedule, but it needs to update!") + } catch (exception: Exception) { + if (exception.cause !is ServerError) + return@withContext MyResult.Failure(exception) + logger.info("Can't get group schedule, because it needs to first update!") + } + + val updateResult = updateMainPage() + if (updateResult is MyResult.Failure) { + logger.info("Can't update site main page!") + if (firstPassResponse != null) + return@withContext MyResult.Success(firstPassResponse.group) + + return@withContext updateResult + } + logger.info("Site main page successfully updated!") + + val secondPassFuture = RequestFuture.newFuture() + ScheduleGetRequest( + ScheduleGetRequestData(groupName), + context, + secondPassFuture, + secondPassFuture ).send() try { - MyResult.Success(responseFuture.get().group) + MyResult.Success(secondPassFuture.get().group) } catch (exception: Exception) { MyResult.Failure(exception) } diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetResponse.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetResponse.kt index bf6620a..b1a3918 100644 --- a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetResponse.kt +++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleGetResponse.kt @@ -8,5 +8,6 @@ data class ScheduleGetResponse( val updatedAt: String, val group: Group, val etag: String, - val lastChangedDays: ArrayList + val lastChangedDays: ArrayList, + val updateRequired: Boolean ) \ No newline at end of file diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdate.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdate.kt new file mode 100644 index 0000000..2c0da64 --- /dev/null +++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdate.kt @@ -0,0 +1,22 @@ +package ru.n08i40k.polytechnic.next.network.data.schedule + +import android.content.Context +import com.android.volley.Response +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import ru.n08i40k.polytechnic.next.network.data.AuthorizedRequest + +class ScheduleUpdateRequest( + private val data: ScheduleUpdateRequestData, + context: Context, + listener: Response.Listener, + errorListener: Response.ErrorListener? = null +) : AuthorizedRequest( + context, Method.POST, "schedule/update-site-main-page", Response.Listener { + listener.onResponse(null) + }, errorListener +) { + override fun getBody(): ByteArray { + return Json.encodeToString(data).toByteArray() + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdateRequestData.kt b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdateRequestData.kt new file mode 100644 index 0000000..092c41d --- /dev/null +++ b/app/src/main/java/ru/n08i40k/polytechnic/next/network/data/schedule/ScheduleUpdateRequestData.kt @@ -0,0 +1,6 @@ +package ru.n08i40k.polytechnic.next.network.data.schedule + +import kotlinx.serialization.Serializable + +@Serializable +data class ScheduleUpdateRequestData(val mainPage: String) \ No newline at end of file