Skip to content

Commit

Permalink
class, class, two classes
Browse files Browse the repository at this point in the history
  • Loading branch information
gt22 committed May 29, 2020
1 parent 4219adf commit 2faadbd
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 98 deletions.
4 changes: 4 additions & 0 deletions src/main/kotlin/EventListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import net.dv8tion.jda.core.events.message.MessageUpdateEvent
import net.dv8tion.jda.core.hooks.SubscribeEvent
import org.jetbrains.exposed.sql.transactions.transaction
import sources.*
import users.Classification
import users.UADABUser
import utils.BashUtils
import java.awt.Color
Expand All @@ -28,6 +29,9 @@ object EventListener {
GlobalScope.launch {
transaction {
jda.users.forEach { UADABUser.fromDiscord(it, openTransaction = false) }
val self = UADABUser.fromDiscord(jda.selfUser)
self.classification = Classification.SYSTEM
self.save()
}
}
GlobalScope.launch {
Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/UADAB.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.google.gson.JsonParser
import commands.MiscCommands
import commands.MusicCommands
import commands.SystemCommands
import commands.UserCommands
import io.ktor.client.HttpClient
import io.ktor.client.engine.apache.Apache
import net.dv8tion.jda.core.JDA
Expand Down Expand Up @@ -43,7 +44,7 @@ object UADAB {
cfg.dbPass
)
commandClient = CommandClient(cfg.prefix)
commandClient.register(SystemCommands, MiscCommands, MusicCommands)
commandClient.register(SystemCommands, MiscCommands, MusicCommands, UserCommands)

bot = JDABuilder(cfg.token)
.setBulkDeleteSplittingEnabled(false)
Expand Down
6 changes: 6 additions & 0 deletions src/main/kotlin/argparser/spec/RangeArg.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ package argparser.spec
class RangeArgResult(val from: Int?, val to: Int?) : ArgResult() {
override val type: String = "range"

val isEmpty
get() = from == null && to == null

val isNotEmpty
get() = !isEmpty

operator fun component1() = from
operator fun component2() = to
}
Expand Down
4 changes: 1 addition & 3 deletions src/main/kotlin/cmd/CommandBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
package cmd

import argparser.ArgParser
import dsl.Init
import users.Classification
import users.default


typealias Init<T> = T.() -> Unit

@DslMarker
annotation class CommandBuilderDsl

Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/cmd/ICommandList.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cmd

import dsl.Init
import dsl.PaginatedEmbedCreator

interface ICommandList {
Expand Down
80 changes: 1 addition & 79 deletions src/main/kotlin/commands/MiscCommands.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package commands

import argparser.spec.RangeArgResult
import cmd.*
import dsl.Init
import commands.MiscCommands.replyCat
import dsl.PaginatedEmbedCreator
import dsl.paginatedEmbed
Expand Down Expand Up @@ -29,7 +30,6 @@ import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import javax.imageio.ImageIO

typealias MonitorBuilder = PaginatedEmbedCreator.() -> Unit
object MiscCommands : ICommandList {

override val cat: CommandCategory =
Expand Down Expand Up @@ -227,84 +227,6 @@ object MiscCommands : ICommandList {
}
}
}
command("monitor") {
help = "Can you hear me?"
aliases { +"mon" }
val nameArg by parser.plain("user")
val leftover by parser.leftoverDelegate()
action {
val name = nameArg.value ?: return@action replyCat {
title = "Invalid args"
color = RED
+"No user specified"
}
val users = Getters.getUser(name).toList()
if (users.isEmpty()) {
return@action replyCat {
title = "No users found"
color = RED
+"$name matched no used"
}
}
// Async fetch all users with images
val userData = GlobalScope.async(Dispatchers.IO) {
users.map { userImage(it) }.map { monitorInfo(it.first, it.second) }
}
// on complete reply message
// if error - send error message
// if success, for each user create and fill new page
userData.invokeOnCompletion {
replyCat {
it?.let {
title = "Unable to monitor"
+"Something went wrong with boxing:\n"
+it.toString()
} ?: userData.getCompleted().forEach {
page { this@replyCat.it() }
}
}
}
}
}
}

// Пиздани, если это так не работает (в плане асинхронности)
/**
* Blocking fetch image for user and return pair of user name image
*/
private suspend fun userImage(user: UADABUser): Pair<UADABUser, ByteArray> =
user to ByteArrayOutputStream().apply {
ImageIO.write(user.getBoxedImageAsync().await(), "png", this)
}.toByteArray()

/**
* Get a function that build a single page for {user} with {image}
*/
private fun monitorInfo(user: UADABUser, imageData: ByteArray): MonitorBuilder = {
title = "Info about ${user.name}"
thumbnail = "attachment://boxed_avatar.png"
inline field "Classification" to user.classification.name
inline field "SSN" to user.ssn.redactedSSNString
append field "Name" to user.name
inline field "Location" to (user.discord.mutualGuilds.mapNotNull { guild ->
guild.getMember(user.discord)?.voiceState?.channel?.let { voice ->
guild to voice
}
}.firstOrNull()?.let { location ->
"${location.first.name}/${location.second.name}"
} ?: "[UNKNOWN]")
"boxed_avatar.png" attach imageData
inline field "Aliases" to "${user.discord.name}\n${
user.discord.mutualGuilds.mapNotNull { guild ->
guild.getMember(user.discord).nickname ?: null
}.toSet().joinToString("\n")
}"
}

