diff --git a/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialContent.scala b/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialContent.scala
index 38d7761..3858c7e 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialContent.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialContent.scala
@@ -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)
diff --git a/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialTwitterParser.scala b/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialTwitterParser.scala
index 8bf591f..f238a26 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialTwitterParser.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialTwitterParser.scala
@@ -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
diff --git a/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialWeiboParser.scala b/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialWeiboParser.scala
index 96ee634..871f365 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialWeiboParser.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/data/social/SocialWeiboParser.scala
@@ -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"""🔸${h(api.data.user.screen_name)}
|
|${ch(api.data.text)}
|${parseMStatus_forRetweeted(api.data)}
- |${h(api.data.created_at)}""".stripMargin
+ |${h(api.data.created_at)}""".stripMargin
val content_withPicPlaceholder =
// language=html
s"""🔸${h(api.data.user.screen_name)}
|
|${ch(api.data.text)}${parseMStatus_forPicPreview(api.data)}
|${parseMStatus_forRetweeted(api.data)}
- |${h(api.data.created_at)}""".stripMargin
+ |${h(api.data.created_at)}""".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}",