make http:sticker/id basic usable

This commit is contained in:
A.C.Sukazyo Eyre 2024-04-20 20:38:21 +08:00
parent f2bd0a38c2
commit 9ddfa6539d
Signed by: Eyre_S
GPG Key ID: C17CE40291207874
4 changed files with 70 additions and 5 deletions

View File

@ -2,23 +2,45 @@ package cc.sukazyo.cono.morny.core.http.api
import cats.effect.IO
import cc.sukazyo.cono.morny.data.TelegramImages
import cc.sukazyo.cono.morny.util.StringEnsure.firstLine
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
import org.http4s.{Header, MediaType, Response}
import org.http4s.dsl.io.*
import org.http4s.headers.`Content-Type`
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
object HttpStatus extends HttpStatus
trait HttpStatus {
private type ResponseT = Response[IO]
private type ResponseIO = IO[ResponseT]
extension (response: ResponseT) {
def setMornyInternalErrorHeader (e: Throwable): ResponseT =
response.setMornyInternalErrorHeader(
e.getClass.getSimpleName,
e.getMessage,
e.toLogString
e.getClass.getSimpleName.firstLine,
e.getMessage.firstLine,
URLEncoder.encode(e.toLogString, StandardCharsets.UTF_8) // todo: maybe extract this const
)
/** Set HTTP Header that shows Morny's Internal Server Error related information.
*
* It will set the following headers, corresponding to this method's parameters, you
* can customize those values.
* - Morny-Internal-Error-Type
* - Morny-Internal-Error-Message
* - Morny-Internal-Error-Detail
*
* **Notice that ANY header value MUST NOT contains line breaking!** Or it will only
* returns an empty 500 response.
*
* @return the [[ResponseT]], with above headers added.
*/
def setMornyInternalErrorHeader (
`Morny-Internal-Error-Type`: String,
`Morny-Internal-Error-Message`: String,

View File

@ -0,0 +1,24 @@
package cc.sukazyo.cono.morny.stickers_get
import java.nio.charset.StandardCharsets
enum StickerType {
case WEBP
case WEBM
case PNG
}
object StickerType {
class UnknownStickerTypeException (message: String)
extends Exception (s"Unknown sticker type: $message")
// @throws[UnknownStickerTypeException]
def check (stickerFile: Array[Byte]): StickerType =
val header = new String(stickerFile.take(50), StandardCharsets.UTF_8)
if header.contains("WEBP") then WEBP
else if header.contains("webm") then WEBM
else if header.contains("PNG") then PNG
else throw UnknownStickerTypeException("Unable to infer file type.")
}

View File

@ -3,12 +3,15 @@ package cc.sukazyo.cono.morny.stickers_get.http
import cats.effect.IO
import cc.sukazyo.cono.morny.core.http.api.HttpService4Api
import cc.sukazyo.cono.morny.core.MornyCoeur
import cc.sukazyo.cono.morny.stickers_get.StickerType
import cc.sukazyo.cono.morny.stickers_get.StickerType.UnknownStickerTypeException
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.File.getContent
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.execute
import com.pengrad.telegrambot.request.GetFile
import com.pengrad.telegrambot.TelegramBot
import org.http4s.HttpRoutes
import org.http4s.{HttpRoutes, MediaType}
import org.http4s.dsl.io.*
import org.http4s.headers.`Content-Type`
import java.io.IOException
@ -23,8 +26,16 @@ class StickerService (using coeur: MornyCoeur) extends HttpService4Api {
try {
given TelegramBot = coeur.account
val file = response.file.getContent
val file_type: MediaType = StickerType.check(file) match
case StickerType.WEBP => MediaType.image.webp
case StickerType.WEBM => MediaType.video.webm
case StickerType.PNG => MediaType.image.png
Ok(file)
.map(_.withContentType(`Content-Type`(file_type)))
} catch {
case e: UnknownStickerTypeException =>
MornyInternalServerError()
.map(_.setMornyInternalErrorHeader(e))
case e: IOException =>
MornyServiceUnavailable()
.map(_.setMornyInternalErrorHeader(e))

View File

@ -4,6 +4,14 @@ object StringEnsure {
extension (str: String) {
/** Take the first line of this String.
*
* It will find the first `\n` (unicode 0x0a, aka. LF) or `\n` (unicode 0x0e, aka. CR)
* and take all the chars before it, and ignores all the contents after it.
*/
def firstLine : String =
str.takeWhile(c => (c != '\n') && (c != '\r'))
/** Ensure the string have a length not smaller that the given length.
*
* If the length of the string is smaller than the given length, then the string will be padded