Skip to content
This repository has been archived by the owner on Aug 18, 2020. It is now read-only.

Commit

Permalink
Started refactoring. Changed framework structure. Added credential se…
Browse files Browse the repository at this point in the history
…rvice.
  • Loading branch information
sebinside committed Jul 23, 2018
1 parent a2a4398 commit dfdf51c
Show file tree
Hide file tree
Showing 26 changed files with 403 additions and 226 deletions.
46 changes: 46 additions & 0 deletions credentials.xml
@@ -0,0 +1,46 @@
<credentials>
<entry>
<type>
codeoverflow.youtube.login
</type>
<identifier>
sebinside
</identifier>
<values>
<entry>
<key>
a key
</key>
<value>
a value
</value>
</entry>
</values>
</entry>
<entry>
<type>
codeoverflow.twitch.api
</type>
<identifier>
skate702
</identifier>
<values>
<entry>
<key>
apiKey
</key>
<value>
oauth:xxx
</value>
</entry>
<entry>
<key>
anotherKey
</key>
<value>
xyz
</value>
</entry>
</values>
</entry>
</credentials>
2 changes: 1 addition & 1 deletion src/main/scala/ScalatraBootstrap.scala
@@ -1,5 +1,5 @@
import javax.servlet.ServletContext
import org.codeoverflow.chatoverflow.web.rest.PluginExampleServerlet
import org.codeoverflow.chatoverflow.ui.web.rest.PluginExampleServerlet
import org.scalatra._

/**
Expand Down
59 changes: 37 additions & 22 deletions src/main/scala/org/codeoverflow/chatoverflow/ChatOverflow.scala
Expand Up @@ -5,21 +5,23 @@ import java.security.Policy
import org.apache.log4j.Logger
import org.codeoverflow.chatoverflow.api.io.input.chat.TwitchChatInput
import org.codeoverflow.chatoverflow.api.plugin.configuration.{ParameterRequirement, SourceRequirement}
import org.codeoverflow.chatoverflow.config.Configuration
import org.codeoverflow.chatoverflow.framework.{PluginFramework, PluginId, PluginManagerImpl, SandboxSecurityPolicy}
import org.codeoverflow.chatoverflow.io.connector.{TwitchConnector, TwitchCredentials}
import org.codeoverflow.chatoverflow.io.input.chat.TwitchChatInputImpl
import org.codeoverflow.chatoverflow.registry.{ConnectorRegistry, PluginRegistry}
import org.codeoverflow.chatoverflow.config.{ConfigurationService, CredentialsService}
import org.codeoverflow.chatoverflow.framework.{PluginFramework, PluginManagerImpl, SandboxSecurityPolicy}
import org.codeoverflow.chatoverflow.registry.PluginInstanceRegistry
//import org.codeoverflow.chatoverflow.service.twitch.TwitchConnector
//import org.codeoverflow.chatoverflow.service.twitch.impl.TwitchChatInputImpl

object ChatOverflow {

val pluginFolderPath = "plugins/"
val configFolderPath = "config/"
val credentialsFilePath = "credentials.xml"
private val logger = Logger.getLogger(this.getClass)

private var pluginFramework: PluginFramework = _
private var pluginRegistry: PluginRegistry = _
private var configuration: Configuration = _
private var pluginRegistry: PluginInstanceRegistry = _
private var configurationService: ConfigurationService = _
private var credentialsService: CredentialsService = _

def main(args: Array[String]): Unit = {
println("Minzig!")
Expand All @@ -28,8 +30,21 @@ object ChatOverflow {
// Initialize chat overflow plugin framework
init()

// Add all configured plugins to the plugin registry
loadPlugins()
// Add all configured plugin instances to the plugin registry
loadPluginInstances()

// Play with some credentials
credentialsService = new CredentialsService(credentialsFilePath, "test123".toCharArray)
/*val cred1 = new Credentials("skate702")
cred1.addValue("apiKey", "oauth:xxx")
cred1.addValue("anotherKey", "xyz")
val cred2 = new Credentials("sebinside")
cred2.addValue("a key", "a value")
credentialsService.addCredentials("codeoverflow.twitch.api", cred1)
credentialsService.addCredentials("codeoverflow.youtube.login", cred2)*/
credentialsService.load()
println(credentialsService.getCredentials("codeoverflow.twitch.api", "skate702").get.getValue("apiKey"))
//credentialsService.save()

