diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/event/MornyOnInlineQuery.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/event/MornyOnInlineQuery.scala
index e8f4069..4d92f83 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/bot/event/MornyOnInlineQuery.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/bot/event/MornyOnInlineQuery.scala
@@ -28,6 +28,8 @@ class MornyOnInlineQuery (using queryManager: MornyQueries) (using coeur: MornyC
if (r isPersonal) isPersonal = true
resultAnswers += r.result
}
+ cacheTime = 1
+ logger debug "Inline Query remote caches is DISABLED, you may received duplicate queries logs."
if (results isEmpty) return;
diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnGetSocial.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnGetSocial.scala
index 807da28..7463a46 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnGetSocial.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/bot/event/OnGetSocial.scala
@@ -66,11 +66,11 @@ object OnGetSocial {
case Left(texts) =>
weibo.guessWeiboStatusUrl(texts.trim)
case Right(url) =>
- weibo.parseWeiboStatusUrl(url.trim).toList
- }.map(f => {
+ weibo.parseWeiboStatusUrl(url.trim).map(url -> _).toList
+ }.map { (url, status) =>
succeed += 1
- tryFetchSocialOfWeibo(f)
- })
+ tryFetchSocialOfWeibo(status, url)
+ }
{
val bilibiliVideos: List[BiliVideoId] = text match
@@ -124,13 +124,13 @@ object OnGetSocial {
"Error on requesting FixTweet API\n" + exceptionLog(e)
coeur.daemons.reporter.exception(e, "Error on requesting FixTweet API")
- private def tryFetchSocialOfWeibo (url: weibo.StatusUrlInfo)(using replyChat: Long, replyToMessage: Int)(using coeur: MornyCoeur) =
+ private def tryFetchSocialOfWeibo (url: weibo.StatusUrlInfo, rawUrl: String)(using replyChat: Long, replyToMessage: Int)(using coeur: MornyCoeur) =
import io.circe.{DecodingFailure, ParsingFailure}
import sttp.client3.{HttpError, SttpClientException}
import weibo.MApi
try {
val api = MApi.Fetch.statuses_show(url.id)
- SocialWeiboParser.parseMStatus(api).outputToTelegram
+ SocialWeiboParser.parseMStatus(api)(rawUrl).outputToTelegram
} catch
case e: HttpError[?] =>
coeur.account exec SendMessage(
diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolSocialContent.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolSocialContent.scala
index 6e20066..3006c65 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolSocialContent.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolSocialContent.scala
@@ -52,17 +52,17 @@ class ShareToolSocialContent extends ITelegramQuery {
SocialTwitterParser.parseFXTweet(FXApi.Fetch.status(Some(tweet.statusPath), tweet.statusId))
.genInlineQueryResults(using
"morny/share/tweet/content", tweet.statusId,
- "Twitter Tweet Content"
+ "[Twitter]"
)
}
}
private def weiboStatus (query: String): List[InlineQueryUnit[_]] = {
- weibo.guessWeiboStatusUrl(query).flatMap { status =>
- SocialWeiboParser.parseMStatus(MApi.Fetch.statuses_show(status.id))
+ weibo.guessWeiboStatusUrl(query).flatMap { (url, status) =>
+ SocialWeiboParser.parseMStatus(MApi.Fetch.statuses_show(status.id))(url)
.genInlineQueryResults(using
"morny/share/weibo/status/content", status.id,
- "Weibo Content"
+ "[Weibo]"
)
}
}
diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolTwitter.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolTwitter.scala
index a950f86..330568f 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolTwitter.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolTwitter.scala
@@ -29,11 +29,15 @@ class ShareToolTwitter extends ITelegramQuery {
getQueryTweetId(ID_PREFIX_FX, tweet),
getTweetName(TITLE_FX, tweet),
s"https://fxtwitter.com/${tweet.statusPath}"
+ ).description(
+ "URL only, and Fix-Tweet web preview available."
)),
InlineQueryUnit(InlineQueryResultArticle(
getQueryTweetId(ID_PREFIX_VX, tweet),
getTweetName(TITLE_VX, tweet),
s"https://vxtwitter.com/${tweet.statusPath}"
+ ).description(
+ "URL only, and VxTwitter web preview available."
))
)
)
diff --git a/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolXhs.scala b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolXhs.scala
index a91ea76..c461d65 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolXhs.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/bot/query/ShareToolXhs.scala
@@ -32,7 +32,7 @@ class ShareToolXhs extends ITelegramQuery {
getTitle(xhsLink),
xhsLink.link
).description(
- "URL only." + (if maybeFromShare.nonEmpty then s" from $maybeFromShare" else "")
+ "URL only." + (if maybeFromShare.nonEmpty then s" from ${maybeFromShare.get}" else "")
))
)
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 0c153d2..38d7761 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
@@ -30,11 +30,13 @@ import com.pengrad.telegrambot.request.{SendMediaGroup, SendMessage}
* parser/formatter implementation.
*/
case class SocialContent (
+ title: String,
+ description: String,
text_html: String,
text_withPicPlaceholder: String,
medias: List[SocialMedia],
medias_mosaic: Option[SocialMedia] = None,
- thumbnail: Option[SocialMedia] = None
+ thumbnail: Option[SocialMedia] = None,
) {
def thumbnailOrElse[T] (orElse: T): String | T =
@@ -61,31 +63,55 @@ 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.
InlineQueryUnit(InlineQueryResultPhoto(
s"[$id_head/photo/mosaic]$id_param",
medias_mosaic.get.asInstanceOf[SocialMediaWithUrl].url,
thumbnailOrElse(medias_mosaic.get.asInstanceOf[SocialMediaWithUrl].url)
- ).title(s"$name").caption(text_html).parseMode(ParseMode.HTML)) :: Nil
+ ).title(
+ s"$name $title"
+ ).description(
+ s"Pictures are 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").caption(text_html).parseMode(ParseMode.HTML)) :: Nil
+ ).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 (text only)",
+ s"$name $title",
InputTextMessageContent(text_withPicPlaceholder).parseMode(ParseMode.HTML)
+ ).description(
+ s"Plain text only. $description"
)) :: Nil
else
+ // There are never any medias.
InlineQueryUnit(InlineQueryResultArticle(
s"[$id_head/text]$id_param",
- s"$name",
+ s"$name $title",
InputTextMessageContent(text_html).parseMode(ParseMode.HTML)
+ ).description(
+ description
)) :: Nil
) ::: Nil
}
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 b8cef11..8bf591f 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
@@ -5,6 +5,8 @@ import cc.sukazyo.cono.morny.data.social.SocialContent.SocialMediaType.{Photo, V
import cc.sukazyo.cono.morny.extra.twitter.{FXApi, FXTweet}
import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramParseEscape.escapeHtml as h
+import cc.sukazyo.cono.morny.util.StringEnsure.ensureNotExceed
+
object SocialTwitterParser {
def parseFXTweet_forMediaPlaceholderInContent (tweet: FXTweet): String =
@@ -21,7 +23,7 @@ object SocialTwitterParser {
// language=html
s"""❌ Fix-Tweet ${api.code}
|${h(api.message)}""".stripMargin
- SocialContent(content, content, Nil)
+ SocialContent("ERROR", "ERROR", content, content, Nil)
case Some(tweet) =>
val content: String =
// language=html
@@ -39,9 +41,11 @@ object SocialTwitterParser {
|
|💬${tweet.replies} 🔗${tweet.retweets} ❤️${tweet.likes}
|${h(tweet.created_at)}""".stripMargin
+ val title: String = tweet.text.ensureNotExceed(35)
+ val description: String = tweet.url
tweet.media match
case None =>
- SocialContent(content, content_withMediasPlaceholder, Nil)
+ SocialContent(title, description, content, content_withMediasPlaceholder, Nil)
case Some(media) =>
val mediaGroup: List[SocialMedia] =
(
@@ -60,7 +64,11 @@ object SocialTwitterParser {
val mediaMosaic = media.mosaic match
case Some(mosaic) => Some(SocialMediaWithUrl(mosaic.formats.jpeg)(Photo))
case None => None
- SocialContent(content, content_withMediasPlaceholder, mediaGroup, mediaMosaic, thumbnail)
+ SocialContent(
+ if title.nonEmpty then title else
+ s"from ${tweet.author.name}",
+ description, content, content_withMediasPlaceholder, mediaGroup, mediaMosaic, thumbnail
+ )
}
}
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 7acaa08..96ee634 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
@@ -7,6 +7,8 @@ import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramParseEscape.{cleanupH
import io.circe.{DecodingFailure, ParsingFailure}
import sttp.client3.{HttpError, SttpClientException}
+import cc.sukazyo.cono.morny.util.StringEnsure.ensureNotExceed
+
object SocialWeiboParser {
def parseMStatus_forPicPreview (status: MStatus): String =
@@ -24,7 +26,7 @@ object SocialWeiboParser {
case None => ""
@throws[HttpError[?] | SttpClientException | ParsingFailure | DecodingFailure]
- def parseMStatus (api: MApi[MStatus]): SocialContent = {
+ def parseMStatus (api: MApi[MStatus])(originUrl: String): SocialContent = {
val content =
// language=html
s"""🔸${h(api.data.user.screen_name)}
@@ -39,12 +41,18 @@ object SocialWeiboParser {
|${ch(api.data.text)}${parseMStatus_forPicPreview(api.data)}
|${parseMStatus_forRetweeted(api.data)}
|${h(api.data.created_at)}""".stripMargin
+ val title = api.data.text.ensureNotExceed(35)
+ val description: String = originUrl
api.data.pics match
case None =>
- SocialContent(content, content_withPicPlaceholder, Nil)
+ SocialContent(title, description, content, content_withPicPlaceholder, Nil)
case Some(pics) =>
val mediaGroup = pics.map(f => SocialMediaWithBytesData(MApi.Fetch.pic(f.large.url))(Photo))
- SocialContent(content, content_withPicPlaceholder, mediaGroup)
+ SocialContent(
+ if title.nonEmpty then title else
+ s"from ${api.data.user.screen_name}",
+ description, content, content_withPicPlaceholder, mediaGroup
+ )
}
}
diff --git a/src/main/scala/cc/sukazyo/cono/morny/extra/weibo/package.scala b/src/main/scala/cc/sukazyo/cono/morny/extra/weibo/package.scala
index abf4e30..b63e929 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/extra/weibo/package.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/extra/weibo/package.scala
@@ -30,9 +30,9 @@ package object weibo {
case REGEX_WEIBO_STATUS_URL(_, uid, id, _) => Some(StatusUrlInfo(uid, id))
case _ => None
- def guessWeiboStatusUrl (text: String): List[StatusUrlInfo] =
+ def guessWeiboStatusUrl (text: String): List[(String, StatusUrlInfo)] =
REGEX_WEIBO_STATUS_URL.findAllMatchIn(text).map(matches => {
- StatusUrlInfo(matches.group(2), matches.group(3))
+ matches.group(0) -> StatusUrlInfo(matches.group(2), matches.group(3))
}).toList
def genWeiboStatusUrl (url: StatusUrlInfo): String =
diff --git a/src/main/scala/cc/sukazyo/cono/morny/util/StringEnsure.scala b/src/main/scala/cc/sukazyo/cono/morny/util/StringEnsure.scala
index 3fd795e..cfdbf72 100644
--- a/src/main/scala/cc/sukazyo/cono/morny/util/StringEnsure.scala
+++ b/src/main/scala/cc/sukazyo/cono/morny/util/StringEnsure.scala
@@ -12,6 +12,11 @@ object StringEnsure {
} else str
}
+ def ensureNotExceed (size: Int, ellipsis: String = "..."): String = {
+ if (str.length <= size) str
+ else str.take(size) + ellipsis
+ }
+
def deSensitive (keepStart: Int = 2, keepEnd: Int = 4, sensitive_cover: Char = '*'): String =
(str take keepStart) + (sensitive_cover.toString*(str.length-keepStart-keepEnd)) + (str takeRight keepEnd)