Skip to content

Commit

Permalink
BeHaveDo
Browse files Browse the repository at this point in the history
  • Loading branch information
Glen D Sanford committed Aug 15, 2012
1 parent bbc6692 commit d5c3b0a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 81 deletions.
76 changes: 6 additions & 70 deletions src/main/scala/nu/glen/followbackbot/Responder.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package nu.glen.followbackbot

import twitter4j.{Status, StatusUpdate}
import util.matching.Regex

object Responder {
/**
Expand All @@ -13,10 +12,12 @@ object Responder {
def simple(responder: SimpleResponder): Responder = { status =>
// get the untruncated retweet text if status is a retweet
val text =
if (status.isRetweet)
status.getRetweetedStatus.getText
else
status.getText
Option(
if (status.isRetweet)
status.getRetweetedStatus.getText
else
status.getText
).getOrElse("").trim

responder(text) map { response =>
// add @reply prefix
Expand Down Expand Up @@ -51,68 +52,3 @@ object Responder {
def merged(responders: Responder*): Responder =
(status) => responders.foldLeft[Option[StatusUpdate]](None)(_ orElse _(status))
}

/**
* Base class for SimpleResponders which extract a keyword which, when processed,
* serves as the prefix for the rest of the extracted text. keywords are filtered against
* a Set[String] of stop words.
*/
abstract class KeywordPrefixResponder(stopWords: Set[String])
extends SimpleResponder
with SimpleLogger
{
/**
* extract the keyword and remaining text from a status text
*
* @param statusText the text from which to extract
*/
def extract(statusText: String): Option[(String, String)]

/**
* combine the keyword (now vetted against stopwords) with the rest of the
* string to form the tweet.
*
* @param filteredKeyword the keyword, filtered against stop words
* @param rest the rest of the sentence to be combined with the keyword
*/
def combine(filteredKeyword: String, rest: String): String

def apply(statusText: String): Option[String] = {
extract(statusText) flatMap { case (keyword, rest) =>
if (stopWords.contains(keyword)) {
log.info(" Skipping tweet with stop word: %s", keyword)
None
} else {
Some(combine(keyword, rest))
}
}
}
}

/**
* A KeywordPrefixResponder that uses a regex for extraction
*/
abstract class RegexKeywordPrefixResponder(stopWords: Set[String], regex: Regex)
extends KeywordPrefixResponder(stopWords)
{
override def extract(statusText: String): Option[(String, String)] = statusText match {
case regex(keyword, rest) => Some((keyword.toLowerCase, rest))
case _ => None
}
}

/**
* A RegexKeywordPrefixResponder which (poorly) matches gerrunds as keywords
*/
abstract class GerrundKeywordPrefixResponder
extends RegexKeywordPrefixResponder(
Ing.stopWords,
""".*?\b([a-z\-A-Z]+[iI][nN][gG])\b\"?(.*?)\"?""".r)

/**
* A RegexKeywordPrefixResponder which (poorly) matches past-tense verbs as keywords
*/
abstract class PastTenseKeywordPrefixResponder
extends RegexKeywordPrefixResponder(
Ed.stopWords,
""".*?\b([a-z\-A-Z]+[eE][dD])\b\"?(.*?)\"?""".r)
5 changes: 3 additions & 2 deletions src/main/scala/nu/glen/yourmombot/YourMomBot.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ object YourMomBot
extends FollowBackBot(
Responder.rateLimited(
Responder.merged(
Responder.simple(YourMomPastTenseResponder),
Responder.simple(YourMomGerrundResponder)
Responder.logOnly(Responder.simple(new YourMomBeHaveResponder)),
Responder.simple(new YourMomPastTenseResponder),
Responder.simple(new YourMomGerrundResponder)
),
RateLimiter.merged(
RateLimiter.perHour(2),
Expand Down
16 changes: 11 additions & 5 deletions src/main/scala/nu/glen/yourmombot/YourMomResponder.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package nu.glen.yourmombot

import nu.glen.followbackbot.{GerrundKeywordPrefixResponder, PastTenseKeywordPrefixResponder}
import nu.glen.followbackbot.{
BeHaveKeywordPrefixResponder,
GerrundKeywordPrefixResponder,
PastTenseKeywordPrefixResponder
}

object YourMomGerrundResponder extends GerrundKeywordPrefixResponder {
override def name = "YourMomGerrundResponder"
class YourMomGerrundResponder extends GerrundKeywordPrefixResponder {
override def combine(gerrund: String, rest: String) = "Your mom's %s%s".format(gerrund, rest)
}

object YourMomPastTenseResponder extends PastTenseKeywordPrefixResponder {
override def name = "YourMomPastTenseResponder"
class YourMomPastTenseResponder extends PastTenseKeywordPrefixResponder {
override def combine(verb: String, rest: String) = "Your mom %s%s".format(verb, rest)
}

class YourMomBeHaveDoResponder extends BeHaveDoKeywordPrefixResponder {
override def combine(verb: String, rest: String) = "Your mom %s%s".format(verb, rest)
}
27 changes: 23 additions & 4 deletions src/test/scala/nu/glen/yourmombot/YourMomResponderSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,46 @@ class YourMomResponderSpec extends FunSpec {
// most of the unit tests for this are in ResponderSpec, since the only
// thing this class does is prefix "Your Mom's"
describe("YourMomGerrundResponder") {
val responder = new YourMomGerrundResponder

it("should extract a simple sentance") {
val result = YourMomGerrundResponder("I'm hoping this works")
val result = responder("I'm hoping this works")
assert(result == Some("Your mom's hoping this works"))
}

it("should return None for no ing") {
val result = YourMomGerrundResponder("foobar")
val result = responder("foobar")
assert(result == None)
}
}

// most of the unit tests for this are in ResponderSpec, since the only
// thing this class does is prefix "Your Mom's"
describe("YourMomPastTenseResponder") {
val responder = new YourMomPastTenseResponder

it("should extract a simple sentance") {
val result = YourMomPastTenseResponder("I hoped this worked")
val result = responder("I hoped this worked")
assert(result == Some("Your mom hoped this worked"))
}

it("should return None for no ed") {
val result = YourMomPastTenseResponder("foobar")
val result = responder("foobar")
assert(result == None)
}
}

describe("YourMomBeHaveResponder") {
val responder = new YourMomBeHaveDoResponder

it("should extract") {
val result = responder("I didn't much care for that")
println(result)
assert(result == Some("Your mom didn't much care for that"))
}

it("should return None") {
val result = responder("foobar")
assert(result == None)
}
}
Expand Down

0 comments on commit d5c3b0a

Please sign in to comment.