cha inline social content results rules

now it follows the following rules:

1. If there contains images
  1.1 If there supports mosaic image, then provide a result with mosaic image with text content.
  1.2 If the previous one is not supported, then provide a result with the first image with text content.
  1.3 If the previous two are not supported, then provide a result with only text content.
  1.4 And for each image that supports, provide a image only (with a source url) result.
2. If there contains no image, just provide the text content result.
This commit is contained in:
A.C.Sukazyo Eyre 2024-09-11 22:11:46 +08:00
parent bd204a3cd7
commit 7c90b1f9af
Signed by: Eyre_S
GPG Key ID: C17CE40291207874
3 changed files with 78 additions and 48 deletions

View File

@ -9,6 +9,8 @@ import cc.sukazyo.cono.morny.util.tgapi.formatting.NamingUtils.inlineQueryId
import com.pengrad.telegrambot.model.request.*
import com.pengrad.telegrambot.request.{SendMediaGroup, SendMessage}
import scala.collection.mutable.ListBuffer
/** Model of social networks' status. for example twitter tweet or
* weibo status.
*
@ -61,9 +63,12 @@ case class SocialContent (
}
def genInlineQueryResults (using id_head: String, id_param: Any, name: String): List[InlineQueryUnit[?]] = {
(
if (medias_mosaic nonEmpty) && (medias_mosaic.get.t == Photo) && medias_mosaic.get.isInstanceOf[SocialMediaWithUrl] then
// It has multi medias, and the mosaic version is provided.
val results = ListBuffer[InlineQueryUnit[?]]()
// It has multi medias, and the mosaic version is provided,
// uses the mosaic version to provide an image+text result.
if (medias.length > 1) && (medias_mosaic nonEmpty) && (medias_mosaic.get.t == Photo) && medias_mosaic.get.isInstanceOf[SocialMediaWithUrl] then
results +=
InlineQueryUnit(InlineQueryResultPhoto(
s"[$id_head/photo/mosaic]$id_param",
medias_mosaic.get.asInstanceOf[SocialMediaWithUrl].url,
@ -71,49 +76,73 @@ case class SocialContent (
).title(
s"$name $title"
).description(
s"Pictures are combined. $description"
s"Medias combined. $description"
).caption(
text_html
).parseMode(ParseMode.HTML)) :: Nil
else if (medias nonEmpty) && (medias.head.t == Photo) then
val media = medias.head
media match
case media_url: SocialMediaWithUrl =>
// the medias is provided, and the first one is in URL format.
// it may still contain multiple medias.
// although in only two implementations, the Twitter implementation will always give a mosaic
// pic; and the Weibo implementation never uses URL formatted medias.
InlineQueryUnit(InlineQueryResultPhoto(
s"[$id_head/photo/0]$id_param",
media_url.url,
thumbnailOrElse(media_url.url)
).title(
s"$name $title"
).description(
s"Pic 1. $description"
).caption(
text_html
).parseMode(ParseMode.HTML)) :: Nil
case _ =>
// the medias are provided but are not in URL format.
// in this case, the plain text version will be used.
InlineQueryUnit(InlineQueryResultArticle(
s"[$id_head/text_only]$id_param",
s"$name $title",
InputTextMessageContent(text_withPicPlaceholder).parseMode(ParseMode.HTML)
).description(
s"Plain text only. $description"
)) :: Nil
else
// There are never any medias.
).parseMode(ParseMode.HTML))
// It has medias, and the first media is URL formatted, then provide the first media with content,
// uses the first media to provide an image1+text result.
else if (medias nonEmpty) && medias.head.isInstanceOf[SocialMediaWithUrl] then
val media = medias.head.asInstanceOf[SocialMediaWithUrl]
results +=
InlineQueryUnit(InlineQueryResultPhoto(
s"[$id_head/photo/0/contented]$id_param",
media.url,
thumbnailOrElse(media.url)
).title(
s"$name $title"
).description(
s"Pic 1/${medias.length}, with content. $description"
).caption(
text_html
).parseMode(ParseMode.HTML))
// It has medias, and all the previous method failed,
// then a plain text version will be provided.
else if medias.nonEmpty then
results +=
InlineQueryUnit(InlineQueryResultArticle(
s"[$id_head/text_only]$id_param",
s"$name $title",
InputTextMessageContent(text_withPicPlaceholder).parseMode(ParseMode.HTML)
).description(
s"Plain text. $description"
))
// The medias is provided, iterate all the medias and provide a media-only result.
// Note that the media are not URL formatted will be ignored.
val resultsMediaOnly: IndexedSeq[InlineQueryUnit[?]] = if medias nonEmpty then for mediaId <- medias.indices yield {
val media = medias(mediaId)
media match
case media_url: SocialMediaWithUrl =>
InlineQueryUnit(InlineQueryResultPhoto(
s"[$id_head/photo/$mediaId/bare]$id_param",
media_url.url,
thumbnailOrElse(media_url.url)
).title(
s"$name $title"
).description(
s"Pic ${mediaId+1}/${medias.length}, pic only. $description"
).caption(
media_url.sourceUrl
))
case _ => null
} else Nil.toIndexedSeq
results ++= resultsMediaOnly
// If there are no any medias, use the plain text mode.
if results isEmpty then
results +=
InlineQueryUnit(InlineQueryResultArticle(
s"[$id_head/text]$id_param",
s"$name $title",
InputTextMessageContent(text_html).parseMode(ParseMode.HTML)
).description(
description
)) :: Nil
) ::: Nil
))
results.toList
}
}
@ -123,16 +152,16 @@ object SocialContent {
enum SocialMediaType:
case Photo
case Video
sealed trait SocialMedia(val t: SocialMediaType) {
sealed trait SocialMedia(val t: SocialMediaType, val sourceUrl: String) {
def genTelegramInputMedia: InputMedia[?]
}
case class SocialMediaWithUrl (url: String)(t: SocialMediaType) extends SocialMedia(t) {
case class SocialMediaWithUrl (url: String)(t: SocialMediaType, sourceUrl: String) extends SocialMedia(t, sourceUrl) {
override def genTelegramInputMedia: InputMedia[_] =
t match
case Photo => InputMediaPhoto(url)
case Video => InputMediaVideo(url)
}
case class SocialMediaWithBytesData (data: Array[Byte])(t: SocialMediaType) extends SocialMedia(t) {
case class SocialMediaWithBytesData (data: Array[Byte])(t: SocialMediaType, sourceUrl: String) extends SocialMedia(t, sourceUrl) {
override def genTelegramInputMedia: InputMedia[_] =
t match
case Photo => InputMediaPhoto(data)

View File

@ -51,18 +51,18 @@ object SocialTwitterParser {
(
media.photos match
case None => List.empty
case Some(photos) => for i <- photos yield SocialMediaWithUrl(i.url)(Photo)
case Some(photos) => for i <- photos yield SocialMediaWithUrl(i.url)(Photo, tweet.url)
) ::: (
media.videos match
case None => List.empty
case Some(videos) => for i <- videos yield SocialMediaWithUrl(i.url)(Video)
case Some(videos) => for i <- videos yield SocialMediaWithUrl(i.url)(Video, tweet.url)
)
val thumbnail =
if media.videos.nonEmpty then
Some(SocialMediaWithUrl(media.videos.get.head.thumbnail_url)(Photo))
Some(SocialMediaWithUrl(media.videos.get.head.thumbnail_url)(Photo, tweet.url))
else None
val mediaMosaic = media.mosaic match
case Some(mosaic) => Some(SocialMediaWithUrl(mosaic.formats.jpeg)(Photo))
case Some(mosaic) => Some(SocialMediaWithUrl(mosaic.formats.jpeg)(Photo, tweet.url))
case None => None
SocialContent(
if title.nonEmpty then title else

View File

@ -27,27 +27,28 @@ object SocialWeiboParser {
@throws[HttpError[?] | SttpClientException | ParsingFailure | DecodingFailure]
def parseMStatus (api: MApi[MStatus])(originUrl: String): SocialContent = {
val statusUrl: String = genWeiboStatusUrl(StatusUrlInfo(api.data.user.id.toString, api.data.id))
val content =
// language=html
s"""🔸<b><a href="${api.data.user.profile_url}">${h(api.data.user.screen_name)}</a></b>
|
|${ch(api.data.text)}
|${parseMStatus_forRetweeted(api.data)}
|<i><a href="${genWeiboStatusUrl(StatusUrlInfo(api.data.user.id.toString, api.data.id))}">${h(api.data.created_at)}</a></i>""".stripMargin
|<i><a href="$statusUrl">${h(api.data.created_at)}</a></i>""".stripMargin
val content_withPicPlaceholder =
// language=html
s"""🔸<b><a href="${api.data.user.profile_url}">${h(api.data.user.screen_name)}</a></b>
|
|${ch(api.data.text)}${parseMStatus_forPicPreview(api.data)}
|${parseMStatus_forRetweeted(api.data)}
|<i><a href="${genWeiboStatusUrl(StatusUrlInfo(api.data.user.id.toString, api.data.id))}">${h(api.data.created_at)}</a></i>""".stripMargin
|<i><a href="$statusUrl">${h(api.data.created_at)}</a></i>""".stripMargin
val title = api.data.text.ensureNotExceed(35)
val description: String = originUrl
api.data.pics match
case None =>
SocialContent(title, description, content, content_withPicPlaceholder, Nil)
case Some(pics) =>
val mediaGroup = pics.map(f => SocialMediaWithBytesData(MApi.Fetch.pic(f.large.url))(Photo))
val mediaGroup = pics.map(f => SocialMediaWithBytesData(MApi.Fetch.pic(f.large.url))(Photo, statusUrl))
SocialContent(
if title.nonEmpty then title else
s"from ${api.data.user.screen_name}",