Skip to content
This repository has been archived by the owner on May 22, 2023. It is now read-only.

Handle newlines in raid text message #57

Merged
merged 3 commits into from
Sep 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object Application {
val cachedBosses = getCachedBosses(protobufStorage, bossStorageConfig.cacheKey)

// Start RaidFinder
val raidFinder = RaidFinder.withBacklog(initialBosses = cachedBosses)
val raidFinder = RaidFinder.withBackfill(initialBosses = cachedBosses)

// Periodically flush bosses to cache
val bossFlushCancelable = scheduler.scheduleWithFixedDelay(
Expand Down
20 changes: 10 additions & 10 deletions stream/src/main/scala/walfie/gbf/raidfinder/RaidFinder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ trait RaidFinder {

object RaidFinder {
val DefaultCacheSizePerBoss = 20
val DefaultBacklogSize = 200
val DefaultBackfillSize = 200

/** Stream tweets without looking up old tweets first */
def withoutBacklog(
def withoutBackfill(
twitterStream: TwitterStream = TwitterStreamFactory.getSingleton,
cachedTweetsPerBoss: Int = DefaultCacheSizePerBoss,
initialBosses: Seq[RaidBoss] = Seq.empty
Expand All @@ -32,31 +32,31 @@ object RaidFinder {
}

/** Search for old tweets first before streaming new tweets */
def withBacklog(
def withBackfill(
twitter: Twitter = TwitterFactory.getSingleton,
twitterStream: TwitterStream = TwitterStreamFactory.getSingleton,
backlogSize: Int = DefaultBacklogSize,
backfillSize: Int = DefaultBackfillSize,
cachedTweetsPerBoss: Int = DefaultCacheSizePerBoss,
initialBosses: Seq[RaidBoss] = Seq.empty
)(implicit scheduler: Scheduler): DefaultRaidFinder = {
import TwitterSearcher._

// Get backlog of tweets, then sort them by earliest first
// Get backfill of tweets, then sort them by earliest first
// TODO: This is getting kinda complex -- should write a test
val backlogTask: Task[Seq[Status]] =
val backfillTask: Task[Seq[Status]] =
TwitterSearcher(twitter, TwitterSearcher.ReverseChronological)
.observable(DefaultSearchTerm, None, MaxCount)
.flatMap(Observable.fromIterable)
.take(backlogSize)
.take(backfillSize)
.toListL
.map(_.sortBy(_.getCreatedAt)) // earliest first

// Once the backlog is populated, new tweets will stream in
val backlogObservable = Observable.fromTask(backlogTask).flatMap(Observable.fromIterable)
// Once the backfill is populated, new tweets will stream in
val backfillObservable = Observable.fromTask(backfillTask).flatMap(Observable.fromIterable)
val newStatusesObservable = TwitterStreamer(twitterStream).observable

new DefaultRaidFinder(
backlogObservable ++ newStatusesObservable, cachedTweetsPerBoss, initialBosses
backfillObservable ++ newStatusesObservable, cachedTweetsPerBoss, initialBosses
) {
override def onShutdown(): Unit = {
twitterStream.cleanUp()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import scala.util.Try

object StatusParser {
/** Regexes to match raid request tweets */
val RaidRegexJapanese = "(.*)参加者募集!参戦ID:([0-9A-F]+)\n(.+)\n?.*".r
val RaidRegexEnglish = "(.*)I need backup!Battle ID: ([0-9A-F]+)\n(.+)\n?.*".r
val RaidRegexJapanese = "((?s).*)参加者募集!参戦ID:([0-9A-F]+)\n(.+)\n?.*".r
val RaidRegexEnglish = "((?s).*)I need backup!Battle ID: ([0-9A-F]+)\n(.+)\n?.*".r

/**
* Regex to get boss level from full name
Expand Down
79 changes: 69 additions & 10 deletions stream/src/test/scala/walfie/gbf/raidfinder/StatusParserSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import twitter4j._
import walfie.gbf.raidfinder.domain._

class StatusParserSpec extends StatusParserSpecHelpers {
"parse a valid status in Japanese" in {
"parse a valid status in Japanese" - {
val expectedRaidTweet = RaidTweet(
tweetId = 12345L,
screenName = "walfieee",
Expand All @@ -28,12 +28,41 @@ class StatusParserSpec extends StatusParserSpecHelpers {
lastSeen = now
)

StatusParser.parse(mockStatus()) shouldBe Some {
RaidInfo(expectedRaidTweet, expectedRaidBoss)
"with extra text" in {
StatusParser.parse(mockStatus()) shouldBe Some {
RaidInfo(expectedRaidTweet, expectedRaidBoss)
}
}

"with newlines in extra text" in {
val text = """
|Hey
|Newlines
|Are
|Cool
|参加者募集!参戦ID:ABCD1234
|Lv60 オオゾラッコ
|http://example.com/image-that-is-ignored.png""".stripMargin.trim

StatusParser.parse(mockStatus(text = text)) shouldBe Some {
RaidInfo(expectedRaidTweet.copy(text = "Hey\nNewlines\nAre\nCool"), expectedRaidBoss)
}
}

"without extra text" in {
val text = """
|参加者募集!参戦ID:ABCD1234
|Lv60 オオゾラッコ
|http://example.com/image-that-is-ignored.png""".stripMargin.trim

StatusParser.parse(mockStatus(text = text)) shouldBe Some {
RaidInfo(expectedRaidTweet.copy(text = ""), expectedRaidBoss)
}
}

}

"parse a valid status in English" in {
"parse a valid status in English" - {
val expectedRaidTweet = RaidTweet(
tweetId = 12345L,
screenName = "walfieee",
Expand All @@ -51,13 +80,43 @@ class StatusParserSpec extends StatusParserSpecHelpers {
lastSeen = now
)

val text = """
|INSERT CUSTOM MESSAGE HERE I need backup!Battle ID: ABCD1234
|Lvl 60 Ozorotter""".stripMargin.trim
val status = mockStatus(text = text)
"with extra text" in {
val text = """
|INSERT CUSTOM MESSAGE HERE I need backup!Battle ID: ABCD1234
|Lvl 60 Ozorotter""".stripMargin.trim
val status = mockStatus(text = text)

StatusParser.parse(status) shouldBe Some {
RaidInfo(expectedRaidTweet, expectedRaidBoss)
}
}

"with newlines in extra text" in {
val text = """
|Hey
|Newlines
|Are
|Cool
|I need backup!Battle ID: ABCD1234
|Lvl 60 Ozorotter
|http://example.com/image-that-is-ignored.png""".stripMargin.trim
val status = mockStatus(text = text)

StatusParser.parse(status) shouldBe Some {
RaidInfo(expectedRaidTweet.copy(text = "Hey\nNewlines\nAre\nCool"), expectedRaidBoss)
}
}

"without extra text" in {
val text = """
|I need backup!Battle ID: ABCD1234
|Lvl 60 Ozorotter
|http://example.com/image-that-is-ignored.png""".stripMargin.trim
val status = mockStatus(text = text)

StatusParser.parse(status) shouldBe Some {
RaidInfo(expectedRaidTweet, expectedRaidBoss)
StatusParser.parse(status) shouldBe Some {
RaidInfo(expectedRaidTweet.copy(text = ""), expectedRaidBoss)
}
}
}

Expand Down