Skip to content

Commit

Permalink
Added spam-list functionality to the link listener for things that sh…
Browse files Browse the repository at this point in the history
…ould not be sent to the channel.
  • Loading branch information
CO2-Codes committed Nov 29, 2021
1 parent bc42e4b commit 2f8217b
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 36 deletions.
18 changes: 9 additions & 9 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name := "Scala-IRC-bot"

ThisBuild / version := "1.2.0"

scalaVersion := "3.0.0"
scalaVersion := "3.1.0"

scalacOptions ++= Seq(
"-deprecation", // Emit warning and location for usages of deprecated APIs.
Expand All @@ -24,16 +24,16 @@ lazy val ircBot = project.in(file("."))
libraryDependencies ++= Seq(
// Use snapshot to prevent an issue with incompatible transitive dependencies.
"com.github.pircbotx" % "pircbotx" % "master-SNAPSHOT",
"com.github.pureconfig" %% "pureconfig-core" % "0.16.0",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"com.typesafe.akka" %% "akka-http" % "10.2.4" cross CrossVersion.for3Use2_13,
"com.typesafe.akka" %% "akka-actor" % "2.6.15" cross CrossVersion.for3Use2_13,
"com.typesafe.akka" %% "akka-stream" % "2.6.15" cross CrossVersion.for3Use2_13,
"com.github.pureconfig" %% "pureconfig-core" % "0.17.1",
"ch.qos.logback" % "logback-classic" % "1.2.7",
"com.typesafe.akka" %% "akka-http" % "10.2.7" cross CrossVersion.for3Use2_13,
"com.typesafe.akka" %% "akka-actor" % "2.6.17" cross CrossVersion.for3Use2_13,
"com.typesafe.akka" %% "akka-stream" % "2.6.17" cross CrossVersion.for3Use2_13,
"org.apache.commons" % "commons-text" % "1.9",
"com.danielasfregola" %% "twitter4s" % "7.0" cross CrossVersion.for3Use2_13,
"com.google.api-client" % "google-api-client" % "1.32.1",
"com.google.apis" % "google-api-services-youtube" % "v3-rev20210624-1.32.1",
"org.scalatest" %% "scalatest" % "3.2.9" % "test",
"com.google.api-client" % "google-api-client" % "1.32.2",
"com.google.apis" % "google-api-services-youtube" % "v3-rev20210915-1.32.1",
"org.scalatest" %% "scalatest" % "3.2.10" % "test",
),
)
.settings(assembly / test := {})
Expand Down
2 changes: 2 additions & 0 deletions example.conf
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ link-listener {

youtube-api-key = "" // Optional, if set, tries to parse youtube link titles using the youtube API which seems more stable than the website

spam-list = ["bad words", "other bad words"] // Case insensitive list of terms that, when they appear in a title, are never sent to the channel. Optional

use-http-proxy = true // Optional, if set, will use the default akka http proxy settings for all non-youtube/non-twitter http requests

// Additionally, akka needs to be told the proxy server's host and port.
Expand Down
2 changes: 1 addition & 1 deletion project/assembly.sbt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.0.0")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.1.0")
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.5.3")
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.5.4
sbt.version=1.5.5
48 changes: 33 additions & 15 deletions src/main/scala/codes/co2/ircbot/config/BotConfiguration.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ case class LinkListenerConfig(
twitterApi: Option[TwitterApi],
youtubeApiKey: Option[String],
useHttpProxy: Option[Boolean],
) derives ConfigReader
spamList: Option[Seq[String]],
) derives ConfigReader {
val lowerCaseSpamList = spamList.map(_.map(_.toLowerCase)).getOrElse(Seq.empty)
}

case class AdminListenerConfig(helpText: String, puppetMasters: Option[Seq[String]]) derives ConfigReader

