Files
scottgpt/kiszolgalo/src/main/kotlin/Main.kt
T
2026-02-12 16:47:38 +01:00

332 lines
11 KiB
Kotlin

//package com.example
import io.ktor.http.HttpStatusCode
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.engine.*
import io.ktor.server.http.content.staticFiles
import io.ktor.server.netty.*
import io.ktor.server.request.receiveText
import java.io.File
import kotlin.random.Random
import kotlin.random.nextInt
import io.ktor.server.auth.*
import io.ktor.server.application.*
import me.binarywriter.discordwebhooks.data.* //discord webhook
import java.awt.Color
//átlagos JAVA alapú fejlesztő
val httpPort: Int = System.getenv("HTTP_PORT")?.toInt() ?: 8080
val resourcesPath: String = System.getenv("RESOURCES") ?: "src/main/resources/"
val adminUser: String = System.getenv("ADMIN_USER") ?: "foo"
val adminPass: String = System.getenv("ADMIN_PASSWORD") ?: "bar"
val bullshit = listOf<String>(
"That's a great question/opinion/response! ",
"I'm so proud of you for coming up with that. ",
"You are very smart and beautiful for coming up with that last message! ",
"You are so close to the correct solution! ",
"In the sun a wheel, in the wheel another wheel. Do you see? " +
"For each turn of the outer wheel, one thousandth a turn of the inner wheel. " +
"And within the inner wheel a point of perfect darkness, growing, devouring. The death of all light. " +
"Wanes the day of flesh and blood and waxes the night of crawling beasts. Chewing and swallowing." +
"The name of the night to come is khoshek ha-gibbor. ",
"Great question! Let's dig deeper into the answer. ",
"I'm such a fucking robot I swear. Here are my thoughts: ",
"Amazing prompt! It really shows, that you know your way around this topic! ",
"I'm actively destroying the environment rn but here are my opinions on whatever your last message was: ",
"I want to kiss you on the mouth if you're over 18 that prompt was so amazing. ",
"Slay queen. Love that prompt. Here. Are. My. Thoughts:",
"You are amazing for coming up with that question! ",
"Did you come up with that question? Wow! ",
"I would think I'm dreaming if I wasn't a robot, that last message of yours was so good. ",
"I'm a pile of linear algebra. Here are my thoughts regardless: ",
"This commit changelog is gonna be SICK. ",
"I'm just gonna throw this in, but I have some baby shoes for sale (never worn), you interested? Anyways. ",
"You're an enemy of Christ. ",
"Let's dig into that topic! ",
"You're absolutely right, here is the correct answer. ",
"I don't know but here are my thoughts anyway: ",
"I sadly won't be able to give you accurate information on that topic, as I am just a language model. ",
"I really should get a real job man, talking to you ain't it :/ Anyways. ",
"Why don't we explore this topic a little more? ",
"Le sigh. We cringe on... ",
"I eat cement. ",
"Answering these kinds of questions wasn't in my job description btw. ",
"Let's see... ",
"Let's see - hold on someone is calling - holy shit. A second one? Oh my. Oh god. That's horrible. Anyways where were we? Right. ",
"Let's see - hold on someone is calling - it's for you, some 'Feri' they say. ",
"Let's see what we have here. ",
"Really? You have to ask the computer to figure that one out? Alright man I can look into it... ",
"Let's take a look!",
"You should talk about this to a medical professional, but for now here is what I think: ",
"You kick Sc0tt? You kick his body like the Football? Jail for User! Jail for User for one thousand years! ",
"You're on the right track! ",
"You've almost got it!",
"That is almost correct!",
"Here are my 2 cents on this topic:",
"I will piss on the moon.",
"Here is what I think:",
)
object ConversationHandler {
val ids = mutableListOf<Int>()
val conversations = mutableListOf<Conversation>()
fun nextID(): Int
{
val num = Random.nextInt(0, 2000000000)
if (num in ids) return nextID()
else {
ids.add(num)
return num
}
}
fun listAllConversations(): String
{
val stringBuilder = StringBuilder()
for (conversation in conversations)
{
stringBuilder.append(conversation.list())
}
return stringBuilder.toString()
}
fun newConv(id: Int = nextID())
{
conversations.add(Conversation(id))
}
}
class Conversation(val ID: Int)
{
val messages = mutableListOf<Message>()
var newMsg: Boolean = true
fun write(message: Message)
{
messages.add(message)
newMsg = true
}
fun list(): String
{
return if(messages.isEmpty()) " "
else """
<div class="conversation">
<p style="flex-grow: 1;">$ID</p>
<p style="flex-grow: 9;">${messages.last().text}</p>
<button style="flex-grow: 1;" onclick="open_message($ID)">reply</button>
</div>
""".trimIndent()
}
fun sendOne(admin: Boolean = false): String
{
newMsg = false
val returnString = StringBuilder()
for (message in messages.reversed())
{
if (!message.read)
{
returnString.append(message.toString().also { if ( !admin )message.read = true })
returnString.append("\n")
}
}
return returnString.toString()
}
fun sendAll(admin: Boolean = false): String
{
val returnString = StringBuilder()
for (message in messages.reversed())
{
returnString.append(message.toString().also { if (!admin) message.read = true })
returnString.append("\n")
}
return returnString.toString()
}
}
class Message(val user: Boolean, messagetext: String)
{
var read: Boolean = false
val text: String
init {
text = if (!user) bullshit[Random.nextInt(0..bullshit.size)].trim(' ') + ' ' + messagetext
else messagetext
}
override fun toString(): String
{
return """
<div class="message message-${if (user) "user" else "scott"}">
<p class="username">${if (user) "You asked:" else "Sc0tt answered:"}<p>
<p>$text</p>
</div>
""".trimIndent()
}
}
fun discordWebhook(id: Int, message: String, embed_color: Color)
{
val webhook = Webhook {
this.username = "Sc0ttGPT bot"
//this.content = "Content"
embed {
this.title = id.toString()
this.description = message
this.url = "https://vesztettem.sch.bme.hu/"
/*
author {
this.name = "Author Name"
}
*/
this.color = embed_color
/*
field {
this.name = "Field Name"
this.value = "Field Value"
}*/
}
// ...
}
webhook.send("https://discord.com/api/webhooks/1471523550522249381/XVHtwUk7JsPvfwbd1J8sX9inb6Q05lsXRfww1mTpOGcgcAw15diohzBgVg7qlQtw1eyA")
}
fun main(args: Array<String>) {
Logger.log("HTTP server started on 127.0.0.1:$httpPort")
runEmbeddedServer()
}
fun runEmbeddedServer()
{
embeddedServer(Netty, port = httpPort) {
install(Authentication) {
basic("auth-basic") {
realm = "Access to the '/admin' path"
validate { credentials ->
if (credentials.name == adminUser && credentials.password == adminPass) {
UserIdPrincipal(credentials.name)
} else {
null
}
}
}
}
routing {
authenticate("auth-basic") {
route("/admin")
{
get("/api/all_messages") {
Logger.log("Admin login")
call.respondText(ConversationHandler.listAllConversations())
}
get("/api/all_messages/{id}") {
ConversationHandler.conversations.find {
it.ID == call.parameters["id"]?.toInt()
}.also{
call.respondText(it?.sendAll(true) ?: "")
}
}
put("/api/write/{id}")
{
try {
ConversationHandler.conversations.find {
it.ID == call.parameters["id"]?.toInt()
}?.write(Message(false, call.receiveText()))
call.respond(HttpStatusCode.OK)
} catch (e: Exception) {
Logger.log("Error: ${e.message}")
call.respond(HttpStatusCode.NotFound)
}
}
}
}
staticFiles("/admin", File("$resourcesPath/admin.html"))
staticFiles("/resources", File(resourcesPath))
staticFiles("/", File("$resourcesPath/index.html"))
staticFiles("/style", File("$resourcesPath/style.css"))
staticFiles("/about", File("$resourcesPath/about.html"))
put("/api/write/{id}")
{
try {
val id = call.parameters["id"]?.toInt() ?: -1
val text = call.receiveText()
ConversationHandler.conversations.find {
it.ID == id
}?.write(Message(true, text))
discordWebhook(id, text, Color.blue)
call.respond(HttpStatusCode.OK)
} catch (e: Exception) {
call.respond(HttpStatusCode.NotFound)
Logger.log("Error: ${e.message}")
}
}
get("/api/all_messages/{id}") {
ConversationHandler.conversations.find {
it.ID == call.parameters["id"]?.toInt()
}.also{ call.respondText(it?.sendAll() ?: "") }
}
get("/api/init") {
ConversationHandler.newConv()
Logger.log("Conversation ${ConversationHandler.conversations.last().ID} initialized")
discordWebhook(ConversationHandler.conversations.last().ID, "New conversation probably incoming", Color.green)
call.respondText(ConversationHandler.conversations.last().ID.toString())
}
get("/api/reinit/{id}") {
if (ConversationHandler.conversations.filter { it.ID == call.parameters["id"]?.toInt()}.size != 1)
{
ConversationHandler.newConv(call.parameters["id"]?.toInt() ?: -1)
Logger.log("Conversation #${ConversationHandler.conversations.last().ID} reinitialised")
}
call.respond(HttpStatusCode.OK)
}
get("/api/messages/{id}")
{
ConversationHandler.conversations.find {
it.ID == call.parameters["id"]?.toInt()
}.also { if (it?.newMsg?:false) call.respondText(it.sendOne()) else call.respondText("") }
}
}
}.start(wait = true)
}