-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
moved source for core to separate repo
- Loading branch information
1 parent
21ace5e
commit fd86947
Showing
35 changed files
with
1,943 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
name := "slack-scala-bot-core" | ||
|
||
version := "0.1" | ||
|
||
scalaVersion := "2.11.5" | ||
|
||
organization := "io.scalac" | ||
|
||
libraryDependencies ++= { | ||
val akkaVersion = "2.3.9" | ||
Seq( | ||
"org.mockito" % "mockito-core" % "1.10.19", | ||
"com.typesafe.akka" %% "akka-actor" % akkaVersion, | ||
"com.typesafe.akka" %% "akka-slf4j" % akkaVersion, | ||
"com.typesafe.akka" %% "akka-testkit" % akkaVersion % "test", | ||
"io.spray" %% "spray-json" % "1.3.1", | ||
"io.spray" %% "spray-client" % "1.3.1", | ||
"io.spray" %% "spray-can" % "1.3.2", | ||
"com.wandoulabs.akka" %% "spray-websocket" % "0.1.4", | ||
"joda-time" % "joda-time" % "2.7", | ||
"org.joda" % "joda-convert" % "1.7", | ||
"org.scalatest" %% "scalatest" % "2.2.1" % "test", | ||
"log4j" % "log4j" % "1.2.17", | ||
"org.slf4j" % "slf4j-api" % "1.7.5", | ||
"org.slf4j" % "slf4j-log4j12" % "1.7.5", | ||
"org.scala-lang.modules" %% "scala-xml" % "1.0.2", | ||
"org.scala-lang" % "scala-compiler" % "2.10.2", | ||
"org.scala-lang" % "jline" % "2.10.2", | ||
"org.twitter4j" % "twitter4j-core" % "4.0.0", | ||
"com.typesafe.slick" %% "slick" % "2.1.0", | ||
"com.h2database" % "h2" % "1.4.186" | ||
) | ||
} | ||
|
||
resolvers += "spray repo" at "http://repo.spray.io" | ||
|
||
publishTo := Some(Resolver.file("file", new File(Path.userHome.absolutePath+"/.m2/repository"))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> | ||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> | ||
<appender name="console" class="org.apache.log4j.ConsoleAppender"> | ||
<param name="Target" value="System.out"/> | ||
<layout class="org.apache.log4j.PatternLayout"> | ||
<param name="ConversionPattern" value="%d [%-20.20t | %-5p] %c - %m%n"/> | ||
</layout> | ||
</appender> | ||
<root> | ||
<priority value="debug"/> | ||
<appender-ref ref="console"/> | ||
</root> | ||
</log4j:configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package io.scalac.slack | ||
|
||
import akka.actor.{ActorContext, ActorRef} | ||
|
||
trait BotModules { | ||
def registerModules(context: ActorContext, websocketClient: ActorRef): Unit | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package io.scalac.slack | ||
|
||
import com.typesafe.config.ConfigFactory | ||
import io.scalac.slack.api.APIKey | ||
|
||
/** | ||
* Created on 20.01.15 22:17 | ||
*/ | ||
object Config { | ||
def websocketKey: String = config.getString("websocket.key") | ||
|
||
private val config = ConfigFactory.load() | ||
|
||
def apiKey: APIKey = APIKey(config.getString("api.key")) | ||
|
||
def baseUrl(endpoint: String) = config.getString("api.base.url") + endpoint | ||
|
||
def scalaLibraryPath = config.getString("scalaLibraryPath") | ||
|
||
def consumerKey: String = config.getString("twitter.consumerKey") | ||
def consumerKeySecret: String = config.getString("twitter.consumerKeySecret") | ||
def accessToken: String = config.getString("twitter.accessToken") | ||
def accessTokenSecret: String = config.getString("twitter.accessTokenSecret") | ||
def twitterGuardians: String = config.getString("twitter.guardians") | ||
} |
36 changes: 36 additions & 0 deletions
36
src/main/scala/io/scalac/slack/IncomingMessageProcessor.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package io.scalac.slack | ||
|
||
import akka.actor.{Actor, ActorLogging} | ||
import io.scalac.slack.common._ | ||
import spray.json._ | ||
|
||
/** | ||
* Created on 08.02.15 23:36 | ||
* Incoming message processor should parse incoming string | ||
* and change into proper protocol | ||
*/ | ||
class IncomingMessageProcessor(eventBus: MessageEventBus) extends Actor with ActorLogging { | ||
|
||
import io.scalac.slack.common.MessageJsonProtocol._ | ||
|
||
override def receive: Receive = { | ||
|
||
case s: String => | ||
try { | ||
val mType = s.parseJson.convertTo[MessageType] | ||
val incomingMessage: IncomingMessage = mType match { | ||
case MessageType("hello", _) => Hello | ||
case MessageType("pong", _) => Pong | ||
case MessageType("message", None) => s.parseJson.convertTo[BaseMessage] | ||
case _ => | ||
UndefinedMessage(s) | ||
} | ||
eventBus.publish(incomingMessage) | ||
} | ||
catch { | ||
case e : Exception => | ||
eventBus.publish(UndefinedMessage(s)) | ||
} | ||
case ignored => //nothing special | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package io.scalac.slack | ||
|
||
import akka.event.{ActorEventBus, LookupClassification} | ||
import io.scalac.slack.common._ | ||
|
||
/** | ||
* Created on 08.02.15 22:16 | ||
*/ | ||
class MessageEventBus extends ActorEventBus with LookupClassification { | ||
override type Event = MessageEvent | ||
|
||
override type Classifier = MessageEventType | ||
|
||
override protected def mapSize(): Int = 2 | ||
|
||
override protected def publish(event: Event, subscriber: Subscriber): Unit = { | ||
subscriber ! event | ||
} | ||
|
||
override protected def classify(event: Event): Classifier = { | ||
event match { | ||
case im: IncomingMessage => Incoming | ||
case om: OutgoingMessage => Outgoing | ||
case rich: RichOutboundMessage => Outgoing | ||
} | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
src/main/scala/io/scalac/slack/OutgoingMessageProcessor.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package io.scalac.slack | ||
|
||
import akka.actor.{Actor, ActorLogging, ActorRef} | ||
import io.scalac.slack.common._ | ||
import io.scalac.slack.websockets.WebSocket | ||
|
||
/** | ||
* Created on 08.02.15 23:00 | ||
* Outgoing message protocol should change received | ||
* protocol into string and send it to websocket | ||
*/ | ||
class OutgoingMessageProcessor(wsActor: ActorRef, eventBus: MessageEventBus) extends Actor with ActorLogging { | ||
|
||
override def receive: Receive = { | ||
case Ping => | ||
wsActor ! WebSocket.Send(Ping.toJson) | ||
|
||
case msg: OutboundMessage => | ||
wsActor ! WebSocket.Send(msg.toJson) | ||
|
||
case ignored => //nothing else | ||
|
||
} | ||
|
||
@throws[Exception](classOf[Exception]) | ||
override def preStart(): Unit = { | ||
eventBus.subscribe(self, Outgoing) | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
src/main/scala/io/scalac/slack/OutgoingRichMessageProcessor.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package io.scalac.slack | ||
|
||
import akka.actor.{Actor, ActorLogging, ActorRef} | ||
import io.scalac.slack.common._ | ||
|
||
/** | ||
* Created on 08.02.15 23:00 | ||
* | ||
*/ | ||
class OutgoingRichMessageProcessor(apiActor: ActorRef, eventBus: MessageEventBus) extends Actor with ActorLogging { | ||
|
||
override def receive: Receive = { | ||
|
||
case msg: RichOutboundMessage => | ||
if (msg.elements.nonEmpty) | ||
apiActor ! msg //trasport through WebAPI until RTM support begin | ||
|
||
case ignored => //nothing else | ||
|
||
} | ||
|
||
@throws[Exception](classOf[Exception]) | ||
override def preStart(): Unit = { | ||
eventBus.subscribe(self, Outgoing) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package io.scalac.slack | ||
|
||
/** | ||
* Created on 21.01.15 01:23 | ||
*/ | ||
sealed trait SlackError | ||
|
||
object ApiTestError extends SlackError | ||
|
||
//no authentication token provided | ||
object NotAuthenticated extends SlackError | ||
|
||
//invalid auth token | ||
object InvalidAuth extends SlackError | ||
|
||
//token is for deleted user or team | ||
object AccountInactive extends SlackError | ||
|
||
//team is being migrated between servers | ||
object MigrationInProgress extends SlackError | ||
|
||
case class UnspecifiedError(msg: String) extends SlackError | ||
|
||
|
||
object SlackError { | ||
def apply(errorName: String) = { | ||
errorName match { | ||
case "not_authed" => NotAuthenticated | ||
case "invalid_auth" => InvalidAuth | ||
case "account_inactive" => AccountInactive | ||
case "migration_in_progress" => MigrationInProgress | ||
case err => new UnspecifiedError(err) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package io.scalac.slack.api | ||
|
||
/** | ||
* Created on 20.01.15 22:56 | ||
*/ | ||
case class APIKey(key: String){ | ||
override def toString: String = key | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package io.scalac.slack.api | ||
|
||
import akka.actor.{Actor, ActorLogging} | ||
import io.scalac.slack.api.ResponseObject._ | ||
import io.scalac.slack.common.JsonProtocols._ | ||
import io.scalac.slack.common.{Attachment, RichOutboundMessage} | ||
import io.scalac.slack.{ApiTestError, Config, SlackError} | ||
import spray.json._ | ||
|
||
import scala.util.{Failure, Success} | ||
|
||
/** | ||
* Created on 21.01.15 20:32 | ||
*/ | ||
class ApiActor extends Actor with ActorLogging { | ||
|
||
import context.dispatcher | ||
import io.scalac.slack.api.Unmarshallers._ | ||
|
||
override def receive = { | ||
|
||
case ApiTest(param, error) => | ||
log.debug("api.test requested") | ||
val send = sender() | ||
val params = Map("param" -> param, "error" -> error).collect { case (key, Some(value)) => key -> value} | ||
|
||
SlackApiClient.get[ApiTestResponse]("api.test", params) onComplete { | ||
case Success(res) => | ||
if (res.ok) { | ||
send ! Ok(res.args) | ||
} | ||
else { | ||
send ! ApiTestError | ||
} | ||
case Failure(ex) => | ||
send ! ex | ||
|
||
} | ||
|
||
case AuthTest(token) => | ||
log.debug("auth.test requested") | ||
val send = sender() | ||
|
||
SlackApiClient.get[AuthTestResponse]("auth.test", Map("token" -> token.key)) onComplete { | ||
case Success(res) => | ||
|
||
if (res.ok) | ||
send ! AuthData(res) | ||
else | ||
send ! SlackError(res.error.get) | ||
case Failure(ex) => | ||
send ! ex | ||
} | ||
|
||
case RtmStart(token) => | ||
log.debug("rtm.start requested") | ||
val send = sender() | ||
|
||
SlackApiClient.get[RtmStartResponse]("rtm.start", Map("token" -> token.key)) onComplete { | ||
|
||
case Success(res) => | ||
if (res.ok) | ||
send ! RtmData(res.url) | ||
send ! res.self | ||
case Failure(ex) => | ||
send ! ex | ||
} | ||
case msg: RichOutboundMessage => | ||
log.debug("chat.postMessage requested") | ||
|
||
val attachments = msg.elements.filter(_.isValid).map(_.toJson).mkString("[", ",", "]") | ||
val params = Map("token" -> Config.apiKey.key, "channel" -> msg.channel, "as_user" -> "true", "attachments" -> attachments) | ||
|
||
SlackApiClient.post[ChatPostMessageResponse]("chat.postMessage", params) onComplete { | ||
case Success(res) => | ||
if (res.ok) { | ||
log.info("[chat.postMessage]: message delivered: " + res.toString) | ||
} | ||
case Failure(ex) => | ||
log.error("[chat.postMessage] Error encountered - " + ex.getMessage) | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package io.scalac.slack.api | ||
|
||
import spray.http.{HttpMethod, HttpRequest} | ||
import spray.json.JsonReader | ||
|
||
import scala.concurrent.Future | ||
|
||
/** | ||
* Created on 25.01.15 22:22 | ||
*/ | ||
trait ApiClient { | ||
|
||
def request[T <: ResponseObject](method: HttpMethod, endpoint: String, params: Map[String, String] = Map.empty[String, String])(implicit reader: JsonReader[T]): Future[T] | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package io.scalac.slack.api | ||
|
||
/** | ||
* Created on 20.01.15 23:59 | ||
* Messages sends between actors | ||
*/ | ||
sealed trait Message | ||
|
||
case object Start extends Message | ||
case object Stop extends Message | ||
case object RegisterModules extends Message | ||
|
||
//API CALLS | ||
case class ApiTest(param: Option[String] = None, error: Option[String] = None) extends Message | ||
|
||
case class AuthTest(token: APIKey) extends Message | ||
|
||
case class RtmStart(token: APIKey) extends Message | ||
|
||
//API RESPONSES | ||
case class Ok(args: Option[Map[String, String]]) extends Message | ||
|
||
case class AuthData(url: String, team: String, user: String, teamId: String, userId: String) extends Message | ||
|
||
case class RtmData(url: String) | ||
|
||
object AuthData { | ||
def apply(atr: AuthData) = atr | ||
} |
Oops, something went wrong.