Bimba.git

commit 0e1775e631f98f56d92ddef038d7e304bef5ea44

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(