Skip to content

Commit

Permalink
Flatten directory structure and other confusions (#53)
Browse files Browse the repository at this point in the history
* Flatten file structure

* Change package domain to yttr.org

* Slightly restructure shared project

* Move SkillDirector and WebhookDirector

* Fix weird copyright comment update issue

* Suffix extensions with Ext

* Move more directors under skills

May think about retiring the concept of directors

* Get rid of useless Key enum

* Set up HOCON

* Replace getenv with HOCON and update JRAW

* Use HOCON in glyph-config too

* Update README to explain more about self hosting
  • Loading branch information
yttrian committed Jul 10, 2021
1 parent 60394d4 commit db8bc0d
Show file tree
Hide file tree
Showing 118 changed files with 658 additions and 555 deletions.
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
[![GitHub](https://img.shields.io/github/license/glyph-discord/glyph.kt)](https://github.com/glyph-discord/glyph.kt/blob/master/LICENSE)
[![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/glyph-discord/glyph.kt/Java%20CI/master)](https://github.com/glyph-discord/glyph.kt/actions)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/yttrian)](https://github.com/sponsors/yttrian)
[![Discord Bots](https://discordbots.org/api/widget/status/248186527161516032.svg?noavatar=true)](https://discordbots.org/bot/248186527161516032)
[![Discord Bots](https://discordbots.org/api/widget/servers/248186527161516032.svg?noavatar=true)](https://discordbots.org/bot/248186527161516032)

# glyph.kt

The Kotlin rewrite of the Glyph Discord bot
The Kotlin rewrite of the Glyph Discord bot.

Glyph is an experimental Discord bot that uses [DialogFlow](https://dialogflow.com/) to attempt to understand and process natural language requests as opposed to a traditional command based bot.
Glyph is an experimental Discord bot that uses [DialogFlow](https://dialogflow.com/) to attempt to understand and
process natural language requests as opposed to a traditional command based bot.

To learn more about how to use Glyph, check out the documentation [here](https://gl.yttr.org/).

## Self Hosting

In order to host your own copy of Glyph, some set up will be required.

This will be further documented in detail later, but the basic idea is that you will need to create and train an agent on DialogFlow to respond to different prompts, and set all the needed environmental variables used in the code.
1. Create and train a [DialogFlow](https://dialogflow.cloud.google.com/) agent that understands all actions Glyph's
skills refer to
- Action is in the format "skill.feedback"
- All references entities must be understood too
- A free ("Trial") plan is sufficient
- You should disable "Log interaction to Dialogflow"
2. Create a Reddit application for the Reddit skill
3. Create a PostgreSQL database and Redis data store
4. Set the needed environment variables as seen in the application.conf files
5. Build and start the bot and config website

If you modify Glyph, [you must make your source code and changes publicly available](LICENSE).

This file was deleted.

9 changes: 0 additions & 9 deletions config/src/main/resources/application.conf

This file was deleted.

33 changes: 29 additions & 4 deletions bot/build.gradle.kts → glyph-bot/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
/*
* build.gradle.kts
*
* Glyph, a Discord bot that uses natural language instead of commands
* powered by DialogFlow and Kotlin
*
* Copyright (C) 2017-2021 by Ian Moore
*
* This file is part of Glyph.
*
* Glyph is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import tanvd.kosogor.proxy.shadowJar

/*
Expand All @@ -24,7 +48,7 @@ import tanvd.kosogor.proxy.shadowJar
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

group = "me.ianmooreis.glyph.bot"
group = "org.yttr.glyph.bot"
version = "1.0"

internal val coroutinesVersion: String by project.extra
Expand All @@ -39,7 +63,7 @@ repositories {
shadowJar {
jar {
archiveName = "glyph-bot.jar"
mainClass = "me.ianmooreis.glyph.bot.GlyphKt"
mainClass = "org.yttr.glyph.bot.GlyphKt"
}
}.task.mergeServiceFiles()

Expand All @@ -48,19 +72,20 @@ tasks.named("stage") {
}

dependencies {
implementation(project(":shared"))
implementation(project(":glyph-shared"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$coroutinesVersion")
implementation("ch.qos.logback:logback-classic:$logbackVersion")
implementation("net.dv8tion:JDA:$jdaVersion")
implementation("club.minnced:discord-webhooks:0.5.7")
implementation("com.google.cloud:google-cloud-storage:1.106.0")
implementation("com.google.cloud:google-cloud-dialogflow:1.0.0")
implementation("net.dean.jraw:JRAW:1.0.0")
implementation("net.dean.jraw:JRAW:1.1.0")
implementation("org.ocpsoft.prettytime:prettytime:4.0.4.Final")
implementation("io.ktor:ktor-client-okhttp:$ktorVersion")
implementation("io.ktor:ktor-client-json-jvm:$ktorVersion")
implementation("io.ktor:ktor-client-serialization-jvm:$ktorVersion")
implementation("com.vdurmont:emoji-java:4.0.0")
implementation("net.jodah:expiringmap:0.5.9")
implementation("commons-codec:commons-codec:1.14")
implementation("com.typesafe:config:1.4.1")
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Glyph, a Discord bot that uses natural language instead of commands
* powered by DialogFlow and Kotlin
*
* Copyright (C) 2017-2020 by Ian Moore
* Copyright (C) 2017-2021 by Ian Moore
*
* This file is part of Glyph.
*
Expand All @@ -22,21 +22,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package me.ianmooreis.glyph.bot
package org.yttr.glyph.bot

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.future.await
import me.ianmooreis.glyph.bot.directors.config.ConfigDirector
import me.ianmooreis.glyph.shared.config.server.ServerConfig
import net.dv8tion.jda.api.entities.Guild
import net.dv8tion.jda.api.events.message.MessageReceivedEvent
import net.dv8tion.jda.api.hooks.ListenerAdapter
import net.dv8tion.jda.api.requests.RestAction
import org.apache.commons.codec.digest.DigestUtils
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.yttr.glyph.bot.skills.config.ConfigDirector
import org.yttr.glyph.shared.config.server.ServerConfig
import kotlin.coroutines.CoroutineContext

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Glyph, a Discord bot that uses natural language instead of commands
* powered by DialogFlow and Kotlin
*
* Copyright (C) 2017-2020 by Ian Moore
* Copyright (C) 2017-2021 by Ian Moore
*
* This file is part of Glyph.
*
Expand All @@ -22,61 +22,68 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package me.ianmooreis.glyph.bot
package org.yttr.glyph.bot

import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import io.lettuce.core.RedisClient
import io.lettuce.core.RedisURI
import me.ianmooreis.glyph.bot.ai.AIAgent
import me.ianmooreis.glyph.bot.ai.dialogflow.Dialogflow
import me.ianmooreis.glyph.bot.directors.AuditingDirector
import me.ianmooreis.glyph.bot.directors.StatusDirector
import me.ianmooreis.glyph.bot.directors.config.ConfigDirector
import me.ianmooreis.glyph.bot.directors.servers.BotList
import me.ianmooreis.glyph.bot.directors.servers.ServerDirector
import me.ianmooreis.glyph.bot.directors.skills.SkillDirector
import me.ianmooreis.glyph.bot.directors.starboard.StarboardDirector
import me.ianmooreis.glyph.bot.messaging.MessagingDirector
import me.ianmooreis.glyph.bot.messaging.quickview.QuickviewDirector
import me.ianmooreis.glyph.bot.skills.DoomsdayClockSkill
import me.ianmooreis.glyph.bot.skills.EphemeralSaySkill
import me.ianmooreis.glyph.bot.skills.FallbackSkill
import me.ianmooreis.glyph.bot.skills.FeedbackSkill
import me.ianmooreis.glyph.bot.skills.HelpSkill
import me.ianmooreis.glyph.bot.skills.RankSkill
import me.ianmooreis.glyph.bot.skills.RedditSkill
import me.ianmooreis.glyph.bot.skills.ServerConfigSkill
import me.ianmooreis.glyph.bot.skills.SnowstampSkill
import me.ianmooreis.glyph.bot.skills.SourceSkill
import me.ianmooreis.glyph.bot.skills.StatusSkill
import me.ianmooreis.glyph.bot.skills.TimeSkill
import me.ianmooreis.glyph.bot.skills.creator.ChangeStatusSkill
import me.ianmooreis.glyph.bot.skills.moderation.BanSkill
import me.ianmooreis.glyph.bot.skills.moderation.GuildInfoSkill
import me.ianmooreis.glyph.bot.skills.moderation.KickSkill
import me.ianmooreis.glyph.bot.skills.moderation.PurgeSkill
import me.ianmooreis.glyph.bot.skills.moderation.UserInfoSkill
import me.ianmooreis.glyph.bot.skills.roles.RoleListSkill
import me.ianmooreis.glyph.bot.skills.roles.RoleSetSkill
import me.ianmooreis.glyph.bot.skills.roles.RoleUnsetSkill
import me.ianmooreis.glyph.bot.skills.wiki.WikiSkill
import me.ianmooreis.glyph.shared.redis.RedisAsync
import net.dv8tion.jda.api.requests.GatewayIntent
import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder
import net.dv8tion.jda.api.utils.cache.CacheFlag
import org.yttr.glyph.bot.ai.AIAgent
import org.yttr.glyph.bot.ai.dialogflow.Dialogflow
import org.yttr.glyph.bot.messaging.MessagingDirector
import org.yttr.glyph.bot.messaging.quickview.QuickviewDirector
import org.yttr.glyph.bot.presentation.BotList
import org.yttr.glyph.bot.presentation.ServerDirector
import org.yttr.glyph.bot.presentation.StatusDirector
import org.yttr.glyph.bot.skills.SkillDirector
import org.yttr.glyph.bot.skills.config.ConfigDirector
import org.yttr.glyph.bot.skills.config.ServerConfigSkill
import org.yttr.glyph.bot.skills.creator.ChangeStatusSkill
import org.yttr.glyph.bot.skills.moderation.AuditingDirector
import org.yttr.glyph.bot.skills.moderation.BanSkill
import org.yttr.glyph.bot.skills.moderation.GuildInfoSkill
import org.yttr.glyph.bot.skills.moderation.KickSkill
import org.yttr.glyph.bot.skills.moderation.PurgeSkill
import org.yttr.glyph.bot.skills.moderation.UserInfoSkill
import org.yttr.glyph.bot.skills.play.DoomsdayClockSkill
import org.yttr.glyph.bot.skills.play.EphemeralSaySkill
import org.yttr.glyph.bot.skills.play.RankSkill
import org.yttr.glyph.bot.skills.play.RedditSkill
import org.yttr.glyph.bot.skills.roles.RoleListSkill
import org.yttr.glyph.bot.skills.roles.RoleSetSkill
import org.yttr.glyph.bot.skills.roles.RoleUnsetSkill
import org.yttr.glyph.bot.skills.starboard.StarboardDirector
import org.yttr.glyph.bot.skills.util.FallbackSkill
import org.yttr.glyph.bot.skills.util.FeedbackSkill
import org.yttr.glyph.bot.skills.util.HelpSkill
import org.yttr.glyph.bot.skills.util.SnowstampSkill
import org.yttr.glyph.bot.skills.util.SourceSkill
import org.yttr.glyph.bot.skills.util.StatusSkill
import org.yttr.glyph.bot.skills.util.TimeSkill
import org.yttr.glyph.bot.skills.wiki.WikiSkill
import org.yttr.glyph.shared.pubsub.redis.RedisAsync

/**
* The Glyph object to use when building the client
*/
object Glyph {
/**
* HOCON config from application.conf
*/
val conf: Config = ConfigFactory.load().getConfig("glyph")

/**
* The current version of Glyph
*/
val version: String = System.getenv("HEROKU_RELEASE_VERSION") ?: "?"
val version: String = conf.getString("version")

private val aiAgent: AIAgent = Dialogflow(System.getenv("DIALOGFLOW_CREDENTIALS").byteInputStream())
private val aiAgent: AIAgent = Dialogflow(conf.getString("dialogflow.credentials").byteInputStream())

private val redis: RedisAsync = RedisClient.create().run {
val redisUri = RedisURI.create(System.getenv("REDIS_URL")).apply {
val redisUri = RedisURI.create(conf.getString("data.redis-url")).apply {
// We are using Heroku Redis which is version 5, but for some reason they give us a username.
// However if we supply the username it runs the version 6 command and fails to login.
username = null
Expand All @@ -85,7 +92,7 @@ object Glyph {
}

private val configDirector = ConfigDirector {
databaseConnectionUri = System.getenv("DATABASE_URL")
databaseConnectionUri = conf.getString("data.database-url")
}

private val skillDirector = SkillDirector().addSkill(
Expand Down Expand Up @@ -118,7 +125,7 @@ object Glyph {
*/
fun run() {
val builder = DefaultShardManagerBuilder.createLight(null).also {
val token = System.getenv("DISCORD_TOKEN")
val token = conf.getString("discord-token")

it.setToken(token)

Expand All @@ -131,18 +138,15 @@ object Glyph {
it.enableCache(CacheFlag.EMOTE)

val serverDirector = ServerDirector { id ->
val discordBotList = BotList(
"Discord Bot List",
"https://top.gg/api/bots/$id/stats",
System.getenv("DISCORDBOTLIST_TOKEN")
)
val discordBots = BotList(
"Discord Bots",
"https://bots.discord.pw/api/bots/$id/stats",
System.getenv("DISCORDBOTS_TOKEN")
)

botList(discordBotList, discordBots)
if (conf.hasPath("bot-list.top")) {
val discordBotList = BotList(
"Discord Bot List",
"https://top.gg/api/bots/$id/stats",
conf.getString("bot-list.top")
)

botList(discordBotList)
}
}

val messagingDirector = MessagingDirector(aiAgent, redis, skillDirector)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package me.ianmooreis.glyph.bot.ai
package org.yttr.glyph.bot.ai

/**
* An AI agent that is capable of processing messages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package me.ianmooreis.glyph.bot.ai
package org.yttr.glyph.bot.ai

/**
* Fulfillment data directly from the agent
Expand All @@ -32,4 +32,4 @@ interface AIFulfillment {
* What the agent wants to say
*/
val speech: String
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package me.ianmooreis.glyph.bot.ai
package org.yttr.glyph.bot.ai

/**
* The response from the agent service
Expand All @@ -43,4 +43,4 @@ interface AIResponse {
*/
val result: AIResult

}
}

0 comments on commit db8bc0d

Please sign in to comment.