Skip to content

Commit

Permalink
shared: Add method to get attendee for event
Browse files Browse the repository at this point in the history
Signed-off-by: Aayush Gupta <[email protected]>
  • Loading branch information
theimpulson committed Oct 13, 2024
1 parent d8ea4c4 commit f97c69d
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package app.opass.ccip.database

import app.opass.ccip.extensions.toAttendee
import app.opass.ccip.extensions.toEvent
import app.opass.ccip.extensions.toEventConfig
import app.opass.ccip.extensions.toLocalizedObject
Expand All @@ -13,6 +14,7 @@ import app.opass.ccip.extensions.toSpeaker
import app.opass.ccip.network.models.common.LocalizedObject
import app.opass.ccip.network.models.event.Event
import app.opass.ccip.network.models.eventconfig.EventConfig
import app.opass.ccip.network.models.fastpass.Attendee
import app.opass.ccip.network.models.schedule.Schedule
import app.opass.ccip.network.models.schedule.Session
import app.opass.ccip.network.models.schedule.Speaker
Expand Down Expand Up @@ -253,4 +255,33 @@ internal class OPassDatabaseHelper {
sessions = getSessions(eventId)
)
}

suspend fun getAttendee(eventId: String, token: String): Attendee? {
return withContext(Dispatchers.IO) {
dbQuery.selectAttendee(eventId, token).executeAsOneOrNull()?.toAttendee()
}
}

suspend fun deleteAttendee(eventId: String, token: String) {
return withContext(Dispatchers.IO) {
dbQuery.deleteAttendee(eventId, token)
}
}

