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

Commit 193aef0

Browse files
committed
Rework inputs & outputs / prettify xml output
1 parent e5ba4b5 commit 193aef0

File tree

8 files changed

+117
-101
lines changed

8 files changed

+117
-101
lines changed

src/main/scala/org/codeoverflow/chatoverflow/configuration/ConfigurationService.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package org.codeoverflow.chatoverflow.configuration
22

3-
import java.io.File
3+
import java.io.{File, PrintWriter}
44

55
import org.codeoverflow.chatoverflow.WithLogger
66
import org.codeoverflow.chatoverflow.api.io
@@ -10,7 +10,7 @@ import org.codeoverflow.chatoverflow.framework.PluginFramework
1010
import org.codeoverflow.chatoverflow.instance.PluginInstanceRegistry
1111
import org.codeoverflow.chatoverflow.registry.TypeRegistry
1212

13-
import scala.xml.{Elem, Node}
13+
import scala.xml.{Elem, Node, PrettyPrinter}
1414

1515
/**
1616
* The configuration service provides methods to work with serialized state information.
@@ -153,7 +153,9 @@ class ConfigurationService(val configFilePath: String) extends WithLogger {
153153
* Saves the xml content to the config xml.
154154
*/
155155
private def saveXML(xmlContent: Node): Unit = {
156-
xml.XML.save(configFilePath, xmlContent)
156+
val writer = new PrintWriter(configFilePath)
157+
writer.print(new PrettyPrinter(120,2).format(xmlContent))
158+
writer.close()
157159
logger info "Saved config file."
158160
}
159161

src/main/scala/org/codeoverflow/chatoverflow/requirement/InputImpl.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import org.codeoverflow.chatoverflow.WithLogger
44
import org.codeoverflow.chatoverflow.api.io.input.Input
55
import org.codeoverflow.chatoverflow.connector.Connector
66

7-
import scala.collection.mutable
7+
import scala.reflect.ClassTag
88