// Testing
System.exit(0)
Expand All @@ -39,19 +54,19 @@ object ChatOverflow {
// This code will be executed when you create a new service in the list with given credentials
// Either standalone or when needed from a created plugin
val sourceId = "skate702"
val connector = new TwitchConnector(sourceId, TwitchCredentials("skate702", "oauth:xxxx"))
ConnectorRegistry.addConnector(connector)
//val connector = new TwitchConnector(sourceId, TwitchCredentials("skate702", "oauth:xxxx"))
//ConnectorRegistry.addConnector(connector)

// Put shit together (kinda hacky)
// This code will be executed during plugin configuration. This connects the connector with the plugin input
val config = pluginRegistry.getConfiguration("supercoolinstance1")
config.getInputs.forEach((_, value) => {
value match {
case value: SourceRequirement[TwitchChatInput] =>
val input = new TwitchChatInputImpl
input.setSource(sourceId)
input.init()
value.setSource(input)
//val input = new TwitchChatInputImpl
//input.setSource(sourceId)
//input.init()
//value.setSource(input)
}
})
config.getParameters.forEach((_, value) => {
Expand All @@ -71,7 +86,7 @@ object ChatOverflow {
// Create plugin framework, registry and manager instance
val pluginManager = new PluginManagerImpl
pluginFramework = PluginFramework(pluginFolderPath)
pluginRegistry = new PluginRegistry(pluginManager)
pluginRegistry = new PluginInstanceRegistry(pluginManager)

// Create sandbox environment for plugins
Policy.setPolicy(new SandboxSecurityPolicy)
Expand All @@ -87,24 +102,24 @@ object ChatOverflow {
}

// Load Configuration
configuration = new Configuration(configFolderPath)
configuration.load()
configurationService = new ConfigurationService(configFolderPath)
configurationService.load()
logger info s"Loaded configuration from '$configFolderPath'."

logger debug "Finished init phase."
}

def loadPlugins(): Unit = {
def loadPluginInstances(): Unit = {
logger info "Loading plugins from config file."

for (pluginInstance <- configuration.pluginInstances) {
for (pluginInstance <- configurationService.pluginInstances) {

val pluggable = pluginFramework.getPluggable(PluginId(pluginInstance.pluginName, pluginInstance.pluginAuthor))
val pluggable = pluginFramework.getPluggable(pluginInstance.pluginName, pluginInstance.pluginAuthor)

pluggable match {
case Some(p) =>
logger info s"Loaded plugin config $pluginInstance."
pluginRegistry.addPlugin(pluginInstance.instanceName, p)
pluginRegistry.addPluginInstance(pluginInstance.instanceName, p)
case None => logger debug s"Unable to load plugin config $pluginInstance. Plugin not found."
}
}
Expand Down

This file was deleted.

@@ -1,37 +1,30 @@
package org.codeoverflow.chatoverflow.config

import java.io.File

class Configuration(val configDirectoryPath: String) {
val configFile = s"$configDirectoryPath/config.xml"

var pluginInstances: Seq[PluginInstanceConfigEntry] = Seq[PluginInstanceConfigEntry]()

def load(): Unit = {

// Create file if non existent
if (!new File(configFile).exists()) {
save()
}

val xmlContent = xml.Utility.trim(xml.XML.loadFile(configFile))

pluginInstances = for (pluginInstance <- xmlContent \ "pluginInstances" \ "_") yield
new PluginInstanceConfigEntry(pluginInstance)

}

def save(): Unit = {

val xmlContent =
<config>
<pluginInstances>
{for (pluginInstance <- pluginInstances) yield pluginInstance.toXml}
</pluginInstances>
</config>

xml.XML.save(configFile, xmlContent)

}

}
import scala.xml.{Elem, Node}

trait Configuration {
def toXml: xml.Elem
}

case class PluginInstance(pluginName: String, pluginAuthor: String, instanceName: String) extends Configuration {
override def toXml: Elem =
<pluginInstance>
<pluginName>
{pluginName}
</pluginName>
<pluginAuthor>
{pluginAuthor}
</pluginAuthor>
<instanceName>
{instanceName}
</instanceName>
</pluginInstance>

def this(xmlNode: Node) = this(
(xmlNode \ "pluginName").text,
(xmlNode \ "pluginAuthor").text,
(xmlNode \ "instanceName").text)

}

// Insert new config options here
@@ -0,0 +1,41 @@
package org.codeoverflow.chatoverflow.config

import java.io.File

class ConfigurationService(val configDirectoryPath: String) {
val configFile = s"$configDirectoryPath/config.xml"

var pluginInstances: Seq[PluginInstance] = Seq[PluginInstance]()

def load(): Unit = {

// Create file if non existent
if (!new File(configFile).exists()) {
save()
}

val xmlContent = xml.Utility.trim(xml.XML.loadFile(configFile))

pluginInstances = for (node <- xmlContent \ "pluginInstances" \ "_") yield
new PluginInstance(node)

// Insert new config options here

}

def save(): Unit = {

val xmlContent =
<config>
<pluginInstances>
{for (pluginInstance <- pluginInstances) yield pluginInstance.toXml}
</pluginInstances>
</config>

// Insert new config options here

xml.XML.save(configFile, xmlContent)

}

}
@@ -0,0 +1,65 @@
package org.codeoverflow.chatoverflow.config

import java.io.File

import org.codeoverflow.chatoverflow.service.Credentials

import scala.collection.mutable

class CredentialsService(val credentialsFilePath: String, password: Array[Char]) {
private val credentials = mutable.Map[(String, String), Credentials]()

def load(): Unit = {

// Create file if non existent
if (!new File(credentialsFilePath).exists()) {
save()
}

// TODO: Decrypt
val xmlContent = xml.Utility.trim(xml.XML.loadFile(credentialsFilePath))

credentials.clear()

for (node <- xmlContent \ "entry") {
val credentialsType = (node \ "type").text
val credentialsIdentifier = (node \ "identifier").text

val entry = new Credentials(credentialsIdentifier)
entry.fromXML(node \ "values")

credentials += (credentialsType, credentialsIdentifier) -> entry
}
}

def save(): Unit = {

val xmlContent =
<credentials>
{for (entry <- credentials.toList) yield {
<entry>
<type>
{entry._1._1}
</type>
<identifier>
{entry._1._2}
</identifier>{entry._2.toXML}
</entry>
}}
</credentials>

// TODO: Encrypt
xml.XML.save(credentialsFilePath, xmlContent)

}

def getCredentials(credentialsType: String, credentialsIdentifier: String): Option[Credentials] =
credentials.get((credentialsType, credentialsIdentifier))

def addCredentials(credentialsType: String, credentials: Credentials): Unit =
this.credentials += (credentialsType, credentials.credentialsIdentifier) -> credentials

def removeCredentials(credentialsType: String, credentialsIdentifier: String): Unit =
credentials -= ((credentialsType, credentialsIdentifier))

}

0 comments on commit dfdf51c

Please sign in to comment.