Skip to content

Whole repo code review#402

Draft
skaluzinski1801 wants to merge 3143 commits into
code-review-basefrom
dev
Draft

Whole repo code review#402
skaluzinski1801 wants to merge 3143 commits into
code-review-basefrom
dev

Conversation

@skaluzinski1801

Copy link
Copy Markdown
Collaborator

Full code review comparing the current state of the repository against the initial commit.

internal class BanUseCase(
private val adminTool: AdminTool,
) {
suspend fun invoke(origin: Source, query: String): Result<Pair<Ban, Source>, BotError> {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pair is not the easiest to read, you can use data class in moments like that to add clarity

import io.github.sophon.core.featureConfig.model.FeatureInfo
import io.github.sophon.discord.feat.core.domain.model.BotOutput

internal class CreateRedirectButtonsUseCase {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extract interface to test

featureList: List<FeatureInfo>
): BotOutput.ButtonSet {
val buttonList = featureList
.mapNotNull { featureInfo ->

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if you receive null list only?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then no buttons, so empty list.

import io.github.sophon.integration.model.AdminResult
import io.github.sophon.integration.model.Source

internal class ProcessFeedbackUseCase(

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

@skaluzinski1801 skaluzinski1801 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

** naming suffix across feat/wiki* modules**
It seems that you have lots of wiki... .modules, it seems to be a pattern

import kotlin.time.ExperimentalTime

@OptIn(ExperimentalTime::class)
internal class AdminDiscordFeature(

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is noice actually, you've extracted all business logic outside of the feature. Now this code is really easy for you to maintain and test so GJ

@Sophon
Sophon marked this pull request as draft June 28, 2026 19:50
private suspend fun feedback(
origin: Source,
message: String,
): Result<BotOutput, BotError> {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

side question:
That pattern looks as arrow either, have you ever seen it?

isEphemeral: Boolean = false,
): Result<String, BotError> {
return try {
val uuid = Uuid.Companion.random()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally whenever you see any companion object usage like that it means that your code in the current state can't be tested, you can't just mock parameters. In this example you have to mock static. Consider extracting everything that is used within a given class to something constructor parameter related so that it can be mocked/tested easily. The easier it is to test, the easier it is to maintain

@skaluzinski1801 skaluzinski1801 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Hardcoded strings — no localization support

The entire file uses hardcoded English strings (titles like "ERROR", button labels like "EXAMPLES", "COMMANDS", "HELP", and all description/instruction text). There is no abstraction for translations, making it impossible to localize without rewriting everything.

Consider introducing a translations wrapper:

interface ResourceWrapper {
    fun provideTranslation(trans: Translation): String
}

sealed interface Translation {
    sealed interface Error : Translation {
        data object Title : Error
        data class Description(val detail: String) : Error
    }
    sealed interface Button : Translation {
        data object Examples : Button
        data object Commands : Button
        data object Help : Button
    }
    // ...
}

This way all user-facing strings are resolved through ResourceWrapper, and adding a new locale only requires implementing the interface for that language. The same pattern should be applied across the entire bot module, not just this file.

@skaluzinski1801 skaluzinski1801 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mistake comment


val botOutput = BotOutput(
primaryEmbedBuilder = {
title = "Join $userName's lobby!"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want those fields to be hardcoded in english?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot stuff is only in English, it's Discord after all.

}
}
}
.map { }

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map{} ?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Map because we return EmptyResult.

Hence the map{} is for Unit.

return mapIndexed { index, move ->
val query = "$charName ${move.input}"
BotOutput.EmbedButton(
label = (index + 1).toString(),

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

index + 1 === magic maths

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Sophon added 30 commits July 24, 2026 18:47
First word, then last word, then game icon as fallback
…holder_char_icons

refactor (dreamcancel): character icons
…button

Refactor/sorry/dustloop feedback button
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants