Skip to content

Commit

Permalink
v4.2.6 RC
Browse files Browse the repository at this point in the history
v4.2.6 RC
  • Loading branch information
NovaFox161 committed Mar 24, 2024
2 parents 770f00d + 5a2af29 commit 55d803f
Show file tree
Hide file tree
Showing 102 changed files with 3,728 additions and 4,165 deletions.
22 changes: 11 additions & 11 deletions .github/workflows/gradle.yml
Expand Up @@ -16,28 +16,28 @@ jobs:
matrix:
java: [ 17 ]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/cache@v1
- uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Install NPM
uses: actions/setup-node@v2
uses: actions/setup-node@v4
with:
node-version: 14.8.0

- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v2
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: 'adopt'

- name: Validate gradle
uses: gradle/wrapper-validation-action@v1
uses: gradle/wrapper-validation-action@v2

- name: Change wrapper permissions
run: chmod +x ./gradlew
Expand All @@ -51,24 +51,24 @@ jobs:
if: ${{ github.event_name != 'pull_request' && (github.ref_name == 'develop' || github.ref_name == 'master') }}
needs: build
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/cache@v1
- uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Install NPM
uses: actions/setup-node@v2
uses: actions/setup-node@v4
with:
node-version: 14.8.0

- name: Set up JDK
uses: actions/setup-java@v2
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'adopt'
Expand All @@ -82,7 +82,7 @@ jobs:
SCW_USER: ${{ secrets.SCW_USER }}
SCW_SECRET: ${{ secrets.SCW_SECRET }}
with:
command: ./gradlew jib -Djib.to.auth.username=${SCW_USER} -Djib.to.auth.password=${SCW_SECRET}
command: ./gradlew clean jib -Djib.to.auth.username=${SCW_USER} -Djib.to.auth.password=${SCW_SECRET} -Djib.console=plain
attempt_limit: 25
# 1 minute in ms
attempt_delay: 60000
Expand All @@ -92,7 +92,7 @@ jobs:
if: github.ref_name == 'develop'
needs: publish-artifacts
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0

Expand Down
341 changes: 224 additions & 117 deletions README.md

Large diffs are not rendered by default.

