Skip to content

Commit

Permalink
Add Loritta's daily shop notifications to be relayed to guilds
Browse files Browse the repository at this point in the history
  • Loading branch information
MrPowerGamerBR committed Nov 12, 2024
1 parent 02e0dcb commit 03c7f60
Show file tree
Hide file tree
Showing 22 changed files with 954 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package net.perfectdreams.loritta.common.utils.placeholders

import net.perfectdreams.loritta.i18n.I18nKeysData

data object DailyShopTrinketsNotificationMessagePlaceholders : SectionPlaceholders<DailyShopTrinketsNotificationMessagePlaceholders.DailyShopTrinketsNotificationPlaceholder> {
override val type = PlaceholderSectionType.DAILY_SHOP_TRINKETS_NOTIFICATION_MESSAGE

sealed interface DailyShopTrinketsNotificationPlaceholder : MessagePlaceholder

object DailyShopDateShortPlaceholder : GenericPlaceholders.GenericPlaceholder(null), DailyShopTrinketsNotificationPlaceholder {
override val names = listOf(Placeholders.DAILY_SHOP_DATE_SHORT.toVisiblePlaceholder())
override val renderType = MessagePlaceholder.RenderType.TEXT
}
object GuildNamePlaceholder : GenericPlaceholders.GuildNamePlaceholder(I18nKeysData.Placeholders.Generic.GuildName), DailyShopTrinketsNotificationPlaceholder
object GuildSizePlaceholder : GenericPlaceholders.GuildSizePlaceholder(I18nKeysData.Placeholders.Generic.GuildSize), DailyShopTrinketsNotificationPlaceholder
object GuildIconUrlPlaceholder : GenericPlaceholders.GuildIconUrlPlaceholder(I18nKeysData.Placeholders.Generic.GuildIconUrl), DailyShopTrinketsNotificationPlaceholder

override val placeholders = listOf<DailyShopTrinketsNotificationPlaceholder>(
DailyShopDateShortPlaceholder,
GuildNamePlaceholder,
GuildSizePlaceholder,
GuildIconUrlPlaceholder
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ enum class PlaceholderSectionType {
LEAVE_MESSAGE,
TWITCH_STREAM_ONLINE_MESSAGE,
BLUESKY_POST_MESSAGE,
YOUTUBE_POST_MESSAGE
YOUTUBE_POST_MESSAGE,
DAILY_SHOP_TRINKETS_NOTIFICATION_MESSAGE
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ object Placeholders {
// ===[ BLUESKY ]===
val BLUESKY_POST_URL = LorittaPlaceholder("post.url")

// ===[ DAILY SHOP TRINKETS ]===
val DAILY_SHOP_DATE_SHORT = LorittaPlaceholder("daily-shop.date-short")

object Deprecated {
val USER_ID = LorittaPlaceholder("user-id")
val USER_DISCRIMINATOR = LorittaPlaceholder("user-discriminator")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ sealed interface SectionPlaceholders<T : MessagePlaceholder> {
LeaveMessagePlaceholders,
TwitchStreamOnlineMessagePlaceholders,
BlueskyPostMessagePlaceholders,
YouTubePostMessagePlaceholders
YouTubePostMessagePlaceholders,
DailyShopTrinketsNotificationMessagePlaceholders
)

init {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SonhosTransactionsExecutor(val loritta: LorittaBot) : LorittaSlashCommandE
userFacingTransactionTypeFilter: List<TransactionType>
): suspend InlineMessage<*>.() -> (Unit) = {
content = ""

// If the list is empty, we will use *all* transaction types in the filter
// This makes it easier because you don't need to manually deselect every single filter before you can filter by a specific
// transaction type.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package net.perfectdreams.loritta.morenitta.utils

import io.ktor.client.request.*
import io.ktor.http.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import mu.KotlinLogging
import net.perfectdreams.loritta.cinnamon.pudding.tables.Backgrounds
import net.perfectdreams.loritta.cinnamon.pudding.tables.ProfileDesigns
import net.perfectdreams.loritta.morenitta.LorittaBot
import net.perfectdreams.loritta.cinnamon.pudding.tables.*
import net.perfectdreams.loritta.morenitta.LorittaBot
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction

class LorittaDailyShopUpdateTask(val loritta: LorittaBot) : Runnable {
companion object {
Expand All @@ -23,17 +24,35 @@ class LorittaDailyShopUpdateTask(val loritta: LorittaBot) : Runnable {
logger.info { "Generating a new daily shop..." }

runBlocking {
loritta.pudding.transaction {
val resultId = loritta.pudding.transaction {
val newShop = DailyShops.insertAndGetId {
it[generatedAt] = System.currentTimeMillis()
}

getAndAddRandomBackgroundsToShop(newShop)
getAndAddRandomProfileDesignsToShop(newShop)

newShop
}

// Notify that it was refreshed
val shards = loritta.config.loritta.clusters.instances

shards.map {
GlobalScope.launch {
try {
logger.info { "Sending daily shop refresh request to other clusters..." }
loritta.httpWithoutTimeout.post("${it.getUrl(loritta)}/daily-shop-refreshed?dailyShopId=${resultId}") {
userAgent(loritta.lorittaCluster.getUserAgent(loritta))
}
} catch (e: Exception) {
logger.warn(e) { "Shard ${it.name} ${it.id} offline!" }
}
}
}
}
}

private fun getAndAddRandomBackgroundsToShop(shopId: EntityID<Long>) {
val allBackgrounds = Backgrounds.select {
Backgrounds.enabled eq true and (Backgrounds.availableToBuyViaDreams eq true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.*
import net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.bluesky.*
import net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.commands.ConfigureCommandsRoute
import net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.commands.PutConfigureCommandsRoute
import net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.dailyshoptrinkets.ConfigureDailyShopTrinketsNotificationsRoute
import net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.dailyshoptrinkets.PutConfigureDailyShopTrinketsNotificationsRoute
import net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.reactionevents.ConfigureReactionEventsRoute
import net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.reactionevents.PutConfigureReactionEventsRoute
import net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.twitch.*
Expand Down Expand Up @@ -109,6 +111,9 @@ object DefaultRoutes {
ConfigureReactionEventsRoute(loritta),
PutConfigureReactionEventsRoute(loritta),

ConfigureDailyShopTrinketsNotificationsRoute(loritta),
PutConfigureDailyShopTrinketsNotificationsRoute(loritta),

// Reps
UserReputationRoute(loritta),

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.dailyshoptrinkets

import io.ktor.server.application.*
import net.dv8tion.jda.api.entities.Guild
import net.perfectdreams.i18nhelper.core.I18nContext
import net.perfectdreams.loritta.cinnamon.pudding.tables.servers.moduleconfigs.LorittaDailyShopNotificationsConfigs
import net.perfectdreams.loritta.common.locale.BaseLocale
import net.perfectdreams.loritta.common.utils.UserPremiumPlans
import net.perfectdreams.loritta.morenitta.LorittaBot
import net.perfectdreams.loritta.morenitta.dao.ServerConfig
import net.perfectdreams.loritta.morenitta.website.routes.dashboard.RequiresGuildAuthLocalizedDashboardRoute
import net.perfectdreams.loritta.morenitta.website.utils.extensions.respondHtml
import net.perfectdreams.loritta.morenitta.website.views.dashboard.guild.dailyshoptrinkets.GuildDailyShopTrinketsNotificationsView
import net.perfectdreams.loritta.serializable.ColorTheme
import net.perfectdreams.loritta.serializable.config.GuildDailyShopTrinketsNotificationsConfig
import net.perfectdreams.loritta.temmiewebsession.LorittaJsonWebSession
import net.perfectdreams.temmiediscordauth.TemmieDiscordAuth
import org.jetbrains.exposed.sql.selectAll

class ConfigureDailyShopTrinketsNotificationsRoute(loritta: LorittaBot) : RequiresGuildAuthLocalizedDashboardRoute(loritta, "/configure/daily-shop-trinkets") {
override suspend fun onDashboardGuildAuthenticatedRequest(
call: ApplicationCall,
locale: BaseLocale,
i18nContext: I18nContext,
discordAuth: TemmieDiscordAuth,
userIdentification: LorittaJsonWebSession.UserIdentification,
guild: Guild,
serverConfig: ServerConfig,
colorTheme: ColorTheme
) {
val databaseConfig = loritta.transaction {
LorittaDailyShopNotificationsConfigs.selectAll()
.where {
LorittaDailyShopNotificationsConfigs.id eq guild.idLong
}
.firstOrNull()
}

val config = if (databaseConfig != null) {
GuildDailyShopTrinketsNotificationsConfig(
databaseConfig[LorittaDailyShopNotificationsConfigs.notifyShopTrinkets],
databaseConfig[LorittaDailyShopNotificationsConfigs.shopTrinketsChannelId],
databaseConfig[LorittaDailyShopNotificationsConfigs.shopTrinketsMessage],

databaseConfig[LorittaDailyShopNotificationsConfigs.notifyNewTrinkets],
databaseConfig[LorittaDailyShopNotificationsConfigs.newTrinketsChannelId],
databaseConfig[LorittaDailyShopNotificationsConfigs.newTrinketsMessage],
)
} else {
GuildDailyShopTrinketsNotificationsConfig(
false,
null,
GuildDailyShopTrinketsNotificationsView.defaultShopTrinketsTemplate.content,

false,
null,
GuildDailyShopTrinketsNotificationsView.defaultNewTrinketsTemplate.content
)
}

call.respondHtml(
GuildDailyShopTrinketsNotificationsView(
loritta.newWebsite!!,
i18nContext,
locale,
getPathWithoutLocale(call),
loritta.getLegacyLocaleById(locale.id),
userIdentification,
UserPremiumPlans.getPlanFromValue(loritta.getActiveMoneyFromDonations(userIdentification.id.toLong())),
colorTheme,
guild,
"daily_shop_trinkets",
config
).generateHtml()
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package net.perfectdreams.loritta.morenitta.website.routes.dashboard.configure.dailyshoptrinkets

import io.ktor.server.application.*
import io.ktor.server.request.*
import net.dv8tion.jda.api.entities.Guild
import net.perfectdreams.i18nhelper.core.I18nContext
import net.perfectdreams.loritta.cinnamon.pudding.tables.servers.moduleconfigs.LorittaDailyShopNotificationsConfigs
import net.perfectdreams.loritta.common.locale.BaseLocale
import net.perfectdreams.loritta.common.utils.UserPremiumPlans
import net.perfectdreams.loritta.morenitta.LorittaBot
import net.perfectdreams.loritta.morenitta.dao.ServerConfig
import net.perfectdreams.loritta.morenitta.website.routes.dashboard.RequiresGuildAuthLocalizedDashboardRoute
import net.perfectdreams.loritta.morenitta.website.utils.EmbeddedSpicyModalUtils.headerHXTrigger
import net.perfectdreams.loritta.morenitta.website.utils.extensions.respondHtml
import net.perfectdreams.loritta.morenitta.website.views.dashboard.guild.dailyshoptrinkets.GuildDailyShopTrinketsNotificationsView
import net.perfectdreams.loritta.serializable.ColorTheme
import net.perfectdreams.loritta.serializable.EmbeddedSpicyToast
import net.perfectdreams.loritta.serializable.config.GuildDailyShopTrinketsNotificationsConfig
import net.perfectdreams.loritta.temmiewebsession.LorittaJsonWebSession
import net.perfectdreams.temmiediscordauth.TemmieDiscordAuth
import org.jetbrains.exposed.sql.upsert

class PutConfigureDailyShopTrinketsNotificationsRoute(loritta: LorittaBot) : RequiresGuildAuthLocalizedDashboardRoute(loritta, "/configure/daily-shop-trinkets") {
override suspend fun onDashboardGuildAuthenticatedRequest(
call: ApplicationCall,
locale: BaseLocale,
i18nContext: I18nContext,
discordAuth: TemmieDiscordAuth,
userIdentification: LorittaJsonWebSession.UserIdentification,
guild: Guild,
serverConfig: ServerConfig,
colorTheme: ColorTheme
) {
val params = call.receiveParameters()

val result = loritta.newSuspendedTransaction {
LorittaDailyShopNotificationsConfigs.upsert(LorittaDailyShopNotificationsConfigs.id) {
it[LorittaDailyShopNotificationsConfigs.id] = guild.idLong
it[LorittaDailyShopNotificationsConfigs.notifyShopTrinkets] = params["notifyShopTrinkets"] == "on"
it[LorittaDailyShopNotificationsConfigs.shopTrinketsChannelId] = params["shopTrinketsChannelId"]?.toLong()
it[LorittaDailyShopNotificationsConfigs.shopTrinketsMessage] = params["shopTrinketsMessage"]

it[LorittaDailyShopNotificationsConfigs.notifyNewTrinkets] = params["notifyNewTrinkets"] == "on"
it[LorittaDailyShopNotificationsConfigs.newTrinketsChannelId] = params["newTrinketsChannelId"]?.toLong()
it[LorittaDailyShopNotificationsConfigs.newTrinketsMessage] = params["newTrinketsMessage"]
}
}

val config = GuildDailyShopTrinketsNotificationsConfig(
result[LorittaDailyShopNotificationsConfigs.notifyShopTrinkets],
result[LorittaDailyShopNotificationsConfigs.shopTrinketsChannelId],
result[LorittaDailyShopNotificationsConfigs.shopTrinketsMessage],

result[LorittaDailyShopNotificationsConfigs.notifyNewTrinkets],
result[LorittaDailyShopNotificationsConfigs.newTrinketsChannelId],
result[LorittaDailyShopNotificationsConfigs.newTrinketsMessage],
)

call.response.headerHXTrigger {
playSoundEffect = "config-saved"
showSpicyToast(EmbeddedSpicyToast.Type.SUCCESS, "Configuração salva!")
}

call.respondHtml(
GuildDailyShopTrinketsNotificationsView(
loritta.newWebsite!!,
i18nContext,
locale,
getPathWithoutLocale(call),
loritta.getLegacyLocaleById(locale.id),
userIdentification,
UserPremiumPlans.getPlanFromValue(loritta.getActiveMoneyFromDonations(userIdentification.id.toLong())),
colorTheme,
guild,
"daily_shop_trinkets",
config
).generateHtml()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class DailyShopRoute(loritta: LorittaBot) : RequiresDiscordLoginLocalizedDashboa
setMetaProperty("og:site_name", "Loritta")
setMetaProperty("og:title", "Loja Diária")
setMetaProperty("og:description", "Bem-vind@ a loja diária de itens! O lugar para comprar itens para o seu \"+perfil\" da Loritta!\n\nTodo o dia as 00:00 UTC (21:00 no horário do Brasil) a loja é atualizada com novos itens! Então volte todo o dia para verificar ^-^")
setMetaProperty("og:image", loritta.config.loritta.website.url + "assets/img/loritta_daily_shop.png")
setMetaProperty("og:image", "https://stuff.loritta.website/loritta-daily-shop-nicholas.png")
setMetaProperty("og:image:width", "320")
setMetaProperty("og:ttl", "660")
setMetaProperty("og:image:width", "320")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ abstract class GuildDashboardView(
appendEntry("/guild/${guild.id}/configure/event-log", true, locale["modules.sectionNames.eventLog"], "fa fa-eye", false)
appendEntry("/guild/${guild.id}/configure/youtube", true, "YouTube", "fab fa-youtube", false)
appendEntry("/guild/${guild.id}/configure/twitch", true, "Twitch", "fab fa-twitch", false)
appendEntry("/guild/${guild.id}/configure/bluesky", true, "Bluesky", "fab fa-bluesky", true)
appendEntry("/guild/${guild.id}/configure/bluesky", true, "Bluesky", "fab fa-bluesky", false)
appendEntry("/guild/${guild.id}/configure/daily-shop-trinkets", true, i18nContext.get(I18nKeysData.Website.Dashboard.DailyShopTrinkets.Title), "fa-solid fa-store", true)

hr(classes = "divider") {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ abstract class LegacyGuildDashboardView(
appendEntry("/guild/${guild.id}/configure/youtube", false, "YouTube", "fab fa-youtube", "youtube")
appendEntry("/guild/${guild.id}/configure/twitch", false, "Twitch", "fab fa-twitch", "twitch")
appendEntry("/guild/${guild.id}/configure/bluesky", false, "Bluesky", "fab fa-bluesky", "bluesky")
appendEntry("/guild/${guild.id}/configure/daily-shop-trinkets", false, i18nContext.get(I18nKeysData.Website.Dashboard.DailyShopTrinkets.Title), "fa-solid fa-store", "daily_shop_trinkets")

hr(classes = "divider") {}

Expand Down
Loading

0 comments on commit 03c7f60

Please sign in to comment.