fix: apply API changes
This commit is contained in:
@@ -19,11 +19,14 @@ import ru.sweetbread.unn.db.loadSchedule
|
|||||||
import ru.sweetbread.unn.db.loadUserByBitrixId
|
import ru.sweetbread.unn.db.loadUserByBitrixId
|
||||||
import ru.sweetbread.unn.ui.layout.LoginData
|
import ru.sweetbread.unn.ui.layout.LoginData
|
||||||
import ru.sweetbread.unn.ui.layout.client
|
import ru.sweetbread.unn.ui.layout.client
|
||||||
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
|
import java.time.ZoneId
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
|
||||||
private lateinit var PHPSESSID: String
|
private lateinit var PHPSESSID: String
|
||||||
private lateinit var CSRF: String
|
private lateinit var CSRF: String
|
||||||
lateinit var ME: User
|
lateinit var ME: User
|
||||||
@@ -31,8 +34,10 @@ lateinit var ME: User
|
|||||||
const val portalURL = "https://portal.unn.ru"
|
const val portalURL = "https://portal.unn.ru"
|
||||||
const val ruzapiURL = "$portalURL/ruzapi"
|
const val ruzapiURL = "$portalURL/ruzapi"
|
||||||
const val vuzapiURL = "$portalURL/bitrix/vuz/api"
|
const val vuzapiURL = "$portalURL/bitrix/vuz/api"
|
||||||
|
const val prtl2URL = "$portalURL/portal2/api"
|
||||||
const val restURL = "$portalURL/rest"
|
const val restURL = "$portalURL/rest"
|
||||||
|
|
||||||
|
|
||||||
enum class Type(val s: String) {
|
enum class Type(val s: String) {
|
||||||
Student("student"),
|
Student("student"),
|
||||||
Group("group"),
|
Group("group"),
|
||||||
@@ -109,7 +114,6 @@ class User(
|
|||||||
|
|
||||||
class Post(
|
class Post(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val blogId: Int,
|
|
||||||
val authorId: Int,
|
val authorId: Int,
|
||||||
val enableComments: Boolean,
|
val enableComments: Boolean,
|
||||||
val numComments: Int,
|
val numComments: Int,
|
||||||
@@ -123,6 +127,7 @@ class AvatarSet(
|
|||||||
val small: String
|
val small: String
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authorize user by [login] and [password]
|
* Authorize user by [login] and [password]
|
||||||
*
|
*
|
||||||
@@ -147,12 +152,11 @@ suspend fun auth(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (r.status.value == 302) {
|
if (r.status.value == 302) {
|
||||||
|
Log.d("tmp", "158")
|
||||||
PHPSESSID =
|
PHPSESSID =
|
||||||
"""PHPSESSID=([\w\d]+)""".toRegex().find(r.headers["Set-Cookie"]!!)!!.groupValues[1]
|
"""PHPSESSID=([\w\d]+)""".toRegex().find(r.headers["Set-Cookie"]!!)!!.groupValues[1]
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
|
||||||
getMyself(login)
|
getMyself(login)
|
||||||
getCSRF()
|
getCSRF()
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -162,42 +166,45 @@ suspend fun auth(
|
|||||||
* Save info about current [User] in memory
|
* Save info about current [User] in memory
|
||||||
*/
|
*/
|
||||||
private suspend fun getMyself(login: String) {
|
private suspend fun getMyself(login: String) {
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
Log.d("tmp", "getMyself")
|
||||||
val studentinfo = JSONObject(client.get("$ruzapiURL/studentinfo") {
|
// WARNING: trailing / is important, 'cuz API devs are eating shit
|
||||||
parameter("uns", login.substring(1))
|
val studentinfo = JSONObject(client.get("$ruzapiURL/studentinfo/") {
|
||||||
}.bodyAsText())
|
header("Cookie", "PHPSESSID=$PHPSESSID")
|
||||||
|
parameter("uns", login.drop(1))
|
||||||
|
}.bodyAsText())
|
||||||
|
|
||||||
val user = JSONObject(
|
val user = JSONObject(
|
||||||
client.get("$vuzapiURL/user") {
|
client.get("$vuzapiURL/user") {
|
||||||
header("Cookie", "PHPSESSID=$PHPSESSID")
|
header("Cookie", "PHPSESSID=$PHPSESSID")
|
||||||
}.bodyAsText()
|
}.bodyAsText()
|
||||||
)
|
)
|
||||||
|
|
||||||
ME = User(
|
Log.d("studentInfo", studentinfo.toString(2))
|
||||||
unnId = studentinfo.getString("id").toInt(),
|
|
||||||
bitrixId = user.getInt("bitrix_id"),
|
ME = User(
|
||||||
userId = user.getInt("id"),
|
unnId = studentinfo.getString("id").toInt(),
|
||||||
type = when (studentinfo.getString("type")) {
|
bitrixId = user.getInt("bitrix_id"),
|
||||||
"lecturer" -> Type.Lecturer // ig,,,
|
userId = user.getInt("id"),
|
||||||
else -> Type.Student
|
type = when (studentinfo.getString("type")) {
|
||||||
},
|
"lecturer" -> Type.Lecturer // ig,,,
|
||||||
email = user.getString("email"),
|
else -> Type.Student
|
||||||
nameRu = user.getString("fullname"),
|
},
|
||||||
nameEn = user.getString("fullname_en"),
|
email = user.getString("email"),
|
||||||
isMale = user.getString("sex") == "M",
|
nameRu = user.getString("fullname"),
|
||||||
birthday = LocalDate.parse(
|
nameEn = user.getString("fullname_en"),
|
||||||
user.getString("birthdate"),
|
isMale = user.getString("sex") == "M",
|
||||||
DateTimeFormatter.ofPattern("yyyy-MM-dd")
|
birthday = Instant
|
||||||
),
|
.parse(user.getString("birthdate"))
|
||||||
avatar = user.getJSONObject("photo").let {
|
.atZone(ZoneId.of("Europe/Moscow"))
|
||||||
AvatarSet(
|
.toLocalDate(),
|
||||||
it.getString("orig"),
|
avatar = user.getJSONObject("photo").let {
|
||||||
it.getString("thumbnail"),
|
AvatarSet(
|
||||||
it.getString("small"),
|
it.getString("orig"),
|
||||||
)
|
it.getString("thumbnail"),
|
||||||
}
|
it.getString("small"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getScheduleDay(
|
suspend fun getScheduleDay(
|
||||||
@@ -223,7 +230,7 @@ suspend fun getSchedule(
|
|||||||
start: LocalDate,
|
start: LocalDate,
|
||||||
finish: LocalDate
|
finish: LocalDate
|
||||||
): ArrayList<ScheduleUnit> {
|
): ArrayList<ScheduleUnit> {
|
||||||
val unnDatePattern = DateTimeFormatter.ofPattern("yyyy.MM.dd")
|
val unnDatePattern = DateTimeFormatter.ofPattern("yyyy-MM-dd")
|
||||||
|
|
||||||
val r = client.get("$ruzapiURL/schedule/${type.s}/$id") {
|
val r = client.get("$ruzapiURL/schedule/${type.s}/$id") {
|
||||||
parameter("start", start.format(unnDatePattern))
|
parameter("start", start.format(unnDatePattern))
|
||||||
@@ -302,36 +309,36 @@ suspend fun getSchedule(
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCSRF() {
|
suspend fun getCSRF() {
|
||||||
|
Log.d("tmp", "getCSRF")
|
||||||
val r = client.get("$restURL/log.blogpost.get") {
|
val r = client.get("$restURL/log.blogpost.get") {
|
||||||
header("Cookie", "PHPSESSID=$PHPSESSID")
|
header("Cookie", "PHPSESSID=$PHPSESSID")
|
||||||
parameter("sessid", "")
|
parameter("sessid", "")
|
||||||
}
|
}
|
||||||
CSRF = JSONObject(r.bodyAsText()).getString("sessid")
|
CSRF = JSONObject(r.bodyAsText()).getString("sessid")
|
||||||
|
Log.d("tmp", "end getCSRF")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getBlogposts(): ArrayList<Post> {
|
suspend fun getBlogposts(): ArrayList<Post> {
|
||||||
val r = client.get("$restURL/log.blogpost.get") {
|
val r = client.get("$prtl2URL/news.php") {
|
||||||
header("Cookie", "PHPSESSID=$PHPSESSID")
|
header("Cookie", "PHPSESSID=$PHPSESSID")
|
||||||
parameter("sessid", CSRF)
|
header("x-bitrix-sessid-token", CSRF)
|
||||||
}
|
}
|
||||||
val json = JSONObject(r.bodyAsText())
|
val result = JSONArray(r.bodyAsText())
|
||||||
val result = json.getJSONArray("result")
|
|
||||||
|
|
||||||
val out = arrayListOf<Post>()
|
val out = arrayListOf<Post>()
|
||||||
for (i in 0 until result.length()) {
|
for (i in 0 until result.length()) {
|
||||||
val el = result.getJSONObject(i)
|
val el = result.getJSONObject(i)
|
||||||
out.add(
|
out.add(
|
||||||
Post(
|
Post(
|
||||||
id = el.getString("ID").toInt(),
|
id = el.getString("id").toInt(),
|
||||||
blogId = el.getString("BLOG_ID").toInt(),
|
authorId = el.getJSONObject("author").getInt("id").toInt(),
|
||||||
authorId = el.getString("AUTHOR_ID").toInt(),
|
enableComments = true, // FIXME: Delete the field or get correct value
|
||||||
enableComments = el.getString("ENABLE_COMMENTS") == "Y",
|
numComments = el.getString("commentsnum").toInt(),
|
||||||
numComments = el.getString("NUM_COMMENTS").toInt(),
|
|
||||||
date = LocalDateTime.parse(
|
date = LocalDateTime.parse(
|
||||||
el.getString("DATE_PUBLISH"),
|
el.getString("time"),
|
||||||
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'+03:00'")
|
DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss")
|
||||||
),
|
),
|
||||||
content = el.getString("DETAIL_TEXT")
|
content = el.getString("fulltext")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -375,10 +382,10 @@ suspend fun getUser(id: Int): User {
|
|||||||
nameRu = json.getString("fullname"),
|
nameRu = json.getString("fullname"),
|
||||||
nameEn = json.getString("fullname_en"),
|
nameEn = json.getString("fullname_en"),
|
||||||
isMale = json.getString("sex") == "M",
|
isMale = json.getString("sex") == "M",
|
||||||
birthday = LocalDate.parse(
|
birthday = Instant
|
||||||
json.getString("birthdate"),
|
.parse(json.getString("birthdate"))
|
||||||
DateTimeFormatter.ofPattern("yyyy-MM-dd")
|
.atZone(ZoneId.of("Europe/Moscow"))
|
||||||
),
|
.toLocalDate(),
|
||||||
avatar = json.getJSONObject("photo").let {
|
avatar = json.getJSONObject("photo").let {
|
||||||
AvatarSet(
|
AvatarSet(
|
||||||
it.getString("orig"),
|
it.getString("orig"),
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ class UNNApp : Application() {
|
|||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
super.attachBaseContext(base)
|
super.attachBaseContext(base)
|
||||||
|
|
||||||
initAcra {
|
// initAcra {
|
||||||
buildConfigClass = BuildConfig::class.java
|
// buildConfigClass = BuildConfig::class.java
|
||||||
reportFormat = StringFormat.JSON
|
// reportFormat = StringFormat.JSON
|
||||||
httpSender {
|
// httpSender {
|
||||||
uri = BuildConfig.ACRA_URL
|
// uri = BuildConfig.ACRA_URL
|
||||||
basicAuthLogin = BuildConfig.ACRA_LOGIN
|
// basicAuthLogin = BuildConfig.ACRA_LOGIN
|
||||||
basicAuthPassword = BuildConfig.ACRA_PASS
|
// basicAuthPassword = BuildConfig.ACRA_PASS
|
||||||
httpMethod = HttpSender.Method.POST
|
// httpMethod = HttpSender.Method.POST
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
package ru.sweetbread.unn.ui
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import io.ktor.client.request.forms.submitForm
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import io.ktor.client.request.parameter
|
||||||
|
import io.ktor.client.statement.bodyAsText
|
||||||
|
import io.ktor.http.parameters
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
import ru.sweetbread.unn.ui.layout.LoginData
|
||||||
|
import ru.sweetbread.unn.ui.layout.client
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
private lateinit var PHPSESSID: String
|
||||||
|
lateinit var ME: User
|
||||||
|
|
||||||
|
const val portalURL = "https://portal.unn.ru"
|
||||||
|
const val ruzapiURL = "$portalURL/ruzapi"
|
||||||
|
|
||||||
|
enum class Type(val s: String) {
|
||||||
|
Student("student"),
|
||||||
|
Group("group"),
|
||||||
|
Lecturer("lecturer"),
|
||||||
|
Auditorium("auditorium")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class LecturerRank(val s: String) {
|
||||||
|
Lecturer("Lecturer"),
|
||||||
|
SLecturer("Senior Lecturer")
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScheduleUnit(
|
||||||
|
val auditorium: Auditorium,
|
||||||
|
val date: LocalDate,
|
||||||
|
val discipline: Discipline,
|
||||||
|
val kindOfWork: KindOfWork,
|
||||||
|
val lecturers: ArrayList<Lecturer>,
|
||||||
|
val stream: String,
|
||||||
|
val begin: LocalTime,
|
||||||
|
val end: LocalTime)
|
||||||
|
|
||||||
|
class Auditorium (val name: String,
|
||||||
|
val oid: Int,
|
||||||
|
val floor: Int,
|
||||||
|
val building: Building)
|
||||||
|
class Building(val name: String,
|
||||||
|
val gid: Int,
|
||||||
|
val oid: Int)
|
||||||
|
|
||||||
|
class Discipline (val name: String,
|
||||||
|
val oid: Int,
|
||||||
|
val type: Int)
|
||||||
|
|
||||||
|
class KindOfWork (val name: String,
|
||||||
|
val oid: Int,
|
||||||
|
val uid: String,
|
||||||
|
val complexity: Int)
|
||||||
|
|
||||||
|
class Lecturer (val name: String,
|
||||||
|
val rank: LecturerRank,
|
||||||
|
val email: String,
|
||||||
|
val oid: Int,
|
||||||
|
val uid: String)
|
||||||
|
|
||||||
|
class User (val id: String,
|
||||||
|
val uns: String,
|
||||||
|
val type: Type,
|
||||||
|
val email: String,
|
||||||
|
val name: String,
|
||||||
|
val info: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authorize user by [login] and [password]
|
||||||
|
*
|
||||||
|
* Also defines local vars [PHPSESSID] and [ME.id]
|
||||||
|
*/
|
||||||
|
suspend fun auth(login: String = LoginData.login, password: String = LoginData.password, forced: Boolean = false): Boolean {
|
||||||
|
if (!forced) {
|
||||||
|
if (::PHPSESSID.isInitialized and ::ME.isInitialized)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val r = client.submitForm("$portalURL/auth/?login=yes",
|
||||||
|
formParameters = parameters {
|
||||||
|
append("AUTH_FORM", "Y")
|
||||||
|
append("TYPE", "AUTH")
|
||||||
|
append("backurl", "/")
|
||||||
|
append("USER_LOGIN", login)
|
||||||
|
append("USER_PASSWORD", password)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (r.status.value == 302) {
|
||||||
|
PHPSESSID = """PHPSESSID=([\w\d]+)""".toRegex().find(r.headers["Set-Cookie"]!!)!!.groupValues[1]
|
||||||
|
getMyself(login)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun getMyself(login: String) {
|
||||||
|
val r = client.get("$ruzapiURL/studentinfo") {
|
||||||
|
parameter("uns", login.substring(1))
|
||||||
|
}
|
||||||
|
val json = JSONObject(r.bodyAsText())
|
||||||
|
ME = User(
|
||||||
|
id = json.getString("id"),
|
||||||
|
uns = json.getString("uns"),
|
||||||
|
type = when(json.getString("type")) {
|
||||||
|
"lecturer" -> Type.Lecturer // ig...
|
||||||
|
else -> Type.Student
|
||||||
|
},
|
||||||
|
email = json.getString("email"),
|
||||||
|
name = json.getString("fio"),
|
||||||
|
info = json.getString("info")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSchedule(type: Type = Type.Student, id: String = ME.id, start: LocalDate, finish: LocalDate): ArrayList<ScheduleUnit> {
|
||||||
|
val r = client.get("$ruzapiURL/schedule/${type.s}/$id") {
|
||||||
|
parameter("start", start.format(DateTimeFormatter.ofPattern("yyyy.MM.dd")))
|
||||||
|
parameter("finish", finish.format(DateTimeFormatter.ofPattern("yyyy.MM.dd")))
|
||||||
|
parameter("lng", "1")
|
||||||
|
}
|
||||||
|
val json = JSONArray(r.bodyAsText())
|
||||||
|
val out = arrayListOf<ScheduleUnit>()
|
||||||
|
for (i in 0 until json.length()) {
|
||||||
|
val unit = json.getJSONObject(i)
|
||||||
|
val lecturesJson = unit.getJSONArray("listOfLecturers")
|
||||||
|
val lecturers = arrayListOf<Lecturer>()
|
||||||
|
|
||||||
|
for (j in 0 until lecturesJson.length()) {
|
||||||
|
val lecturer = lecturesJson.getJSONObject(j)
|
||||||
|
lecturers.add(
|
||||||
|
Lecturer(
|
||||||
|
name = lecturer.getString("lecturer"),
|
||||||
|
email = lecturer.getString("lecturerEmail"),
|
||||||
|
oid = lecturer.getInt("lecturerOid"),
|
||||||
|
uid = lecturer.getString("lecturerUID"),
|
||||||
|
rank = when (lecturer.getString("lecturer_rank")) {
|
||||||
|
"СТПРЕП" -> LecturerRank.SLecturer
|
||||||
|
else -> LecturerRank.Lecturer
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.add(
|
||||||
|
ScheduleUnit(
|
||||||
|
auditorium = Auditorium(
|
||||||
|
name = unit.getString("auditorium"),
|
||||||
|
oid = unit.getInt("auditoriumOid"),
|
||||||
|
floor = unit.getInt("auditoriumfloor"),
|
||||||
|
building = Building(
|
||||||
|
name = unit.getString("building"),
|
||||||
|
gid = unit.getInt("buildingGid"),
|
||||||
|
oid = unit.getInt("buildingOid")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
date = LocalDate.parse(unit.getString("date"), DateTimeFormatter.ofPattern("yyyy.MM.dd")),
|
||||||
|
discipline = Discipline(
|
||||||
|
name = unit.getString("discipline"),
|
||||||
|
oid = unit.getInt("disciplineOid"),
|
||||||
|
type = unit.getInt("disciplinetypeload")
|
||||||
|
),
|
||||||
|
kindOfWork = KindOfWork(
|
||||||
|
name = unit.getString("kindOfWork"),
|
||||||
|
complexity = unit.getInt("kindOfWorkComplexity"),
|
||||||
|
oid = unit.getInt("kindOfWorkOid"),
|
||||||
|
uid = unit.getString("kindOfWorkUid")
|
||||||
|
),
|
||||||
|
lecturers = lecturers,
|
||||||
|
stream = unit.getString("stream"),
|
||||||
|
begin = LocalTime.parse(unit.getString("beginLesson"), DateTimeFormatter.ofPattern("HH:mm")),
|
||||||
|
end = LocalTime.parse(unit.getString("endLesson"), DateTimeFormatter.ofPattern("HH:mm"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
@@ -278,7 +278,6 @@ fun UserItemPreview() {
|
|||||||
fun PostItemPreview() {
|
fun PostItemPreview() {
|
||||||
val post = Post(
|
val post = Post(
|
||||||
id = 154923,
|
id = 154923,
|
||||||
blogId = 121212,
|
|
||||||
authorId = 165945,
|
authorId = 165945,
|
||||||
enableComments = true,
|
enableComments = true,
|
||||||
numComments = 0,
|
numComments = 0,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[versions]
|
[versions]
|
||||||
acraHttp = "5.11.3"
|
acraHttp = "5.11.3"
|
||||||
agp = "8.5.2"
|
agp = "8.7.0"
|
||||||
calendar = "2.5.4"
|
calendar = "2.5.4"
|
||||||
coilCompose = "2.7.0"
|
coilCompose = "2.7.0"
|
||||||
compose = "1.6.4" # Updating this will cause an error!
|
compose = "1.6.4" # Updating this will cause an error!
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#Sat Mar 16 18:30:45 MSK 2024
|
#Sat Mar 16 18:30:45 MSK 2024
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
Reference in New Issue
Block a user