9-
abstract class InputImpl[C <: Connector] extends Connection[C] with Input with WithLogger {
9+
abstract class InputImpl[C <: Connector](implicit ct: ClassTag[C]) extends Connection[C] with Input with WithLogger {
1010

1111
/**
1212
* Inits this connection, checks if teh source connector is defined, and can be inited, then calls start

src/main/scala/org/codeoverflow/chatoverflow/requirement/OutputImpl.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import org.codeoverflow.chatoverflow.WithLogger
44
import org.codeoverflow.chatoverflow.api.io.output.Output
55
import org.codeoverflow.chatoverflow.connector.Connector
66

7-
import scala.collection.mutable
7+
import scala.reflect.ClassTag
88

9-
abstract class OutputImpl[C <: Connector] extends Connection[C] with Output with WithLogger {
9+
abstract class OutputImpl[C <: Connector](implicit ct: ClassTag[C]) extends Connection[C] with Output with WithLogger {
1010

1111
/**
1212
* Inits this connection, checks if teh source connector is defined, and can be inited, then calls start

src/main/scala/org/codeoverflow/chatoverflow/requirement/service/discord/impl/DiscordChatInputImpl.scala

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import scala.collection.mutable.ListBuffer
2222
@Impl(impl = classOf[DiscordChatInput], connector = classOf[DiscordChatConnector])
2323
class DiscordChatInputImpl extends InputImpl[DiscordChatConnector] with DiscordChatInput with WithLogger {
2424

25-
private var channelId = getSourceIdentifier
25+
private var channelId: Option[String] = None
2626
private val messages: ListBuffer[DiscordChatMessage] = ListBuffer[DiscordChatMessage]()
2727
private val privateMessages: ListBuffer[DiscordChatMessage] = ListBuffer[DiscordChatMessage]()
2828
private val messageHandler = ListBuffer[Consumer[DiscordChatMessage]]()
@@ -33,7 +33,6 @@ class DiscordChatInputImpl extends InputImpl[DiscordChatConnector] with DiscordC
3333
private val privateMessageDeleteHandler = ListBuffer[Consumer[DiscordChatMessage]]()
3434

3535
override def start(): Boolean = {
36-
setChannel(getSourceIdentifier)
3736
sourceConnector.get.addMessageReceivedListener(onMessage)
3837
sourceConnector.get.addMessageUpdateListener(onMessageUpdate)
3938
sourceConnector.get.addMessageDeleteListener(onMessageDelete)
@@ -47,15 +46,17 @@ class DiscordChatInputImpl extends InputImpl[DiscordChatConnector] with DiscordC
4746
*/
4847
private def onMessage(event: MessageReceivedEvent): Unit = {
4948
if (event.getMessage.getType == MessageType.DEFAULT) {
50-
val message = DiscordChatInputImpl.parse(event.getMessage)
51-
event.getChannelType match {
52-
case ChannelType.TEXT if event.getTextChannel.getId == channelId =>
53-
messageHandler.foreach(_.accept(message))
54-
messages += message
55-
case ChannelType.PRIVATE =>
56-
privateMessageHandler.foreach(_.accept(message))
57-
privateMessages += message
58-
case _ => //Unknown channel, do nothing
49+
if (channelId.isDefined) {
50+
val message = DiscordChatInputImpl.parse(event.getMessage)
51+
event.getChannelType match {
52+
case ChannelType.TEXT if event.getTextChannel.getId == channelId.get =>
53+
messageHandler.foreach(_.accept(message))
54+
messages += message
55+
case ChannelType.PRIVATE =>
56+
privateMessageHandler.foreach(_.accept(message))
57+
privateMessages += message
58+
case _ => //Unknown channel, do nothing
59+
}
5960
}
6061
}
6162
}
@@ -94,20 +95,22 @@ class DiscordChatInputImpl extends InputImpl[DiscordChatConnector] with DiscordC
9495
* @param event a event with an deleted message
9596
*/
9697
private def onMessageDelete(event: MessageDeleteEvent): Unit = {
97-
val id = event.getMessageId
98-
event.getChannelType match {
99-
case ChannelType.TEXT if event.getTextChannel.getId == channelId =>
100-
val i = messages.indexWhere(_.getId == id)
101-
if (i != -1) {
102-
val oldMessage = messages.remove(i)
103-
messageDeleteHandler.foreach(_.accept(oldMessage))
104-
}
105-
case ChannelType.PRIVATE =>
106-
val i = privateMessages.indexWhere(_.getId == id)
107-
if (i != -1) {
108-
val oldMessage = privateMessages.remove(i)
109-
privateMessageDeleteHandler.foreach(_.accept(oldMessage))
110-
}
98+
if (channelId.isDefined) {
99+
val id = event.getMessageId
100+
event.getChannelType match {
101+
case ChannelType.TEXT if event.getTextChannel.getId == channelId.get =>
102+
val i = messages.indexWhere(_.getId == id)
103+
if (i != -1) {
104+
val oldMessage = messages.remove(i)
105+
messageDeleteHandler.foreach(_.accept(oldMessage))
106+
}
107+
case ChannelType.PRIVATE =>
108+
val i = privateMessages.indexWhere(_.getId == id)
109+
if (i != -1) {
110+
val oldMessage = privateMessages.remove(i)
111+
privateMessageDeleteHandler.foreach(_.accept(oldMessage))
112+
}
113+
}
111114
}
112115
}
113116

@@ -122,26 +125,35 @@ class DiscordChatInputImpl extends InputImpl[DiscordChatConnector] with DiscordC
122125

123126
privateMessages.filter(_.getTimestamp > currentTime - lastMilliseconds).toList.asJava
124127
}
125-
override def registerMessageHandler(handler: Consumer[DiscordChatMessage]): Unit = messageHandler += handler
128+
override def registerMessageHandler(handler: Consumer[DiscordChatMessage]): Unit = {
129+
if (channelId.isEmpty) throw new IllegalStateException("first set the channel for this input")
130+
messageHandler += handler
131+
}
126132

127133
override def registerPrivateMessageHandler(handler : Consumer[DiscordChatMessage]): Unit = privateMessageHandler += handler
128134

129-
override def registerMessageEditHandler(handler: BiConsumer[DiscordChatMessage, DiscordChatMessage]): Unit = messageEditHandler += handler
135+
override def registerMessageEditHandler(handler: BiConsumer[DiscordChatMessage, DiscordChatMessage]): Unit = {
136+
if (channelId.isEmpty) throw new IllegalStateException("first set the channel for this input")
137+
messageEditHandler += handler
138+
}
130139

131140
override def registerPrivateMessageEditHandler(handler: BiConsumer[DiscordChatMessage, DiscordChatMessage]): Unit = privateMessageEditHandler += handler
132141

133-
override def registerMessageDeleteHandler(handler: Consumer[DiscordChatMessage]): Unit = messageDeleteHandler += handler
142+
override def registerMessageDeleteHandler(handler: Consumer[DiscordChatMessage]): Unit = {
143+
if (channelId.isEmpty) throw new IllegalStateException("first set the channel for this input")
144+
messageDeleteHandler += handler
145+
}
134146

135147
override def registerPrivateMessageDeleteHandler(handler: Consumer[DiscordChatMessage]): Unit = privateMessageDeleteHandler += handler
136148

137149
override def setChannel(channelId: String): Unit = {
138150
sourceConnector.get.getTextChannel(channelId) match {
139-
case Some(_) => this.channelId = channelId
151+
case Some(_) => this.channelId = Some(channelId.trim)
140152
case None => throw new IllegalArgumentException("Channel with that id doesn't exist")
141153
}
142154
}
143155

144-
override def getChannelId: String = channelId
156+
override def getChannelId: String = channelId.get
145157

146158
override def getMessage(messageId: String): DiscordChatMessage =
147159
messages.find(_.getId == messageId).getOrElse(privateMessages.find(_.getId == messageId).orNull)

src/main/scala/org/codeoverflow/chatoverflow/requirement/service/discord/impl/DiscordChatOutputImpl.scala

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,30 @@ package org.codeoverflow.chatoverflow.requirement.service.discord.impl
33
import org.codeoverflow.chatoverflow.WithLogger
44
import org.codeoverflow.chatoverflow.api.io.output.chat.DiscordChatOutput
55
import org.codeoverflow.chatoverflow.registry.Impl
6-
import org.codeoverflow.chatoverflow.requirement.Connection
6+
import org.codeoverflow.chatoverflow.requirement.OutputImpl
77
import org.codeoverflow.chatoverflow.requirement.service.discord.DiscordChatConnector
88

99
/**
1010
* This is the implementation of the discord chat output, using the discord connector.
1111
*/
1212
@Impl(impl = classOf[DiscordChatOutput], connector = classOf[DiscordChatConnector])
13-
class DiscordChatOutputImpl extends Connection[DiscordChatConnector] with DiscordChatOutput with WithLogger {
13+
class DiscordChatOutputImpl extends OutputImpl[DiscordChatConnector] with DiscordChatOutput with WithLogger {
1414

15-
private var channelId: String = _
15+
private var channelId: Option[String] = None
1616

17+
override def start(): Boolean = true
1718

1819
override def setChannel(channelId: String): Unit = {
1920
sourceConnector.get.getTextChannel(channelId) match {
20-
case Some(_) => this.channelId = channelId
21+
case Some(_) => this.channelId = Some(channelId.trim)
2122
case None => throw new IllegalArgumentException("Channel with that id doesn't exist")
2223
}
2324
}
2425

25-
override def getChannelId: String = channelId
26+
override def getChannelId: String = channelId.get
2627

27-
override def init(): Boolean = {
28-
if (sourceConnector.isDefined) {
29-
if (sourceConnector.get.isRunning || sourceConnector.get.init()) {
30-
setChannel(getSourceIdentifier)
31-
true
32-
} else false
33-
} else {
34-
logger warn "Source Connector not set."
35-
false
36-
}
37-
}
38-
39-
override def sendChatMessage(message: String): Unit = sourceConnector.get.sendChatMessage(channelId, message)
40-
41-
override def serialize(): String = getSourceIdentifier
42-
43-
override def deserialize(value: String): Unit = {
44-
setSourceConnector(value)
28+
override def sendChatMessage(message: String): Unit = {
29+
val channel = channelId.getOrElse(throw new IllegalStateException("first set the channel for this output"))
30+
sourceConnector.get.sendChatMessage(channel, message)
4531
}
4632
}

src/main/scala/org/codeoverflow/chatoverflow/requirement/service/twitch/chat/TwitchChatConnector.scala

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import org.pircbotx.cap.EnableCapHandler
66
import org.pircbotx.hooks.events.{MessageEvent, UnknownEvent}
77
import org.pircbotx.{Configuration, PircBotX}
88

9+
import scala.collection.mutable.ListBuffer
10+
911
/**
1012
* The twitch connector connects to the irc service to work with chat messages.
1113
*
@@ -17,7 +19,7 @@ class TwitchChatConnector(override val sourceIdentifier: String) extends Connect
1719
override protected var requiredCredentialKeys: List[String] = List(oauthKey)
1820
override protected var optionalCredentialKeys: List[String] = List()
1921
private var bot: PircBotX = _
20-
private var currentChannel: String = _
22+
private val channels = ListBuffer[String]()
2123

2224
def addMessageEventListener(listener: MessageEvent => Unit): Unit = {
2325
twitchChatListener.addMessageEventListener(listener)
@@ -27,24 +29,19 @@ class TwitchChatConnector(override val sourceIdentifier: String) extends Connect
2729
twitchChatListener.addUnknownEventListener(listener)
2830
}
2931

30-
def setChannel(channel: String): Unit = {
31-
// Todo: Leave channel
32-
setCurrentChannel(channel)
33-
bot.send().joinChannel(currentChannel)
34-
// TODO: TEST!
32+
def joinChannel(channel: String): Unit = {
33+
bot.send().joinChannel(channel)
34+
channels += channel
3535
}
3636

37-
private def setCurrentChannel(channel: String): Unit = {
38-
if (channel.startsWith("#")) {
39-
currentChannel = channel.toLowerCase
40-
} else {
41-
currentChannel = "#" + channel.toLowerCase
42-
}
43-
}
37+
def isJoined(channel: String): Boolean = channels.contains(channel)
4438

4539
override def getUniqueTypeString: String = this.getClass.getName
4640

47-
def sendChatMessage(chatMessage: String): Unit = bot.send().message(currentChannel, chatMessage)
41+
def sendChatMessage(channel: String, chatMessage: String): Unit = {
42+
if (!isJoined(channel)) throw new IllegalArgumentException(s"you must join the '$channel' channel, before you can send messages to it")
43+
bot.send().message(channel, chatMessage)
44+
}
4845

4946
private def getConfig: Configuration = {
5047

@@ -56,8 +53,6 @@ class TwitchChatConnector(override val sourceIdentifier: String) extends Connect
5653
logger warn s"key '$oauthKey' not found in credentials for '$sourceIdentifier'."
5754
}
5855

59-
setCurrentChannel(sourceIdentifier)
60-
6156
new Configuration.Builder()
6257
.setAutoNickChange(false)
6358
.setOnJoinWhoEnabled(false)
@@ -67,7 +62,6 @@ class TwitchChatConnector(override val sourceIdentifier: String) extends Connect
6762
.addServer("irc.chat.twitch.tv")
6863
.setName(credentials.get.credentialsIdentifier)
6964
.setServerPassword(password.getOrElse(""))
70-
.addAutoJoinChannel(currentChannel)
7165
.addListener(twitchChatListener)
7266
.buildConfiguration()
7367
} else {

src/main/scala/org/codeoverflow/chatoverflow/requirement/service/twitch/chat/impl/TwitchChatInputImpl.scala

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,35 +30,39 @@ class TwitchChatInputImpl extends InputImpl[chat.TwitchChatConnector] with Twitc
3030
private val messageHandler = ListBuffer[Consumer[TwitchChatMessage]]()
3131
private val privateMessageHandler = ListBuffer[Consumer[TwitchChatMessage]]()
3232

33+
private var currentChannel: Option[String] = None
34+
3335
override def start(): Boolean = {
3436
sourceConnector.get.addMessageEventListener(onMessage)
3537
sourceConnector.get.addUnknownEventListener(onUnknown)
3638
true
3739
}
3840

3941
private def onMessage(event: MessageEvent): Unit = {
40-
val message = event.getMessage
41-
val color = if (event.getV3Tags.get("color").contains("#")) event.getV3Tags.get("color") else ""
42-
val subscriber = event.getV3Tags.get("subscriber") == "1"
43-
val moderator = event.getV3Tags.get("mod") == "1"
44-
val broadcaster = event.getV3Tags.get("badges").contains("broadcaster/1")
45-
val turbo = event.getV3Tags.get("badges").contains("turbo/1")
46-
val author = new TwitchChatMessageAuthor(event.getUser.getNick,color, broadcaster, moderator, subscriber, turbo)
47-
val channel = new Channel(event.getChannelSource)
48-
val emoticons = new java.util.ArrayList[ChatEmoticon]()
49-
wholeEmoticonRegex.findAllMatchIn(event.getV3Tags.get("emotes")).foreach(matchedElement => {
50-
val id = matchedElement.group(1)
51-
emoticonRegex.findAllMatchIn(matchedElement.group(2)).foreach(matchedElement => {
52-
val index = matchedElement.group(1).toInt
53-
val regex = message.substring(index, matchedElement.group(2).toInt + 1)
54-
val emoticon = new TwitchChatEmoticon(regex, id, index)
55-
emoticons.add(emoticon)
42+
if (currentChannel.isDefined && event.getChannelSource == currentChannel.get) {
43+
val message = event.getMessage
44+
val color = if (event.getV3Tags.get("color").contains("#")) event.getV3Tags.get("color") else ""
45+
val subscriber = event.getV3Tags.get("subscriber") == "1"
46+
val moderator = event.getV3Tags.get("mod") == "1"
47+
val broadcaster = event.getV3Tags.get("badges").contains("broadcaster/1")
48+
val turbo = event.getV3Tags.get("badges").contains("turbo/1")
49+
val author = new TwitchChatMessageAuthor(event.getUser.getNick, color, broadcaster, moderator, subscriber, turbo)
50+
val channel = new Channel(event.getChannelSource)
51+
val emoticons = new java.util.ArrayList[ChatEmoticon]()
52+
wholeEmoticonRegex.findAllMatchIn(event.getV3Tags.get("emotes")).foreach(matchedElement => {
53+
val id = matchedElement.group(1)
54+
emoticonRegex.findAllMatchIn(matchedElement.group(2)).foreach(matchedElement => {
55+
val index = matchedElement.group(1).toInt
56+
val regex = message.substring(index, matchedElement.group(2).toInt + 1)
57+
val emoticon = new TwitchChatEmoticon(regex, id, index)
58+
emoticons.add(emoticon)
59+
})
5660
})
57-
})
58-
val msg = new TwitchChatMessage(author, message, event.getTimestamp, channel, emoticons)
61+
val msg = new TwitchChatMessage(author, message, event.getTimestamp, channel, emoticons)
5962

60-
messageHandler.foreach(consumer => consumer.accept(msg))
61-
messages += msg
63+
messageHandler.foreach(consumer => consumer.accept(msg))
64+
messages += msg
65+
}
6266
}
6367

6468
private def onUnknown(event: UnknownEvent): Unit = {
@@ -76,6 +80,7 @@ class TwitchChatInputImpl extends InputImpl[chat.TwitchChatConnector] with Twitc
7680
}
7781

7882
override def getLastMessages(lastMilliseconds: Long): java.util.List[TwitchChatMessage] = {
83+
if (currentChannel.isEmpty) throw new IllegalStateException("first set the channel for this input")
7984
val currentTime = Calendar.getInstance.getTimeInMillis
8085

8186
messages.filter(_.getTimestamp > currentTime - lastMilliseconds).toList.asJava
@@ -88,10 +93,15 @@ class TwitchChatInputImpl extends InputImpl[chat.TwitchChatConnector] with Twitc
8893
privateMessages.filter(_.getTimestamp > currentTime - lastMilliseconds).toList.asJava
8994
}
9095

91-
override def registerMessageHandler(handler: Consumer[TwitchChatMessage]): Unit = messageHandler += handler
96+
override def registerMessageHandler(handler: Consumer[TwitchChatMessage]): Unit = {
97+
if (currentChannel.isEmpty) throw new IllegalStateException("first set the channel for this input")
98+
messageHandler += handler
99+
}
92100

93101
override def registerPrivateMessageHandler(handler: Consumer[TwitchChatMessage]): Unit = privateMessageHandler += handler
94102

95-
override def setChannel(channel: String): Unit = sourceConnector.get.setChannel(channel)
96-
103+
override def setChannel(channel: String): Unit = {
104+
currentChannel = Some(channel.trim)
105+
if (!sourceConnector.get.isJoined(channel.trim)) sourceConnector.get.joinChannel(channel.trim)
106+
}
97107
}

0 commit comments

Comments
 (0)