Author: Adam Evyčędo <git@apiote.xyz>
get stops from Transitous
app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt | 2 app/src/main/java/xyz/apiote/bimba/czwek/api/queryables.kt | 125 + app/src/main/java/xyz/apiote/bimba/czwek/api/settings.kt | 8 app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt | 13
diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt index ce68b7ac246599433119ef2f5aef9f8daf9c0cde..bdb383c7bb383976507ceeed0a8db083413fef7f 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt @@ -208,7 +208,7 @@ } } } -private fun isNetworkAvailable(context: Context): Boolean { +internal fun isNetworkAvailable(context: Context): Boolean { val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/queryables.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/queryables.kt new file mode 100644 index 0000000000000000000000000000000000000000..fe0b7bde7d55f820581244d91dd74a775ab0b19f --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/queryables.kt @@ -0,0 +1,125 @@ +package xyz.apiote.bimba.czwek.api + +import android.content.Context +import android.os.Build +import android.util.JsonReader +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import xyz.apiote.bimba.czwek.R +import xyz.apiote.bimba.czwek.api.responses.ErrorResponse +import xyz.apiote.bimba.czwek.repo.Position +import xyz.apiote.bimba.czwek.repo.Queryable +import xyz.apiote.bimba.czwek.repo.Stop +import xyz.apiote.bimba.czwek.repo.TrafficResponseException +import java.io.IOException +import java.net.HttpURLConnection +import java.net.URL + +suspend fun getTransitousQueryables(query: String, context: Context): List<Queryable> { + if (!isNetworkAvailable(context)) { + throw TrafficResponseException(0, "", Error(0, R.string.error_offline, R.drawable.error_net)) + } + + val json = """ + { + "destination": { + "type": "Module", + "target": "/guesser" + }, + "content_type": "StationGuesserRequest", + "content": { + "input": "$query", + "guess_count": 6 + } + }""" + val result = withContext(Dispatchers.IO) { + val url = URL("https://routing.spline.de/api/") + val c = (url.openConnection() as HttpURLConnection).apply { + setRequestProperty( + "User-Agent", + "${context.getString(R.string.applicationId)}/${context.getString(R.string.versionName)} (${Build.VERSION.SDK_INT})" + ) + addRequestProperty("Content-Type", "application/json") + requestMethod = "POST" + doOutput = true + outputStream.write(json.toByteArray()) + } + try { + if (c.responseCode == 200) { + Result(c.inputStream, null) + } else { + val (string, image) = mapHttpError(c.responseCode) + Result(c.errorStream, Error(c.responseCode, string, image)) + } + } catch (e: IOException) { + Result(null, Error(0, R.string.error_connecting, R.drawable.error_server)) + } + } + + if (result.error != null) { + if (result.stream != null) { + val response = withContext(Dispatchers.IO) { ErrorResponse.unmarshal(result.stream) } + throw TrafficResponseException(result.error.statusCode, response.message, result.error) + } else { + throw TrafficResponseException(result.error.statusCode, "", result.error) + } + } else { + return withContext(Dispatchers.IO) { + val queryables = mutableListOf<Queryable>() + val r = JsonReader(result.stream!!.bufferedReader()) + r.beginObject() + while (r.hasNext()) { + val rootFieldName = r.nextName() // content + if (rootFieldName == "content") { + r.beginObject() + r.nextName() // guesses + r.beginArray() + while (r.hasNext()) { + var id = "" + var name = "" + var latitude = 0.0 + var longitude = 0.0 + r.beginObject() + while (r.hasNext()) { + val fieldName = r.nextName() + when (fieldName) { + "id" -> id = r.nextString() + "name" -> name = r.nextString() + "pos" -> { + r.beginObject() + while (r.hasNext()) { + val positionFieldName = r.nextName() + when (positionFieldName) { + "lat" -> latitude = r.nextDouble() + "lng" -> longitude = r.nextDouble() + } + } + r.endObject() + } + } + } + r.endObject() + queryables.add( + Stop( + code = id, + name = name, + nodeName = name, + zone = "", + feedID = "transitous", + position = Position(latitude = latitude, longitude = longitude), + changeOptions = emptyList() + ) + ) + } + r.endArray() + r.endObject() + } else { + r.skipValue() + } + } + r.endObject() + + return@withContext queryables + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/settings.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/settings.kt new file mode 100644 index 0000000000000000000000000000000000000000..2e53c8f207147ae333a35de77d9854e0e3c2c4e6 --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/settings.kt @@ -0,0 +1,8 @@ +package xyz.apiote.bimba.czwek.api + +import android.content.Context +import androidx.preference.PreferenceManager + +fun isTransitousEnabled(context: Context): Boolean { + return PreferenceManager.getDefaultSharedPreferences(context).getBoolean("transitous_enabled", false) +} \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt index 1ba24e3cbe16562fe30e5fb186d1087c948659c4..6255bb1ab1f911681dd3577064d557f01667a668 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt @@ -46,6 +46,7 @@ import xyz.apiote.bimba.czwek.api.responses.QueryablesResponseV1 import xyz.apiote.bimba.czwek.api.responses.QueryablesResponseV2 import xyz.apiote.bimba.czwek.api.responses.QueryablesResponseV3 import xyz.apiote.bimba.czwek.api.responses.QueryablesResponseV4 +import xyz.apiote.bimba.czwek.api.getTransitousQueryables import java.time.LocalDate // todo [3.2] in Repository check if responses are BARE or HTML @@ -234,7 +235,17 @@ override suspend fun queryQueryables( query: String, context: Context ): List<Queryable>? { - return getQueryables(query, null, context, "query") + val transitousQueryables = //if (isTransitousEnabled(context)) { + getTransitousQueryables(query, context) + /*} else { + null + }*/ + val bimbaQueryables = getQueryables(query, null, context, "query") + return if (transitousQueryables == null && bimbaQueryables == null) { + null + } else { + (transitousQueryables ?: listOf()) + (bimbaQueryables ?: listOf()) + } // TODO sort } override suspend fun locateQueryables(