-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Rewrite lastrun file logic Changed lastrun file from a custom format to a JSON file. If a `lastrun.json` file doesn't exist yet, the old format will be automatically migrated. * Add shadowban command The command does nothing but add the shadowban to the lastrun file. * Add shadowban module This module actually does all the work for the shadowban, removing all comments, attachments, and bug reports from shadowbanned users. I've modified the `ExecutionTimeframe` so that it also stores all shadowbans; as a consequence, the module needs to be able to access the entire timeframe instead of just the `lastRunTime`. I've chosen to add an alternative way to implement modules if more details are needed; it might make sense to migrate to this for all modules in the future; or alternatively do a refactor so that a module can access anything non-static it needs from its invocation arguments. * Add debug option to not ignore commands sent by bot user
- Loading branch information
1 parent
82fa74c
commit b4be4c3
Showing
21 changed files
with
790 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package io.github.mojira.arisa | ||
|
||
import com.beust.klaxon.Converter | ||
import com.beust.klaxon.JsonValue | ||
import com.beust.klaxon.Klaxon | ||
import com.beust.klaxon.KlaxonException | ||
import java.io.File | ||
import java.time.Instant | ||
import java.time.temporal.ChronoUnit | ||
|
||
class EpochMilliInstantConverter : Converter { | ||
override fun canConvert(cls: Class<*>) = cls == Instant::class.java | ||
override fun toJson(value: Any) = '"' + (value as Instant).toEpochMilli().toString() + '"' | ||
override fun fromJson(jv: JsonValue): Instant = jv.string?.let { str -> | ||
Instant.ofEpochMilli(str.toLong()) | ||
} ?: run { | ||
println("Can't read $jv from json") | ||
LastRunFile.defaultTime() | ||
} | ||
} | ||
|
||
val instantConverter = EpochMilliInstantConverter() | ||
|
||
data class Shadowban( | ||
val user: String, | ||
val since: Instant, | ||
val until: Instant | ||
) { | ||
fun banTimeContains(instant: Instant): Boolean = instant in since..until | ||
} | ||
|
||
data class LastRunFile( | ||
val time: Instant? = defaultTime(), | ||
val failedTickets: Set<String>? = emptySet(), | ||
val shadowbans: List<Shadowban>? = emptyList() | ||
) { | ||
companion object { | ||
fun defaultTime(): Instant = | ||
Instant.now().minus(LastRun.DEFAULT_START_TIME_MINUTES_BEFORE_NOW, ChronoUnit.MINUTES) | ||
|
||
fun read(readFromFile: () -> String): LastRunFile { | ||
val default = LastRunFile( | ||
time = defaultTime(), | ||
failedTickets = setOf(), | ||
shadowbans = listOf() | ||
) | ||
|
||
@SuppressWarnings("SwallowedException") | ||
val result = try { | ||
Klaxon().converter(instantConverter).parse<LastRunFile>(readFromFile()) | ||
} catch (e: KlaxonException) { | ||
default | ||
} | ||
|
||
return result ?: default | ||
} | ||
} | ||
|
||
fun write(writeToFile: (String) -> Unit) { | ||
val result = Klaxon().converter(instantConverter).toJsonString(this) | ||
writeToFile(result) | ||
} | ||
} | ||
|
||
class LastRunFileService( | ||
private val fileName: String, | ||
private val legacyFileName: String | ||
) { | ||
fun writeLastRunFile(file: LastRunFile) { | ||
val lastRunFile = File(fileName) | ||
file.write(lastRunFile::writeText) | ||
} | ||
|
||
fun getLastRunFile(): LastRunFile { | ||
val lastRunFile = File(fileName) | ||
if (!lastRunFile.exists()) migrateLegacyFile() | ||
|
||
return LastRunFile.read(lastRunFile::readText) | ||
} | ||
|
||
// Migrate old last-run file | ||
private fun migrateLegacyFile() { | ||
val legacyFile = File(legacyFileName) | ||
|
||
val legacyContents = if (legacyFile.exists()) legacyFile.readText() else "" | ||
|
||
val newFileContents = convertLegacyFile(legacyContents) | ||
newFileContents.write { | ||
val newFile = File(fileName) | ||
newFile.writeText(it) | ||
} | ||
|
||
legacyFile.delete() | ||
} | ||
|
||
companion object { | ||
fun convertLegacyFile(legacyContents: String): LastRunFile { | ||
val fileComponents = legacyContents.trim().split(',') | ||
|
||
val time = if (fileComponents[0].isNotEmpty()) { | ||
Instant.ofEpochMilli(fileComponents[0].toLong()) | ||
} else { | ||
LastRunFile.defaultTime() | ||
} | ||
|
||
val failedTickets = fileComponents.subList(1, fileComponents.size).toSet() | ||
|
||
return LastRunFile(time, failedTickets, shadowbans = emptyList()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.