17 changes: 9 additions & 8 deletions build.gradle.kts
Expand Up @@ -27,7 +27,7 @@ buildscript {
allprojects {
//Project props
group = "org.dreamexposure.discal"
version = "4.2.5"
version = "4.2.6"
description = "DisCal"

//Plugins
Expand All @@ -40,11 +40,9 @@ allprojects {
val discord4jVersion: String by properties
val discord4jStoresVersion: String by properties
val discordWebhookVersion: String by properties
// Database\
val mikuR2dbcMySqlVersion: String by properties
val mySqlConnectorJava: String by properties
// Serialization
val kotlinxSerializationJsonVersion: String by properties
val orgJsonVersion: String by properties
// Observability
val logbackContribVersion: String by properties
// Google libs
Expand Down Expand Up @@ -76,7 +74,10 @@ allprojects {
// Discord
implementation("com.discord4j:discord4j-core:$discord4jVersion")
implementation("com.discord4j:stores-redis:$discord4jStoresVersion")
implementation("club.minnced:discord-webhooks:$discordWebhookVersion")
implementation("club.minnced:discord-webhooks:$discordWebhookVersion") {
// Due to vulnerability in older versions: https://github.com/advisories/GHSA-rm7j-f5g5-27vv
exclude(group = "org.json", module = "json")
}

// Spring
implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
Expand All @@ -87,14 +88,14 @@ allprojects {
implementation("org.springframework.boot:spring-boot-starter-actuator")

// Database
implementation("dev.miku:r2dbc-mysql:$mikuR2dbcMySqlVersion")
implementation("mysql:mysql-connector-java:$mySqlConnectorJava")
implementation("io.asyncer:r2dbc-mysql")
implementation("com.mysql:mysql-connector-j")

// Serialization
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationJsonVersion")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
implementation("org.json:json")
implementation("org.json:json:$orgJsonVersion")

// Observability
implementation("ch.qos.logback.contrib:logback-json-classic:$logbackContribVersion")
Expand Down
2 changes: 1 addition & 1 deletion cam/build.gradle.kts
Expand Up @@ -33,7 +33,7 @@ jib {
}

image = "rg.nl-ams.scw.cloud/dreamexposure/discal-cam"
tags = mutableSetOf("latest", version.toString(), buildVersion)
tags = mutableSetOf("latest", buildVersion)
}

val baseImage: String by properties
Expand Down
Expand Up @@ -4,20 +4,21 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import kotlinx.coroutines.reactor.awaitSingle
import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import org.dreamexposure.discal.cam.json.discord.AccessTokenResponse
import org.dreamexposure.discal.cam.json.discord.AuthorizationInfo
import org.dreamexposure.discal.core.config.Config
import org.dreamexposure.discal.core.exceptions.AuthenticationException
import org.dreamexposure.discal.core.utils.GlobalVal
import org.dreamexposure.discal.core.utils.GlobalVal.HTTP_CLIENT
import org.springframework.stereotype.Component
import reactor.core.publisher.Mono
import reactor.core.scheduler.Schedulers

@Component
class DiscordOauthHandler(
private val objectMapper: ObjectMapper,
private val httpClient: OkHttpClient,
) {
private val cdnUrl = "https://cdn.discordapp.com"
private val redirectUrl = Config.URL_DISCORD_REDIRECT.getString()
Expand All @@ -38,7 +39,7 @@ class DiscordOauthHandler(
.header("Content-Type", "application/x-www-form-urlencoded")
.build()

val response = Mono.fromCallable(HTTP_CLIENT.newCall(tokenExchangeRequest)::execute)
val response = Mono.fromCallable(httpClient.newCall(tokenExchangeRequest)::execute)
.subscribeOn(Schedulers.boundedElastic())
.awaitSingle()

Expand Down Expand Up @@ -66,7 +67,7 @@ class DiscordOauthHandler(
.header("Content-Type", "application/x-www-form-urlencoded")
.build()

val response = Mono.fromCallable(HTTP_CLIENT.newCall(tokenExchangeRequest)::execute)
val response = Mono.fromCallable(httpClient.newCall(tokenExchangeRequest)::execute)
.subscribeOn(Schedulers.boundedElastic())
.awaitSingle()

Expand All @@ -88,7 +89,7 @@ class DiscordOauthHandler(
.header("Authorization", "Bearer $accessToken")
.build()

val response = Mono.fromCallable(HTTP_CLIENT.newCall(request)::execute)
val response = Mono.fromCallable(httpClient.newCall(request)::execute)
.subscribeOn(Schedulers.boundedElastic())
.awaitSingle()

Expand Down
Expand Up @@ -6,6 +6,7 @@ import com.google.api.client.http.HttpStatusCodes.STATUS_CODE_BAD_REQUEST
import com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK
import kotlinx.coroutines.reactor.awaitSingle
import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import org.dreamexposure.discal.cam.json.google.ErrorData
import org.dreamexposure.discal.cam.json.google.RefreshData
Expand All @@ -20,7 +21,6 @@ import org.dreamexposure.discal.core.logger.LOGGER
import org.dreamexposure.discal.core.`object`.network.discal.CredentialData
import org.dreamexposure.discal.core.`object`.new.Calendar
import org.dreamexposure.discal.core.utils.GlobalVal.DEFAULT
import org.dreamexposure.discal.core.utils.GlobalVal.HTTP_CLIENT
import org.springframework.stereotype.Component
import reactor.core.publisher.Mono
import reactor.core.scheduler.Schedulers
Expand All @@ -32,6 +32,7 @@ class GoogleAuth(
private val credentialService: CredentialService,
private val calendarService: CalendarService,
private val objectMapper: ObjectMapper,
private val httpClient: OkHttpClient,
) {

suspend fun requestNewAccessToken(calendar: Calendar): CredentialData? {
Expand Down Expand Up @@ -79,7 +80,7 @@ class GoogleAuth(
.build()


val response = Mono.fromCallable(HTTP_CLIENT.newCall(request)::execute)
val response = Mono.fromCallable(httpClient.newCall(request)::execute)
.subscribeOn(Schedulers.boundedElastic())
.awaitSingle()

Expand All @@ -99,7 +100,7 @@ class GoogleAuth(

if (body.error == "invalid_grant") {
LOGGER.debug(DEFAULT, "[Google] Access to resource has been revoked")
throw AccessRevokedException()
throw AccessRevokedException() // TODO: How should I handle this for external calendars? Right now we just delete everything
} else {
LOGGER.error(DEFAULT, "[Google] Error requesting new access token | ${response.code} | ${response.message} | $body")
null
Expand Down
2 changes: 1 addition & 1 deletion client/build.gradle.kts
Expand Up @@ -32,7 +32,7 @@ jib {
}

image = "rg.nl-ams.scw.cloud/dreamexposure/discal-client"
tags = mutableSetOf("latest", version.toString(), buildVersion)
tags = mutableSetOf("latest", buildVersion)
}

val baseImage: String by properties
Expand Down
@@ -0,0 +1,53 @@
package org.dreamexposure.discal.client.business.cronjob

import discord4j.core.GatewayDiscordClient
import kotlinx.coroutines.reactor.awaitSingle
import kotlinx.coroutines.reactor.mono
import org.dreamexposure.discal.core.business.AnnouncementService
import org.dreamexposure.discal.core.business.MetricService
import org.dreamexposure.discal.core.config.Config
import org.dreamexposure.discal.core.extensions.asMinutes
import org.dreamexposure.discal.core.logger.LOGGER
import org.dreamexposure.discal.core.utils.GlobalVal.DEFAULT
import org.springframework.boot.ApplicationArguments
import org.springframework.boot.ApplicationRunner
import org.springframework.stereotype.Component
import org.springframework.util.StopWatch
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono

@Component
class AnnouncementCronJob(
private val discordClient: GatewayDiscordClient,
private val announcementService: AnnouncementService,
private val metricService: MetricService,
) : ApplicationRunner {
private val interval = Config.TIMING_ANNOUNCEMENT_TASK_RUN_INTERVAL_MINUTES.getLong().asMinutes()
private val maxDifference = interval

override fun run(args: ApplicationArguments?) {
Flux.interval(interval)
.onBackpressureDrop()
.flatMap { doAction() }
.doOnError { LOGGER.error(DEFAULT, "!-Announcement run error-! Failed to process announcements for all guilds", it) }
.onErrorResume { Mono.empty() }
.subscribe()
}

private fun doAction() = mono {
val taskTimer = StopWatch()
taskTimer.start()

val guilds = discordClient.guilds.collectList().awaitSingle()

guilds.forEach { guild ->
try {
announcementService.processAnnouncementsForGuild(guild.id, maxDifference)
} catch (ex: Exception) {
LOGGER.error("Failed to process announcements for guild | guildId:${guild.id.asLong()}", ex)
}
}
taskTimer.stop()
metricService.recordAnnouncementTaskDuration("cronjob", taskTimer.totalTimeMillis)
}
}
@@ -0,0 +1,61 @@
package org.dreamexposure.discal.client.business.cronjob

import kotlinx.coroutines.reactor.mono
import org.dreamexposure.discal.Application.Companion.getShardCount
import org.dreamexposure.discal.Application.Companion.getShardIndex
import org.dreamexposure.discal.core.business.MetricService
import org.dreamexposure.discal.core.business.StaticMessageService
import org.dreamexposure.discal.core.config.Config
import org.dreamexposure.discal.core.extensions.asMinutes
import org.dreamexposure.discal.core.logger.LOGGER
import org.dreamexposure.discal.core.utils.GlobalVal.DEFAULT
import org.springframework.boot.ApplicationArguments
import org.springframework.boot.ApplicationRunner
import org.springframework.stereotype.Component
import org.springframework.util.StopWatch
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import java.time.Duration
import java.time.Instant

@Component
class StaticMessageUpdateCronJob(
private val staticMessageService: StaticMessageService,
private val metricService: MetricService,
):ApplicationRunner {
override fun run(args: ApplicationArguments?) {
Flux.interval(Config.TIMING_STATIC_MESSAGE_UPDATE_TASK_RUN_INTERVAL_MINUTES.getLong().asMinutes())
.onBackpressureDrop()
.flatMap { doUpdate() }
.onErrorResume { Mono.empty() }
.subscribe()
}

private fun doUpdate() = mono {
val taskTimer = StopWatch()
taskTimer.start()

try {
val messages = staticMessageService.getStaticMessagesForShard(getShardIndex(), getShardCount())
//We have no interest in updating the message so close to its last update
.filter { Duration.between(Instant.now(), it.lastUpdate).abs().toMinutes() >= 30 }
// Only update messages in range
.filter { Duration.between(Instant.now(), it.scheduledUpdate).toMinutes() <= 60 }

LOGGER.debug("StaticMessageUpdateCronJob | Found ${messages.size} messages to update for shard ${getShardIndex()}")

messages.forEach {
try {
staticMessageService.updateStaticMessage(it.guildId, it.messageId)
} catch (ex: Exception) {
LOGGER.error("Failed to update static message | guildId:${it.guildId} | messageId:${it.messageId}", ex)
}
}
} catch (ex: Exception) {
LOGGER.error(DEFAULT, "StaticMessageUpdateCronJob failure", ex)
} finally {
taskTimer.stop()
metricService.recordStaticMessageTaskDuration("cronjob", taskTimer.totalTimeMillis)
}
}
}

0 comments on commit 55d803f

Please sign in to comment.