Expand All @@ -59,23 +62,38 @@ object BotConfiguration {

def loadLinkListenerConfig(path: Path): LinkListenerConfig = ConfigSource.default(ConfigSource.file(path))
.at("link-listener").load[LinkListenerConfig]
.fold(failures => {
log.info(s"Could not load link-listener config, reason ${failures.toList.map(_.description)} Using default config.")
LinkListenerConfig(None, None, None, None)
}, success => success)
.fold(
failures => {
log.info(
s"Could not load link-listener config, reason ${failures.toList.map(_.description)} Using default config."
)
LinkListenerConfig(None, None, None, None, None)
},
success => success,
)

def loadAdminListenerConfig(path: Path): AdminListenerConfig = ConfigSource.default(ConfigSource.file(path))
.at("admin-listener").load[AdminListenerConfig]
.fold(failures => {
log.info(s"Could not load admin-listener config, reason ${failures.toList.map(_.description)} Using default config.")
AdminListenerConfig("", None)
}, success => success)

def loadPronounListenerConfig(path: Path): PronounListenerConfig = ConfigSource.default(ConfigSource.file(path))
.at("pronoun-listener").load[PronounListenerConfig]
.fold(failures => {
log.info(s"Could not load pronoun-listener config, reason ${failures.toList.map(_.description)} Using default config.")
.fold(
failures => {
log.info(
s"Could not load admin-listener config, reason ${failures.toList.map(_.description)} Using default config."
)
AdminListenerConfig("", None)
},
success => success,
)

def loadPronounListenerConfig(path: Path): PronounListenerConfig = ConfigSource.default(ConfigSource.file(path))
.at("pronoun-listener").load[PronounListenerConfig]
.fold(
failures => {
log.info(
s"Could not load pronoun-listener config, reason ${failures.toList.map(_.description)} Using default config."
)
PronounListenerConfig("pronouns.txt")
}, success => success)
},
success => success,
)

}
31 changes: 21 additions & 10 deletions src/main/scala/codes/co2/ircbot/listeners/links/LinkListener.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ class LinkListener(httpClient: HttpClient, config: LinkListenerConfig, generalCo
) extends GenericListener(generalConfig) {
val log: Logger = LoggerFactory.getLogger(getClass)

implicit val httpSettings: ConnectionPoolSettings = if (config.useHttpProxy.getOrElse(false)) {
ConnectionPoolSettings(system)
.withConnectionSettings(
ClientConnectionSettings(system)
.withTransport(ClientTransport.httpsProxy())
)
} else ConnectionPoolSettings(system)
implicit val httpSettings: ConnectionPoolSettings =
if (config.useHttpProxy.getOrElse(false)) {
ConnectionPoolSettings(system)
.withConnectionSettings(
ClientConnectionSettings(system)
.withTransport(ClientTransport.httpsProxy())
)
} else ConnectionPoolSettings(system)

val twitterClientOpt: Option[TwitterRestClient] =
config.twitterApi.map { twitterApi =>
Expand Down Expand Up @@ -71,7 +72,15 @@ class LinkListener(httpClient: HttpClient, config: LinkListenerConfig, generalCo

def send(title: String): Unit = {
log.info(s"Sending $title to ${channel.getName}")
channel.send().message(s"$boldTag$title$normalTag")

val lowerCaseTitle = title.toLowerCase()

if (config.lowerCaseSpamList.exists(spamWord => lowerCaseTitle.contains(spamWord))) {
channel.send().message("Are you a spammer?")
} else {
channel.send().message(s"$boldTag$title$normalTag")
}

}

if (lowerCase.contains("http://") || lowerCase.contains("https://")) {
Expand Down Expand Up @@ -108,7 +117,8 @@ class LinkListener(httpClient: HttpClient, config: LinkListenerConfig, generalCo
private def getAsTweetOpt(link: String): Option[Future[String]] = {
for {

twitterClient <- twitterClientOpt // This order because don't even bother the regex if the twitterClient doesn't exist
twitterClient <-
twitterClientOpt // This order because don't even bother the regex if the twitterClient doesn't exist
tweetId <- LinkParser.tryGetTwitterId(link)
tweet = twitterClient.getTweet(
tweetId,
Expand All @@ -128,7 +138,8 @@ class LinkListener(httpClient: HttpClient, config: LinkListenerConfig, generalCo
private def getAsYoutubeOpt(link: String): Option[Future[Option[String]]] = {
for {

youtubeClient <- youtubeClientOpt // This order because don't even bother the regex if the youtubeClient doesn't exist
youtubeClient <-
youtubeClientOpt // This order because don't even bother the regex if the youtubeClient doesn't exist
youtubeId <- LinkParser.tryGetYoutubeId(link)
request = youtubeClient.client.videos().list(List("snippet").asJava)
response = Future(request.setId(List(youtubeId).asJava).setKey(youtubeClient.key).execute())
Expand Down

0 comments on commit 2f8217b

Please sign in to comment.