change Morny use sttp as http client

This commit is contained in:
A.C.Sukazyo Eyre 2023-10-19 21:43:29 +08:00
parent a32018d600
commit c19134811d
Signed by: Eyre_S
GPG Key ID: C17CE40291207874
9 changed files with 123 additions and 103 deletions

View File

@ -77,22 +77,26 @@ repositories {
dependencies { dependencies {
api "org.scala-lang:scala3-library_3:${proj_scala_lib}" api group: 'org.scala-lang', name: 'scala3-library_3', version: proj_scala_lib
compileOnlyApi "com.github.spotbugs:spotbugs-annotations:${lib_spotbugs_v}" final scala = (String name) -> "${name}_$proj_scala_api"
compileOnlyApi group: 'com.github.spotbugs', name: 'spotbugs-annotations', version: lib_spotbugs_v
implementation "cc.sukazyo:messiva:${lib_messiva_v}" implementation group: 'cc.sukazyo', name: 'messiva', version: lib_messiva_v
implementation "cc.sukazyo:resource-tools:${lib_resourcetools_v}" implementation group: 'cc.sukazyo', name: 'resource-tools', version: lib_resourcetools_v
testImplementation "cc.sukazyo:resource-tools:${lib_resourcetools_v}" testImplementation group: 'cc.sukazyo', name: 'resource-tools', version: lib_resourcetools_v
implementation "com.github.pengrad:java-telegram-bot-api:${lib_javatelegramapi_v}" implementation group: 'com.github.pengrad', name: 'java-telegram-bot-api', version: lib_javatelegramapi_v
implementation "com.squareup.okhttp3:okhttp:${lib_okhttp_v}" implementation group: 'com.softwaremill.sttp.client3', name: scala('core'), version: lib_sttp_v
implementation "com.google.code.gson:gson:${lib_gson_v}" implementation group: 'com.softwaremill.sttp.client3', name: scala('okhttp-backend'), version: lib_sttp_v
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: lib_okhttp_v
implementation group: 'com.google.code.gson', name: 'gson', version: lib_gson_v
testImplementation group: 'org.scalatest', name: scala('scalatest'), version: lib_scalatest_v
testImplementation group: 'org.scalatest', name: scala('scalatest-freespec'), version: lib_scalatest_v
testRuntimeOnly group: 'org.scala-lang.modules', name: scala('scala-xml'), version: lib_scalamodule_xml_v
testImplementation "org.scalatest:scalatest_$proj_scala_api:${lib_scalatest_v}"
testImplementation "org.scalatest:scalatest-freespec_$proj_scala_api:${lib_scalatest_v}"
testRuntimeOnly "org.scala-lang.modules:scala-xml_$proj_scala_api:${lib_scalamodule_xml_v}"
testRuntimeOnly 'com.vladsch.flexmark:flexmark-all:0.64.6'
// for generating HTML report // required by gradle-scalatest plugin // for generating HTML report // required by gradle-scalatest plugin
testRuntimeOnly group: 'com.vladsch.flexmark', name: 'flexmark-all', version: '0.64.6'
} }

View File

@ -5,7 +5,7 @@ MORNY_ARCHIVE_NAME = morny-coeur
MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono MORNY_CODE_STORE = https://github.com/Eyre-S/Coeur-Morny-Cono
MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s MORNY_COMMIT_PATH = https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s
VERSION = 1.2.1-pre1 VERSION = 1.2.1-pre2
USE_DELTA = false USE_DELTA = false
VERSION_DELTA = VERSION_DELTA =
@ -22,6 +22,7 @@ lib_resourcetools_v = 0.2.2
lib_javatelegramapi_v = 6.2.0 lib_javatelegramapi_v = 6.2.0
lib_sttp_v = 3.9.0
lib_okhttp_v = 4.11.0 lib_okhttp_v = 4.11.0
lib_gson_v = 2.10.1 lib_gson_v = 2.10.1

View File

@ -8,6 +8,7 @@ import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
import com.pengrad.telegrambot.model.Update import com.pengrad.telegrambot.model.Update
import com.pengrad.telegrambot.model.request.ParseMode import com.pengrad.telegrambot.model.request.ParseMode
import com.pengrad.telegrambot.request.{SendMessage, SendSticker} import com.pengrad.telegrambot.request.{SendMessage, SendSticker}
import sttp.client3.{HttpError, SttpClientException}
import java.io.IOException import java.io.IOException
import scala.language.postfixOps import scala.language.postfixOps
@ -71,7 +72,7 @@ class Nbnhhsh (using coeur: MornyCoeur) extends ITelegramCommand {
message toString message toString
).parseMode(ParseMode HTML).replyToMessageId(event.message.messageId) ).parseMode(ParseMode HTML).replyToMessageId(event.message.messageId)
} catch case e: IOException => { } catch case e: (HttpError[_] | SttpClientException) => {
coeur.account exec SendMessage( coeur.account exec SendMessage(
event.message.chat.id, event.message.chat.id,
s"""[Exception] in query: s"""[Exception] in query:

View File

@ -1,12 +1,13 @@
package cc.sukazyo.cono.morny.data package cc.sukazyo.cono.morny.data
import cc.sukazyo.cono.morny.util.BiliTool import cc.sukazyo.cono.morny.util.BiliTool
import cc.sukazyo.cono.morny.util.SttpPublic.Schemes
import cc.sukazyo.cono.morny.util.UseSelect.select import cc.sukazyo.cono.morny.util.UseSelect.select
import okhttp3.{HttpUrl, OkHttpClient, Request} import sttp.client3.{basicRequest, ignore, HttpError, SttpClientException}
import sttp.client3.okhttp.OkHttpSyncBackend
import sttp.model.Uri
import java.io.IOException
import scala.util.matching.Regex import scala.util.matching.Regex
import scala.util.Using
object BilibiliForms { object BilibiliForms {
@ -51,11 +52,7 @@ object BilibiliForms {
case _ => throw IllegalArgumentException(s"not a valid Bilibili video link: $url") case _ => throw IllegalArgumentException(s"not a valid Bilibili video link: $url")
private val httpClient = OkHttpClient private val httpClient = OkHttpSyncBackend()
.Builder()
.followSslRedirects(true)
.followRedirects(false)
.build()
/** get the bilibili video url from b23.tv share url. /** get the bilibili video url from b23.tv share url.
* *
@ -68,28 +65,32 @@ object BilibiliForms {
* @return bilibili video url with tracking params * @return bilibili video url with tracking params
*/ */
@throws[IllegalStateException|IllegalArgumentException] @throws[IllegalStateException|IllegalArgumentException]
def destructB23Url (url: String): String = def destructB23Url (url: String): String = {
val _url: HttpUrl = HttpUrl.parse(
if url startsWith "http://" then url.replaceFirst("http://", "https://") else url val uri = try Uri.unsafeParse(url).scheme(Schemes.HTTPS) catch
) case e: IllegalArgumentException => throw IllegalArgumentException("not a b23.tv url", e)
if _url == null then throw IllegalArgumentException("not a valid url: " + url) if uri.host.orNull != "b23.tv" then throw
if _url.host != "b23.tv" then throw IllegalArgumentException(s"not a b23 share link: $url") IllegalArgumentException(s"not a b23.tv url: $uri")
if (!_url.pathSegments.isEmpty) && _url.pathSegments.get(0).matches(REGEX_BILI_ID.regex) then else if uri.pathSegments.segments.size < 1 then
throw IllegalArgumentException(s"is a b23 video link: $url ; (use parse_videoUrl directly)") throw IllegalArgumentException(s"empty b23.tv url: $uri")
val result: Option[String] = else if uri.pathSegments.segments.head.v matches REGEX_BILI_ID.regex then
throw IllegalArgumentException(s"is a b23 video link: $uri . (use parse_videoUrl instead)")
try { try {
Using(httpClient.newCall(Request.Builder().url(_url).build).execute()) { response => val response = basicRequest
if response.isRedirect then .get(uri)
val _u = response header "Location" .followRedirects(false)
if _u != null then .response(ignore)
Some(_u) .send(httpClient)
else throw IllegalStateException("unable to get b23.tv redir location from: " + response) try response.header("Location").get
else throw IllegalStateException("unable to get b23.tv redir location from: " + response) catch case _: NoSuchElementException =>
}.get throw IllegalStateException("unable to get b23.tv redir location from: " + response)
} catch case e: IOException => } catch
throw IllegalStateException("get b23.tv failed.", e) case e: HttpError[_] =>
result match throw IllegalStateException("failed parse b23.tv response.", e)
case Some(_result) => _result case e: SttpClientException =>
case None => throw IllegalStateException("unable to parse from b23.tv .") throw IllegalStateException("failed request from b23.tv: ", e)
}
} }

View File

@ -1,11 +1,9 @@
package cc.sukazyo.cono.morny.data package cc.sukazyo.cono.morny.data
import cc.sukazyo.cono.morny.util.OkHttpPublic.MediaTypes
import com.google.gson.Gson import com.google.gson.Gson
import okhttp3.{OkHttpClient, Request, RequestBody, ResponseBody} import sttp.client3.{asString, basicRequest, HttpError, SttpClientException, UriContext}
import sttp.client3.okhttp.OkHttpSyncBackend
import java.io.IOException import sttp.model.MediaType
import scala.util.Using
object NbnhhshQuery { object NbnhhshQuery {
@ -14,24 +12,19 @@ object NbnhhshQuery {
private case class GuessRequest (text: String) private case class GuessRequest (text: String)
private val API_URL = "https://lab.magiconch.com/api/nbnhhsh/" private val API_URL = uri"https://lab.magiconch.com/api/nbnhhsh/"
private val API_GUESS_METHOD = "guess/" private val API_GUESS_METHOD = uri"$API_URL/guess/"
private val httpClient = OkHttpClient() private val httpClient = OkHttpSyncBackend()
@throws[IOException] @throws[HttpError[_]|SttpClientException]
def sendGuess (text: String): GuessResult = { def sendGuess (text: String): GuessResult = {
val requestJsonText = Gson().toJson(GuessRequest(text)) val http = basicRequest
val request = Request.Builder() .body(Gson().toJson(GuessRequest(text))).contentType(MediaType.ApplicationJson)
.url(API_URL + API_GUESS_METHOD) .post(API_GUESS_METHOD)
.post(RequestBody.create(requestJsonText, MediaTypes.JSON)) .response(asString.getRight)
.build .send(httpClient)
Using (httpClient.newCall(request).execute) { response => Gson().fromJson(s"{ 'words': ${http.body} }", classOf[GuessResult])
val body = response.body
if body eq null then throw IOException("Nbnhhsh Request: body is null.")
val x = s"{ 'words': ${body.string} }"
Gson().fromJson(x, classOf[GuessResult])
}.get
} }
} }

View File

@ -1,27 +1,29 @@
package cc.sukazyo.cono.morny.data.ip186 package cc.sukazyo.cono.morny.data.ip186
import okhttp3.{OkHttpClient, Request} import cc.sukazyo.cono.morny.util.SttpPublic.Schemes
import sttp.client3.{asString, basicRequest, HttpError, SttpClientException, UriContext}
import sttp.client3.okhttp.OkHttpSyncBackend
import sttp.model.Uri
import java.io.IOException import java.io.IOException
import scala.language.postfixOps import scala.language.postfixOps
import scala.util.Using
object IP186QueryHandler { object IP186QueryHandler {
private val SITE_URL = "https://ip.186526.xyz/" private val SITE_HOST = "ip.186526.xyz"
private val QUERY_PARAM_IP = "type=json&format=true" private val QUERY_PARAM_IP = Map("type" -> "json", "format" -> "true")
private val QUERY_PARAM_WHOIS = "type=plain" private val QUERY_PARAM_WHOIS = Map("type" -> "plain")
private val httpClient = OkHttpClient() private val httpClient = OkHttpSyncBackend()
@throws[IOException] @throws[IOException]
def query_ip (ip: String): IP186Response = def query_ip (ip: String): IP186Response =
commonQuery(SITE_URL + ip, QUERY_PARAM_IP) commonQuery(uri"/$ip?$QUERY_PARAM_IP")
@throws[IOException] @throws[IOException]
//noinspection ScalaWeakerAccess //noinspection ScalaWeakerAccess
def query_whois (domain: String): IP186Response = def query_whois (domain: String): IP186Response =
commonQuery(SITE_URL+"whois/"+domain, QUERY_PARAM_WHOIS) commonQuery(uri"/whois/$domain?$QUERY_PARAM_WHOIS")
@throws[IOException] @throws[IOException]
def query_whoisPretty (domain: String): IP186Response = def query_whoisPretty (domain: String): IP186Response =
@ -29,13 +31,28 @@ object IP186QueryHandler {
IP186Response(raw.url, raw.body substring(0, (raw.body indexOf "<<<")+3)) IP186Response(raw.url, raw.body substring(0, (raw.body indexOf "<<<")+3))
@throws[IOException] @throws[IOException]
private def commonQuery (requestUrl: String, queryParam: String): IP186Response = { private def commonQuery (requestPath: Uri): IP186Response = {
val request = Request.Builder().url(requestUrl + "?" + queryParam).build try
Using ((httpClient newCall request) execute) { response => val uri = requestPath.scheme(Schemes.HTTPS).host(SITE_HOST)
val _body = response.body IP186Response(
if _body eq null then throw IOException("Response of ip186: body is empty!") uri.toString,
IP186Response(requestUrl, _body.string) basicRequest
}.get .get(uri)
.response(asString.getRight)
.send(httpClient)
.body
)
catch
case e: SttpClientException =>
throw IOException("request to ip186 failed: " + e.getMessage, e)
case e: HttpError[_] =>
throw IOException("failed get from ip186: " + e.getMessage, e)
// val request = Request.Builder().url(requestUrl + "?" + queryParam).build
// Using ((httpClient newCall request) execute) { response =>
// val _body = response.body
// if _body eq null then throw IOException("Response of ip186: body is empty!")
// IP186Response(requestUrl, _body.string)
// }.get
} }
} }

View File

@ -1,13 +0,0 @@
package cc.sukazyo.cono.morny.util
import okhttp3.MediaType
/** some public values of [[okhttp3]] */
object OkHttpPublic {
/** predefined [[okhttp3]] [[MediaType]]s */
object MediaTypes:
/** [[MediaType]] of [[https://en.wikipedia.org/wiki/JSON JSON]]. using encoding ''UTF-8'' */
val JSON: MediaType = MediaType.get("application/json; charset=utf-8")
}

View File

@ -0,0 +1,10 @@
package cc.sukazyo.cono.morny.util
object SttpPublic {
object Schemes {
val HTTP = "http"
val HTTPS = "https"
}
}

View File

@ -1,29 +1,35 @@
package cc.sukazyo.cono.morny.util.tgapi.formatting package cc.sukazyo.cono.morny.util.tgapi.formatting
import com.pengrad.telegrambot.model.User import com.pengrad.telegrambot.model.User
import okhttp3.{OkHttpClient, Request} import sttp.client3.{asString, basicRequest, HttpError, SttpClientException, UriContext}
import sttp.client3.okhttp.OkHttpSyncBackend
import java.io.IOException import java.io.IOException
import scala.util.matching.Regex import scala.util.matching.Regex
import scala.util.Using
object TelegramUserInformation { object TelegramUserInformation {
private val DC_QUERY_SOURCE_SITE = "https://t.me/"
private val DC_QUERY_PROCESSOR_REGEX: Regex = "(cdn[1-9]).tele(sco.pe|gram-cdn.org)"r private val DC_QUERY_PROCESSOR_REGEX: Regex = "(cdn[1-9]).tele(sco.pe|gram-cdn.org)"r
private val httpClient = OkHttpClient() private val httpClient = OkHttpSyncBackend()
@throws[IllegalArgumentException|IOException] @throws[IllegalArgumentException|IOException]
def getDataCenterFromUser (username: String): String = { def getDataCenterFromUser (username: String): String = {
val request = Request.Builder().url(DC_QUERY_SOURCE_SITE + username).build
Using (httpClient.newCall(request) execute) { response => try
val body = response.body val body = basicRequest
if body eq null then "<empty-upstream-response>" .get(uri"https://t.me/$username")
else DC_QUERY_PROCESSOR_REGEX.findFirstMatchIn(body.string) match .response(asString.getRight)
.send(httpClient)
.body
DC_QUERY_PROCESSOR_REGEX.findFirstMatchIn(body) match
case Some(res) => res.group(1) case Some(res) => res.group(1)
case None => "<no-cdn-information>" case None => "<no-cdn-information>"
} get catch
case _: SttpClientException =>
"<error-http-request>"
case _: HttpError[_] =>
"<error-parse-response>"
} }
def getFormattedInformation (user: User): String = { def getFormattedInformation (user: User): String = {