suspend fun addAttendee(eventId: String, attendee: Attendee) {
withContext(Dispatchers.IO) {
dbQuery.transaction {
dbQuery.deleteAttendee(eventId, attendee.token)
dbQuery.insertAttendee(
userId = attendee.userId,
attr = Json.encodeToString(attendee.attr),
firstUse = attendee.firstUse,
role = attendee.role,
scenarios = Json.encodeToString(attendee.scenarios),
token = attendee.token,
eventId = eventId
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2024 OPass
* SPDX-License-Identifier: GPL-3.0-only
*/

package app.opass.ccip.extensions

import app.opass.ccip.database.AttendeeTable
import app.opass.ccip.network.models.fastpass.Attendee
import app.opass.ccip.network.models.fastpass.Scenario
import kotlinx.serialization.json.Json

internal fun AttendeeTable.toAttendee(): Attendee {
return Attendee(
attr = Json.decodeFromString<Map<String, String>>(this.attr),
eventId = this.eventId,
firstUse = this.firstUse,
role = this.role,
scenarios = Json.decodeFromString<List<Scenario>>(this.scenarios),
token = this.token,
userId = this.eventId,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import app.opass.ccip.network.models.common.LocalizedObject
import app.opass.ccip.network.models.event.Event
import app.opass.ccip.network.models.eventconfig.EventConfig
import app.opass.ccip.network.models.eventconfig.FeatureType
import app.opass.ccip.network.models.fastpass.Attendee
import app.opass.ccip.network.models.schedule.Schedule
import app.opass.ccip.network.models.schedule.Session
import app.opass.ccip.network.models.schedule.Speaker
Expand Down Expand Up @@ -78,6 +79,41 @@ class PortalHelper {
}
}

/**
* Fetches [Attendee] for specified event using given token from event's FastPass feature
* @param eventId ID of the event
* @param token Token to identify attendee
* @param forceReload Whether to ignore cache, false by default
* @return null if attendee hasn't been cached yet or token is invalid; Attendee otherwise
*/
suspend fun getAttendee(
eventId: String,
token: String,
forceReload: Boolean = false
): Attendee? {
val eventConfig = dbHelper.getEventConfig(eventId) ?: return null
val feat = eventConfig.features.find { f -> f.type == FeatureType.FAST_PASS } ?: return null

val cachedAttendee = dbHelper.getAttendee(eventId, token)
return if (cachedAttendee != null && !forceReload) {
cachedAttendee
} else {
client.getFastPassStatus(feat.url!!, token).also {
dbHelper.addAttendee(eventId, it)
}
}
}

/**
* Deletes an attendee's information from the database. Apps may call this method when a user
* wants to logout from the OPass app.
* @param eventId ID of the event
* @param token Token to identify attendee
*/
suspend fun deleteAttendee(eventId: String, token: String) {
dbHelper.deleteAttendee(eventId, token)
}

/**
* Fetches [Schedule] for specified id from Event's website
* @param eventId ID of the event
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ package app.opass.ccip.network

import app.opass.ccip.network.models.event.Event
import app.opass.ccip.network.models.eventconfig.EventConfig
import app.opass.ccip.network.models.fastpass.Attendee
import app.opass.ccip.network.models.schedule.Schedule
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.defaultRequest
import io.ktor.client.request.get
import io.ktor.client.request.parameter
import io.ktor.client.request.url
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json

Expand Down Expand Up @@ -44,4 +47,11 @@ internal class PortalClient {
suspend fun getEventSchedule(url: String): Schedule {
return universalClient.get(url).body()
}

suspend fun getFastPassStatus(url: String, token: String): Attendee {
return universalClient.get {
url(url)
parameter("token", token)
}.body()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2024 OPass
* SPDX-License-Identifier: GPL-3.0-only
*/

package app.opass.ccip.network.models.fastpass

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class Attendee(
val attr: Map<String, String> = emptyMap(),

@SerialName("event_id")
val eventId: String,

@SerialName("first_use")
val firstUse: Long,

val role: String,
val scenarios: List<Scenario>,
val token: String,

@SerialName("user_id")
val userId: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2024 OPass
* SPDX-License-Identifier: GPL-3.0-only
*/

package app.opass.ccip.network.models.fastpass

import app.opass.ccip.extensions.localized
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class Scenario(
val attr: Map<String, String> = emptyMap(),

@SerialName("available_time")
val availableTime: Long,

val countdown: Int,

@SerialName("display_text")
val _displayText: Localized,

@SerialName("expire_time")
val expireTime: Long,

val disabled: String,

val id: String,
val order: Int,
val used: Int
) {
val displayText: String
get() = localized(_displayText.en, _displayText.zh)

@Serializable
data class Localized(
@SerialName("en-US")
val en: String,

@SerialName("zh-TW")
val zh: String
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@ CREATE TABLE SessionTable (

CREATE INDEX idx_SessionTable_title ON SessionTable(titleEn, titleZh, eventId);

-- Create Attendee table and index

CREATE TABLE AttendeeTable(
primaryId INTEGER PRIMARY KEY AUTOINCREMENT,
userId TEXT NOT NULL,
attr TEXT NOT NULL,
firstUse INTEGER NOT NULL,
role TEXT NOT NULL,
scenarios TEXT NOT NULL,
token TEXT NOT NULL,
eventId TEXT NOT NULL,
FOREIGN KEY (eventId) REFERENCES EventConfigTable(id) ON DELETE CASCADE
);

-- Named queries for event table

selectAllEvents:
Expand Down Expand Up @@ -202,3 +216,15 @@ DELETE FROM SessionTable WHERE eventId = :eventId;
insertSession:
INSERT INTO SessionTable (id, titleEn, titleZh, descriptionEn, descriptionZh, start, end, room, speakers, tags, type, broadcast, liveUrl, url, coWriteUrl, slide, language, qa, record, eventId)
VALUES (:id, :titleEn, :titleZh, :descriptionEn, :descriptionZh, :start, :end, :room, :speakers, :tags, :type, :broadcast, :liveUrl, :url, :coWriteUrl, :slide, :language, :qa, :record, :eventId);

-- Named queries for attendee table

selectAttendee:
SELECT * FROM AttendeeTable WHERE eventId = :eventId AND token = :token;

deleteAttendee:
DELETE FROM AttendeeTable WHERE eventId = :eventId AND token = :token;

insertAttendee:
INSERT INTO AttendeeTable (userId, attr, firstUse, role, scenarios, token, eventId)
VALUES (:userId, :attr, :firstUse, :role, :scenarios, :token, :eventId);

0 comments on commit f97c69d

Please sign in to comment.