Places available renamed to seats left
This commit is contained in:
@@ -41,7 +41,7 @@ object CommandParser {
|
||||
try {
|
||||
when (command) {
|
||||
"create" -> handleCreate(user, room, args)
|
||||
"join" -> Usecase.joinTravel(room, user)
|
||||
"join" -> Usecase.joinTravel(room, user, args)
|
||||
"leave" -> Usecase.leaveTravel(room, user)
|
||||
"cancel" -> Usecase.cancelTravel(room, user)
|
||||
}
|
||||
@@ -70,7 +70,7 @@ object CommandParser {
|
||||
from = args[0],
|
||||
to = args[1],
|
||||
time = unixTime,
|
||||
places = args[4].toIntOrNull() ?: 0,
|
||||
seats = args[4].toIntOrNull() ?: 0,
|
||||
description = args.subList(5, args.size).joinToString(" ")
|
||||
)
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ import org.jetbrains.exposed.dao.IntEntityClass
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
|
||||
object TravelsTable: IntIdTable() {
|
||||
object TravelsTable : IntIdTable() {
|
||||
val roomId = varchar("room_id", 255)
|
||||
val driver = varchar("driver", 255)
|
||||
val from = varchar("from", 255)
|
||||
val to = varchar("to", 255)
|
||||
val time = long("time")
|
||||
val places = integer("places")
|
||||
val seats = integer("seats")
|
||||
val description = varchar("description", 1023)
|
||||
}
|
||||
|
||||
@@ -24,15 +24,16 @@ class TravelEntity(id: EntityID<Int>) : IntEntity(id) {
|
||||
this.from = travel.options.from
|
||||
this.to = travel.options.to
|
||||
this.time = travel.options.time
|
||||
this.places = travel.options.places
|
||||
this.seats = travel.options.seats
|
||||
this.description = travel.options.description
|
||||
}
|
||||
}
|
||||
|
||||
var roomId by TravelsTable.roomId
|
||||
var driver by TravelsTable.driver
|
||||
var from by TravelsTable.from
|
||||
var to by TravelsTable.to
|
||||
var time by TravelsTable.time
|
||||
var places by TravelsTable.places
|
||||
var seats by TravelsTable.seats
|
||||
var description by TravelsTable.description
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package eu.fosil.okupamicoche.matrix.event
|
||||
|
||||
import eu.fosil.okupamicoche.matrix.event.message.JOIN_MESSAGE_EVENT_TYPE
|
||||
import eu.fosil.okupamicoche.matrix.event.message.JoinMessageEventContent
|
||||
import eu.fosil.okupamicoche.matrix.event.message.TRAVEL_MESSAGE_EVENT_TYPE
|
||||
import eu.fosil.okupamicoche.matrix.event.message.TravelJoinMessageEventContent
|
||||
import eu.fosil.okupamicoche.matrix.event.message.TravelMessageEventContent
|
||||
import eu.fosil.okupamicoche.matrix.event.state.MEMBERSHIP_STATE_EVENT_TYPE
|
||||
import eu.fosil.okupamicoche.matrix.event.state.MembershipStateEventContent
|
||||
import eu.fosil.okupamicoche.matrix.event.state.TRAVEL_STATE_EVENT_TYPE
|
||||
import eu.fosil.okupamicoche.matrix.event.state.TravelMembershipStateEventContent
|
||||
import eu.fosil.okupamicoche.matrix.event.state.TravelStateEventContent
|
||||
import net.folivo.trixnity.core.model.events.MessageEventContent
|
||||
import net.folivo.trixnity.core.model.events.StateEventContent
|
||||
@@ -16,10 +16,10 @@ import net.folivo.trixnity.core.serialization.events.EventContentSerializerMappi
|
||||
object TravelEventContentSerializerMappings : BaseEventContentSerializerMappings() {
|
||||
override val message: Set<EventContentSerializerMapping<out MessageEventContent>> = setOf(
|
||||
EventContentSerializerMapping.of<TravelMessageEventContent>(TRAVEL_MESSAGE_EVENT_TYPE),
|
||||
EventContentSerializerMapping.of<JoinMessageEventContent>(JOIN_MESSAGE_EVENT_TYPE)
|
||||
EventContentSerializerMapping.of<TravelJoinMessageEventContent>(JOIN_MESSAGE_EVENT_TYPE)
|
||||
)
|
||||
override val state: Set<EventContentSerializerMapping<out StateEventContent>> = setOf(
|
||||
EventContentSerializerMapping.of<TravelStateEventContent>(TRAVEL_STATE_EVENT_TYPE),
|
||||
EventContentSerializerMapping.of<MembershipStateEventContent>(MEMBERSHIP_STATE_EVENT_TYPE)
|
||||
EventContentSerializerMapping.of<TravelMembershipStateEventContent>(MEMBERSHIP_STATE_EVENT_TYPE)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import net.folivo.trixnity.core.model.events.RelatesTo
|
||||
const val JOIN_MESSAGE_EVENT_TYPE = "eu.fosil.travel.join"
|
||||
|
||||
@Serializable
|
||||
data class JoinMessageEventContent(
|
||||
data class TravelJoinMessageEventContent(
|
||||
@SerialName("room")
|
||||
val room: String,
|
||||
@SerialName("user")
|
||||
@@ -21,8 +21,8 @@ data class TravelMessageEventContent(
|
||||
val to: String,
|
||||
@SerialName("time")
|
||||
val time: Long,
|
||||
@SerialName("places")
|
||||
val places: Int,
|
||||
@SerialName("seats")
|
||||
val seats: Int,
|
||||
@SerialName("description")
|
||||
val description: String,
|
||||
@SerialName("duplicateNum")
|
||||
@@ -38,7 +38,7 @@ data class TravelMessageEventContent(
|
||||
travel.options.from,
|
||||
travel.options.to,
|
||||
travel.options.time,
|
||||
travel.options.places,
|
||||
travel.options.seats,
|
||||
travel.options.description,
|
||||
travel.duplicateNum,
|
||||
travel.canceled
|
||||
|
||||
@@ -9,14 +9,17 @@ import net.folivo.trixnity.core.model.events.m.room.Membership
|
||||
const val MEMBERSHIP_STATE_EVENT_TYPE = "eu.fosil.travel.member"
|
||||
|
||||
@Serializable
|
||||
data class MembershipStateEventContent(
|
||||
data class TravelMembershipStateEventContent(
|
||||
@SerialName("user")
|
||||
val user: String,
|
||||
@SerialName("membership")
|
||||
val membership: String
|
||||
val membership: String,
|
||||
@SerialName("seats")
|
||||
val seats: Int
|
||||
) : StateEventContent {
|
||||
constructor(userId: UserId, membership: Membership) : this(
|
||||
constructor(userId: UserId, membership: Membership, seats: Int = 1) : this(
|
||||
userId.full,
|
||||
membership.value
|
||||
membership.value,
|
||||
seats
|
||||
)
|
||||
}
|
||||
@@ -18,8 +18,8 @@ data class TravelStateEventContent(
|
||||
val to: String,
|
||||
@SerialName("time")
|
||||
val time: Long,
|
||||
@SerialName("places")
|
||||
val places: Int,
|
||||
@SerialName("seats")
|
||||
val seats: Int,
|
||||
@SerialName("description")
|
||||
val description: String,
|
||||
@SerialName("duplicateNum")
|
||||
@@ -37,7 +37,7 @@ data class TravelStateEventContent(
|
||||
travelOptions.from,
|
||||
travelOptions.to,
|
||||
travelOptions.time,
|
||||
travelOptions.places,
|
||||
travelOptions.seats,
|
||||
travelOptions.description,
|
||||
duplicateNum,
|
||||
canceled
|
||||
|
||||
@@ -19,7 +19,7 @@ class TravelOptions(
|
||||
var from: String,
|
||||
var to: String,
|
||||
var time: Long,
|
||||
var places: Int,
|
||||
var seats: Int,
|
||||
var description: String
|
||||
) {
|
||||
fun getRoomAliasPrefix(): String {
|
||||
@@ -41,8 +41,8 @@ class TravelOptions(
|
||||
|
||||
fun getRoomName(duplicateNum: Int?, travelers: List<UserId>? = null): String {
|
||||
val attemptSuffix = if ((duplicateNum ?: 0) > 0) " ($duplicateNum)" else ""
|
||||
val availablePlaces = places - (travelers?.size ?: 0)
|
||||
val availableSeats = seats - (travelers?.size ?: 0)
|
||||
|
||||
return getRoomNamePrefix() + " | $availablePlaces places available" + attemptSuffix
|
||||
return getRoomNamePrefix() + " | $availableSeats seats available" + attemptSuffix
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.fosil.okupamicoche.model
|
||||
|
||||
import eu.fosil.okupamicoche.matrix.MatrixApiClient
|
||||
import eu.fosil.okupamicoche.matrix.event.state.MembershipStateEventContent
|
||||
import eu.fosil.okupamicoche.matrix.event.state.TravelMembershipStateEventContent
|
||||
import eu.fosil.okupamicoche.matrix.event.state.TravelStateEventContent
|
||||
import net.folivo.trixnity.clientserverapi.client.getStateEvent
|
||||
import net.folivo.trixnity.core.model.RoomId
|
||||
@@ -30,7 +30,7 @@ object TravelRepository {
|
||||
from = travelCreatedstateEvent.from,
|
||||
to = travelCreatedstateEvent.to,
|
||||
time = travelCreatedstateEvent.time,
|
||||
places = travelCreatedstateEvent.places,
|
||||
seats = travelCreatedstateEvent.seats,
|
||||
description = travelCreatedstateEvent.description
|
||||
),
|
||||
travelers = getTravelers(roomId) ?: listOf(),
|
||||
@@ -44,25 +44,27 @@ object TravelRepository {
|
||||
).getOrNull()?.driver == userId.full
|
||||
|
||||
suspend fun getTravelMembership(roomId: RoomId, userId: UserId) =
|
||||
MatrixApiClient.client.rooms.getStateEvent<MembershipStateEventContent>(
|
||||
MatrixApiClient.client.rooms.getStateEvent<TravelMembershipStateEventContent>(
|
||||
roomId,
|
||||
userId.full.substring(1) // Synapse throws 403 if stateKey starts with '@'
|
||||
).getOrNull()?.membership
|
||||
|
||||
suspend fun getTravelers(roomId: RoomId) = MatrixApiClient.client.rooms.getState(roomId).getOrNull()?.filter {
|
||||
val content = it.content
|
||||
(content is MembershipStateEventContent) && (content.membership == Membership.JOIN.value)
|
||||
(content is TravelMembershipStateEventContent) && (content.membership == Membership.JOIN.value)
|
||||
}?.map { UserId("@${it.stateKey}") }
|
||||
|
||||
suspend fun getAvailablePlaces(roomId: RoomId): Int? {
|
||||
// Get travel total places (not counting driver)
|
||||
suspend fun getSeatsLeft(roomId: RoomId): Int? {
|
||||
// Get travel total seats (not counting driver)
|
||||
val roomState = MatrixApiClient.client.rooms.getStateEvent<TravelStateEventContent>(roomId).getOrNull()
|
||||
?: return null
|
||||
|
||||
// TODO sum seats per traveler
|
||||
|
||||
// Get travelers count
|
||||
val travelersCount = getTravelers(roomId)?.size ?: 0
|
||||
|
||||
return roomState.places - travelersCount
|
||||
return roomState.seats - travelersCount
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -94,10 +94,10 @@ private suspend fun sendCreateMessageEvents(
|
||||
// Send text message to main room
|
||||
val displayName = TravelRepository.getDisplayName(travel.driver)
|
||||
val body = "$displayName created a new travel! ${travel.options.from}-${travel.options.to}" +
|
||||
" on $date $time with ${travel.options.places} free places."
|
||||
" on $date $time with ${travel.options.seats} free seats."
|
||||
val formattedBody =
|
||||
"\uD83D\uDE97 $displayName created a new travel!<br><br>${travel.options.from}-${travel.options.to}" +
|
||||
" on $date $time with ${travel.options.places} free places."
|
||||
" on $date $time with ${travel.options.seats} free seats."
|
||||
MatrixApiClient.client.rooms.sendMessageEvent(
|
||||
mainRoomId,
|
||||
RoomMessageEventContent.TextMessageEventContent(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.fosil.okupamicoche.usecase.travel
|
||||
|
||||
import eu.fosil.okupamicoche.matrix.MatrixApiClient
|
||||
import eu.fosil.okupamicoche.matrix.event.state.MembershipStateEventContent
|
||||
import eu.fosil.okupamicoche.matrix.event.state.TravelMembershipStateEventContent
|
||||
import eu.fosil.okupamicoche.model.TravelRepository
|
||||
import eu.fosil.okupamicoche.usecase.Usecase
|
||||
import net.folivo.trixnity.core.model.RoomId
|
||||
@@ -11,11 +11,15 @@ import net.folivo.trixnity.core.model.events.m.room.RoomMessageEventContent
|
||||
|
||||
suspend fun Usecase.joinTravel(
|
||||
roomId: RoomId,
|
||||
userId: UserId
|
||||
userId: UserId,
|
||||
args: List<String>
|
||||
) {
|
||||
val isTravel = TravelRepository.isTravel(roomId)
|
||||
val isDriver = TravelRepository.isDriver(roomId, userId)
|
||||
val membershipState = TravelRepository.getTravelMembership(roomId, userId)
|
||||
val seatsLeft = TravelRepository.getSeatsLeft(roomId) ?: 0
|
||||
// Seats asked by traveler, 1 if no specified
|
||||
val seats = args.firstOrNull()?.toIntOrNull() ?: 1
|
||||
|
||||
if (!isTravel) {
|
||||
MatrixApiClient.sendErrorTextMessage(roomId, "There is no travel.")
|
||||
@@ -23,8 +27,12 @@ suspend fun Usecase.joinTravel(
|
||||
MatrixApiClient.sendErrorTextMessage(roomId, "You are the driver, you don't need to join.")
|
||||
} else if (membershipState == Membership.JOIN.value) {
|
||||
MatrixApiClient.sendErrorTextMessage(roomId, "You are already joined.")
|
||||
} else if (seatsLeft == 0) {
|
||||
MatrixApiClient.sendErrorTextMessage(roomId, "Travel is full, no seats left.")
|
||||
} else if (seatsLeft < seats) {
|
||||
MatrixApiClient.sendErrorTextMessage(roomId, "Not enough seats left, only $seatsLeft available.")
|
||||
} else {
|
||||
sendJoinedMessageEvents(roomId, userId)
|
||||
sendJoinedMessageEvents(roomId, userId, seats)
|
||||
val roomNameInfo = Usecase.getRoomNameInfoFromRoomId(roomId)
|
||||
MatrixApiClient.setRoomName(roomId, roomNameInfo?.name)
|
||||
}
|
||||
@@ -32,19 +40,22 @@ suspend fun Usecase.joinTravel(
|
||||
|
||||
private suspend fun sendJoinedMessageEvents(
|
||||
roomId: RoomId,
|
||||
userId: UserId
|
||||
userId: UserId,
|
||||
seats: Int
|
||||
) {
|
||||
// Send membership change state event to travel room
|
||||
MatrixApiClient.client.rooms.sendStateEvent(
|
||||
roomId,
|
||||
MembershipStateEventContent(userId, Membership.JOIN),
|
||||
TravelMembershipStateEventContent(userId, Membership.JOIN, seats),
|
||||
stateKey = userId.full.substring(1) // Synapse throws 403 if stateKey starts with '@'
|
||||
).getOrThrow()
|
||||
|
||||
// Send text message to travel room
|
||||
val displayName = TravelRepository.getDisplayName(userId)
|
||||
val availablePlaces = TravelRepository.getAvailablePlaces(roomId)
|
||||
val messageBody = "$displayName joined the travel! Places available: $availablePlaces"
|
||||
val seatsLeft = TravelRepository.getSeatsLeft(roomId)
|
||||
val messageBody = "$displayName joined the travel!" +
|
||||
(if (seats == 1) null else " They are using $seats seats.") +
|
||||
" Seats left: $seatsLeft"
|
||||
MatrixApiClient.client.rooms.sendMessageEvent(
|
||||
roomId,
|
||||
RoomMessageEventContent.TextMessageEventContent(messageBody)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.fosil.okupamicoche.usecase.travel
|
||||
|
||||
import eu.fosil.okupamicoche.matrix.MatrixApiClient
|
||||
import eu.fosil.okupamicoche.matrix.event.state.MembershipStateEventContent
|
||||
import eu.fosil.okupamicoche.matrix.event.state.TravelMembershipStateEventContent
|
||||
import eu.fosil.okupamicoche.model.TravelRepository
|
||||
import eu.fosil.okupamicoche.usecase.Usecase
|
||||
import net.folivo.trixnity.core.model.RoomId
|
||||
@@ -43,14 +43,14 @@ private suspend fun sendLeftMessageEvents(
|
||||
// Send membership change state event to travel room
|
||||
MatrixApiClient.client.rooms.sendStateEvent(
|
||||
roomId,
|
||||
MembershipStateEventContent(userId, Membership.LEAVE),
|
||||
TravelMembershipStateEventContent(userId, Membership.LEAVE),
|
||||
stateKey = userId.full.substring(1) // Synapse throws 403 if stateKey starts with '@'
|
||||
).getOrThrow()
|
||||
|
||||
// Send text message to travel room
|
||||
val displayName = TravelRepository.getDisplayName(userId)
|
||||
val availablePlaces = TravelRepository.getAvailablePlaces(roomId)
|
||||
val messageBody = "$displayName left the travel. Places available: $availablePlaces"
|
||||
val availableSeats = TravelRepository.getSeatsLeft(roomId)
|
||||
val messageBody = "$displayName left the travel. Seats available: $availableSeats"
|
||||
MatrixApiClient.client.rooms.sendMessageEvent(
|
||||
roomId,
|
||||
RoomMessageEventContent.TextMessageEventContent(messageBody)
|
||||
|
||||
Reference in New Issue
Block a user