diff --git a/app/src/main/assets/plugins.json b/app/src/main/assets/plugins.json index b3d36ca2..14448cf7 100644 --- a/app/src/main/assets/plugins.json +++ b/app/src/main/assets/plugins.json @@ -7,14 +7,6 @@ "author": "huanchengfly", "version": "1.0", "main_class": "com.huanchengfly.tieba.post.plugins.PluginCommentLookup" - }, - { - "id": "AsoulCnki", - "name": "枝网查重", - "desc": "调用枝网查重 API 查询重复小作文", - "author": "huanchengfly", - "version": "1.0", - "main_class": "com.huanchengfly.tieba.post.plugins.asoulcnki.PluginAsoulCnki" } ] } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/MyURLSpan.java b/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/MyURLSpan.java deleted file mode 100644 index 4c704951..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/MyURLSpan.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.huanchengfly.tieba.post.plugins.asoulcnki; - -import android.content.Context; -import android.text.TextPaint; -import android.text.style.ClickableSpan; -import android.view.View; - -import androidx.annotation.NonNull; - -import com.huanchengfly.tieba.post.R; -import com.huanchengfly.tieba.post.ui.common.theme.utils.ThemeUtils; -import com.huanchengfly.tieba.post.utils.UtilsKt; - -public class MyURLSpan extends ClickableSpan { - public String url; - private final Context context; - - public MyURLSpan(Context context, String url) { - super(); - this.url = url; - this.context = context; - } - - @Override - public void updateDrawState(@NonNull TextPaint ds) { - super.updateDrawState(ds); - ds.setColor(ThemeUtils.getColorByAttr(this.context, R.attr.colorAccent)); - ds.setUnderlineText(false); - } - - @Override - public void onClick(@NonNull View view) { - UtilsKt.launchUrl(context, url); - //context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); - } -} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/PluginAsoulCnki.kt b/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/PluginAsoulCnki.kt deleted file mode 100644 index b8eb66d7..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/PluginAsoulCnki.kt +++ /dev/null @@ -1,176 +0,0 @@ -package com.huanchengfly.tieba.post.plugins.asoulcnki - -import android.graphics.Bitmap -import android.text.SpannableStringBuilder -import android.text.Spanned -import android.view.View -import android.widget.ProgressBar -import android.widget.TextView -import com.huanchengfly.tieba.post.R -import com.huanchengfly.tieba.post.api.models.ThreadContentBean -import com.huanchengfly.tieba.post.components.LinkTouchMovementMethod -import com.huanchengfly.tieba.post.components.spans.MyImageSpan -import com.huanchengfly.tieba.post.plugins.IPlugin -import com.huanchengfly.tieba.post.plugins.asoulcnki.api.CheckApi -import com.huanchengfly.tieba.post.plugins.asoulcnki.models.CheckApiBody -import com.huanchengfly.tieba.post.plugins.interfaces.IApp -import com.huanchengfly.tieba.post.plugins.models.PluginManifest -import com.huanchengfly.tieba.post.plugins.registerMenuItem -import com.huanchengfly.tieba.post.toJson -import com.huanchengfly.tieba.post.ui.common.theme.utils.ThemeUtils -import com.huanchengfly.tieba.post.utils.DisplayUtil -import com.huanchengfly.tieba.post.utils.Util -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.RequestBody.Companion.toRequestBody -import java.text.NumberFormat -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale - -class PluginAsoulCnki(app: IApp, manifest: PluginManifest) : IPlugin(app, manifest) { - override fun onEnable() { - super.onEnable() - registerMenuItem( - "asoul_cnki_check", - context.getString(R.string.plugin_asoul_cnki_check) - ) { data -> - val dialog = app.showLoadingDialog() - val body = CheckApiBody(getPostTextContent(data)).toJson() - launch(Dispatchers.IO + job) { - val result = - CheckApi.instance.checkAsync(body.toRequestBody("application/json, charset=utf-8".toMediaTypeOrNull())) - .await() - launch(Dispatchers.Main + job) { - dialog.cancel() - if (result.code == 0) { - val numberFormatter = NumberFormat.getNumberInstance().apply { - maximumFractionDigits = 2 - minimumFractionDigits = 2 - } - app.showAlertDialog { - setTitle("查重结果") - val percent = "${numberFormatter.format(result.data.rate * 100.0)}%" - val resultForCopy = context.getString( - R.string.plugin_asoul_cnki_result, - formatDateTime("yyyy-MM-dd HH:mm:ss"), - percent, - if (result.data.related.isNotEmpty()) { - context.getString( - R.string.plugin_asoul_cnki_related, - result.data.related[0].replyUrl, - result.data.related[0].reply.mName, - formatDateTime( - "yyyy-MM-dd HH:mm", - result.data.related[0].reply.ctime * 1000L - ) - ) - } else { - "" - } - ) - val view = View.inflate( - context, - R.layout.plugin_asoul_cnki_dialog_check_result, - null - ) - val percentView = view.findViewById(R.id.check_result_percent) - val progress = - view.findViewById(R.id.check_result_progress) - val relatedView = view.findViewById(R.id.check_result_related) - val relatedTitle = - view.findViewById(R.id.check_result_related_title) - val relatedContent = - view.findViewById(R.id.check_result_related_content) - percentView.text = context.getString( - R.string.plugin_asoul_cnki_check_result_percent, - percent - ) - progress.progress = (result.data.rate * 10000).toInt() - if (result.data.related.isNullOrEmpty()) { - relatedView.visibility = View.GONE - } else { - relatedView.visibility = View.VISIBLE - relatedTitle.text = context.getString( - R.string.plugin_asoul_cnki_check_result_related, - result.data.related.size - ) - } - val relatedContentText = SpannableStringBuilder() - result.data.related.forEach { - relatedContentText.appendLink("${it.reply.mName} 的评论", it.replyUrl) - .append("\n") - } - relatedContent.apply { - text = relatedContentText - movementMethod = LinkTouchMovementMethod.getInstance() - } - setView(view) - setPositiveButton(R.string.btn_copy_check_result) { _, _ -> - app.copyText(resultForCopy) - } - setNegativeButton(R.string.btn_close, null) - } - } else { - app.toastShort("查重失败 ${result.code}") - } - } - } - } - } - - private fun SpannableStringBuilder.appendLink( - text: CharSequence, - url: String - ): SpannableStringBuilder { - val spannableStringBuilder = SpannableStringBuilder() - val size = DisplayUtil.sp2px(context, 14f) - val bitmap = Util.tintBitmap( - Bitmap.createScaledBitmap( - Util.getBitmapFromVectorDrawable( - context, - R.drawable.ic_link - ), - size, - size, - true - ), - ThemeUtils.getColorByAttr(context, R.attr.colorAccent) - ) - spannableStringBuilder.append( - "[链接]", - MyImageSpan(context, bitmap), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE - ) - spannableStringBuilder.append(" ") - spannableStringBuilder.append( - text, - MyURLSpan(context, url), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE - ) - return append(spannableStringBuilder) - } - - fun getPostTextContent(item: ThreadContentBean.PostListItemBean): String { - val stringBuilder = StringBuilder() - for (contentBean in item.content ?: emptyList()) { - when (contentBean.type) { - "2" -> contentBean.setText("#(" + contentBean.c + ")") - "3", "20" -> contentBean.setText("[图片]\n") - "10" -> contentBean.setText("[语音]\n") - } - if (contentBean.text != null) { - stringBuilder.append(contentBean.text) - } - } - return stringBuilder.toString() - } - - private fun formatDateTime( - pattern: String, - timestamp: Long = System.currentTimeMillis() - ): String { - return SimpleDateFormat(pattern, Locale.getDefault()).format(Date(timestamp)) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/CheckApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/CheckApi.kt deleted file mode 100644 index 13868183..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/CheckApi.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.huanchengfly.tieba.post.plugins.asoulcnki.api - -import com.huanchengfly.tieba.post.api.retrofit.NullOnEmptyConverterFactory -import com.huanchengfly.tieba.post.api.retrofit.adapter.DeferredCallAdapterFactory -import com.huanchengfly.tieba.post.api.retrofit.converter.gson.GsonConverterFactory -import okhttp3.ConnectionPool -import okhttp3.OkHttpClient -import retrofit2.Retrofit - -object CheckApi { - private val connectionPool = ConnectionPool() - - val instance: ICheckApi by lazy { - Retrofit.Builder() - .baseUrl("https://asoulcnki.asia/") - .addCallAdapterFactory(DeferredCallAdapterFactory()) - .addConverterFactory(NullOnEmptyConverterFactory()) - .addConverterFactory(GsonConverterFactory.create()) - .client(OkHttpClient.Builder().apply { - connectionPool(connectionPool) - sslSocketFactory( - SSLSocketClient.getSSLSocketFactory(), - SSLSocketClient.getX509TrustManager() - ) - hostnameVerifier(SSLSocketClient.getHostnameVerifier()) - }.build()) - .build() - .create(ICheckApi::class.java) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/CommonHeaderInterceptor.kt b/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/CommonHeaderInterceptor.kt deleted file mode 100644 index a21e4c31..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/CommonHeaderInterceptor.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.huanchengfly.tieba.post.plugins.asoulcnki.api - -import com.huanchengfly.tieba.post.api.ParamExpression -import com.huanchengfly.tieba.post.api.forEachNonNull -import okhttp3.Interceptor -import okhttp3.Response - -class CommonHeaderInterceptor(private vararg val additionHeaders: ParamExpression) : Interceptor { - override fun intercept(chain: Interceptor.Chain): Response { - val request = chain.request() - val headers = request.headers - - return chain.proceed(request.newBuilder().apply { - additionHeaders.forEachNonNull { name, value -> - if (headers[name] == null) addHeader(name, value) - } - }.build()) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/ICheckApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/ICheckApi.kt deleted file mode 100644 index 1e7db310..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/ICheckApi.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.huanchengfly.tieba.post.plugins.asoulcnki.api - -import com.huanchengfly.tieba.post.plugins.asoulcnki.models.CheckResult -import kotlinx.coroutines.Deferred -import okhttp3.RequestBody -import retrofit2.http.Body -import retrofit2.http.Headers -import retrofit2.http.POST - -interface ICheckApi { - @POST("/v1/api/check") - @Headers("content-type: application/json;charset=UTF-8") - fun checkAsync( - @Body requestBody: RequestBody - ): Deferred -} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/SSLSocketClient.java b/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/SSLSocketClient.java deleted file mode 100644 index e3064e06..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/api/SSLSocketClient.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.huanchengfly.tieba.post.plugins.asoulcnki.api; - -import java.security.KeyStore; -import java.security.SecureRandom; -import java.security.cert.X509Certificate; -import java.util.Arrays; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - - -public class SSLSocketClient { - - //获取这个SSLSocketFactory - public static SSLSocketFactory getSSLSocketFactory() { - try { - SSLContext sslContext = SSLContext.getInstance("SSL"); - sslContext.init(null, getTrustManager(), new SecureRandom()); - return sslContext.getSocketFactory(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - //获取TrustManager - private static TrustManager[] getTrustManager() { - return new TrustManager[]{ - new X509TrustManager() { - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) { - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) { - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[]{}; - } - } - }; - } - - //获取HostnameVerifier - public static HostnameVerifier getHostnameVerifier() { - return (s, sslSession) -> true; - } - - public static X509TrustManager getX509TrustManager() { - X509TrustManager trustManager = null; - try { - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init((KeyStore) null); - TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); - if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { - throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers)); - } - trustManager = (X509TrustManager) trustManagers[0]; - } catch (Exception e) { - e.printStackTrace(); - } - - return trustManager; - } -} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/models/CheckApiBody.kt b/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/models/CheckApiBody.kt deleted file mode 100644 index 4ead4034..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/models/CheckApiBody.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.huanchengfly.tieba.post.plugins.asoulcnki.models - -data class CheckApiBody( - val text: String -) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/models/CheckResult.kt b/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/models/CheckResult.kt deleted file mode 100644 index 6ef5fe18..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/plugins/asoulcnki/models/CheckResult.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.huanchengfly.tieba.post.plugins.asoulcnki.models - -import androidx.annotation.Keep -import com.google.gson.annotations.SerializedName - -@Keep -data class CheckResult( - val code: Int, // 0 - val `data`: Data, - val message: String // success -) { - @Keep - data class Data( - @SerializedName("end_time") - val endTime: Int, // 1629010807 - val rate: Double, // 1.0 - val related: List, - @SerializedName("start_time") - val startTime: Int // 1606137506 - ) { - @Keep - data class Related( - val rate: Double, // 1.0 - val reply: Reply, - @SerializedName("reply_url") - val replyUrl: String // https://www.bilibili.com/video/av377092608/#reply5051494613 - ) { - @Keep - data class Reply( - val content: String, // 曾几何时,我也想像asoul的beeeeeeeela一样做幸福滤镜下的事至少在这层滤镜下,beeeeeeeela的一举一动都是随心所欲且浪漫真实的当我看到beeeeeeeela能像个二次元一样和弹幕大谈特谈50音,当我看到beeeeeeeela能够笑着在夜里唱着不知道练了多少遍的云烟成雨,当我看到她可以在失落后得到安抚和拥抱…以往的笑意消散殆尽,剩下的只有我对beeeeeeeela浪漫的感动和一种无中生有的失意了。我也想像她一样。但这是虚假的,每次在烂醉酩酊起来后依然会痛苦,每次在浪费时间的时候都能意识到,你不能感受到我感受到的东西。但就算是这样,没了你我可能就会完蛋了吧。因为我们需要一个梦。 - val ctime: Int, // 1627881576 - @SerializedName("dynamic_id") - val dynamicId: String, // 553473662133564230 - @SerializedName("like_num") - val likeNum: Int, // 9 - @SerializedName("m_name") - val mName: String, // 走出童年 - val mid: Int, // 671239951 - val oid: String, // 377092608 - @SerializedName("origin_rpid") - val originRpid: String, // -1 - val rpid: String, // 5051494613 - @SerializedName("similar_count") - val similarCount: Int, // 1 - @SerializedName("similar_like_sum") - val similarLikeSum: Int, // 424 - @SerializedName("type_id") - val typeId: Int, // 1 - val uid: Int // 672346917 - ) - } - } -} \ No newline at end of file