val RangeArgResult.isEmpty
get() = from == null && to == null

val RangeArgResult.isNotEmpty
get() = !isEmpty

}
7 changes: 6 additions & 1 deletion src/main/kotlin/commands/MusicCommands.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package commands

import cmd.*
import dsl.Init
import dsl.PaginatedEmbedCreator
import dsl.embed
import music.*
Expand Down Expand Up @@ -383,7 +384,7 @@ object MusicCommands : ICommandList {
replyCat {
title = "Volume changed"
color = GREEN
+"New volume is ${value}"
+"New volume is $value"
}
}

Expand Down Expand Up @@ -453,6 +454,10 @@ object MusicCommands : ICommandList {
title = "Everything went wrong everywhere"
+"Unable to load anything..."
}
is MHNoMoreTracks -> replyCat {
color = YELLOW
title = "Loaded all possible tracks"
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/commands/SystemCommands.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import UADAB
import cmd.CommandCategory
import cmd.CommandListBuilder
import cmd.ICommandList
import cmd.Init
import dsl.Init
import dsl.embed
import net.dv8tion.jda.core.Permission
import users.Classification
Expand Down
157 changes: 157 additions & 0 deletions src/main/kotlin/commands/UserCommands.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package commands

import cmd.CommandCategory
import cmd.CommandListBuilder
import cmd.ICommandList
import dsl.BaseEmbedCreater
import dsl.Init
import getters.Getters
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import users.Classification
import users.UADABUser
import users.assets
import utils.getters.Wrapper
import java.awt.Color
import java.awt.Color.GREEN
import java.awt.Color.RED
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import javax.imageio.ImageIO

object UserCommands : ICommandList {

override val cat = CommandCategory("System", Color(0x5E5E5E), "http://52.48.142.75/images/gear.png")

override fun init(): Init<CommandListBuilder> = {
command("monitor") {
help = "Can you hear me?"
aliases { +"mon" }
val nameArg by parser.plain("user")
val leftover by parser.leftoverDelegate()
action {
val name = nameArg.value ?: return@action replyCat {
title = "Invalid args"
color = RED
+"No user specified"
}
val users = Getters.getUser(name).toList()
if (users.isEmpty()) {
return@action replyCat {
title = "No users found"
color = RED
+"$name matched no used"
}
}
// Async fetch all users with images
val userData = GlobalScope.async(Dispatchers.IO) {
users
.map { it to it.getBoxedImageAsync().await().toByteArray() }
.map { (user, img) -> monitorInfo(user, img) }
}
// on complete reply message
// if error - send error message
// if success, for each user create and fill new page
userData.invokeOnCompletion {
replyCat {
it?.let {
title = "Unable to monitor"
+"Something went wrong with boxing:\n"
+it.toString()
} ?: userData.getCompleted().forEach(::page)
}
}
}
}
command("reclass") {
help = "Change classification of user"
val nameArg by parser.plain("user")
val leftover by parser.leftoverDelegate()
allowed to assets
action {
val name = nameArg.value ?: return@action replyCat {
title = "Invalid args"
color = RED
+"No user specified"
}
val cls =
leftover.joinToString(" ").let(Classification.Companion::getOrNull) ?: return@action replyCat {
title = "Invalid args"
color = RED
+"Classification is not classification"
}

val wuser = Getters.getUser(nameArg.value!!)
when (wuser.state) {
Wrapper.WrapperState.NONE -> replyCat {
title = "No users found"
color = RED
+"$name matched no used"
}
Wrapper.WrapperState.MULTI -> replyCat {
title = "Many users found"
color = RED
+"$name matched too many users used"
}
Wrapper.WrapperState.SINGLE -> {
val user = wuser.getSingle()
val acls = author.classification.permissionLevel
val ucls = user.classification.permissionLevel
val tcls = cls.permissionLevel
if (acls < tcls || (ucls > tcls && acls <= ucls)) {
return@action replyCat {
title = "Insufficient permission"
color = RED
if (author.classification == Classification.ADMIN) {
+"Admin is not admin"
}
}
}
user.classification = cls
user.save()
user.getBoxedImageAsync().run {
invokeOnCompletion {
replyCat {
title = "Success"
color = GREEN
+"${user.name} is now ${cls.name}"
if (it == null) thumbnail = "boxed_avatar.png" attach getCompleted().toByteArray()
}
}
}
}
}
}
}
}

private fun BufferedImage.toByteArray(): ByteArray =
ByteArrayOutputStream().apply {
ImageIO.write(this@toByteArray, "png", this@apply)
}.toByteArray()

/**
* Get a function that build a single page for {user} with {image}
*/
private fun monitorInfo(user: UADABUser, imageData: ByteArray): Init<BaseEmbedCreater> = {
title = "Info about ${user.name}"
thumbnail = "boxed_avatar.png" attach imageData
inline field "Classification" to user.classification.name
inline field "SSN" to user.ssn.redactedSSNString
append field "Name" to user.name
inline field "Location" to (user.discord.mutualGuilds.mapNotNull { guild ->
guild.getMember(user.discord)?.voiceState?.channel?.let { voice ->
guild to voice
}
}.firstOrNull()?.let { (guild, voice) ->
"${guild.name}/${voice.name}"
} ?: "[UNKNOWN]")
inline field "Aliases" to "${user.discord.name}\n${
user.discord.mutualGuilds.mapNotNull { guild ->
guild.getMember(user.discord).nickname ?: null
}.toSet().joinToString("\n")
}"
}

}
9 changes: 6 additions & 3 deletions src/main/kotlin/dsl/EmbedBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,19 @@ open class BaseEmbedCreater {
setElement(::FooterBuilder, init)
}

open infix fun String.attach(stream: InputStream) {
open infix fun String.attach(stream: InputStream): String {
attachments[this] = stream
return "attachment://${this}"
}

open infix fun String.attach(stream: File) {
open infix fun String.attach(stream: File): String {
attachments[this] = FileInputStream(stream)
return "attachment://${this}"
}

open infix fun String.attach(stream: ByteArray) {
open infix fun String.attach(stream: ByteArray): String {
attachments[this] = ByteArrayInputStream(stream)
return "attachment://${this}"
}

private inline fun <T : ElementBuilder> setElement(eBuilder: (EmbedBuilder) -> T, init: Init<T>) {
Expand Down
Loading

0 comments on commit 2faadbd

Please sign in to comment.