-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,42 @@ | ||
# Compiled class file | ||
*.class | ||
.gradle | ||
build/ | ||
!gradle/wrapper/gradle-wrapper.jar | ||
!**/src/main/**/build/ | ||
!**/src/test/**/build/ | ||
|
||
# Log file | ||
*.log | ||
### IntelliJ IDEA ### | ||
.idea/modules.xml | ||
.idea/jarRepositories.xml | ||
.idea/compiler.xml | ||
.idea/libraries/ | ||
*.iws | ||
*.iml | ||
*.ipr | ||
out/ | ||
!**/src/main/**/out/ | ||
!**/src/test/**/out/ | ||
|
||
# BlueJ files | ||
*.ctxt | ||
### Eclipse ### | ||
.apt_generated | ||
.classpath | ||
.factorypath | ||
.project | ||
.settings | ||
.springBeans | ||
.sts4-cache | ||
bin/ | ||
!**/src/main/**/bin/ | ||
!**/src/test/**/bin/ | ||
|
||
# Mobile Tools for Java (J2ME) | ||
.mtj.tmp/ | ||
### NetBeans ### | ||
/nbproject/private/ | ||
/nbbuild/ | ||
/dist/ | ||
/nbdist/ | ||
/.nb-gradle/ | ||
|
||
# Package Files # | ||
*.jar | ||
*.war | ||
*.nar | ||
*.ear | ||
*.zip | ||
*.tar.gz | ||
*.rar | ||
### VS Code ### | ||
.vscode/ | ||
|
||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml | ||
hs_err_pid* | ||
replay_pid* | ||
### Mac OS ### | ||
.DS_Store |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,8 @@ | ||
# slackcat-kt | ||
|
||
Slackcat but strongly typed | ||
|
||
## Note | ||
|
||
The`*Graphs.kt` classes are a very simple global singleton dependency graph. | ||
For a real app, you would use something like Dagger instead. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import com.slackcat.SlackcatProperties | ||
import com.slackcat.plugins.extentsion.SlackcatExtension | ||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile | ||
|
||
plugins { | ||
id("com.slackcat.plugins.application") | ||
kotlin("plugin.serialization") version "1.5.21" | ||
} | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
|
||
slackcat { | ||
features { | ||
coroutines() | ||
reflection() | ||
exposed() | ||
} | ||
} | ||
|
||
val slackcatProperties = SlackcatProperties(project) | ||
|
||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
implementation(project(":features:slackcat")) | ||
implementation(project(":data:chat")) | ||
|
||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.1") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.slackcat.app | ||
|
||
fun main(args: Array<String>) { | ||
val slackcatApp = SlackcatApp() | ||
slackcatApp.onCreate(args.joinToString(" ")) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.slackcat.app | ||
|
||
import com.slackcat.app.modules.date.DateModule | ||
import com.slackcat.app.modules.kudos.KudosModule | ||
import com.slackcat.app.modules.ping.PingModule | ||
import com.slackcat.app.modules.status.StatusModule | ||
import com.features.slackcat.SlackcatBot | ||
import com.features.slackcat.models.SlackcatModule | ||
import kotlin.reflect.KClass | ||
|
||
|
||
class SlackcatApp { | ||
val modules: Array<KClass<out SlackcatModule>> = arrayOf( | ||
DateModule::class, | ||
KudosModule::class, | ||
PingModule::class, | ||
StatusModule::class | ||
) | ||
|
||
|
||
fun onCreate(args: String?) { | ||
val slackcatBot = SlackcatBot( | ||
modules = modules, | ||
coroutineScope = SlackcatAppGraph.globalScope | ||
) | ||
slackcatBot.start(args) | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.slackcat.app | ||
|
||
import com.features.slackcat.client.SlackcatNetworkClient | ||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Dispatchers | ||
|
||
object SlackcatAppGraph { | ||
val globalScope = CoroutineScope(Dispatchers.IO) | ||
|
||
val slackcatNetworkClient = SlackcatNetworkClient() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.slackcat.app.modules.date | ||
|
||
import com.slackcat.chat.models.IncomingChatMessage | ||
import com.slackcat.chat.models.OutgoingChatMessage | ||
import com.features.slackcat.models.SlackcatModule | ||
import java.text.SimpleDateFormat | ||
import java.util.Date | ||
|
||
class DateModule : SlackcatModule() { | ||
override fun onInvoke(incomingChatMessage: IncomingChatMessage) { | ||
val dateFormat = SimpleDateFormat("MMMM dd, hh:mm a") | ||
val currentDate = Date() | ||
val dateString = dateFormat.format(currentDate) | ||
|
||
sendMessage( | ||
OutgoingChatMessage( | ||
channelId = incomingChatMessage.channeId, | ||
text= "Currently, it's $dateString where I am" | ||
), | ||
) | ||
} | ||
|
||
override fun provideCommand(): String = "date" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.slackcat.app.modules.kudos | ||
|
||
import kotlinx.coroutines.Dispatchers | ||
import org.jetbrains.exposed.sql.* | ||
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction | ||
|
||
class KudosDAO { | ||
data class KudosRow(val id: Int, val userId: String, val count: Int) | ||
|
||
object KudosTable : Table() { | ||
val id = integer("id").autoIncrement() | ||
val userId = text("user_id") | ||
val count = integer("count") | ||
override val primaryKey = PrimaryKey(id) | ||
} | ||
|
||
suspend fun upsertKudos(userId: String): KudosRow { | ||
return dbQuery { | ||
val existingUser = KudosTable.select { KudosTable.userId eq userId }.singleOrNull() | ||
if (existingUser == null) { | ||
// User does not exist, insert new user | ||
KudosTable.insert { | ||
it[KudosTable.userId] = userId | ||
it[count] = 1 | ||
} | ||
} else { | ||
// User exists, increment count | ||
KudosTable.update({ KudosTable.userId eq userId }) { | ||
with(SqlExpressionBuilder) { | ||
it.update(count, count + 1) | ||
} | ||
} | ||
} | ||
|
||
val resultRow = KudosTable.select { KudosTable.userId eq userId }.single() | ||
return@dbQuery KudosRow( | ||
id = resultRow[KudosTable.id], | ||
userId = resultRow[KudosTable.userId], | ||
count = resultRow[KudosTable.count], | ||
) | ||
} | ||
} | ||
} | ||
|
||
suspend fun <T> dbQuery(block: suspend () -> T): T = newSuspendedTransaction(Dispatchers.IO) { block() } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.slackcat.app.modules.kudos | ||
|
||
import com.slackcat.app.SlackcatAppGraph.globalScope | ||
import com.slackcat.chat.models.IncomingChatMessage | ||
import com.slackcat.chat.models.OutgoingChatMessage | ||
import com.features.slackcat.models.SlackcatModule | ||
import com.features.slackcat.models.StorageModule | ||
import kotlinx.coroutines.launch | ||
|
||
class KudosModule : SlackcatModule(), StorageModule { | ||
val kudosDAO = KudosDAO() | ||
|
||
override fun onInvoke(incomingChatMessage: IncomingChatMessage) { | ||
globalScope.launch { | ||
val ids = extractUserIds(incomingChatMessage.userText) | ||
ids.forEach { | ||
val updatedKudos = kudosDAO.upsertKudos(it) | ||
sendMessage( | ||
OutgoingChatMessage( | ||
channelId = incomingChatMessage.channeId, | ||
text = "Bob now has $updatedKudos" | ||
), | ||
) | ||
} | ||
} | ||
} | ||
|
||
override fun provideCommand(): String = "++" | ||
|
||
override fun provideTable() = KudosDAO.KudosTable | ||
|
||
private fun extractUserIds(userText: String): List<String> { | ||
val pattern = """<@(\w+)>""".toRegex() | ||
return pattern.findAll(userText).map { it.groupValues[1] }.toList() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.slackcat.app.modules.ping | ||
|
||
import com.slackcat.chat.models.IncomingChatMessage | ||
import com.slackcat.chat.models.OutgoingChatMessage | ||
import com.features.slackcat.models.SlackcatModule | ||
|
||
class PingModule : SlackcatModule() { | ||
override fun onInvoke(incomingChatMessage: IncomingChatMessage) { | ||
sendMessage( | ||
OutgoingChatMessage( | ||
channelId = incomingChatMessage.channeId, | ||
text = "pong" | ||
) | ||
) | ||
} | ||
|
||
override fun provideCommand(): String = "ping" | ||
} |