Created
June 28, 2011 09:28
-
-
Save kaja47/1050801 to your computer and use it in GitHub Desktop.
stripbot source
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
scalaVersion := "2.9.0-1" | |
libraryDependencies += "commons-codec" % "commons-codec" % "1.4" | |
libraryDependencies += "oauth.signpost" % "signpost-core" % "1.2.1.1" | |
libraryDependencies += "org.jdom" % "jdom" % "1.1" | |
libraryDependencies += "rome" % "rome" % "0.9" | |
libraryDependencies += "jtwitter" % "jtwitter" % "1.8.3" from "http://www.winterwell.com/software/jtwitter/jtwitter.jar" |
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
// https://twitter.com/#!/stripbot | |
package stripBot | |
import scala.actors.Actor | |
import scala.actors.Actor._ | |
import java.net.{ URL, URLEncoder, MalformedURLException } | |
import java.io.{ FileReader, BufferedReader, FileWriter, IOException } | |
import java.util.Date | |
import com.sun.syndication.feed.synd.SyndEntry | |
import com.sun.syndication.io.{ SyndFeedInput, XmlReader } | |
import winterwell.jtwitter.{ Twitter, OAuthSignpostClient } | |
object Main extends App { | |
val tweeter = new Tweeter("stripbot", Config.oauthKey, Config.oauthSecret) | |
val rssFetcher = new Fetcher(Config.sources, tweeter) | |
rssFetcher.start | |
tweeter.start | |
} | |
object Config { | |
val sources = Seq( | |
StripSource("Bugemos", "http://bugemos.com/?q=rss.xml"), | |
StripSource("balónek strip", "http://lubosbranda.blog.idnes.cz/rss/"), | |
StripSource("bezejmenný hrdina", "http://picasaweb.google.com/data/feed/base/user/marusjakub/albumid/5110845406354432785?alt=rss&kind=photo&hl=cs"), | |
StripSource("ITBiz", "http://www.itbiz.cz/taxonomy/term/25/0/feed"), | |
StripSource("iDNES komix", "http://servis.idnes.cz/rss.asp?c=komiksy"), | |
StripSource("XKCD", "http://xkcd.com/rss.xml", "EN"), | |
StripSource("Questionable Content", "http://www.questionablecontent.net/QCRSS.xml", "EN"), | |
StripSource("Johny Wander", "http://www.johnnywander.com/feed", "EN"), | |
StripSource("Wasted Talent", "http://feeds2.feedburner.com/WastedTalentRss", "EN"), | |
StripSource("chainsawsuit", "http://feeds.feedburner.com/Chainsawsuit", "EN"), | |
StripSource("Cyanide & happyiness", "http://feeds.feedburner.com/Explosm", "EN", { e => e.getTitle.matches("""\d+\.\d+.\d+""") }) | |
) | |
val oauthKey = "---YOUR-OAUTH-KEY---" | |
val oauthSecret = "---YOUR-OAUTH-SECRET---" | |
} | |
// --- main actors | |
class Fetcher(sources: Seq[StripSource], tweeter: Tweeter) extends Actor { | |
val lastCheckFile = "lastCheck.txt" | |
def checkRss(source: StripSource, lastCheck: Date) = | |
for { | |
e <- Util.readRssFromUrl(source.rssUrl) | |
if source.filterFn(e) | |
if e.getPublishedDate != null && e.getPublishedDate.after(lastCheck) | |
} yield e | |
def formatMessage(source: StripSource, entry: SyndEntry) = | |
source.name+" - "+entry.getTitle.trim+" "+Util.shortenUrl(entry.getLink)+" "+source.lang+" #stripy" | |
def getLastCheck: Date = { | |
var line = Util readLine lastCheckFile | |
if (line == null || line == "") new Date() else new Date(line.toLong) | |
} | |
def setLastCheck = Util.writeLine(lastCheckFile, "" + new Date().getTime) | |
def act { | |
println(sources.mkString("\n")) | |
loop { | |
var lastCheck = getLastCheck | |
println("Last check: " + lastCheck) | |
for { | |
source <- sources | |
entry <- checkRss(source, lastCheck) | |
} tweeter ! formatMessage(source, entry) | |
setLastCheck | |
Thread.sleep(1000 * 60 * 60) // 1 hour | |
} | |
} | |
} | |
class Tweeter(username: String, oauthKey: String, oauthSecret: String) extends Actor { | |
val accessTokensFile = "accessTokens.txt" | |
def connectToTwitter = { | |
val tokens = Util readLine accessTokensFile | |
val oauthClient = | |
if (tokens.nonEmpty) { | |
val t = tokens.split(" ") | |
new OAuthSignpostClient(oauthKey, oauthSecret, t(0), t(1)) | |
} else { | |
val oauthClient = new OAuthSignpostClient(oauthKey, oauthSecret, "oob") | |
oauthClient.authorizeDesktop() | |
val v = OAuthSignpostClient.askUser("Please enter the verification PIN from Twitter") | |
oauthClient.setAuthorizationCode(v) | |
Util.writeLine(accessTokensFile, oauthClient.getAccessToken.mkString(" ")) | |
oauthClient | |
} | |
new Twitter(username, oauthClient) | |
} | |
def act { | |
val twitter = connectToTwitter | |
loop { | |
react { | |
case m => | |
twitter.updateStatus(m.toString) | |
println("tweeted: " + m.toString) | |
} | |
} | |
} | |
} | |
// ---- | |
case class StripSource (name: String, rssUrl: String, lang: String = "CZ", filterFn: SyndEntry => Boolean = x => true) | |
object Util { | |
def readLine(f: String) = io.Source.fromFile(f).getLines.next | |
def writeLine(f: String, data: String) = { | |
val fw = new FileWriter(f) | |
fw write data | |
fw.close() | |
} | |
def readRssFromUrl(url: String): List[SyndEntry] = { | |
try { | |
val i = new SyndFeedInput().build(new XmlReader(new URL(url))).getEntries | |
List(i.toArray(new Array[SyndEntry](0)) : _*) | |
} catch { | |
case _ => List() | |
} | |
} | |
def shortenUrl(url: String) = { | |
val line = io.Source.fromURL("http://url.k47.cz/api/get/?url=" + URLEncoder.encode(url, "UTF8")).getLines.next | |
if (line startsWith "ERROR") throw new MalformedURLException | |
line | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment