Add support for more generic notification

This is a start to have different kinds of notifications. It is
possible to be notified via e-mail, matrix or gotify. It also extends
the current "periodic query" for due items by allowing notification
over different channels. A "generic periodic query" variant is added
as well.
This commit is contained in:
eikek
2021-11-22 00:22:51 +01:00
parent 93a828720c
commit 4ffc8d1f14
175 changed files with 13041 additions and 599 deletions

View File

@ -6,6 +6,8 @@
package docspell.common
import io.circe.{Decoder, Encoder}
final case class ItemQueryString(query: String) {
def isEmpty: Boolean =
query.isEmpty
@ -15,4 +17,9 @@ object ItemQueryString {
def apply(qs: Option[String]): ItemQueryString =
ItemQueryString(qs.getOrElse(""))
implicit val jsonEncoder: Encoder[ItemQueryString] =
Encoder.encodeString.contramap(_.query)
implicit val jsonDecoder: Decoder[ItemQueryString] =
Decoder.decodeString.map(ItemQueryString.apply)
}

View File

@ -103,6 +103,8 @@ case class LenientUri(
val fragPart = fragment.map(f => s"#$f").getOrElse("")
s"$schemePart:$authPart$pathPart$queryPart$fragPart"
}
override def toString(): String =
asString
}
object LenientUri {

View File

@ -6,8 +6,11 @@
package docspell.common
import java.io.{PrintWriter, StringWriter}
import cats.Applicative
import cats.effect.Sync
import cats.effect.{Ref, Sync}
import cats.implicits._
import fs2.Stream
import docspell.common.syntax.all._
@ -42,6 +45,28 @@ trait Logger[F[_]] { self =>
def error(ex: Throwable)(msg: => String): Stream[F, Unit] =
Stream.eval(self.error(ex)(msg))
}
def andThen(other: Logger[F])(implicit F: Sync[F]): Logger[F] = {
val self = this
new Logger[F] {
def trace(msg: => String) =
self.trace(msg) >> other.trace(msg)
override def debug(msg: => String) =
self.debug(msg) >> other.debug(msg)
override def info(msg: => String) =
self.info(msg) >> other.info(msg)
override def warn(msg: => String) =
self.warn(msg) >> other.warn(msg)
override def error(ex: Throwable)(msg: => String) =
self.error(ex)(msg) >> other.error(ex)(msg)
override def error(msg: => String) =
self.error(msg) >> other.error(msg)
}
}
}
object Logger {
@ -88,4 +113,31 @@ object Logger {
log.ferror(msg)
}
def buffer[F[_]: Sync](): F[(Ref[F, Vector[String]], Logger[F])] =
for {
buffer <- Ref.of[F, Vector[String]](Vector.empty[String])
logger = new Logger[F] {
def trace(msg: => String) =
buffer.update(_.appended(s"TRACE $msg"))
def debug(msg: => String) =
buffer.update(_.appended(s"DEBUG $msg"))
def info(msg: => String) =
buffer.update(_.appended(s"INFO $msg"))
def warn(msg: => String) =
buffer.update(_.appended(s"WARN $msg"))
def error(ex: Throwable)(msg: => String) = {
val ps = new StringWriter()
ex.printStackTrace(new PrintWriter(ps))
buffer.update(_.appended(s"ERROR $msg:\n$ps"))
}
def error(msg: => String) =
buffer.update(_.appended(s"ERROR $msg"))
}
} yield (buffer, logger)
}

View File

@ -27,7 +27,7 @@ case class NotifyDueItemsArgs(
daysBack: Option[Int],
tagsInclude: List[Ident],
tagsExclude: List[Ident]
) {}
)
object NotifyDueItemsArgs {