Skip to content

Commit 1212dba

Browse files
committed
Got ahead of myself
Recreated some of the V2 endpoints that the legacy website still needs. Definitely could do a better job at fixing this code, but for now I'm looking just to make sure it works functionally the same and I care less about making this respect new patterns since its deprecated anyways
1 parent 2a4ce80 commit 1212dba

File tree

5 files changed

+294
-0
lines changed

5 files changed

+294
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.dreamexposure.discal.core.`object`.new.model.discal.v2
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty
4+
import discord4j.common.util.Snowflake
5+
import org.dreamexposure.discal.core.`object`.new.Calendar
6+
import java.time.ZoneId
7+
8+
@Deprecated("Prefer to use V3 APIs, this is for compatibility for the old site old")
9+
data class CalendarV2Model(
10+
@JsonProperty("guild_id")
11+
val guildId: Snowflake,
12+
@JsonProperty("calendar_id")
13+
val calendarId: String,
14+
@JsonProperty("calendar_address")
15+
val calendarAddress: String,
16+
@JsonProperty("calendar_number")
17+
val calendarNumber: Int,
18+
val host: String,
19+
@JsonProperty("host_link")
20+
val hostLink: String,
21+
val external: Boolean,
22+
val name: String,
23+
val description: String,
24+
val timezone: ZoneId,
25+
val link: String,
26+
) {
27+
constructor(calendar: Calendar): this(
28+
guildId = calendar.metadata.guildId,
29+
calendarId = calendar.metadata.id,
30+
calendarAddress = calendar.metadata.address,
31+
calendarNumber = calendar.metadata.number,
32+
host = calendar.metadata.host.name,
33+
hostLink = calendar.hostLink,
34+
external = calendar.metadata.external,
35+
name = calendar.name,
36+
description = calendar.description,
37+
timezone = calendar.timezone,
38+
link = calendar.link,
39+
)
40+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.dreamexposure.discal.core.`object`.new.model.discal.v2
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty
4+
import discord4j.common.util.Snowflake
5+
import org.dreamexposure.discal.core.`object`.event.Recurrence
6+
import org.dreamexposure.discal.core.`object`.new.Calendar
7+
import org.dreamexposure.discal.core.`object`.new.Event
8+
9+
@Deprecated("Prefer to use V3 API implementation. This exists to maintain compatibility for the legacy website")
10+
data class EventV2Model(
11+
@JsonProperty("guild_id")
12+
val guildId: Snowflake,
13+
val calendar: CalendarV2Model,
14+
@JsonProperty("event_id")
15+
val eventId: String,
16+
@JsonProperty("epoch_start")
17+
val epochStart: Long,
18+
@JsonProperty("epoch_end")
19+
val epochEnd: Long,
20+
val name: String,
21+
val description: String,
22+
val location: String,
23+
@JsonProperty("is_parent")
24+
val isParent: Boolean,
25+
val color: String,
26+
val recur: Boolean,
27+
val recurrence: Recurrence,
28+
val rrule: String,
29+
val image: String,
30+
) {
31+
constructor(event: Event, calendar: Calendar): this(
32+
guildId = event.guildId,
33+
calendar = CalendarV2Model(calendar),
34+
eventId = event.id,
35+
epochStart = event.start.toEpochMilli(),
36+
epochEnd = event.end.toEpochMilli(),
37+
name = event.name,
38+
description = event.description,
39+
location = event.location,
40+
isParent = !event.id.contains("_"),
41+
color = event.color.name,
42+
recur = event.recur,
43+
recurrence = event.recurrence,
44+
rrule = event.recurrence.toRRule(),
45+
image = event.image,
46+
)
47+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.dreamexposure.discal.server.endpoints.v2.calendar
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper
4+
import discord4j.common.util.Snowflake
5+
import kotlinx.coroutines.reactor.mono
6+
import kotlinx.serialization.encodeToString
7+
import org.dreamexposure.discal.core.annotations.SecurityRequirement
8+
import org.dreamexposure.discal.core.business.CalendarService
9+
import org.dreamexposure.discal.core.logger.LOGGER
10+
import org.dreamexposure.discal.core.`object`.new.model.discal.v2.CalendarV2Model
11+
import org.dreamexposure.discal.core.utils.GlobalVal
12+
import org.dreamexposure.discal.server.utils.Authentication
13+
import org.dreamexposure.discal.server.utils.responseMessage
14+
import org.json.JSONException
15+
import org.json.JSONObject
16+
import org.springframework.http.server.reactive.ServerHttpResponse
17+
import org.springframework.web.bind.annotation.PostMapping
18+
import org.springframework.web.bind.annotation.RequestBody
19+
import org.springframework.web.bind.annotation.RequestMapping
20+
import org.springframework.web.bind.annotation.RestController
21+
import org.springframework.web.server.ServerWebExchange
22+
import reactor.core.publisher.Mono
23+
24+
@RestController
25+
@RequestMapping("/v2/calendar")
26+
class GetCalendarEndpoint(
27+
private val authentication: Authentication,
28+
private val calendarService: CalendarService,
29+
private val objectMapper: ObjectMapper,
30+
) {
31+
@PostMapping("/get", produces = ["application/json"])
32+
@SecurityRequirement(disableSecurity = true, scopes = [])
33+
fun getCalendar(swe: ServerWebExchange, response: ServerHttpResponse, @RequestBody rBody: String): Mono<String> {
34+
return authentication.authenticate(swe).flatMap { authState ->
35+
if (!authState.success) {
36+
response.rawStatusCode = authState.status
37+
return@flatMap Mono.just(GlobalVal.JSON_FORMAT.encodeToString(authState))
38+
}
39+
40+
//Handle request
41+
val body = JSONObject(rBody)
42+
val guildId = Snowflake.of(body.getString("guild_id"))
43+
val calNumber = body.getInt("calendar_number")
44+
45+
return@flatMap mono {calendarService.getCalendar(guildId, calNumber) }
46+
.map(::CalendarV2Model)
47+
.map { objectMapper.writeValueAsString(it) }
48+
.switchIfEmpty(responseMessage("Calendar not found")
49+
.doOnNext { response.rawStatusCode = GlobalVal.STATUS_NOT_FOUND }
50+
)
51+
}.onErrorResume(JSONException::class.java) {
52+
LOGGER.trace("[API-v2] JSON error. Bad request?", it)
53+
54+
response.rawStatusCode = GlobalVal.STATUS_BAD_REQUEST
55+
return@onErrorResume responseMessage("Bad Request")
56+
}.onErrorResume {
57+
LOGGER.error(GlobalVal.DEFAULT, "[API-v2] get calendar error", it)
58+
59+
response.rawStatusCode = GlobalVal.STATUS_INTERNAL_ERROR
60+
return@onErrorResume responseMessage("Internal Server Error")
61+
}
62+
}
63+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package org.dreamexposure.discal.server.endpoints.v2.calendar
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper
4+
import discord4j.common.util.Snowflake
5+
import kotlinx.coroutines.reactor.mono
6+
import org.dreamexposure.discal.core.logger.LOGGER
7+
import org.dreamexposure.discal.core.annotations.SecurityRequirement
8+
import org.dreamexposure.discal.core.business.CalendarService
9+
import org.dreamexposure.discal.core.utils.GlobalVal
10+
import org.dreamexposure.discal.server.utils.Authentication
11+
import org.dreamexposure.discal.server.utils.responseMessage
12+
import org.json.JSONArray
13+
import org.json.JSONException
14+
import org.json.JSONObject
15+
import org.springframework.http.server.reactive.ServerHttpResponse
16+
import org.springframework.web.bind.annotation.PostMapping
17+
import org.springframework.web.bind.annotation.RequestBody
18+
import org.springframework.web.bind.annotation.RequestMapping
19+
import org.springframework.web.bind.annotation.RestController
20+
import org.springframework.web.server.ServerWebExchange
21+
import reactor.core.publisher.Mono
22+
import java.time.Instant
23+
import kotlinx.serialization.encodeToString
24+
import org.dreamexposure.discal.core.`object`.new.model.discal.v2.EventV2Model
25+
26+
27+
@RestController
28+
@RequestMapping("/v2/events/list")
29+
class ListEventMonthEndpoint(
30+
private val authentication: Authentication,
31+
private val calendarService: CalendarService,
32+
private val objectMapper: ObjectMapper,
33+
) {
34+
@PostMapping("/month", produces = ["application/json"])
35+
@SecurityRequirement(disableSecurity = true, scopes = [])
36+
fun listByMonth(swe: ServerWebExchange, response: ServerHttpResponse, @RequestBody rBody: String): Mono<String> {
37+
return authentication.authenticate(swe).flatMap { authState ->
38+
if (!authState.success) {
39+
response.rawStatusCode = authState.status
40+
return@flatMap Mono.just(GlobalVal.JSON_FORMAT.encodeToString(authState))
41+
}
42+
43+
//Handle request
44+
val body = JSONObject(rBody)
45+
val guildId = Snowflake.of(body.getString("guild_id"))
46+
val calendarNumber = body.getInt("calendar_number")
47+
val start = Instant.ofEpochMilli(body.getLong("epoch_start"))
48+
val daysInMonth = body.getInt("days_in_month")
49+
50+
51+
mono { calendarService.getCalendar(guildId, calendarNumber) }.flatMap { calendar ->
52+
mono { calendarService.getEventsInMonth(guildId, calendarNumber, start, daysInMonth) }.map { events ->
53+
events.map { objectMapper.writeValueAsString(EventV2Model(it, calendar)) }
54+
}
55+
}.map(::JSONArray)
56+
.map { JSONObject().put("events", it).put("message", "Success").toString() }
57+
.doOnNext { response.rawStatusCode = GlobalVal.STATUS_SUCCESS }
58+
.switchIfEmpty(responseMessage("Calendar not found")
59+
.doOnNext { response.rawStatusCode = GlobalVal.STATUS_NOT_FOUND }
60+
)
61+
}.onErrorResume(JSONException::class.java) {
62+
LOGGER.trace("[API-v2] JSON error. Bad request?", it)
63+
64+
response.rawStatusCode = GlobalVal.STATUS_BAD_REQUEST
65+
return@onErrorResume responseMessage("Bad Request")
66+
}.onErrorResume {
67+
LOGGER.error(GlobalVal.DEFAULT, "[API-v2] list events by month error", it)
68+
69+
response.rawStatusCode = GlobalVal.STATUS_INTERNAL_ERROR
70+
return@onErrorResume responseMessage("Internal Server Error")
71+
}
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package org.dreamexposure.discal.server.endpoints.v2.event.list
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper
4+
import discord4j.common.util.Snowflake
5+
import kotlinx.coroutines.reactor.mono
6+
import kotlinx.serialization.encodeToString
7+
import org.dreamexposure.discal.core.annotations.SecurityRequirement
8+
import org.dreamexposure.discal.core.business.CalendarService
9+
import org.dreamexposure.discal.core.logger.LOGGER
10+
import org.dreamexposure.discal.core.`object`.new.model.discal.v2.EventV2Model
11+
import org.dreamexposure.discal.core.utils.GlobalVal
12+
import org.dreamexposure.discal.server.utils.Authentication
13+
import org.dreamexposure.discal.server.utils.responseMessage
14+
import org.json.JSONArray
15+
import org.json.JSONException
16+
import org.json.JSONObject
17+
import org.springframework.http.server.reactive.ServerHttpResponse
18+
import org.springframework.web.bind.annotation.PostMapping
19+
import org.springframework.web.bind.annotation.RequestBody
20+
import org.springframework.web.bind.annotation.RequestMapping
21+
import org.springframework.web.bind.annotation.RestController
22+
import org.springframework.web.server.ServerWebExchange
23+
import reactor.core.publisher.Mono
24+
import java.time.Instant
25+
26+
@RestController
27+
@RequestMapping("/v2/events/list")
28+
class ListEventRangeEndpoint(
29+
private val authentication: Authentication,
30+
private val calendarService: CalendarService,
31+
private val objectMapper: ObjectMapper,
32+
) {
33+
@PostMapping("/range", produces = ["application/json"])
34+
@SecurityRequirement(disableSecurity = true, scopes = [])
35+
fun listByRange(swe: ServerWebExchange, response: ServerHttpResponse, @RequestBody rBody: String): Mono<String> {
36+
return authentication.authenticate(swe).flatMap { authState ->
37+
if (!authState.success) {
38+
response.rawStatusCode = authState.status
39+
return@flatMap Mono.just(GlobalVal.JSON_FORMAT.encodeToString(authState))
40+
}
41+
42+
//Handle request
43+
val body = JSONObject(rBody)
44+
val guildId = Snowflake.of(body.getString("guild_id"))
45+
val calendarNumber = body.getInt("calendar_number")
46+
val start = Instant.ofEpochMilli(body.getLong("epoch_start"))
47+
val end = Instant.ofEpochMilli(body.getLong("epoch_end"))
48+
49+
mono { calendarService.getCalendar(guildId, calendarNumber) }.flatMap { calendar ->
50+
mono { calendarService.getEventsInTimeRange(guildId, calendarNumber, start, end) }.map { events ->
51+
events.map { objectMapper.writeValueAsString(EventV2Model(it, calendar)) }
52+
}
53+
}.map(::JSONArray)
54+
.map { JSONObject().put("events", it).put("message", "Success").toString() }
55+
.doOnNext { response.rawStatusCode = GlobalVal.STATUS_SUCCESS }
56+
.switchIfEmpty(responseMessage("Calendar not found")
57+
.doOnNext { response.rawStatusCode = GlobalVal.STATUS_NOT_FOUND }
58+
)
59+
}.onErrorResume(JSONException::class.java) {
60+
LOGGER.trace("[API-v2] JSON error. Bad request?", it)
61+
62+
response.rawStatusCode = GlobalVal.STATUS_BAD_REQUEST
63+
return@onErrorResume responseMessage("Bad Request")
64+
}.onErrorResume {
65+
LOGGER.error(GlobalVal.DEFAULT, "[API-v2] list events by range error", it)
66+
67+
response.rawStatusCode = GlobalVal.STATUS_INTERNAL_ERROR
68+
return@onErrorResume responseMessage("Internal Server Error")
69+
}
70+
}
71+
}

0 commit comments

Comments
 (0)