Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Karasiq committed Mar 10, 2016
1 parent c05cd07 commit eb335d9
Show file tree
Hide file tree
Showing 15 changed files with 68 additions and 57 deletions.
2 changes: 1 addition & 1 deletion README.MD
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# nanoboard [![Build Status](https://travis-ci.org/Karasiq/nanoboard.svg?branch=master)](https://travis-ci.org/Karasiq/nanoboard) [![Build status](https://ci.appveyor.com/api/projects/status/05l8dnixhn375kjm?svg=true)](https://ci.appveyor.com/project/Karasiq/nanoboard) [![Version](http://img.shields.io/badge/version-1.0.5--M1-blue.svg?style=flat)](https://github.com/Karasiq/nanoboard/releases)
# nanoboard [![Build Status](https://travis-ci.org/Karasiq/nanoboard.svg?branch=master)](https://travis-ci.org/Karasiq/nanoboard) [![Build status](https://ci.appveyor.com/api/projects/status/05l8dnixhn375kjm?svg=true)](https://ci.appveyor.com/project/Karasiq/nanoboard) [![Version](http://img.shields.io/badge/version-1.0.5-blue.svg?style=flat)](https://github.com/Karasiq/nanoboard/releases)
Scala [nanoboard](https://github.com/nanoboard/nanoboard) implementation

# Links
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import sbtassembly.Plugin.AssemblyKeys._

lazy val commonSettings = Seq(
organization := "com.github.karasiq",
version := "1.0.5-M1",
version := "1.0.5",
isSnapshot := version.value.endsWith("SNAPSHOT"),
scalaVersion := "2.11.7"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ final class ThreadContainer(val context: Var[NanoboardContext], postsPerPage: In
val prevOffset = math.max(0, offset - postsPerPage)
val previousButton = ButtonBuilder(ButtonStyle.info)(
"angle-double-left".fontAwesome(FontAwesome.fixedWidth),
s"From $prevOffset to ${prevOffset + postsPerPage}",
locale.fromTo(prevOffset, prevOffset + postsPerPage),
onclick := Bootstrap.jsClick { _
context() = NanoboardContext.Recent(prevOffset)
})
Expand Down
2 changes: 1 addition & 1 deletion library/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
nanoboard {
version = 1.0.5-M1
version = 1.0.5
client-version = karasiq-nanoboard v${nanoboard.version}
encryption-key = "nano"
bitmessage {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
package com.karasiq.nanoboard

import java.time._
import java.time.format.{DateTimeFormatter, DateTimeFormatterBuilder, TextStyle}
import java.time.temporal.ChronoField
import java.util.Locale

import com.karasiq.nanoboard.encoding.{DataCipher, DefaultNanoboardMessageFormat}
import com.typesafe.config.ConfigFactory
import org.apache.commons.codec.binary.Hex

case class NanoboardMessage(parent: String, text: String) {
Expand All @@ -15,27 +9,5 @@ case class NanoboardMessage(parent: String, text: String) {
}

object NanoboardMessage extends DefaultNanoboardMessageFormat {
private val clientVersion = ConfigFactory.load().getString("nanoboard.client-version")

private val timestampFormat = new DateTimeFormatterBuilder()
.appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
.appendLiteral(", ")
.appendValue(ChronoField.DAY_OF_MONTH)
.appendLiteral('/')
.appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT)
.appendLiteral('/')
.appendValue(ChronoField.YEAR)
.appendLiteral(", ")
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.appendLiteral(" (")
.appendZoneOrOffsetId()
.appendLiteral(")")
.toFormatter(Locale.ENGLISH)

val hashRegex = "(?i)[a-f0-9]{32}".r

def newMessage(parent: String, text: String): NanoboardMessage = {
val header = s"[g]${timestampFormat.format(ZonedDateTime.now())}, client: $clientVersion[/g]"
NanoboardMessage(parent, s"$header\n$text")
}
val hashFormat = "(?i)[a-f0-9]{32}".r
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.karasiq.nanoboard

import java.time.format.{DateTimeFormatter, DateTimeFormatterBuilder, TextStyle}
import java.time.temporal.ChronoField
import java.time.{ZoneId, ZonedDateTime}
import java.util.Locale

import com.typesafe.config.{Config, ConfigFactory}

import scala.util.Try

object NanoboardMessageGenerator {
def fromConfig(config: Config = ConfigFactory.load()) = {
new NanoboardMessageGenerator(config.getString("nanoboard.client-version"), Try(ZoneId.of(config.getString("nanoboard.default-time-zone"))).getOrElse(ZoneId.systemDefault()))
}
}

class NanoboardMessageGenerator(clientVersion: String, defaultTimeZone: ZoneId) {
protected val timestampFormat = new DateTimeFormatterBuilder()
.appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
.appendLiteral(", ")
.appendValue(ChronoField.DAY_OF_MONTH)
.appendLiteral('/')
.appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT)
.appendLiteral('/')
.appendValue(ChronoField.YEAR)
.appendLiteral(", ")
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.appendLiteral(" (")
.appendZoneOrOffsetId()
.appendLiteral(")")
.toFormatter(Locale.ENGLISH)

def newMessage(parent: String, text: String): NanoboardMessage = {
val header = s"[g]${timestampFormat.format(ZonedDateTime.now(defaultTimeZone))}, client: $clientVersion[/g]"
NanoboardMessage(parent, s"$header\n$text")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ final class BitMessageTransport(config: Config)(implicit ac: ActorSystem, am: Ac
.run()

post {
(path("api" / "add" / NanoboardMessage.hashRegex) & entity(as[String])) { (parent, message)
(path("api" / "add" / NanoboardMessage.hashFormat) & entity(as[String])) { (parent, message)
queue.offer(NanoboardMessage(parent, BitMessageTransport.fromBase64(message)))
complete(StatusCodes.OK)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ class BoardPngSource(encoding: DataEncodingStage)(implicit as: ActorSystem, am:
val decoded: String = encoding.decode(data).utf8String
NanoboardMessage.parseMessages(decoded)
}
.recoverWith { case _ Source.empty }
}

def imagesFromPage(url: String): Source[String, akka.NotUsed] = {
Source.fromFuture(http.singleRequest(HttpRequest(uri = url)))
.flatMapConcat(_.entity.dataBytes.fold(ByteString.empty)(_ ++ _))
.flatMapConcat(data imagesFromPage(Jsoup.parse(data.utf8String, url)))
.recoverWith { case _ Source.empty }
}

protected def imagesFromPage(page: Document): Source[String, akka.NotUsed] = {
Expand Down
2 changes: 1 addition & 1 deletion setup/setup.iss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#define OutputName "nanoboard-server"
#define MyAppName "Nanoboard"
#define MyAppVersion "1.0.5-M1"
#define MyAppVersion "1.0.5"
#define MyAppPublisher "Karasiq, Inc."
#define MyAppURL "http://www.github.com/Karasiq/nanoboard"
#define MyAppExeName "nanoboard.exe"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import akka.util.ByteString
import com.karasiq.nanoboard.encoding.DataEncodingStage._
import com.karasiq.nanoboard.encoding.stages.{GzipCompression, PngEncoding, SalsaCipher}
import com.karasiq.nanoboard.model._
import com.karasiq.nanoboard.{NanoboardCategory, NanoboardMessage}
import com.karasiq.nanoboard.{NanoboardCategory, NanoboardMessage, NanoboardMessageGenerator}
import com.typesafe.config.{Config, ConfigFactory}
import slick.driver.H2Driver.api._

Expand All @@ -24,6 +24,7 @@ object NanoboardSlickDispatcher {
}

private[dispatcher] final class NanoboardSlickDispatcher(db: Database, config: Config, postSink: Sink[NanoboardMessage, _])(implicit ec: ExecutionContext, as: ActorSystem, am: ActorMaterializer) extends NanoboardDispatcher {
private val messageGenerator = NanoboardMessageGenerator.fromConfig(config)
private val postQueue = Source.queue(20, OverflowStrategy.dropHead)
.to(postSink)
.run()
Expand Down Expand Up @@ -96,7 +97,7 @@ private[dispatcher] final class NanoboardSlickDispatcher(db: Database, config: C
}

override def reply(parent: String, text: String): Future[NanoboardMessageData] = {
val newMessage: NanoboardMessage = NanoboardMessage.newMessage(parent, text)
val newMessage: NanoboardMessage = messageGenerator.newMessage(parent, text)
postQueue.offer(newMessage)
db.run(Post.addReply(newMessage)).map(_ NanoboardMessageData(Some(parent), newMessage.hash, newMessage.text, 0))
}
Expand Down
21 changes: 12 additions & 9 deletions src/main/scala/com/karasiq/nanoboard/server/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import java.util.concurrent.TimeUnit
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding
import akka.stream._
import akka.stream.scaladsl._
import akka.stream.{ActorMaterializer, ActorMaterializerSettings}
import com.karasiq.nanoboard.dispatcher.NanoboardSlickDispatcher
import com.karasiq.nanoboard.model.{Place, Post, _}
import com.karasiq.nanoboard.server.cache.MapDbNanoboardCache
Expand Down Expand Up @@ -107,14 +107,17 @@ object Main extends App {
val messageSource = UrlPngSource.fromConfig(config)
val updateInterval = FiniteDuration(config.getDuration("nanoboard.scheduler.update-interval", TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS)

actorSystem.scheduler.schedule(10 seconds, updateInterval) {
Source.fromPublisher(db.stream(Place.list()))
.flatMapMerge(4, messageSource.imagesFromPage)
.filterNot(cache.contains)
.alsoTo(Sink.foreach(image cache += image))
.flatMapMerge(8, messageSource.messagesFromImage)
.runWith(dbMessageSink)
}
val placeFlow = Flow[String]
.flatMapMerge(4, messageSource.imagesFromPage)
.filterNot(cache.contains)
.alsoTo(Sink.foreach(image cache += image))
.flatMapMerge(8, messageSource.messagesFromImage)
.withAttributes(ActorAttributes.supervisionStrategy(Supervision.resumingDecider))

Source.tick(10 seconds, updateInterval, ())
.flatMapConcat(_ Source.fromPublisher(db.stream(Place.list())))
.via(placeFlow)
.runWith(dbMessageSink)

// REST server
val server = NanoboardServer(dispatcher)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ private[server] final class NanoboardMessageStream extends GraphStage[FanInShape
override def onPush(): Unit = {
subscription = grab(input)
request()
// emit(output, NanoboardMessage.newMessage("cd94a3d60f2f521806abebcd3dc3f549", "Test"))
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ private[server] final class NanoboardServer(dispatcher: NanoboardDispatcher)(imp
val route = {
get {
encodeResponse {
path("post" / NanoboardMessage.hashRegex) { hash
path("post" / NanoboardMessage.hashFormat) { hash
complete(StatusCodes.OK, dispatcher.post(hash))
} ~
(pathPrefix("posts") & parameters('offset.as[Int].?(0), 'count.as[Int].?(100))) { (offset, count)
path(NanoboardMessage.hashRegex) { hash
path(NanoboardMessage.hashFormat) { hash
complete(StatusCodes.OK, dispatcher.thread(hash, offset, count))
} ~
pathEndOrSingleSlash {
Expand Down Expand Up @@ -112,13 +112,13 @@ private[server] final class NanoboardServer(dispatcher: NanoboardDispatcher)(imp
}
} ~
delete {
path("post" / NanoboardMessage.hashRegex) { hash
path("post" / NanoboardMessage.hashFormat) { hash
extractLog { log
log.info("Post permanently deleted: {}", hash)
complete(StatusCodes.OK, dispatcher.delete(hash))
}
} ~
path("pending" / NanoboardMessage.hashRegex) { hash
path("pending" / NanoboardMessage.hashFormat) { hash
complete(StatusCodes.OK, dispatcher.markAsNotPending(hash))
}
} ~
Expand All @@ -131,7 +131,7 @@ private[server] final class NanoboardServer(dispatcher: NanoboardDispatcher)(imp
log.info("Categories updated: {}", categories)
complete(StatusCodes.OK, dispatcher.updateCategories(categories))
} ~
path("pending" / NanoboardMessage.hashRegex) { hash
path("pending" / NanoboardMessage.hashFormat) { hash
complete(StatusCodes.OK, dispatcher.markAsPending(hash))
}
} ~
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ private[server] final class MessageValidator(config: Config) {
private val spamFilter = config.getStringList("nanoboard.scheduler.spam-filter").toVector

def isMessageValid(message: NanoboardMessage): Boolean = {
message.parent.matches(NanoboardMessage.hashRegex.regex) &&
message.parent.matches(NanoboardMessage.hashFormat.regex) &&
message.text.nonEmpty &&
message.text.length <= maxPostSize &&
spamFilter.forall(!message.text.matches(_))
Expand Down
4 changes: 2 additions & 2 deletions src/test/scala/DatabaseTest.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import com.karasiq.nanoboard.NanoboardMessage
import com.karasiq.nanoboard.NanoboardMessageGenerator
import com.karasiq.nanoboard.model._
import org.scalatest.{BeforeAndAfterAll, FlatSpec, Matchers}
import slick.driver.H2Driver.api._
Expand All @@ -8,7 +8,7 @@ import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._

class DatabaseTest extends FlatSpec with Matchers with BeforeAndAfterAll {
val testMessage = NanoboardMessage.newMessage("8b8cfb7574741838450e286909e8fd1f", "Hello world!")
val testMessage = NanoboardMessageGenerator.fromConfig().newMessage("8b8cfb7574741838450e286909e8fd1f", "Hello world!")
val db = Database.forConfig("nanoboard.test-database")

"Database" should "add entry" in {
Expand Down

0 comments on commit eb335d9

Please sign in to comment.