Created
June 29, 2016 10:06
-
-
Save euch/b104d1e40ee4bbea8bbf9d4fcfbccb25 to your computer and use it in GitHub Desktop.
Fetch OpenTTD server statistics from http://openttd.org
This file contains hidden or 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
| def getOpenTTDServerInfoCached(serverName: String): Option[String] = { | |
| val cacheKey = OpenTTDServerInfo(serverName) | |
| reachabilityCache.get(cacheKey) match { | |
| case Some(expired) if expired.time.plusMinutes(1).isBefore(now) => reachabilityCache.update(cacheKey, getOpenTTDServerInfo(cacheKey)) | |
| case None => reachabilityCache.put(cacheKey, getOpenTTDServerInfo(cacheKey)) | |
| case Some(actual) => | |
| } | |
| reachabilityCache.get(cacheKey) match { | |
| case Some(info) => info.status | |
| case None => None | |
| } | |
| } | |
| private def getOpenTTDServerInfo(openTTDServerInfo: OpenTTDServerInfo): ReachabilityOnTime = { | |
| val cleaner = new HtmlCleaner | |
| def getServerPage(serverName: String): Option[String] = try { | |
| cleaner.clean(new URL("https://www.openttd.org/en/servers")).getElementsByName("tr", true) | |
| .filter(elem => StringEscapeUtils.unescapeHtml4(elem.getText.toString).contains(openTTDServerInfo.serverName)) | |
| .map(elem => "https://www.openttd.org/" + elem.getAllChildren.get(3).asInstanceOf[TagNode].getAllChildren.get(0).asInstanceOf[TagNode].getAllChildren.get(0).asInstanceOf[TagNode].getAttributeByName("href")) | |
| .headOption | |
| } catch { | |
| case th: Throwable => | |
| println(s"failed to get openttd server page ${th.getMessage}") | |
| th.printStackTrace() | |
| None | |
| } | |
| getServerPage(openTTDServerInfo.serverName) match { | |
| case None => | |
| return ReachabilityOnTime(reachable = false, now) | |
| case Some(sp) => | |
| val elements = cleaner.clean(new URL(sp)).getElementsByName("tr", true).toList | |
| def getRowByName(name: String): Option[String] = try { | |
| elements.filter(_.getAllChildren.get(0) match { | |
| case tn: TagNode => | |
| tn.getAllChildren.get(0) match { | |
| case cn: ContentNode => cn.getContent.equals(name) | |
| case not => false | |
| } | |
| case not => false | |
| }).map(_.getAllChildren.get(1).asInstanceOf[TagNode].getText.toString).headOption | |
| } catch { | |
| case th: Throwable => None | |
| } | |
| val currentDate = getRowByName("Current date:") | |
| val clients = getRowByName("Clients:") | |
| return ReachabilityOnTime(reachable = true, now, status = Some(s"""Clients: ${clients.getOrElse("n/a")}<br/>Date: ${currentDate.getOrElse("n/a")}<br><a href=$sp>more info</a>""")) | |
| } | |
| ReachabilityOnTime(reachable = false, now) | |
| } | |
| private def now = LocalDateTime.now() | |
| private val reachabilityCache = mutable.ParHashMap[CacheKey, ReachabilityOnTime]() | |
| private trait CacheKey | |
| private case class OpenTTDServerInfo(serverName: String) extends CacheKey | |
| private case class HostPort(host: String, port: Int) extends CacheKey | |
| case class ReachabilityOnTime(reachable: Boolean, time: LocalDateTime, status: Option[String] = None) | |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Cache should store Future, of course