diff --git a/mobile/app/src/main/java/com/odweta/solen/CalWeekFragment.kt b/mobile/app/src/main/java/com/odweta/solen/CalWeekFragment.kt index dc0689a..205d3c1 100644 --- a/mobile/app/src/main/java/com/odweta/solen/CalWeekFragment.kt +++ b/mobile/app/src/main/java/com/odweta/solen/CalWeekFragment.kt @@ -283,7 +283,7 @@ class DayFragment(private val position: Int) : Fragment(R.layout.fragment_day) { val dayEndTextView = TextView(requireContext()) val endTime = day.subjects[day.subjects.size - 1].end - val dayEndString = "Day ends at $endTime" + val dayEndString = "Den končí v $endTime" dayEndTextView.text = dayEndString dayEndTextView.textSize = 20f dayEndTextView.setPadding(0, 30, 0, 30) diff --git a/mobile/app/src/main/java/com/odweta/solen/MainActivity.kt b/mobile/app/src/main/java/com/odweta/solen/MainActivity.kt index 59fd399..e51bff9 100644 --- a/mobile/app/src/main/java/com/odweta/solen/MainActivity.kt +++ b/mobile/app/src/main/java/com/odweta/solen/MainActivity.kt @@ -1,8 +1,12 @@ package com.odweta.solen +import android.R.id.input +import android.annotation.SuppressLint +import android.os.Build import android.os.Bundle import android.util.Log import android.view.View +import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers @@ -11,12 +15,13 @@ import kotlinx.coroutines.withContext import okhttp3.FormBody import okhttp3.OkHttpClient import okhttp3.Request +import org.json.JSONArray import org.json.JSONObject import java.io.IOException import java.text.SimpleDateFormat -import java.util.Calendar -import java.util.Date -import java.util.Locale +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + class MainActivity : AppCompatActivity(), MainActivityListener { companion object { @@ -24,14 +29,35 @@ class MainActivity : AppCompatActivity(), MainActivityListener { val dateMap = mutableMapOf() } - private val username = "x" - private val password = "y" + private val client = OkHttpClient() + + private val username = "USERNAME" + private val password = "PASSWORD" + private val apiBaseUrl = "https://aplikace.skolaonline.cz/solapi/api" + private val tokenUrl = "$apiBaseUrl/connect/token" + private var token = "" + private val userDataUrl = "$apiBaseUrl/v1/user" + private var userData = JSONObject() + private var studentId = "" + private val timeTableUrl = "$apiBaseUrl/v1/timeTable" + private val marksUrl = "$apiBaseUrl/v1/students/$studentId/marks/list" + + private suspend fun setupAPI() { + return withContext(Dispatchers.IO) { + token = getToken() + userData = getUserDataJSON() + studentId = getStudentId() + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_cal_week) - launch() + lifecycleScope.launch { + setupAPI() + launch() + } } override fun onLaunch(view: View) { @@ -40,14 +66,14 @@ class MainActivity : AppCompatActivity(), MainActivityListener { private fun launch() { lifecycleScope.launch { - val week = parseJSON(getCalWeekJSON(username, password)) + val week = parseJSON(getTimeTableJSON()) for ((i, day) in week.withIndex()) { dayMap[i] = day } - val currentDate = SimpleDateFormat("d.M.", Locale.getDefault()).format(Date()) - val dayOfWeek = Calendar.DAY_OF_WEEK - dateMap[currentDate] = dayOfWeek - 2 + //val currentDate = SimpleDateFormat("", Locale.getDefault()).format(Date()) + //val dayOfWeek = Calendar.DAY_OF_WEEK + //dateMap[currentDate] = dayOfWeek - 2 val mainFragment = CalWeekFragment() supportFragmentManager.beginTransaction() @@ -56,58 +82,91 @@ class MainActivity : AppCompatActivity(), MainActivityListener { } } - private suspend fun getCalWeekJSON(username: String, password: String): String { - val url = "http://127.0.0.1:8080/fetch.php" - val client = OkHttpClient() - + private suspend fun getToken(): String { return withContext(Dispatchers.IO) { val request = Request.Builder() - .url(url) + .url(tokenUrl) + .header("Content-Type", "application/x-www-form-urlencoded") .post( FormBody.Builder() + .add("grant_type", "password") .add("username", username) .add("password", password) - .add("cal_week", "true") + .add("client_id", "test_client") + .add("scope", "openid offline_access profile sol_api") .build() ) .build() try { val resp = client.newCall(request).execute() - resp.body?.string() - } catch (e: IOException) { - """{ - "body": [ - { - "name": "Login failed", - "date": "Login failed", - "subjects": [ - "name": "Login failed", - "place": "Login failed", - "teacher": "Login failed", - "is_substitute": "Login failed", - "number": 0, - "start": "Login failed", - "end": "Login failed" - ] - } - ], - "status_code": 1 - }""".trimMargin() + val respString = resp.body?.string() + val respJson = respString?.let { JSONObject(it) } + val token = respJson?.get("access_token").toString() + token + } catch (e: Exception) { + "0" } - }.toString() + } } + private fun getStudentId(): String { + return userData.get("personID").toString() + } + + private suspend fun getUserDataJSON(): JSONObject { + return withContext(Dispatchers.IO) { + val request = Request.Builder() + .url(userDataUrl) + .header("Content-Type", "application/x-www-form-urlencoded") + .header("Authorization", "Bearer $token") // using Bearer auth token + .get() + .build() + + try { + val resp = client.newCall(request).execute() + val respJSON = JSONObject(resp.body?.string().toString()) + respJSON + } catch (e: IOException) { + JSONObject("""0""") + } + } + } + + private suspend fun getTimeTableJSON(): String { + // I now figured out how to use the SOL API (kinda), yay + + return withContext(Dispatchers.IO) { + val request = Request.Builder() + .url(timeTableUrl) + .header("Content-Type", "application/x-www-form-urlencoded") + .header("Authorization", "Bearer $token") + .get() + .build() + + try { + val resp = client.newCall(request).execute() + //Log.d("d", resp.body?.string().toString()) + //Log.d("d", JSONObject(resp.body?.string().toString()).get("subject").toString()) + resp.body?.string().toString() + } catch (e: IOException) { + "0" + } + } + } + + @RequiresApi(Build.VERSION_CODES.O) private fun parseJSON(jsonString: String): List { val jsonObject = JSONObject(jsonString) /* * return a List that looks like this: - * ["Po", "8.1.", ["D", "207", "Strakova S.", 0, 1, "08:00", "08:45"]] + * [, , [, , , , , , ]] + * ["Po", "8.1.", ["D", "207", "Strakova S.", 0, 1, "08:00", "08:45" ]] */ // Access the "body" array from the main JSON object - val bodyArray = jsonObject.getJSONArray("body") + val bodyArray = jsonObject.getJSONArray("days") val week = mutableListOf() @@ -119,27 +178,82 @@ class MainActivity : AppCompatActivity(), MainActivityListener { } for (obj in jsonObjectList) { - val name = obj.get("name").toString() - val date = obj.get("date").toString() + val dateRAW = obj.get("date").toString() + var dayStr = dateRAW.split("T")[0].split("-")[2] + var monthStr = dateRAW.split("T")[0].split("-")[1] + + if (dayStr[0] == '0') { dayStr = dayStr.slice(1..dayStr.length-1) } + if (monthStr[0] == '0') { monthStr = monthStr.slice(1..monthStr.length-1) } + + val date = "$dayStr. $monthStr." + + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss") + val localDateTime = LocalDateTime.parse(dateRAW, formatter) + + val name = when (localDateTime.dayOfWeek.toString()) { + "Monday" -> "Pondělí" + "Tuesday" -> "Úterý" + "Wednesday" -> "Středa" + "Thursday" -> "Čtvrtek" + "Friday" -> "Pátek" + "Saturday" -> "Sobota" + "Sunday" -> "Neděle" + else -> "Invalid day" + } + val subjects = mutableListOf() val subjectJSONList = mutableListOf() - val subjectArray = obj.getJSONArray("subjects") + val subjectArray = obj.getJSONArray("schedules") for (i in 0 until subjectArray.length()) { subjectJSONList.add(subjectArray.getJSONObject(i)) } + var i = 0 for (subj in subjectJSONList) { - val subject = Subject() - subject.name = subj.get("name").toString() - subject.place = subj.get("place").toString() - subject.teacher = subj.get("teacher").toString() - subject.substitute = subj.get("is_substitute").toString() - subject.number = subj.get("number").toString() - subject.start = subj.get("start").toString() - subject.end = subj.get("end").toString() + val kind = subj.getJSONObject("hourKind").get("id") + if ( + (subj.getJSONObject("hourType").get("id") == "SUPLOVANA") || + (subj.getJSONObject("hourKind").get("id") != "SUPLOVANI" && subj.getJSONObject("hourKind").get("id") != "") + ) { + Log.d("skip", "skipping $i times | kind: $kind") + i += 1 + continue + } + Log.d("skip", "did not skip!") - subjects.add(subject) + val subject = Subject() + subject.name = subj.getJSONObject("subject").get("name").toString() + Log.d("debug", subject.name) + subject.place = subj.getJSONArray("rooms").getJSONObject(0).get("abbrev").toString() + subject.teacher = subj.getJSONArray("teachers").getJSONObject(0).get("displayName").toString() + if (subj.getJSONObject("hourType").get("id").toString() == "ROZVRH") { + subject.substitute = "0" + } else if (subj.getJSONObject("hourType").get("id").toString() == "SUPLOVANI") { + subject.substitute = "1" + } + val hourspan = subj.getJSONArray("detailHours").length() + if (hourspan == 1) { + val detailHours = subj.getJSONArray("detailHours") + subject.number = detailHours.getJSONObject(0).get("id").toString() + subject.start = detailHours.getJSONObject(0).get("timeFrom").toString() + subject.start = subject.start.slice(0..subject.start.length-4) + subject.end = detailHours.getJSONObject(0).get("timeto").toString() + subject.end = subject.end.slice(0..subject.end.length-4) + Log.d("push", "pushing day...") + subjects.add(subject) + } else { + for (i in 0..