initial commit
This commit is contained in:
commit
da99eb4f70
15 changed files with 724 additions and 0 deletions
68
src/main/kotlin/Main.kt
Normal file
68
src/main/kotlin/Main.kt
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package me.koendev
|
||||
|
||||
import java.io.File
|
||||
|
||||
data class ReactableOffer(
|
||||
val room: Room,
|
||||
val offer: Offer,
|
||||
val floorInfo: FloorInfo
|
||||
)
|
||||
|
||||
fun main() {
|
||||
val rooms = getRooms().filter { room ->
|
||||
room.unitType == config.general.unitType
|
||||
}
|
||||
val offers = getOffers().offers.filter { offer ->
|
||||
offer.adres[0].plaats !in listOf(
|
||||
"ZWOLLE",
|
||||
"GRONINGEN",
|
||||
"TILBURG"
|
||||
) + if (!config.general.allowZeist) "ZEIST" else ""
|
||||
}
|
||||
|
||||
val coupled = rooms.mapNotNull { room ->
|
||||
val offer: Offer? = offers.find { room.wocasId.toInt() == it.eenheidNummer.toInt() }
|
||||
|
||||
if (offer == null) null else ReactableOffer(room, offer, getFloorInfo(room))
|
||||
}.filter {
|
||||
val gender = it.floorInfo.genderPreference
|
||||
|
||||
((gender == "female" && config.gender.female) ||
|
||||
(gender == "male" && config.gender.male) ||
|
||||
(gender == "none" && config.gender.none)) &&
|
||||
|
||||
((config.general.smoking == -1 && !it.floorInfo.smokingAllowed) || (config.general.smoking == 1 && it.floorInfo.smokingAllowed) || config.general.smoking == 0) &&
|
||||
|
||||
((config.general.pets == -1 && !it.floorInfo.petsAllowed) || (config.general.pets == 1 && it.floorInfo.petsAllowed) || config.general.pets == 0)
|
||||
}
|
||||
|
||||
val fileName = "offers.md"
|
||||
val out = File(fileName)
|
||||
|
||||
val str = StringBuilder()
|
||||
|
||||
coupled.forEach {
|
||||
val address = it.offer.adres[0]
|
||||
|
||||
str.append("## [${address.straatnaam} ${address.nummer}, ${address.plaats.lowercase().capitalize()}](https://sshxl.nl/nl/aanbod/${it.room.flowId}-${address.straatnaam.lowercase().replace(" ", "-")})\n")
|
||||
str.append("- Huisgenoten: ${it.room.numberOfRooms-1}\n")
|
||||
|
||||
val genderString = when (it.floorInfo.genderPreference) {
|
||||
"none" -> "Geen voorkeur"
|
||||
"male" -> "Man"
|
||||
"female" -> "Vrouw"
|
||||
else -> it.floorInfo.genderPreference
|
||||
}
|
||||
str.append("- Geslacht: $genderString\n")
|
||||
|
||||
|
||||
str.append("- Roken: ${if (it.floorInfo.smokingAllowed) "Mag" else "Mag niet"}\n")
|
||||
str.append("- Huisdieren: ${if (it.floorInfo.petsAllowed) "Mogen" else "Mogen niet"}\n")
|
||||
str.append("\n")
|
||||
str.append("### Message: \n\n${it.floorInfo.description}\n")
|
||||
|
||||
str.append("\n\n")
|
||||
}
|
||||
out.writeText(str.toString())
|
||||
println("${coupled.size} offers found, wrote to $fileName")
|
||||
}
|
||||
24
src/main/kotlin/TOML.kt
Normal file
24
src/main/kotlin/TOML.kt
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package me.koendev
|
||||
|
||||
import de.thelooter.toml.Toml
|
||||
import java.io.File
|
||||
|
||||
data class GeneralConfig(
|
||||
val unitType: String,
|
||||
val allowZeist: Boolean,
|
||||
val smoking: Int,
|
||||
val pets: Int
|
||||
)
|
||||
|
||||
data class GenderConfig(
|
||||
val male: Boolean,
|
||||
val female: Boolean,
|
||||
val none: Boolean
|
||||
)
|
||||
|
||||
data class Config(
|
||||
val general: GeneralConfig,
|
||||
val gender: GenderConfig,
|
||||
)
|
||||
|
||||
val config: Config = Toml().read(File("config.toml")).to(Config::class.java)
|
||||
48
src/main/kotlin/getFloorInfo.kt
Normal file
48
src/main/kotlin/getFloorInfo.kt
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package me.koendev
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
@Serializable
|
||||
data class FloorInfo(
|
||||
@SerialName("WocasId") val wocasId: String,
|
||||
@SerialName("Description") val description: String,
|
||||
@SerialName("HospiteerDate") val hospiteerDate: String?,
|
||||
@SerialName("PreferenceSmokingAllowed") val smokingAllowed: Boolean,
|
||||
@SerialName("PreferencePetsAllowed") val petsAllowed: Boolean,
|
||||
@SerialName("PreferenceGender") val genderPreference: String,
|
||||
@SerialName("NumberOfUnits") val numberOfUnits: Int,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class RoomInfo(
|
||||
@SerialName("ExpireBy") val expireBy: String,
|
||||
@SerialName("RemainingTime") val remainingTime: String,
|
||||
@SerialName("ApplicantCount") val applicantCount: Int,
|
||||
@SerialName("CurrentPosition") val currentPosition: Int,
|
||||
@SerialName("CurrentAdjustedPosition") val currentAdjustedPosition: Int,
|
||||
@SerialName("PotentialPosition") val potentialPosition: Int,
|
||||
@SerialName("ViewingDate") val viewingDate: String,
|
||||
|
||||
@SerialName("FloorInformation") val floorInfo: FloorInfo,
|
||||
|
||||
@SerialName("SubsidiabeleHuur") val subsidiabeleHuur: Double,
|
||||
@SerialName("BruttoHuur") val brutoHuur: Double,
|
||||
@SerialName("IsPublished") val isPublished: Boolean,
|
||||
@SerialName("PublishedOn") val publishedOn: String?,
|
||||
@SerialName("ContractStartDate") val contractStartDate: String,
|
||||
@SerialName("UnitType") val unitType: String,
|
||||
@SerialName("NumberOfRooms") val numberOfRooms: Int,
|
||||
@SerialName("Image") val image: String?,
|
||||
@SerialName("ContractType") val contractType: String,
|
||||
@SerialName("FlowId") val flowId: Int,
|
||||
@SerialName("WocasId") val wocasId: String,
|
||||
@SerialName("Kind") val kind: String,
|
||||
)
|
||||
|
||||
fun getFloorInfo(room: Room): FloorInfo {
|
||||
val response = getEndpoint("offer/${room.flowId}")
|
||||
|
||||
return Json.decodeFromString<RoomInfo>(response).floorInfo
|
||||
}
|
||||
87
src/main/kotlin/getOffers.kt
Normal file
87
src/main/kotlin/getOffers.kt
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package me.koendev
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.net.http.HttpClient
|
||||
import java.net.http.HttpResponse
|
||||
|
||||
@Serializable
|
||||
data class Offers(
|
||||
@SerialName("value") val offers: List<Offer>,
|
||||
@SerialName("@odata.count") val count: Int,
|
||||
@SerialName("isComplete") val isComplete: Boolean
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Offer(
|
||||
@SerialName("adrheeftenh") val adrHeeftEnh: Double,
|
||||
@SerialName("eenheidnummer") val eenheidNummer: Double,
|
||||
@SerialName("object") val `object`: Double,
|
||||
@SerialName("soort_product") val soortProduct: String,
|
||||
@SerialName("ASSSUBJECTPERSK_H") val assSubjectPersk: List<AssSubjectPersk>,
|
||||
@SerialName("ASP_TOTAAL_C") val aspTotaal: List<AspTotaal>,
|
||||
@SerialName("HUUROVEREENKOMST_H") val huurOvereenkomst: List<HuurOvereenkomst>,
|
||||
@SerialName("EENHEID_HUUR") val eenheidHuur: List<EenheidHuur>,
|
||||
@SerialName("ADRES_H") val adres: List<Adres>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class AssSubjectPersk(
|
||||
@SerialName("object") val `object`: Double,
|
||||
@SerialName("pkheeftasp") val pkHeeftAsp: Double,
|
||||
@SerialName("enhheeftkenm") val enhHeeftKenm: Double,
|
||||
@SerialName("kenwaarde") val kenwaarde: String?,
|
||||
@SerialName("waarde") val waarde: String?,
|
||||
@SerialName("KENMERK_H") val kenmerk: List<Kenmerk>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Kenmerk(
|
||||
@SerialName("object") val `object`: Double,
|
||||
@SerialName("code") val code: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class AspTotaal(
|
||||
@SerialName("eenheidnummer") val eenheidNummer: Double,
|
||||
@SerialName("totopp") val totopp: Double,
|
||||
@SerialName("totoppgem") val totoppgem: Double
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class HuurOvereenkomst(
|
||||
@SerialName("object") val `object`: Double,
|
||||
@SerialName("dcnnummer") val dcnnummer: Double,
|
||||
@SerialName("einddatum") val einddatum: String,
|
||||
@SerialName("enhheefthuu") val enhheefthuu: Double
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class EenheidHuur(
|
||||
@SerialName("enh_object") val enhObject: Double,
|
||||
@SerialName("eenheidnummer") val eenheidnummer: Double,
|
||||
@SerialName("enh_nettohuur") val nettoHuur: Double,
|
||||
@SerialName("bruto_huur") val brutoHuur: Double,
|
||||
@SerialName("contract_type") val contractType: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Adres(
|
||||
@SerialName("oid") val oid: Double,
|
||||
@SerialName("straatnaam") val straatnaam: String,
|
||||
@SerialName("plaats") val plaats: String,
|
||||
@SerialName("nummer") val nummer: String,
|
||||
@SerialName("letter") val letter: String?,
|
||||
@SerialName("toevoeging") val toevoeging: String?,
|
||||
@SerialName("postcode") val postcode: String,
|
||||
@SerialName("aanduiding") val aanduiding: String?,
|
||||
@SerialName("locatie") val locatie: String?
|
||||
)
|
||||
|
||||
|
||||
fun getOffers(): Offers {
|
||||
val response = getEndpoint("OData-mv?EENHEID_H?\$filter=((((((((((((((((((((((eenheidnummer%20eq%2033700034)%20or%20(eenheidnummer%20eq%2020214020))%20or%20(eenheidnummer%20eq%2026912101))%20or%20(eenheidnummer%20eq%2026912038))%20or%20(eenheidnummer%20eq%2082200297))%20or%20(eenheidnummer%20eq%2021001262))%20or%20(eenheidnummer%20eq%2036900015))%20or%20(eenheidnummer%20eq%2052000240))%20or%20(eenheidnummer%20eq%2051800177))%20or%20(eenheidnummer%20eq%2036400433))%20or%20(eenheidnummer%20eq%2051900083))%20or%20(eenheidnummer%20eq%2036400019))%20or%20(eenheidnummer%20eq%2046200340))%20or%20(eenheidnummer%20eq%2029602069))%20or%20(eenheidnummer%20eq%2033700216))%20or%20(eenheidnummer%20eq%2011010008))%20or%20(eenheidnummer%20eq%2051900057))%20or%20(eenheidnummer%20eq%2021002009))%20or%20(eenheidnummer%20eq%2052000218))%20or%20(eenheidnummer%20eq%2036400091))%20or%20(eenheidnummer%20eq%2046200669))%20or%20(eenheidnummer%20eq%2029601023))&\$expand=ADRES_H!(\$select=plaats,postcode,straatnaam,nummer,toevoeging,aanduiding,locatie,letter,oid),EENHEID_HUUR!(\$select=eenheidnummer,bruto_huur,enh_nettohuur,enh_object,contract_type),HUUROVEREENKOMST_H!(\$select=dcnnummer,einddatum,enhheefthuu),ASP_TOTAAL_C!(\$select=eenheidnummer,totopp,totoppgem),ASSSUBJECTPERSK_H!(\$select=enhheeftkenm,pkheeftasp,waarde,kenwaarde;\$expand=KENMERK_H!(\$select=code))&\$select=eenheidnummer,adrheeftenh,object,soort_product")
|
||||
|
||||
return Json.decodeFromString<Offers>(response)
|
||||
}
|
||||
43
src/main/kotlin/getRooms.kt
Normal file
43
src/main/kotlin/getRooms.kt
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package me.koendev
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.net.http.HttpClient
|
||||
import java.net.http.HttpResponse
|
||||
|
||||
@Serializable
|
||||
data class Image(
|
||||
@SerialName("FilePathNL") val filePathNL: String?,
|
||||
@SerialName("FilePathEN") val filePathEN: String?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Room(
|
||||
@SerialName("ExpireBy") val expireBy: String,
|
||||
@SerialName("RemainingTime") val remainingTime: String,
|
||||
@SerialName("ApplicantCount") val applicantCount: Int,
|
||||
@SerialName("CurrentPosition") val currentPosition: Int,
|
||||
@SerialName("CurrentAdjustedPosition") val currentAdjustedPosition: Int,
|
||||
@SerialName("PotentialPosition") val potentialPosition: Int,
|
||||
@SerialName("ViewingDate") val viewingDate: String,
|
||||
@SerialName("FloorInformation") val floorInformation: String?,
|
||||
@SerialName("SubsidiabeleHuur") val subsidiabeleHuur: Double,
|
||||
@SerialName("BruttoHuur") val brutoHuur: Double,
|
||||
@SerialName("IsPublished") val isPublished: Boolean,
|
||||
@SerialName("PublishedOn") val publishedOn: String,
|
||||
@SerialName("ContractStartDate") val contractStartDate: String,
|
||||
@SerialName("UnitType") val unitType: String,
|
||||
@SerialName("NumberOfRooms") val numberOfRooms: Int,
|
||||
@SerialName("Image") val image: Image,
|
||||
@SerialName("ContractType") val contractType: String,
|
||||
@SerialName("FlowId") val flowId: Int,
|
||||
@SerialName("WocasId") val wocasId: String,
|
||||
@SerialName("Kind") val kind: String,
|
||||
)
|
||||
|
||||
fun getRooms(): List<Room> {
|
||||
val response = getEndpoint("offer")
|
||||
|
||||
return Json.decodeFromString<List<Room>>(response)
|
||||
}
|
||||
38
src/main/kotlin/requestTemplate.kt
Normal file
38
src/main/kotlin/requestTemplate.kt
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package me.koendev
|
||||
|
||||
import java.net.URI
|
||||
import java.net.http.HttpClient
|
||||
import java.net.http.HttpRequest
|
||||
import java.net.http.HttpResponse
|
||||
|
||||
/**
|
||||
* @param path the endpoint to GET. `sshxl.nl/api/v1/<PATH>`
|
||||
*
|
||||
* @return a HttpRequest with all the necessary properties to GET the endpoint.
|
||||
*/
|
||||
fun buildRequest(path: String): HttpRequest {
|
||||
return HttpRequest.newBuilder()
|
||||
.uri(URI("https://www.sshxl.nl/api/v1/$path"))
|
||||
.header("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0")
|
||||
.header("Accept", "*/*")
|
||||
.header("Accept-Language", "en-US,en;q=0.5")
|
||||
.header(
|
||||
"Cookie",
|
||||
listOf(
|
||||
"cookie_consent_analytics=no",
|
||||
"cookie_consent=no",
|
||||
).joinToString("; ")
|
||||
)
|
||||
.GET()
|
||||
.build()
|
||||
}
|
||||
|
||||
fun getEndpoint(endpoint: String): String {
|
||||
val client = HttpClient.newBuilder()
|
||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
||||
.build()
|
||||
|
||||
val request = buildRequest(endpoint)
|
||||
|
||||
return client.send(request, HttpResponse.BodyHandlers.ofString()).body()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue