整理:code review

This commit is contained in:
pppscn 2023-02-01 10:51:17 +08:00
parent 992fc2eb8c
commit e1660fe9bb
16 changed files with 713 additions and 714 deletions

View File

@ -1,174 +1,174 @@
package com.idormy.sms.forwarder.service package com.idormy.sms.forwarder.service
import android.app.* import android.app.*
import android.content.Intent import android.content.Intent
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.graphics.Color import android.graphics.Color
import android.os.Build import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.text.TextUtils import android.text.TextUtils
import android.util.Log import android.util.Log
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.activity.MainActivity import com.idormy.sms.forwarder.activity.MainActivity
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.utils.* import com.idormy.sms.forwarder.utils.*
import com.jeremyliao.liveeventbus.LiveEventBus import com.jeremyliao.liveeventbus.LiveEventBus
import com.xuexiang.xutil.file.FileUtils import com.xuexiang.xutil.file.FileUtils
import frpclib.Frpclib import frpclib.Frpclib
import io.reactivex.Single import io.reactivex.Single
import io.reactivex.SingleObserver import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async import kotlinx.coroutines.async
@Suppress("PrivatePropertyName", "DeferredResultUnused", "OPT_IN_USAGE") @Suppress("PrivatePropertyName", "DeferredResultUnused", "OPT_IN_USAGE")
class ForegroundService : Service() { class ForegroundService : Service() {
private val TAG: String = "ForegroundService" private val TAG: String = "ForegroundService"
private val compositeDisposable = CompositeDisposable() private val compositeDisposable = CompositeDisposable()
private val frpcObserver = Observer { uid: String -> private val frpcObserver = Observer { uid: String ->
if (Frpclib.isRunning(uid)) { if (Frpclib.isRunning(uid)) {
return@Observer return@Observer
} }
AppDatabase.getInstance(App.context) AppDatabase.getInstance(App.context)
.frpcDao() .frpcDao()
.get(uid) .get(uid)
.flatMap { (uid1, _, config) -> .flatMap { (uid1, _, config) ->
val error = Frpclib.runContent(uid1, config) val error = Frpclib.runContent(uid1, config)
Single.just(error) Single.just(error)
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<String> { .subscribe(object : SingleObserver<String> {
override fun onSubscribe(d: Disposable) { override fun onSubscribe(d: Disposable) {
compositeDisposable.add(d) compositeDisposable.add(d)
} }
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
LiveEventBus.get(EVENT_FRPC_RUNNING_ERROR, String::class.java).post(uid) LiveEventBus.get(EVENT_FRPC_RUNNING_ERROR, String::class.java).post(uid)
} }
override fun onSuccess(msg: String) { override fun onSuccess(msg: String) {
if (!TextUtils.isEmpty(msg)) { if (!TextUtils.isEmpty(msg)) {
Log.e(TAG, msg) Log.e(TAG, msg)
LiveEventBus.get(EVENT_FRPC_RUNNING_ERROR, String::class.java).post(uid) LiveEventBus.get(EVENT_FRPC_RUNNING_ERROR, String::class.java).post(uid)
} else { } else {
LiveEventBus.get(EVENT_FRPC_RUNNING_SUCCESS, String::class.java).post(uid) LiveEventBus.get(EVENT_FRPC_RUNNING_SUCCESS, String::class.java).post(uid)
} }
} }
}) })
} }
private var notificationManager: NotificationManager? = null private var notificationManager: NotificationManager? = null
companion object { companion object {
var isRunning = false var isRunning = false
} }
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
try { try {
//纯客户端模式 //纯客户端模式
if (SettingUtils.enablePureClientMode) return if (SettingUtils.enablePureClientMode) return
notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
startForeground(FRONT_NOTIFY_ID, createForegroundNotification()) startForeground(FRONT_NOTIFY_ID, createForegroundNotification())
//开关通知监听服务 //开关通知监听服务
if (SettingUtils.enableAppNotify && CommonUtils.isNotificationListenerServiceEnabled(this)) { if (SettingUtils.enableAppNotify && CommonUtils.isNotificationListenerServiceEnabled(this)) {
CommonUtils.toggleNotificationListenerService(this) CommonUtils.toggleNotificationListenerService(this)
} }
if (FileUtils.isFileExists(filesDir.absolutePath + "/libs/libgojni.so")) { if (FileUtils.isFileExists(filesDir.absolutePath + "/libs/libgojni.so")) {
//监听Frpc启动指令 //监听Frpc启动指令
LiveEventBus.get(INTENT_FRPC_APPLY_FILE, String::class.java).observeStickyForever(frpcObserver) LiveEventBus.get(INTENT_FRPC_APPLY_FILE, String::class.java).observeStickyForever(frpcObserver)
//自启动的Frpc //自启动的Frpc
GlobalScope.async(Dispatchers.IO) { GlobalScope.async(Dispatchers.IO) {
val frpcList = AppDatabase.getInstance(App.context).frpcDao().getAutorun() val frpcList = AppDatabase.getInstance(App.context).frpcDao().getAutorun()
if (frpcList.isEmpty()) { if (frpcList.isEmpty()) {
Log.d(TAG, "没有自启动的Frpc") Log.d(TAG, "没有自启动的Frpc")
return@async return@async
} }
for (frpc in frpcList) { for (frpc in frpcList) {
val error = Frpclib.runContent(frpc.uid, frpc.config) val error = Frpclib.runContent(frpc.uid, frpc.config)
if (!TextUtils.isEmpty(error)) { if (!TextUtils.isEmpty(error)) {
Log.e(TAG, error) Log.e(TAG, error)
} }
} }
} }
} }
isRunning = true isRunning = true
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
isRunning = false isRunning = false
} }
} }
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
isRunning = true isRunning = true
return START_STICKY return START_STICKY
} }
override fun onDestroy() { override fun onDestroy() {
//纯客户端模式 //纯客户端模式
if (SettingUtils.enablePureClientMode) { if (SettingUtils.enablePureClientMode) {
super.onDestroy() super.onDestroy()
return return
} }
try { try {
stopForeground(true) stopForeground(true)
compositeDisposable.dispose() compositeDisposable.dispose()
isRunning = false isRunning = false
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
super.onDestroy() super.onDestroy()
} }
override fun onBind(intent: Intent): IBinder? { override fun onBind(intent: Intent): IBinder? {
return null return null
} }
private fun createForegroundNotification(): Notification { private fun createForegroundNotification(): Notification {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val importance = NotificationManager.IMPORTANCE_HIGH val importance = NotificationManager.IMPORTANCE_HIGH
val notificationChannel = NotificationChannel(FRONT_CHANNEL_ID, FRONT_CHANNEL_NAME, importance) val notificationChannel = NotificationChannel(FRONT_CHANNEL_ID, FRONT_CHANNEL_NAME, importance)
notificationChannel.description = "Frpc Foreground Service" notificationChannel.description = "Frpc Foreground Service"
notificationChannel.enableLights(true) notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.GREEN notificationChannel.lightColor = Color.GREEN
notificationChannel.vibrationPattern = longArrayOf(0, 1000, 500, 1000) notificationChannel.vibrationPattern = longArrayOf(0, 1000, 500, 1000)
notificationChannel.enableVibration(true) notificationChannel.enableVibration(true)
if (notificationManager != null) { if (notificationManager != null) {
notificationManager!!.createNotificationChannel(notificationChannel) notificationManager!!.createNotificationChannel(notificationChannel)
} }
} }
val builder = NotificationCompat.Builder(this, FRONT_CHANNEL_ID) val builder = NotificationCompat.Builder(this, FRONT_CHANNEL_ID)
builder.setSmallIcon(R.drawable.ic_forwarder) builder.setSmallIcon(R.drawable.ic_forwarder)
builder.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_menu_frpc)) builder.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_menu_frpc))
// TODO: 部分机型标题会重复待排除 // TODO: 部分机型标题会重复待排除
// if (DeviceUtils.getDeviceBrand().contains("Xiaomi")) { // if (DeviceUtils.getDeviceBrand().contains("Xiaomi")) {
builder.setContentTitle(getString(R.string.app_name)) builder.setContentTitle(getString(R.string.app_name))
//} //}
builder.setContentText(SettingUtils.notifyContent.toString()) builder.setContentText(SettingUtils.notifyContent)
builder.setWhen(System.currentTimeMillis()) builder.setWhen(System.currentTimeMillis())
val activityIntent = Intent(this, MainActivity::class.java) val activityIntent = Intent(this, MainActivity::class.java)
val flags = if (Build.VERSION.SDK_INT >= 30) PendingIntent.FLAG_IMMUTABLE else PendingIntent.FLAG_UPDATE_CURRENT val flags = if (Build.VERSION.SDK_INT >= 30) PendingIntent.FLAG_IMMUTABLE else PendingIntent.FLAG_UPDATE_CURRENT
val pendingIntent = PendingIntent.getActivity(this, 0, activityIntent, flags) val pendingIntent = PendingIntent.getActivity(this, 0, activityIntent, flags)
builder.setContentIntent(pendingIntent) builder.setContentIntent(pendingIntent)
return builder.build() return builder.build()
} }
} }

View File

@ -35,7 +35,7 @@ class BarkUtils {
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
val requestUrl: String = setting.server //推送地址 val requestUrl: String = setting.server //推送地址

View File

@ -35,7 +35,7 @@ class DingtalkGroupRobotUtils private constructor() {
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
var requestUrl = if (setting.token.startsWith("http")) setting.token else "https://oapi.dingtalk.com/robot/send?access_token=" + setting.token var requestUrl = if (setting.token.startsWith("http")) setting.token else "https://oapi.dingtalk.com/robot/send?access_token=" + setting.token

View File

@ -126,7 +126,7 @@ class DingtalkInnerRobotUtils private constructor() {
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
val msgParam: MutableMap<String, Any> = mutableMapOf() val msgParam: MutableMap<String, Any> = mutableMapOf()

View File

@ -1,151 +1,151 @@
package com.idormy.sms.forwarder.utils.sender package com.idormy.sms.forwarder.utils.sender
import android.util.Log import android.util.Log
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.setting.EmailSetting import com.idormy.sms.forwarder.entity.setting.EmailSetting
import com.idormy.sms.forwarder.utils.SendUtils import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.mail.Mail import com.idormy.sms.forwarder.utils.mail.Mail
import com.idormy.sms.forwarder.utils.mail.MailSender import com.idormy.sms.forwarder.utils.mail.MailSender
import com.xuexiang.xui.utils.ResUtils import com.xuexiang.xui.utils.ResUtils
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused") @Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class EmailUtils { class EmailUtils {
companion object { companion object {
private val TAG: String = EmailUtils::class.java.simpleName private val TAG: String = EmailUtils::class.java.simpleName
fun sendMsg( fun sendMsg(
setting: EmailSetting, setting: EmailSetting,
msgInfo: MsgInfo, msgInfo: MsgInfo,
rule: Rule?, rule: Rule?,
logId: Long?, logId: Long?,
) { ) {
val title: String = if (rule != null) { val title: String = if (rule != null) {
msgInfo.getTitleForSend(setting.title.toString(), rule.regexReplace) msgInfo.getTitleForSend(setting.title.toString(), rule.regexReplace)
} else { } else {
msgInfo.getTitleForSend(setting.title.toString()) msgInfo.getTitleForSend(setting.title.toString())
} }
val message: String = if (rule != null) { val message: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
//常用邮箱类型的转换 //常用邮箱类型的转换
when (setting.mailType) { when (setting.mailType) {
"@qq.com", "@foxmail.com" -> { "@qq.com", "@foxmail.com" -> {
setting.host = "smtp.qq.com" setting.host = "smtp.qq.com"
setting.port = "465" setting.port = "465"
setting.ssl = true setting.ssl = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@exmail.qq.com" -> { "@exmail.qq.com" -> {
setting.host = "smtp.exmail.qq.com" setting.host = "smtp.exmail.qq.com"
setting.port = "465" setting.port = "465"
setting.ssl = true setting.ssl = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@msn.com" -> { "@msn.com" -> {
setting.host = "smtp-mail.outlook.com" setting.host = "smtp-mail.outlook.com"
setting.port = "587" setting.port = "587"
setting.ssl = false setting.ssl = false
setting.startTls = true setting.startTls = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@outlook.com", "@office365.com", "@live.com", "@hotmail.com" -> { "@outlook.com", "@office365.com", "@live.com", "@hotmail.com" -> {
setting.host = "smtp.office365.com" setting.host = "smtp.office365.com"
setting.port = "587" setting.port = "587"
setting.ssl = false setting.ssl = false
setting.startTls = true setting.startTls = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@gmail.com" -> { "@gmail.com" -> {
setting.host = "smtp.gmail.com" setting.host = "smtp.gmail.com"
setting.port = "587" setting.port = "587"
setting.ssl = true setting.ssl = true
setting.startTls = true setting.startTls = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@yeah.net" -> { "@yeah.net" -> {
setting.host = "smtp.yeah.net" setting.host = "smtp.yeah.net"
setting.port = "465" setting.port = "465"
setting.ssl = true setting.ssl = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@163.com" -> { "@163.com" -> {
setting.host = "smtp.163.com" setting.host = "smtp.163.com"
setting.port = "465" setting.port = "465"
setting.ssl = true setting.ssl = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@126.com" -> { "@126.com" -> {
setting.host = "smtp.126.com" setting.host = "smtp.126.com"
setting.port = "465" setting.port = "465"
setting.ssl = true setting.ssl = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@sina.com" -> { "@sina.com" -> {
setting.host = "smtp.sina.com" setting.host = "smtp.sina.com"
setting.port = "465" setting.port = "465"
setting.ssl = true setting.ssl = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@sina.cn" -> { "@sina.cn" -> {
setting.host = "smtp.sina.cn" setting.host = "smtp.sina.cn"
setting.port = "465" setting.port = "465"
setting.ssl = true setting.ssl = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@139.com" -> { "@139.com" -> {
setting.host = "smtp.139.com" setting.host = "smtp.139.com"
setting.port = "465" setting.port = "465"
setting.ssl = true setting.ssl = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
"@189.cn" -> { "@189.cn" -> {
setting.host = "smtp.189.cn" setting.host = "smtp.189.cn"
setting.port = "465" setting.port = "465"
setting.ssl = true setting.ssl = true
setting.fromEmail += setting.mailType setting.fromEmail += setting.mailType
} }
else -> {} else -> {}
} }
//收件地址 //收件地址
val toAddressList = setting.toEmail.toString().replace("[,;]".toRegex(), ",").trim(',').split(',') val toAddressList = setting.toEmail.toString().replace("[,;]".toRegex(), ",").trim(',').split(',')
//创建邮箱 //创建邮箱
val mail = Mail().apply { val mail = Mail().apply {
mailServerHost = setting.host.toString() mailServerHost = setting.host.toString()
mailServerPort = setting.port.toString() mailServerPort = setting.port.toString()
fromAddress = setting.fromEmail.toString() fromAddress = setting.fromEmail.toString()
fromNickname = msgInfo.getTitleForSend(setting.nickname.toString()) fromNickname = msgInfo.getTitleForSend(setting.nickname.toString())
password = setting.pwd.toString() password = setting.pwd.toString()
toAddress = toAddressList toAddress = toAddressList
subject = title subject = title
content = message.replace("\n", "<br>") content = message.replace("\n", "<br>")
openSSL = setting.ssl == true openSSL = setting.ssl == true
startTls = setting.startTls == true startTls = setting.startTls == true
} }
MailSender.getInstance().sendMail(mail, object : MailSender.OnMailSendListener { MailSender.getInstance().sendMail(mail, object : MailSender.OnMailSendListener {
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
Log.e("MailSender", e.message.toString()) Log.e("MailSender", e.message.toString())
SendUtils.updateLogs(logId, 0, e.message.toString()) SendUtils.updateLogs(logId, 0, e.message.toString())
} }
override fun onSuccess() { override fun onSuccess() {
SendUtils.updateLogs(logId, 2, ResUtils.getString(R.string.request_succeeded)) SendUtils.updateLogs(logId, 2, ResUtils.getString(R.string.request_succeeded))
} }
}) })
} }
fun sendMsg(setting: EmailSetting, msgInfo: MsgInfo) { fun sendMsg(setting: EmailSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null) sendMsg(setting, msgInfo, null, null)
} }
} }
} }

View File

@ -84,7 +84,7 @@ class FeishuAppUtils private constructor() {
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
val msgContent = if ("interactive" == setting.msgType) { val msgContent = if ("interactive" == setting.msgType) {

View File

@ -94,7 +94,7 @@ class FeishuUtils private constructor() {
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
val requestUrl = setting.webhook val requestUrl = setting.webhook

View File

@ -1,89 +1,89 @@
package com.idormy.sms.forwarder.utils.sender package com.idormy.sms.forwarder.utils.sender
import android.util.Log import android.util.Log
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.GotifyResult import com.idormy.sms.forwarder.entity.result.GotifyResult
import com.idormy.sms.forwarder.entity.setting.GotifySetting import com.idormy.sms.forwarder.entity.setting.GotifySetting
import com.idormy.sms.forwarder.utils.SendUtils import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException import com.xuexiang.xhttp2.exception.ApiException
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused") @Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class GotifyUtils { class GotifyUtils {
companion object { companion object {
private val TAG: String = GotifyUtils::class.java.simpleName private val TAG: String = GotifyUtils::class.java.simpleName
fun sendMsg( fun sendMsg(
setting: GotifySetting, setting: GotifySetting,
msgInfo: MsgInfo, msgInfo: MsgInfo,
rule: Rule?, rule: Rule?,
logId: Long?, logId: Long?,
) { ) {
val title: String = if (rule != null) { val title: String = if (rule != null) {
msgInfo.getTitleForSend(setting.title.toString(), rule.regexReplace) msgInfo.getTitleForSend(setting.title.toString(), rule.regexReplace)
} else { } else {
msgInfo.getTitleForSend(setting.title.toString()) msgInfo.getTitleForSend(setting.title.toString())
} }
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
val requestUrl: String = setting.webServer //推送地址 val requestUrl: String = setting.webServer //推送地址
Log.i(TAG, "requestUrl:$requestUrl") Log.i(TAG, "requestUrl:$requestUrl")
//支持HTTP基本认证(Basic Authentication) //支持HTTP基本认证(Basic Authentication)
val regex = "^(https?://)([^:]+):([^@]+)@(.+)" val regex = "^(https?://)([^:]+):([^@]+)@(.+)"
val matches = Regex(regex, RegexOption.IGNORE_CASE).findAll(requestUrl).toList().flatMap(MatchResult::groupValues) val matches = Regex(regex, RegexOption.IGNORE_CASE).findAll(requestUrl).toList().flatMap(MatchResult::groupValues)
Log.i(TAG, "matches = $matches") Log.i(TAG, "matches = $matches")
val request = if (matches.isNotEmpty()) { val request = if (matches.isNotEmpty()) {
XHttp.post(matches[1] + matches[4]).addInterceptor(BasicAuthInterceptor(matches[2], matches[3])) XHttp.post(matches[1] + matches[4]).addInterceptor(BasicAuthInterceptor(matches[2], matches[3]))
} else { } else {
XHttp.post(requestUrl) XHttp.post(requestUrl)
} }
request.params("title", title) request.params("title", title)
.params("message", content) .params("message", content)
.params("priority", setting.priority) .params("priority", setting.priority)
.ignoreHttpsCert() //忽略https证书 .ignoreHttpsCert() //忽略https证书
.keepJson(true) .keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s .timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数 .retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间 .retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时 .retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true) .timeStamp(true)
.execute(object : SimpleCallBack<String>() { .execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) { override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage) Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage) SendUtils.updateLogs(logId, 0, e.displayMessage)
} }
override fun onSuccess(response: String) { override fun onSuccess(response: String) {
Log.i(TAG, response) Log.i(TAG, response)
val resp = Gson().fromJson(response, GotifyResult::class.java) val resp = Gson().fromJson(response, GotifyResult::class.java)
if (resp?.id != null) { if (resp?.id != null) {
SendUtils.updateLogs(logId, 2, response) SendUtils.updateLogs(logId, 2, response)
} else { } else {
SendUtils.updateLogs(logId, 0, response) SendUtils.updateLogs(logId, 0, response)
} }
} }
}) })
} }
fun sendMsg(setting: GotifySetting, msgInfo: MsgInfo) { fun sendMsg(setting: GotifySetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null) sendMsg(setting, msgInfo, null, null)
} }
} }
} }

View File

@ -37,7 +37,7 @@ class PushplusUtils private constructor() {
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
val requestUrl = "https://" + setting.website + "/send" val requestUrl = "https://" + setting.website + "/send"
@ -63,7 +63,6 @@ class PushplusUtils private constructor() {
} }
} }
val requestMsg: String = Gson().toJson(msgMap) val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg") Log.i(TAG, "requestMsg:$requestMsg")

View File

@ -1,83 +1,83 @@
package com.idormy.sms.forwarder.utils.sender package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils import android.text.TextUtils
import android.util.Log import android.util.Log
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.ServerchanResult import com.idormy.sms.forwarder.entity.result.ServerchanResult
import com.idormy.sms.forwarder.entity.setting.ServerchanSetting import com.idormy.sms.forwarder.entity.setting.ServerchanSetting
import com.idormy.sms.forwarder.utils.SendUtils import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException import com.xuexiang.xhttp2.exception.ApiException
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused") @Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class ServerchanUtils { class ServerchanUtils {
companion object { companion object {
private val TAG: String = ServerchanUtils::class.java.simpleName private val TAG: String = ServerchanUtils::class.java.simpleName
fun sendMsg( fun sendMsg(
setting: ServerchanSetting, setting: ServerchanSetting,
msgInfo: MsgInfo, msgInfo: MsgInfo,
rule: Rule?, rule: Rule?,
logId: Long?, logId: Long?,
) { ) {
val title: String = if (rule != null) { val title: String = if (rule != null) {
msgInfo.getTitleForSend(setting.titleTemplate.toString(), rule.regexReplace) msgInfo.getTitleForSend(setting.titleTemplate.toString(), rule.regexReplace)
} else { } else {
msgInfo.getTitleForSend(setting.titleTemplate.toString()) msgInfo.getTitleForSend(setting.titleTemplate.toString())
} }
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
val requestUrl: String = String.format("https://sctapi.ftqq.com/%s.send", setting.sendKey) //推送地址 val requestUrl: String = String.format("https://sctapi.ftqq.com/%s.send", setting.sendKey) //推送地址
Log.i(TAG, "requestUrl:$requestUrl") Log.i(TAG, "requestUrl:$requestUrl")
val request = XHttp.post(requestUrl) val request = XHttp.post(requestUrl)
.params("title", title) .params("title", title)
.params("desp", content) .params("desp", content)
if (!TextUtils.isEmpty(setting.channel)) request.params("channel", setting.channel) if (!TextUtils.isEmpty(setting.channel)) request.params("channel", setting.channel)
if (!TextUtils.isEmpty(setting.openid)) request.params("group", setting.openid) if (!TextUtils.isEmpty(setting.openid)) request.params("group", setting.openid)
request.keepJson(true) request.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s .timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数 .retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间 .retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时 .retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true) .timeStamp(true)
.execute(object : SimpleCallBack<String>() { .execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) { override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage) Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage) SendUtils.updateLogs(logId, 0, e.displayMessage)
} }
override fun onSuccess(response: String) { override fun onSuccess(response: String) {
Log.i(TAG, response) Log.i(TAG, response)
val resp = Gson().fromJson(response, ServerchanResult::class.java) val resp = Gson().fromJson(response, ServerchanResult::class.java)
if (resp?.code == 0L) { if (resp?.code == 0L) {
SendUtils.updateLogs(logId, 2, response) SendUtils.updateLogs(logId, 2, response)
} else { } else {
SendUtils.updateLogs(logId, 0, response) SendUtils.updateLogs(logId, 0, response)
} }
} }
}) })
} }
fun sendMsg(setting: ServerchanSetting, msgInfo: MsgInfo) { fun sendMsg(setting: ServerchanSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null) sendMsg(setting, msgInfo, null, null)
} }
} }
} }

View File

@ -40,7 +40,7 @@ class TelegramUtils private constructor() {
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
var requestUrl = if (setting.apiToken.startsWith("http")) { var requestUrl = if (setting.apiToken.startsWith("http")) {

View File

@ -1,209 +1,209 @@
package com.idormy.sms.forwarder.utils.sender package com.idormy.sms.forwarder.utils.sender
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.text.TextUtils import android.text.TextUtils
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.setting.WebhookSetting import com.idormy.sms.forwarder.entity.setting.WebhookSetting
import com.idormy.sms.forwarder.utils.SendUtils import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xutil.app.AppUtils import com.xuexiang.xutil.app.AppUtils
import java.net.URLEncoder import java.net.URLEncoder
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import javax.crypto.Mac import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec import javax.crypto.spec.SecretKeySpec
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused") @Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class WebhookUtils { class WebhookUtils {
companion object { companion object {
private val TAG: String = WebhookUtils::class.java.simpleName private val TAG: String = WebhookUtils::class.java.simpleName
fun sendMsg( fun sendMsg(
setting: WebhookSetting, setting: WebhookSetting,
msgInfo: MsgInfo, msgInfo: MsgInfo,
rule: Rule?, rule: Rule?,
logId: Long?, logId: Long?,
) { ) {
val from: String = msgInfo.from val from: String = msgInfo.from
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
var requestUrl: String = setting.webServer //推送地址 var requestUrl: String = setting.webServer //推送地址
Log.i(TAG, "requestUrl:$requestUrl") Log.i(TAG, "requestUrl:$requestUrl")
val timestamp = System.currentTimeMillis() val timestamp = System.currentTimeMillis()
val orgContent: String = msgInfo.content val orgContent: String = msgInfo.content
val deviceMark: String = SettingUtils.extraDeviceMark ?: "" val deviceMark: String = SettingUtils.extraDeviceMark
val appVersion: String = AppUtils.getAppVersionName() val appVersion: String = AppUtils.getAppVersionName()
val simInfo: String = msgInfo.simInfo val simInfo: String = msgInfo.simInfo
@SuppressLint("SimpleDateFormat") val receiveTime = @SuppressLint("SimpleDateFormat") val receiveTime =
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date()) //smsVo.getDate() SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date()) //smsVo.getDate()
var sign = "" var sign = ""
if (!TextUtils.isEmpty(setting.secret)) { if (!TextUtils.isEmpty(setting.secret)) {
val stringToSign = "$timestamp\n" + setting.secret val stringToSign = "$timestamp\n" + setting.secret
val mac = Mac.getInstance("HmacSHA256") val mac = Mac.getInstance("HmacSHA256")
mac.init( mac.init(
SecretKeySpec( SecretKeySpec(
setting.secret?.toByteArray(StandardCharsets.UTF_8), setting.secret?.toByteArray(StandardCharsets.UTF_8),
"HmacSHA256" "HmacSHA256"
) )
) )
val signData = mac.doFinal(stringToSign.toByteArray(StandardCharsets.UTF_8)) val signData = mac.doFinal(stringToSign.toByteArray(StandardCharsets.UTF_8))
sign = URLEncoder.encode(String(Base64.encode(signData, Base64.NO_WRAP)), "UTF-8") sign = URLEncoder.encode(String(Base64.encode(signData, Base64.NO_WRAP)), "UTF-8")
} }
var webParams = setting.webParams?.trim() var webParams = setting.webParams?.trim()
//支持HTTP基本认证(Basic Authentication) //支持HTTP基本认证(Basic Authentication)
val regex = "^(https?://)([^:]+):([^@]+)@(.+)" val regex = "^(https?://)([^:]+):([^@]+)@(.+)"
val matches = Regex(regex, RegexOption.IGNORE_CASE).findAll(requestUrl).toList() val matches = Regex(regex, RegexOption.IGNORE_CASE).findAll(requestUrl).toList()
.flatMap(MatchResult::groupValues) .flatMap(MatchResult::groupValues)
Log.i(TAG, "matches = $matches") Log.i(TAG, "matches = $matches")
if (matches.isNotEmpty()) { if (matches.isNotEmpty()) {
requestUrl = matches[1] + matches[4] requestUrl = matches[1] + matches[4]
Log.i(TAG, "requestUrl:$requestUrl") Log.i(TAG, "requestUrl:$requestUrl")
} }
val request = if (setting.method == "GET" && TextUtils.isEmpty(webParams)) { val request = if (setting.method == "GET" && TextUtils.isEmpty(webParams)) {
setting.webServer += (if (setting.webServer.contains("?")) "&" else "?") + "from=" + URLEncoder.encode( setting.webServer += (if (setting.webServer.contains("?")) "&" else "?") + "from=" + URLEncoder.encode(
from, from,
"UTF-8" "UTF-8"
) )
requestUrl += "&content=" + URLEncoder.encode(content, "UTF-8") requestUrl += "&content=" + URLEncoder.encode(content, "UTF-8")
if (!TextUtils.isEmpty(sign)) { if (!TextUtils.isEmpty(sign)) {
requestUrl += "&timestamp=$timestamp" requestUrl += "&timestamp=$timestamp"
requestUrl += "&sign=$sign" requestUrl += "&sign=$sign"
} }
Log.d(TAG, "method = GET, Url = $requestUrl") Log.d(TAG, "method = GET, Url = $requestUrl")
XHttp.get(requestUrl).keepJson(true) XHttp.get(requestUrl).keepJson(true)
} else if (setting.method == "GET" && !TextUtils.isEmpty(webParams)) { } else if (setting.method == "GET" && !TextUtils.isEmpty(webParams)) {
webParams = webParams.toString().replace("[from]", URLEncoder.encode(from, "UTF-8")) webParams = webParams.toString().replace("[from]", URLEncoder.encode(from, "UTF-8"))
.replace("[content]", URLEncoder.encode(content, "UTF-8")) .replace("[content]", URLEncoder.encode(content, "UTF-8"))
.replace("[msg]", URLEncoder.encode(content, "UTF-8")) .replace("[msg]", URLEncoder.encode(content, "UTF-8"))
.replace("[org_content]", URLEncoder.encode(orgContent, "UTF-8")) .replace("[org_content]", URLEncoder.encode(orgContent, "UTF-8"))
.replace("[device_mark]", URLEncoder.encode(deviceMark, "UTF-8")) .replace("[device_mark]", URLEncoder.encode(deviceMark, "UTF-8"))
.replace("[app_version]", URLEncoder.encode(appVersion, "UTF-8")) .replace("[app_version]", URLEncoder.encode(appVersion, "UTF-8"))
.replace("[title]", URLEncoder.encode(simInfo, "UTF-8")) .replace("[title]", URLEncoder.encode(simInfo, "UTF-8"))
.replace("[card_slot]", URLEncoder.encode(simInfo, "UTF-8")) .replace("[card_slot]", URLEncoder.encode(simInfo, "UTF-8"))
.replace("[receive_time]", URLEncoder.encode(receiveTime, "UTF-8")) .replace("[receive_time]", URLEncoder.encode(receiveTime, "UTF-8"))
.replace("\n", "%0A") .replace("\n", "%0A")
if (!TextUtils.isEmpty(setting.secret)) { if (!TextUtils.isEmpty(setting.secret)) {
webParams = webParams.replace("[timestamp]", timestamp.toString()) webParams = webParams.replace("[timestamp]", timestamp.toString())
.replace("[sign]", URLEncoder.encode(sign, "UTF-8")) .replace("[sign]", URLEncoder.encode(sign, "UTF-8"))
} }
requestUrl += if (webParams.startsWith("/")) { requestUrl += if (webParams.startsWith("/")) {
webParams webParams
} else { } else {
(if (requestUrl.contains("?")) "&" else "?") + webParams (if (requestUrl.contains("?")) "&" else "?") + webParams
} }
Log.d(TAG, "method = GET, Url = $requestUrl") Log.d(TAG, "method = GET, Url = $requestUrl")
XHttp.get(requestUrl).keepJson(true) XHttp.get(requestUrl).keepJson(true)
} else if (webParams != null && webParams.isNotEmpty() && webParams.startsWith("{")) { } else if (webParams != null && webParams.isNotEmpty() && webParams.startsWith("{")) {
val bodyMsg = webParams.replace("[from]", from) val bodyMsg = webParams.replace("[from]", from)
.replace("[content]", escapeJson(content)) .replace("[content]", escapeJson(content))
.replace("[msg]", escapeJson(content)) .replace("[msg]", escapeJson(content))
.replace("[org_content]", escapeJson(orgContent)) .replace("[org_content]", escapeJson(orgContent))
.replace("[device_mark]", escapeJson(deviceMark)) .replace("[device_mark]", escapeJson(deviceMark))
.replace("[app_version]", appVersion) .replace("[app_version]", appVersion)
.replace("[title]", escapeJson(simInfo)) .replace("[title]", escapeJson(simInfo))
.replace("[card_slot]", escapeJson(simInfo)) .replace("[card_slot]", escapeJson(simInfo))
.replace("[receive_time]", receiveTime) .replace("[receive_time]", receiveTime)
.replace("[timestamp]", timestamp.toString()) .replace("[timestamp]", timestamp.toString())
.replace("[sign]", sign) .replace("[sign]", sign)
Log.d(TAG, "method = ${setting.method}, Url = $requestUrl, bodyMsg = $bodyMsg") Log.d(TAG, "method = ${setting.method}, Url = $requestUrl, bodyMsg = $bodyMsg")
when (setting.method) { when (setting.method) {
"PUT" -> XHttp.put(requestUrl).keepJson(true).upJson(bodyMsg) "PUT" -> XHttp.put(requestUrl).keepJson(true).upJson(bodyMsg)
"PATCH" -> XHttp.patch(requestUrl).keepJson(true).upJson(bodyMsg) "PATCH" -> XHttp.patch(requestUrl).keepJson(true).upJson(bodyMsg)
else -> XHttp.post(requestUrl).keepJson(true).upJson(bodyMsg) else -> XHttp.post(requestUrl).keepJson(true).upJson(bodyMsg)
} }
} else { } else {
if (webParams == null || webParams.isEmpty()) { if (webParams == null || webParams.isEmpty()) {
webParams = "from=[from]&content=[content]&timestamp=[timestamp]" webParams = "from=[from]&content=[content]&timestamp=[timestamp]"
if (!TextUtils.isEmpty(sign)) webParams += "&sign=[sign]" if (!TextUtils.isEmpty(sign)) webParams += "&sign=[sign]"
} }
Log.d(TAG, "method = ${setting.method}, Url = $requestUrl") Log.d(TAG, "method = ${setting.method}, Url = $requestUrl")
val postRequest = when (setting.method) { val postRequest = when (setting.method) {
"PUT" -> XHttp.put(requestUrl).keepJson(true) "PUT" -> XHttp.put(requestUrl).keepJson(true)
"PATCH" -> XHttp.patch(requestUrl).keepJson(true) "PATCH" -> XHttp.patch(requestUrl).keepJson(true)
else -> XHttp.post(requestUrl).keepJson(true) else -> XHttp.post(requestUrl).keepJson(true)
} }
webParams.trim('&').split("&").forEach { webParams.trim('&').split("&").forEach {
val param = it.split("=") val param = it.split("=")
if (param.size == 2) { if (param.size == 2) {
postRequest.params( postRequest.params(
param[0], param[1].replace("[from]", from) param[0], param[1].replace("[from]", from)
.replace("[content]", content) .replace("[content]", content)
.replace("[msg]", content) .replace("[msg]", content)
.replace("[org_content]", orgContent) .replace("[org_content]", orgContent)
.replace("[device_mark]", deviceMark) .replace("[device_mark]", deviceMark)
.replace("[app_version]", appVersion) .replace("[app_version]", appVersion)
.replace("[title]", simInfo) .replace("[title]", simInfo)
.replace("[card_slot]", simInfo) .replace("[card_slot]", simInfo)
.replace("[receive_time]", receiveTime) .replace("[receive_time]", receiveTime)
.replace("[timestamp]", timestamp.toString()) .replace("[timestamp]", timestamp.toString())
.replace("[sign]", sign) .replace("[sign]", sign)
) )
} }
} }
postRequest postRequest
} }
//添加headers //添加headers
for ((key, value) in setting.headers?.entries!!) { for ((key, value) in setting.headers?.entries!!) {
request.headers(key, value) request.headers(key, value)
} }
//支持HTTP基本认证(Basic Authentication) //支持HTTP基本认证(Basic Authentication)
if (matches.isNotEmpty()) { if (matches.isNotEmpty()) {
request.addInterceptor(BasicAuthInterceptor(matches[2], matches[3])) request.addInterceptor(BasicAuthInterceptor(matches[2], matches[3]))
} }
request.ignoreHttpsCert() //忽略https证书 request.ignoreHttpsCert() //忽略https证书
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s .timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数 .retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间 .retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时 .retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true) .timeStamp(true)
.execute(object : SimpleCallBack<String>() { .execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) { override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage) Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage) SendUtils.updateLogs(logId, 0, e.displayMessage)
} }
override fun onSuccess(response: String) { override fun onSuccess(response: String) {
Log.i(TAG, response) Log.i(TAG, response)
SendUtils.updateLogs(logId, 2, response) SendUtils.updateLogs(logId, 2, response)
} }
}) })
} }
//JSON需要转义的字符 //JSON需要转义的字符
private fun escapeJson(str: String?): String { private fun escapeJson(str: String?): String {
if (str == null) return "null" if (str == null) return "null"
val jsonStr: String = Gson().toJson(str) val jsonStr: String = Gson().toJson(str)
return if (jsonStr.length >= 2) jsonStr.substring(1, jsonStr.length - 1) else jsonStr return if (jsonStr.length >= 2) jsonStr.substring(1, jsonStr.length - 1) else jsonStr
} }
fun sendMsg(setting: WebhookSetting, msgInfo: MsgInfo) { fun sendMsg(setting: WebhookSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null) sendMsg(setting, msgInfo, null, null)
} }
} }
} }

View File

@ -120,7 +120,7 @@ class WeworkAgentUtils private constructor() {
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
val textMsgMap: MutableMap<String, Any> = mutableMapOf() val textMsgMap: MutableMap<String, Any> = mutableMapOf()
@ -132,7 +132,7 @@ class WeworkAgentUtils private constructor() {
val textText: MutableMap<String, Any> = mutableMapOf() val textText: MutableMap<String, Any> = mutableMapOf()
textText["content"] = content textText["content"] = content
textMsgMap["text"] = textText textMsgMap["text"] = textText
var accessToken: String by SharedPreference("access_token_" + setting.agentID, "") val accessToken: String by SharedPreference("access_token_" + setting.agentID, "")
val requestUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$accessToken" val requestUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$accessToken"
Log.i(TAG, "requestUrl:$requestUrl") Log.i(TAG, "requestUrl:$requestUrl")
val requestMsg: String = Gson().toJson(textMsgMap) val requestMsg: String = Gson().toJson(textMsgMap)

View File

@ -28,7 +28,7 @@ class WeworkRobotUtils private constructor() {
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
val requestUrl = setting.webHook val requestUrl = setting.webHook

View File

@ -340,7 +340,7 @@
<string name="sim2_remark" tools:ignore="Typos">SIM2 SubId/Label</string> <string name="sim2_remark" tools:ignore="Typos">SIM2 SubId/Label</string>
<string name="carrier_mobile" tools:ignore="Typos">Label of SIM,\neg. AT&amp;T_88888888</string> <string name="carrier_mobile" tools:ignore="Typos">Label of SIM,\neg. AT&amp;T_88888888</string>
<string name="tip_number_only_error_message">Number must be greater than 0!</string> <string name="tip_number_only_error_message">Number must be greater than 0!</string>
<string name="regexp_number_only" tools:ignore="Typos">^[1-9]?\\d+$</string> <string name="regexp_number_only" tools:ignore="TypographyDashes,Typos">^[1-9]?\\d+$</string>
<string name="low_power_alarm_threshold">Low Power Alarm</string> <string name="low_power_alarm_threshold">Low Power Alarm</string>
<string name="low_power_alarm_threshold_tips">Value range: 099.\nLeft blank or 0 is disabled</string> <string name="low_power_alarm_threshold_tips">Value range: 099.\nLeft blank or 0 is disabled</string>
<string name="retry_interval">Retry Interval</string> <string name="retry_interval">Retry Interval</string>

View File

@ -341,7 +341,7 @@
<string name="sim2_remark" tools:ignore="Typos">SIM2主键/备注</string> <string name="sim2_remark" tools:ignore="Typos">SIM2主键/备注</string>
<string name="carrier_mobile">序号/运营商_手机号</string> <string name="carrier_mobile">序号/运营商_手机号</string>
<string name="tip_number_only_error_message">数字必须大于0!</string> <string name="tip_number_only_error_message">数字必须大于0!</string>
<string name="regexp_number_only" tools:ignore="Typos">^[1-9]?\\d+$</string> <string name="regexp_number_only" tools:ignore="TypographyDashes,Typos">^[1-9]?\\d+$</string>
<string name="low_power_alarm_threshold">安全电量范围(%)</string> <string name="low_power_alarm_threshold">安全电量范围(%)</string>
<string name="low_power_alarm_threshold_tips">超出安全范围将发出预警</string> <string name="low_power_alarm_threshold_tips">超出安全范围将发出预警</string>
<string name="retry_interval">请求重试机制</string> <string name="retry_interval">请求重试机制</string>