修复:极端情况下Gson().fromJson爆空指针错误 #207

pull/231/head
pppscn 2 years ago
parent 74cbddc192
commit 9d75554df0

@ -1,111 +1,111 @@
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.BarkResult
import com.idormy.sms.forwarder.entity.setting.BarkSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import java.util.regex.Pattern
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class BarkUtils {
companion object {
private val TAG: String = BarkUtils::class.java.simpleName
fun sendMsg(
setting: BarkSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val title: String = if (rule != null) {
msgInfo.getTitleForSend(setting.title.toString(), rule.regexReplace)
} else {
msgInfo.getTitleForSend(setting.title.toString())
}
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val requestUrl: String = setting.server //推送地址
Log.i(TAG, "requestUrl:$requestUrl")
//支持HTTP基本认证(Basic Authentication)
val regex = "^(https?://)([^:]+):([^@]+)@(.+)"
val matches = Regex(regex, RegexOption.IGNORE_CASE).findAll(requestUrl).toList().flatMap(MatchResult::groupValues)
Log.i(TAG, "matches = $matches")
val request = if (matches.isNotEmpty()) {
XHttp.post(matches[1] + matches[4]).addInterceptor(BasicAuthInterceptor(matches[2], matches[3]))
} else {
XHttp.post(requestUrl)
}
request.params("title", title)
.params("body", content)
.params("isArchive", 1)
if (!TextUtils.isEmpty(setting.group)) request.params("group", setting.group)
if (!TextUtils.isEmpty(setting.icon)) request.params("icon", setting.icon)
if (!TextUtils.isEmpty(setting.level)) request.params("level", setting.level)
if (!TextUtils.isEmpty(setting.sound)) request.params("sound", setting.sound)
if (!TextUtils.isEmpty(setting.badge)) request.params("badge", setting.badge)
if (!TextUtils.isEmpty(setting.url)) request.params("url", setting.url)
val isCode: Int = content.indexOf("验证码")
val isPassword: Int = content.indexOf("动态密码")
val isPassword2: Int = content.indexOf("短信密码")
if (isCode != -1 || isPassword != -1 || isPassword2 != -1) {
val p = Pattern.compile("(\\d{4,6})")
val m = p.matcher(content)
if (m.find()) {
println(m.group())
request.params("automaticallyCopy", "1")
request.params("copy", m.group())
}
}
request.ignoreHttpsCert() //忽略https证书
.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, BarkResult::class.java)
if (resp.code == 200L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: BarkSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.BarkResult
import com.idormy.sms.forwarder.entity.setting.BarkSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import java.util.regex.Pattern
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class BarkUtils {
companion object {
private val TAG: String = BarkUtils::class.java.simpleName
fun sendMsg(
setting: BarkSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val title: String = if (rule != null) {
msgInfo.getTitleForSend(setting.title.toString(), rule.regexReplace)
} else {
msgInfo.getTitleForSend(setting.title.toString())
}
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val requestUrl: String = setting.server //推送地址
Log.i(TAG, "requestUrl:$requestUrl")
//支持HTTP基本认证(Basic Authentication)
val regex = "^(https?://)([^:]+):([^@]+)@(.+)"
val matches = Regex(regex, RegexOption.IGNORE_CASE).findAll(requestUrl).toList().flatMap(MatchResult::groupValues)
Log.i(TAG, "matches = $matches")
val request = if (matches.isNotEmpty()) {
XHttp.post(matches[1] + matches[4]).addInterceptor(BasicAuthInterceptor(matches[2], matches[3]))
} else {
XHttp.post(requestUrl)
}
request.params("title", title)
.params("body", content)
.params("isArchive", 1)
if (!TextUtils.isEmpty(setting.group)) request.params("group", setting.group)
if (!TextUtils.isEmpty(setting.icon)) request.params("icon", setting.icon)
if (!TextUtils.isEmpty(setting.level)) request.params("level", setting.level)
if (!TextUtils.isEmpty(setting.sound)) request.params("sound", setting.sound)
if (!TextUtils.isEmpty(setting.badge)) request.params("badge", setting.badge)
if (!TextUtils.isEmpty(setting.url)) request.params("url", setting.url)
val isCode: Int = content.indexOf("验证码")
val isPassword: Int = content.indexOf("动态密码")
val isPassword2: Int = content.indexOf("短信密码")
if (isCode != -1 || isPassword != -1 || isPassword2 != -1) {
val p = Pattern.compile("(\\d{4,6})")
val m = p.matcher(content)
if (m.find()) {
println(m.group())
request.params("automaticallyCopy", "1")
request.params("copy", m.group())
}
}
request.ignoreHttpsCert() //忽略https证书
.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, BarkResult::class.java)
if (resp?.code == 200L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: BarkSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
}

@ -1,122 +1,122 @@
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Base64
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.DingtalkResult
import com.idormy.sms.forwarder.entity.setting.DingtalkGroupRobotSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
//钉钉群自定义机器人
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class DingtalkGroupRobotUtils private constructor() {
companion object {
private val TAG: String = DingtalkGroupRobotUtils::class.java.simpleName
fun sendMsg(
setting: DingtalkGroupRobotSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
var requestUrl = if (setting.token.startsWith("http")) setting.token else "https://oapi.dingtalk.com/robot/send?access_token=" + setting.token
if (!TextUtils.isEmpty(setting.secret)) {
val timestamp = System.currentTimeMillis()
val stringToSign = "$timestamp\n" + setting.secret
val mac = Mac.getInstance("HmacSHA256")
mac.init(SecretKeySpec(setting.secret?.toByteArray(StandardCharsets.UTF_8), "HmacSHA256"))
val signData = mac.doFinal(stringToSign.toByteArray(StandardCharsets.UTF_8))
val sign = URLEncoder.encode(String(Base64.encode(signData, Base64.NO_WRAP)), "UTF-8")
requestUrl += "&timestamp=$timestamp&sign=$sign"
}
Log.i(TAG, "requestUrl:$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
msgMap["msgtype"] = "text"
val textText: MutableMap<String, Any> = mutableMapOf()
textText["content"] = content
msgMap["text"] = textText
val atMap: MutableMap<String, Any> = mutableMapOf()
msgMap["at"] = atMap
if (setting.atAll == true) {
atMap["isAtAll"] = true
} else {
atMap["isAtAll"] = false
if (!TextUtils.isEmpty(setting.atMobiles)) {
val atMobilesArray: Array<String>? = setting.atMobiles?.split(",".toRegex())?.toTypedArray()
if (atMobilesArray != null) {
val atMobilesList: MutableList<String> = ArrayList()
for (atMobile in atMobilesArray) {
if (TextUtils.isDigitsOnly(atMobile)) {
atMobilesList.add(atMobile)
}
}
if (atMobilesList.isNotEmpty()) {
atMap["atMobiles"] = atMobilesList
}
}
}
}
val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, DingtalkResult::class.java)
if (resp.errcode == 0L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: DingtalkGroupRobotSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Base64
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.DingtalkResult
import com.idormy.sms.forwarder.entity.setting.DingtalkGroupRobotSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
//钉钉群自定义机器人
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class DingtalkGroupRobotUtils private constructor() {
companion object {
private val TAG: String = DingtalkGroupRobotUtils::class.java.simpleName
fun sendMsg(
setting: DingtalkGroupRobotSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
var requestUrl = if (setting.token.startsWith("http")) setting.token else "https://oapi.dingtalk.com/robot/send?access_token=" + setting.token
if (!TextUtils.isEmpty(setting.secret)) {
val timestamp = System.currentTimeMillis()
val stringToSign = "$timestamp\n" + setting.secret
val mac = Mac.getInstance("HmacSHA256")
mac.init(SecretKeySpec(setting.secret?.toByteArray(StandardCharsets.UTF_8), "HmacSHA256"))
val signData = mac.doFinal(stringToSign.toByteArray(StandardCharsets.UTF_8))
val sign = URLEncoder.encode(String(Base64.encode(signData, Base64.NO_WRAP)), "UTF-8")
requestUrl += "&timestamp=$timestamp&sign=$sign"
}
Log.i(TAG, "requestUrl:$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
msgMap["msgtype"] = "text"
val textText: MutableMap<String, Any> = mutableMapOf()
textText["content"] = content
msgMap["text"] = textText
val atMap: MutableMap<String, Any> = mutableMapOf()
msgMap["at"] = atMap
if (setting.atAll == true) {
atMap["isAtAll"] = true
} else {
atMap["isAtAll"] = false
if (!TextUtils.isEmpty(setting.atMobiles)) {
val atMobilesArray: Array<String>? = setting.atMobiles?.split(",".toRegex())?.toTypedArray()
if (atMobilesArray != null) {
val atMobilesList: MutableList<String> = ArrayList()
for (atMobile in atMobilesArray) {
if (TextUtils.isDigitsOnly(atMobile)) {
atMobilesList.add(atMobile)
}
}
if (atMobilesList.isNotEmpty()) {
atMap["atMobiles"] = atMobilesList
}
}
}
}
val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, DingtalkResult::class.java)
if (resp?.errcode == 0L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: DingtalkGroupRobotSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
}

@ -1,242 +1,242 @@
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.DingtalkInnerRobotResult
import com.idormy.sms.forwarder.entity.setting.DingtalkInnerRobotSetting
import com.idormy.sms.forwarder.utils.MMKVUtils
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xui.utils.ResUtils.getString
import com.xuexiang.xutil.net.NetworkUtils
import okhttp3.Credentials
import okhttp3.Response
import okhttp3.Route
import java.net.Authenticator
import java.net.InetSocketAddress
import java.net.PasswordAuthentication
import java.net.Proxy
//钉钉企业内机器人
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class DingtalkInnerRobotUtils private constructor() {
companion object {
private val TAG: String = DingtalkInnerRobotUtils::class.java.simpleName
fun sendMsg(
setting: DingtalkInnerRobotSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val accessToken: String? = MMKVUtils.getString("accessToken_" + setting.agentID, "")
val expiresIn: Long = MMKVUtils.getLong("expiresIn_" + setting.agentID, 0L)
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
return sendTextMsg(setting, msgInfo, rule, logId)
}
val requestUrl = "https://api.dingtalk.com/v1.0/oauth2/accessToken"
Log.d(TAG, "requestUrl$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
msgMap["appKey"] = setting.appKey
msgMap["appSecret"] = setting.appSecret
val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg")
val request = XHttp.post(requestUrl)
//设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
if (!NetworkUtils.isIP(proxyHost)) {
throw Exception("代理服务器主机名解析失败proxyHost=$proxyHost")
}
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码
if (setting.proxyAuthenticator == true
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
} else {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
}
})
}
}
}
request.upJson(requestMsg)
.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, DingtalkInnerRobotResult::class.java)
if (!TextUtils.isEmpty(resp.accessToken)) {
MMKVUtils.put("accessToken_" + setting.agentID, resp.accessToken)
MMKVUtils.put("expiresIn_" + setting.agentID, System.currentTimeMillis() + ((resp.expireIn ?: 7200) - 120) * 1000L) //提前2分钟过期
sendTextMsg(setting, msgInfo, rule, logId)
} else {
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
}
}
})
}
//发送文本消息
private fun sendTextMsg(
setting: DingtalkInnerRobotSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val requestUrl = "https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend"
Log.d(TAG, "requestUrl$requestUrl")
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val msgParam: MutableMap<String, Any> = mutableMapOf()
if ("sampleMarkdown" == setting.msgKey) {
msgParam["title"] = if (rule != null) {
msgInfo.getTitleForSend(setting.titleTemplate.toString(), rule.regexReplace)
} else {
msgInfo.getTitleForSend(setting.titleTemplate.toString())
}
msgParam["text"] = content
} else {
msgParam["content"] = content
}
val textMsgMap: MutableMap<String, Any> = mutableMapOf()
textMsgMap["robotCode"] = setting.appKey
textMsgMap["userIds"] = setting.userIds.split('|').toTypedArray()
textMsgMap["msgKey"] = setting.msgKey
textMsgMap["msgParam"] = Gson().toJson(msgParam)
val requestMsg: String = Gson().toJson(textMsgMap)
Log.i(TAG, "requestMsg:$requestMsg")
val request = XHttp.post(requestUrl)
//设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
if (!NetworkUtils.isIP(proxyHost)) {
throw Exception("代理服务器主机名解析失败proxyHost=$proxyHost")
}
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码
if (setting.proxyAuthenticator == true
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
} else {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
}
})
}
}
}
request.upJson(requestMsg)
.headers("x-acs-dingtalk-access-token", MMKVUtils.getString("accessToken_" + setting.agentID, ""))
.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, DingtalkInnerRobotResult::class.java)
if (!TextUtils.isEmpty(resp.processQueryKey)) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: DingtalkInnerRobotSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.DingtalkInnerRobotResult
import com.idormy.sms.forwarder.entity.setting.DingtalkInnerRobotSetting
import com.idormy.sms.forwarder.utils.MMKVUtils
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xui.utils.ResUtils.getString
import com.xuexiang.xutil.net.NetworkUtils
import okhttp3.Credentials
import okhttp3.Response
import okhttp3.Route
import java.net.Authenticator
import java.net.InetSocketAddress
import java.net.PasswordAuthentication
import java.net.Proxy
//钉钉企业内机器人
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class DingtalkInnerRobotUtils private constructor() {
companion object {
private val TAG: String = DingtalkInnerRobotUtils::class.java.simpleName
fun sendMsg(
setting: DingtalkInnerRobotSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val accessToken: String? = MMKVUtils.getString("accessToken_" + setting.agentID, "")
val expiresIn: Long = MMKVUtils.getLong("expiresIn_" + setting.agentID, 0L)
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
return sendTextMsg(setting, msgInfo, rule, logId)
}
val requestUrl = "https://api.dingtalk.com/v1.0/oauth2/accessToken"
Log.d(TAG, "requestUrl$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
msgMap["appKey"] = setting.appKey
msgMap["appSecret"] = setting.appSecret
val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg")
val request = XHttp.post(requestUrl)
//设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
if (!NetworkUtils.isIP(proxyHost)) {
throw Exception("代理服务器主机名解析失败proxyHost=$proxyHost")
}
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码
if (setting.proxyAuthenticator == true
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
} else {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
}
})
}
}
}
request.upJson(requestMsg)
.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, DingtalkInnerRobotResult::class.java)
if (!TextUtils.isEmpty(resp?.accessToken)) {
MMKVUtils.put("accessToken_" + setting.agentID, resp.accessToken)
MMKVUtils.put("expiresIn_" + setting.agentID, System.currentTimeMillis() + ((resp.expireIn ?: 7200) - 120) * 1000L) //提前2分钟过期
sendTextMsg(setting, msgInfo, rule, logId)
} else {
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
}
}
})
}
//发送文本消息
private fun sendTextMsg(
setting: DingtalkInnerRobotSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val requestUrl = "https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend"
Log.d(TAG, "requestUrl$requestUrl")
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val msgParam: MutableMap<String, Any> = mutableMapOf()
if ("sampleMarkdown" == setting.msgKey) {
msgParam["title"] = if (rule != null) {
msgInfo.getTitleForSend(setting.titleTemplate.toString(), rule.regexReplace)
} else {
msgInfo.getTitleForSend(setting.titleTemplate.toString())
}
msgParam["text"] = content
} else {
msgParam["content"] = content
}
val textMsgMap: MutableMap<String, Any> = mutableMapOf()
textMsgMap["robotCode"] = setting.appKey
textMsgMap["userIds"] = setting.userIds.split('|').toTypedArray()
textMsgMap["msgKey"] = setting.msgKey
textMsgMap["msgParam"] = Gson().toJson(msgParam)
val requestMsg: String = Gson().toJson(textMsgMap)
Log.i(TAG, "requestMsg:$requestMsg")
val request = XHttp.post(requestUrl)
//设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
if (!NetworkUtils.isIP(proxyHost)) {
throw Exception("代理服务器主机名解析失败proxyHost=$proxyHost")
}
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码
if (setting.proxyAuthenticator == true
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
} else {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
}
})
}
}
}
request.upJson(requestMsg)
.headers("x-acs-dingtalk-access-token", MMKVUtils.getString("accessToken_" + setting.agentID, ""))
.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, DingtalkInnerRobotResult::class.java)
if (!TextUtils.isEmpty(resp?.processQueryKey)) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: DingtalkInnerRobotSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
}

@ -1,163 +1,163 @@
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.FeishuAppResult
import com.idormy.sms.forwarder.entity.setting.FeishuAppSetting
import com.idormy.sms.forwarder.utils.MMKVUtils
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xui.utils.ResUtils.getString
//飞书企业应用
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class FeishuAppUtils private constructor() {
companion object {
private val TAG: String = FeishuAppUtils::class.java.simpleName
fun sendMsg(
setting: FeishuAppSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val accessToken: String? = MMKVUtils.getString("feishu_access_token_" + setting.appId, "")
val expiresIn: Long = MMKVUtils.getLong("feishu_expires_in_" + setting.appId, 0L)
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
return sendTextMsg(setting, msgInfo, rule, logId)
}
val requestUrl = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
Log.d(TAG, "requestUrl$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
msgMap["app_id"] = setting.appId
msgMap["app_secret"] = setting.appSecret
val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, FeishuAppResult::class.java)
if (!TextUtils.isEmpty(resp.tenant_access_token)) {
MMKVUtils.put("feishu_access_token_" + setting.appId, resp.tenant_access_token)
MMKVUtils.put("feishu_expires_in_" + setting.appId, System.currentTimeMillis() + ((resp.expire ?: 7010) - 120) * 1000L) //提前2分钟过期
sendTextMsg(setting, msgInfo, rule, logId)
} else {
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
}
}
})
}
//发送文本消息
private fun sendTextMsg(
setting: FeishuAppSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val requestUrl = "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=user_id"
Log.d(TAG, "requestUrl$requestUrl")
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val msgContent = if ("interactive" == setting.msgType) {
val title = if (rule != null) {
msgInfo.getTitleForSend(setting.titleTemplate, rule.regexReplace)
} else {
msgInfo.getTitleForSend(setting.titleTemplate)
}
"{\"elements\":[{\"tag\":\"markdown\",\"content\":\"**[{{MSG_TITLE}}]({{MSG_URL}})**\\n --------------\\n{{MSG_CONTENT}}\"}]}".trimIndent().replace("{{MSG_TITLE}}", jsonInnerStr(title))
.replace("{{MSG_URL}}", jsonInnerStr("https://github.com/pppscn/SmsForwarder"))
.replace("{{MSG_CONTENT}}", jsonInnerStr(content))
} else {
"{\"text\":\"{{MSG_CONTENT}}\"}".trimIndent().replace("{{MSG_CONTENT}}", jsonInnerStr(content))
}
val textMsgMap: MutableMap<String, Any> = mutableMapOf()
textMsgMap["receive_id"] = setting.receiveId
textMsgMap["msg_type"] = setting.msgType
textMsgMap["content"] = msgContent
val requestMsg: String = Gson().toJson(textMsgMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.headers("Authorization", "Bearer " + MMKVUtils.getString("feishu_access_token_" + setting.appId, ""))
.keepJson(true)
//.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
//Log.d(TAG, "tlsVersion=" + response.handshake().tlsVersion())
//Log.d(TAG, "cipherSuite=" + response.handshake().cipherSuite().toString())
val resp = Gson().fromJson(response, FeishuAppResult::class.java)
if (resp.code == 0L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: FeishuAppSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
private fun jsonInnerStr(string: String?): String {
if (string == null) return "null"
val jsonStr: String = Gson().toJson(string)
return if (jsonStr.length >= 2) jsonStr.substring(1, jsonStr.length - 1) else jsonStr
}
}
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.FeishuAppResult
import com.idormy.sms.forwarder.entity.setting.FeishuAppSetting
import com.idormy.sms.forwarder.utils.MMKVUtils
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xui.utils.ResUtils.getString
//飞书企业应用
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class FeishuAppUtils private constructor() {
companion object {
private val TAG: String = FeishuAppUtils::class.java.simpleName
fun sendMsg(
setting: FeishuAppSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val accessToken: String? = MMKVUtils.getString("feishu_access_token_" + setting.appId, "")
val expiresIn: Long = MMKVUtils.getLong("feishu_expires_in_" + setting.appId, 0L)
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
return sendTextMsg(setting, msgInfo, rule, logId)
}
val requestUrl = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
Log.d(TAG, "requestUrl$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
msgMap["app_id"] = setting.appId
msgMap["app_secret"] = setting.appSecret
val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, FeishuAppResult::class.java)
if (!TextUtils.isEmpty(resp?.tenant_access_token)) {
MMKVUtils.put("feishu_access_token_" + setting.appId, resp.tenant_access_token)
MMKVUtils.put("feishu_expires_in_" + setting.appId, System.currentTimeMillis() + ((resp.expire ?: 7010) - 120) * 1000L) //提前2分钟过期
sendTextMsg(setting, msgInfo, rule, logId)
} else {
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
}
}
})
}
//发送文本消息
private fun sendTextMsg(
setting: FeishuAppSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val requestUrl = "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=user_id"
Log.d(TAG, "requestUrl$requestUrl")
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val msgContent = if ("interactive" == setting.msgType) {
val title = if (rule != null) {
msgInfo.getTitleForSend(setting.titleTemplate, rule.regexReplace)
} else {
msgInfo.getTitleForSend(setting.titleTemplate)
}
"{\"elements\":[{\"tag\":\"markdown\",\"content\":\"**[{{MSG_TITLE}}]({{MSG_URL}})**\\n --------------\\n{{MSG_CONTENT}}\"}]}".trimIndent().replace("{{MSG_TITLE}}", jsonInnerStr(title))
.replace("{{MSG_URL}}", jsonInnerStr("https://github.com/pppscn/SmsForwarder"))
.replace("{{MSG_CONTENT}}", jsonInnerStr(content))
} else {
"{\"text\":\"{{MSG_CONTENT}}\"}".trimIndent().replace("{{MSG_CONTENT}}", jsonInnerStr(content))
}
val textMsgMap: MutableMap<String, Any> = mutableMapOf()
textMsgMap["receive_id"] = setting.receiveId
textMsgMap["msg_type"] = setting.msgType
textMsgMap["content"] = msgContent
val requestMsg: String = Gson().toJson(textMsgMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.headers("Authorization", "Bearer " + MMKVUtils.getString("feishu_access_token_" + setting.appId, ""))
.keepJson(true)
//.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
//Log.d(TAG, "tlsVersion=" + response.handshake().tlsVersion())
//Log.d(TAG, "cipherSuite=" + response.handshake().cipherSuite().toString())
val resp = Gson().fromJson(response, FeishuAppResult::class.java)
if (resp?.code == 0L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: FeishuAppSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
private fun jsonInnerStr(string: String?): String {
if (string == null) return "null"
val jsonStr: String = Gson().toJson(string)
return if (jsonStr.length >= 2) jsonStr.substring(1, jsonStr.length - 1) else jsonStr
}
}
}

@ -1,187 +1,187 @@
package com.idormy.sms.forwarder.utils.sender
import android.util.Base64
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.FeishuResult
import com.idormy.sms.forwarder.entity.setting.FeishuSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import java.nio.charset.StandardCharsets
import java.text.SimpleDateFormat
import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class FeishuUtils private constructor() {
companion object {
private val TAG: String = FeishuUtils::class.java.simpleName
private val MSG_TEMPLATE = """
{
"config": {
"wide_screen_mode": true
},
"elements": [
{
"fields": [
{
"is_short": true,
"text": {
"content": "**时间**\n{{MSG_TIME}}",
"tag": "lark_md"
}
},
{
"is_short": true,
"text": {
"content": "**来源**\n{{MSG_FROM}}",
"tag": "lark_md"
}
}
],
"tag": "div"
},
{
"tag": "div",
"text": {
"content": "{{MSG_CONTENT}}",
"tag": "lark_md"
}
},
{
"tag": "hr"
},
{
"elements": [
{
"content": "[SmsForwarder](https://github.com/pppscn/SmsForwarder)",
"tag": "lark_md"
}
],
"tag": "note"
}
],
"header": {
"template": "turquoise",
"title": {
"content": "{{MSG_TITLE}}",
"tag": "plain_text"
}
}
}
""".trimIndent()
fun sendMsg(
setting: FeishuSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val from: String = msgInfo.from
val title: String = if (rule != null) {
msgInfo.getTitleForSend(setting.titleTemplate.toString(), rule.regexReplace)
} else {
msgInfo.getTitleForSend(setting.titleTemplate.toString())
}
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val requestUrl = setting.webhook
Log.i(TAG, "requestUrl:$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
if (setting.secret != null) {
val timestamp = System.currentTimeMillis() / 1000
val stringToSign = "$timestamp\n" + setting.secret
Log.i(TAG, "stringToSign = $stringToSign")
//使用HmacSHA256算法计算签名
val mac = Mac.getInstance("HmacSHA256")
mac.init(SecretKeySpec(stringToSign.toByteArray(StandardCharsets.UTF_8), "HmacSHA256"))
val signData = mac.doFinal(byteArrayOf())
val sign = String(Base64.encode(signData, Base64.NO_WRAP))
msgMap["timestamp"] = timestamp
msgMap["sign"] = sign
}
//组装报文
val requestMsg: String
if (setting.msgType == null || setting.msgType == "interactive") {
msgMap["msg_type"] = "interactive"
msgMap["card"] = "{{CARD_BODY}}"
requestMsg = Gson().toJson(msgMap).replace("\"{{CARD_BODY}}\"", buildMsg(title, content, from, msgInfo.date))
} else {
msgMap["msg_type"] = "text"
val contentMap: MutableMap<String, Any> = mutableMapOf()
contentMap["text"] = content
msgMap["content"] = contentMap
requestMsg = Gson().toJson(msgMap)
}
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, FeishuResult::class.java)
if (resp.code == 0L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
private fun buildMsg(title: String, content: String, from: String, date: Date): String {
val msgTitle = jsonInnerStr(title)
val msgContent = jsonInnerStr(content)
val msgFrom = jsonInnerStr(from)
val msgTime = jsonInnerStr(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(date))
return MSG_TEMPLATE.replace("{{MSG_TITLE}}", msgTitle)
.replace("{{MSG_TIME}}", msgTime)
.replace("{{MSG_FROM}}", msgFrom)
.replace("{{MSG_CONTENT}}", msgContent)
}
private fun jsonInnerStr(string: String?): String {
if (string == null) return "null"
val jsonStr: String = Gson().toJson(string)
return if (jsonStr.length >= 2) jsonStr.substring(1, jsonStr.length - 1) else jsonStr
}
fun sendMsg(setting: FeishuSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
package com.idormy.sms.forwarder.utils.sender
import android.util.Base64
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.FeishuResult
import com.idormy.sms.forwarder.entity.setting.FeishuSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import java.nio.charset.StandardCharsets
import java.text.SimpleDateFormat
import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class FeishuUtils private constructor() {
companion object {
private val TAG: String = FeishuUtils::class.java.simpleName
private val MSG_TEMPLATE = """
{
"config": {
"wide_screen_mode": true
},
"elements": [
{
"fields": [
{
"is_short": true,
"text": {
"content": "**时间**\n{{MSG_TIME}}",
"tag": "lark_md"
}
},
{
"is_short": true,
"text": {
"content": "**来源**\n{{MSG_FROM}}",
"tag": "lark_md"
}
}
],
"tag": "div"
},
{
"tag": "div",
"text": {
"content": "{{MSG_CONTENT}}",
"tag": "lark_md"
}
},
{
"tag": "hr"
},
{
"elements": [
{
"content": "[SmsForwarder](https://github.com/pppscn/SmsForwarder)",
"tag": "lark_md"
}
],
"tag": "note"
}
],
"header": {
"template": "turquoise",
"title": {
"content": "{{MSG_TITLE}}",
"tag": "plain_text"
}
}
}
""".trimIndent()
fun sendMsg(
setting: FeishuSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val from: String = msgInfo.from
val title: String = if (rule != null) {
msgInfo.getTitleForSend(setting.titleTemplate.toString(), rule.regexReplace)
} else {
msgInfo.getTitleForSend(setting.titleTemplate.toString())
}
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val requestUrl = setting.webhook
Log.i(TAG, "requestUrl:$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
if (setting.secret != null) {
val timestamp = System.currentTimeMillis() / 1000
val stringToSign = "$timestamp\n" + setting.secret
Log.i(TAG, "stringToSign = $stringToSign")
//使用HmacSHA256算法计算签名
val mac = Mac.getInstance("HmacSHA256")
mac.init(SecretKeySpec(stringToSign.toByteArray(StandardCharsets.UTF_8), "HmacSHA256"))
val signData = mac.doFinal(byteArrayOf())
val sign = String(Base64.encode(signData, Base64.NO_WRAP))
msgMap["timestamp"] = timestamp
msgMap["sign"] = sign
}
//组装报文
val requestMsg: String
if (setting.msgType == null || setting.msgType == "interactive") {
msgMap["msg_type"] = "interactive"
msgMap["card"] = "{{CARD_BODY}}"
requestMsg = Gson().toJson(msgMap).replace("\"{{CARD_BODY}}\"", buildMsg(title, content, from, msgInfo.date))
} else {
msgMap["msg_type"] = "text"
val contentMap: MutableMap<String, Any> = mutableMapOf()
contentMap["text"] = content
msgMap["content"] = contentMap
requestMsg = Gson().toJson(msgMap)
}
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, FeishuResult::class.java)
if (resp?.code == 0L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
private fun buildMsg(title: String, content: String, from: String, date: Date): String {
val msgTitle = jsonInnerStr(title)
val msgContent = jsonInnerStr(content)
val msgFrom = jsonInnerStr(from)
val msgTime = jsonInnerStr(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(date))
return MSG_TEMPLATE.replace("{{MSG_TITLE}}", msgTitle)
.replace("{{MSG_TIME}}", msgTime)
.replace("{{MSG_FROM}}", msgFrom)
.replace("{{MSG_CONTENT}}", msgContent)
}
private fun jsonInnerStr(string: String?): String {
if (string == null) return "null"
val jsonStr: String = Gson().toJson(string)
return if (jsonStr.length >= 2) jsonStr.substring(1, jsonStr.length - 1) else jsonStr
}
fun sendMsg(setting: FeishuSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
}

@ -1,105 +1,105 @@
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.PushplusResult
import com.idormy.sms.forwarder.entity.setting.PushplusSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xui.utils.ResUtils
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class PushplusUtils private constructor() {
companion object {
private val TAG: String = PushplusUtils::class.java.simpleName
fun sendMsg(
setting: PushplusSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val title: String = if (rule != null) {
msgInfo.getTitleForSend(setting.titleTemplate.toString(), rule.regexReplace)
} else {
msgInfo.getTitleForSend(setting.titleTemplate.toString())
}
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val requestUrl = "https://" + setting.website + "/send"
Log.i(TAG, "requestUrl:$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
msgMap["token"] = setting.token
msgMap["content"] = content
if (!TextUtils.isEmpty(title)) msgMap["title"] = title
if (!TextUtils.isEmpty(setting.template)) msgMap["template"] = setting.template.toString()
if (!TextUtils.isEmpty(setting.topic)) msgMap["topic"] = setting.topic.toString()
if (setting.website == ResUtils.getString(R.string.pushplus_plus)) {
if (!TextUtils.isEmpty(setting.channel)) msgMap["channel"] = setting.channel.toString()
if (!TextUtils.isEmpty(setting.webhook)) msgMap["webhook"] = setting.webhook.toString()
if (!TextUtils.isEmpty(setting.callbackUrl)) msgMap["callbackUrl"] = setting.callbackUrl.toString()
if (!TextUtils.isEmpty(setting.validTime)) {
val validTime = setting.validTime?.toInt()
if (validTime != null && validTime > 0) {
msgMap["timestamp"] = System.currentTimeMillis() + validTime * 1000L
}
}
}
val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, PushplusResult::class.java)
if (resp.code == 200L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: PushplusSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.PushplusResult
import com.idormy.sms.forwarder.entity.setting.PushplusSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xui.utils.ResUtils
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class PushplusUtils private constructor() {
companion object {
private val TAG: String = PushplusUtils::class.java.simpleName
fun sendMsg(
setting: PushplusSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val title: String = if (rule != null) {
msgInfo.getTitleForSend(setting.titleTemplate.toString(), rule.regexReplace)
} else {
msgInfo.getTitleForSend(setting.titleTemplate.toString())
}
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val requestUrl = "https://" + setting.website + "/send"
Log.i(TAG, "requestUrl:$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
msgMap["token"] = setting.token
msgMap["content"] = content
if (!TextUtils.isEmpty(title)) msgMap["title"] = title
if (!TextUtils.isEmpty(setting.template)) msgMap["template"] = setting.template.toString()
if (!TextUtils.isEmpty(setting.topic)) msgMap["topic"] = setting.topic.toString()
if (setting.website == ResUtils.getString(R.string.pushplus_plus)) {
if (!TextUtils.isEmpty(setting.channel)) msgMap["channel"] = setting.channel.toString()
if (!TextUtils.isEmpty(setting.webhook)) msgMap["webhook"] = setting.webhook.toString()
if (!TextUtils.isEmpty(setting.callbackUrl)) msgMap["callbackUrl"] = setting.callbackUrl.toString()
if (!TextUtils.isEmpty(setting.validTime)) {
val validTime = setting.validTime?.toInt()
if (validTime != null && validTime > 0) {
msgMap["timestamp"] = System.currentTimeMillis() + validTime * 1000L
}
}
}
val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, PushplusResult::class.java)
if (resp?.code == 200L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: PushplusSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
}

@ -1,159 +1,159 @@
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.TelegramResult
import com.idormy.sms.forwarder.entity.setting.TelegramSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xutil.net.NetworkUtils
import okhttp3.Credentials
import okhttp3.Response
import okhttp3.Route
import java.net.*
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class TelegramUtils private constructor() {
companion object {
private val TAG: String = TelegramUtils::class.java.simpleName
fun sendMsg(
setting: TelegramSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
if (setting.method == null || setting.method == "POST") {
msgInfo.content = htmlEncode(msgInfo.content)
msgInfo.simInfo = htmlEncode(msgInfo.simInfo)
}
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
var requestUrl = if (setting.apiToken.startsWith("http")) {
setting.apiToken
} else {
"https://api.telegram.org/bot" + setting.apiToken + "/sendMessage"
}
Log.i(TAG, "requestUrl:$requestUrl")
val request = if (setting.method != null && setting.method == "GET") {
requestUrl += "?chat_id=" + setting.chatId + "&text=" + URLEncoder.encode(content, "UTF-8")
Log.i(TAG, "requestUrl:$requestUrl")
XHttp.get(requestUrl)
} else {
val bodyMap: MutableMap<String, Any> = mutableMapOf()
bodyMap["chat_id"] = setting.chatId
bodyMap["text"] = content
bodyMap["parse_mode"] = "HTML"
bodyMap["disable_web_page_preview"] = "true"
val requestMsg: String = Gson().toJson(bodyMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl).upJson(requestMsg)
}
//设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
if (!NetworkUtils.isIP(proxyHost)) {
throw Exception("代理服务器主机名解析失败proxyHost=$proxyHost")
}
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码
if (setting.proxyAuthenticator == true
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
} else {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
}
})
}
}
}
request.keepJson(true)
//.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, TelegramResult::class.java)
if (resp.ok == true) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: TelegramSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
private fun htmlEncode(source: String?): String {
if (source == null) {
return ""
}
val buffer = StringBuffer()
for (element in source) {
when (element) {
'<' -> buffer.append("&lt;")
'>' -> buffer.append("&gt;")
'&' -> buffer.append("&amp;")
'"' -> buffer.append("&quot;")
//10, 13 -> buffer.append("\n")
else -> buffer.append(element)
}
}
return buffer.toString()
}
}
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.TelegramResult
import com.idormy.sms.forwarder.entity.setting.TelegramSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xutil.net.NetworkUtils
import okhttp3.Credentials
import okhttp3.Response
import okhttp3.Route
import java.net.*
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class TelegramUtils private constructor() {
companion object {
private val TAG: String = TelegramUtils::class.java.simpleName
fun sendMsg(
setting: TelegramSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
if (setting.method == null || setting.method == "POST") {
msgInfo.content = htmlEncode(msgInfo.content)
msgInfo.simInfo = htmlEncode(msgInfo.simInfo)
}
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
var requestUrl = if (setting.apiToken.startsWith("http")) {
setting.apiToken
} else {
"https://api.telegram.org/bot" + setting.apiToken + "/sendMessage"
}
Log.i(TAG, "requestUrl:$requestUrl")
val request = if (setting.method != null && setting.method == "GET") {
requestUrl += "?chat_id=" + setting.chatId + "&text=" + URLEncoder.encode(content, "UTF-8")
Log.i(TAG, "requestUrl:$requestUrl")
XHttp.get(requestUrl)
} else {
val bodyMap: MutableMap<String, Any> = mutableMapOf()
bodyMap["chat_id"] = setting.chatId
bodyMap["text"] = content
bodyMap["parse_mode"] = "HTML"
bodyMap["disable_web_page_preview"] = "true"
val requestMsg: String = Gson().toJson(bodyMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl).upJson(requestMsg)
}
//设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
if (!NetworkUtils.isIP(proxyHost)) {
throw Exception("代理服务器主机名解析失败proxyHost=$proxyHost")
}
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码
if (setting.proxyAuthenticator == true
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
} else {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
}
})
}
}
}
request.keepJson(true)
//.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, TelegramResult::class.java)
if (resp?.ok == true) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: TelegramSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
private fun htmlEncode(source: String?): String {
if (source == null) {
return ""
}
val buffer = StringBuffer()
for (element in source) {
when (element) {
'<' -> buffer.append("&lt;")
'>' -> buffer.append("&gt;")
'&' -> buffer.append("&amp;")
'"' -> buffer.append("&quot;")
//10, 13 -> buffer.append("\n")
else -> buffer.append(element)
}
}
return buffer.toString()
}
}
}

@ -1,226 +1,226 @@
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.DingtalkResult
import com.idormy.sms.forwarder.entity.result.WeworkAgentResult
import com.idormy.sms.forwarder.entity.setting.WeworkAgentSetting
import com.idormy.sms.forwarder.utils.MMKVUtils
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xui.utils.ResUtils.getString
import com.xuexiang.xutil.net.NetworkUtils
import okhttp3.Credentials
import okhttp3.Response
import okhttp3.Route
import java.net.Authenticator
import java.net.InetSocketAddress
import java.net.PasswordAuthentication
import java.net.Proxy
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class WeworkAgentUtils private constructor() {
companion object {
private val TAG: String = WeworkAgentUtils::class.java.simpleName
fun sendMsg(
setting: WeworkAgentSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val accessToken: String? = MMKVUtils.getString("access_token_" + setting.agentID, "")
val expiresIn: Long = MMKVUtils.getLong("expires_in_" + setting.agentID, 0L)
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
return sendTextMsg(setting, msgInfo, rule, logId)
}
var getTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
getTokenUrl += "corpid=" + setting.corpID
getTokenUrl += "&corpsecret=" + setting.secret
Log.d(TAG, "getTokenUrl$getTokenUrl")
val request = XHttp.get(getTokenUrl)
//设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
if (!NetworkUtils.isIP(proxyHost)) {
throw Exception("代理服务器主机名解析失败proxyHost=$proxyHost")
}
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码
if (setting.proxyAuthenticator == true
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
} else {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
}
})
}
}
}
request.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, WeworkAgentResult::class.java)
if (resp.errcode == 0L) {
MMKVUtils.put("access_token_" + setting.agentID, resp.access_token)
MMKVUtils.put("expires_in_" + setting.agentID, System.currentTimeMillis() + ((resp.expires_in ?: 7200) - 120) * 1000L) //提前2分钟过期
sendTextMsg(setting, msgInfo, rule, logId)
} else {
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
}
}
})
}
//发送文本消息
private fun sendTextMsg(
setting: WeworkAgentSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val textMsgMap: MutableMap<String, Any> = mutableMapOf()
textMsgMap["touser"] = setting.toUser.toString()
textMsgMap["toparty"] = setting.toParty.toString()
textMsgMap["totag"] = setting.toTag.toString()
textMsgMap["msgtype"] = "text"
textMsgMap["agentid"] = setting.agentID
val textText: MutableMap<String, Any> = mutableMapOf()
textText["content"] = content
textMsgMap["text"] = textText
val requestUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + MMKVUtils.getString("access_token_" + setting.agentID, "")
Log.i(TAG, "requestUrl:$requestUrl")
val requestMsg: String = Gson().toJson(textMsgMap)
Log.i(TAG, "requestMsg:$requestMsg")
val request = XHttp.post(requestUrl)
//设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
if (!NetworkUtils.isIP(proxyHost)) {
throw Exception("代理服务器主机名解析失败proxyHost=$proxyHost")
}
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码
if (setting.proxyAuthenticator == true
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
} else {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
}
})
}
}
}
request.upJson(requestMsg)
.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, DingtalkResult::class.java)
if (resp.errcode == 0L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: WeworkAgentSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
package com.idormy.sms.forwarder.utils.sender
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.DingtalkResult
import com.idormy.sms.forwarder.entity.result.WeworkAgentResult
import com.idormy.sms.forwarder.entity.setting.WeworkAgentSetting
import com.idormy.sms.forwarder.utils.MMKVUtils
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xui.utils.ResUtils.getString
import com.xuexiang.xutil.net.NetworkUtils
import okhttp3.Credentials
import okhttp3.Response
import okhttp3.Route
import java.net.Authenticator
import java.net.InetSocketAddress
import java.net.PasswordAuthentication
import java.net.Proxy
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class WeworkAgentUtils private constructor() {
companion object {
private val TAG: String = WeworkAgentUtils::class.java.simpleName
fun sendMsg(
setting: WeworkAgentSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val accessToken: String? = MMKVUtils.getString("access_token_" + setting.agentID, "")
val expiresIn: Long = MMKVUtils.getLong("expires_in_" + setting.agentID, 0L)
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
return sendTextMsg(setting, msgInfo, rule, logId)
}
var getTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
getTokenUrl += "corpid=" + setting.corpID
getTokenUrl += "&corpsecret=" + setting.secret
Log.d(TAG, "getTokenUrl$getTokenUrl")
val request = XHttp.get(getTokenUrl)
//设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
if (!NetworkUtils.isIP(proxyHost)) {
throw Exception("代理服务器主机名解析失败proxyHost=$proxyHost")
}
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码
if (setting.proxyAuthenticator == true
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
} else {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
}
})
}
}
}
request.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, WeworkAgentResult::class.java)
if (resp?.errcode == 0L) {
MMKVUtils.put("access_token_" + setting.agentID, resp.access_token)
MMKVUtils.put("expires_in_" + setting.agentID, System.currentTimeMillis() + ((resp.expires_in ?: 7200) - 120) * 1000L) //提前2分钟过期
sendTextMsg(setting, msgInfo, rule, logId)
} else {
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
}
}
})
}
//发送文本消息
private fun sendTextMsg(
setting: WeworkAgentSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val textMsgMap: MutableMap<String, Any> = mutableMapOf()
textMsgMap["touser"] = setting.toUser.toString()
textMsgMap["toparty"] = setting.toParty.toString()
textMsgMap["totag"] = setting.toTag.toString()
textMsgMap["msgtype"] = "text"
textMsgMap["agentid"] = setting.agentID
val textText: MutableMap<String, Any> = mutableMapOf()
textText["content"] = content
textMsgMap["text"] = textText
val requestUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + MMKVUtils.getString("access_token_" + setting.agentID, "")
Log.i(TAG, "requestUrl:$requestUrl")
val requestMsg: String = Gson().toJson(textMsgMap)
Log.i(TAG, "requestMsg:$requestMsg")
val request = XHttp.post(requestUrl)
//设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
if (!NetworkUtils.isIP(proxyHost)) {
throw Exception("代理服务器主机名解析失败proxyHost=$proxyHost")
}
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码
if (setting.proxyAuthenticator == true
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
} else {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication {
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
}
})
}
}
}
request.upJson(requestMsg)
.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, DingtalkResult::class.java)
if (resp?.errcode == 0L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: WeworkAgentSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
}

@ -1,82 +1,82 @@
package com.idormy.sms.forwarder.utils.sender
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.WeworkRobotResult
import com.idormy.sms.forwarder.entity.setting.WeworkRobotSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class WeworkRobotUtils private constructor() {
companion object {
private val TAG: String = WeworkRobotUtils::class.java.simpleName
fun sendMsg(
setting: WeworkRobotSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val requestUrl = setting.webHook
Log.i(TAG, "requestUrl:$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
msgMap["msgtype"] = "text"
val textText: MutableMap<String, Any> = mutableMapOf()
textText["content"] = content
msgMap["text"] = textText
val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, WeworkRobotResult::class.java)
if (resp.errcode == 0L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: WeworkRobotSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
package com.idormy.sms.forwarder.utils.sender
import android.util.Log
import com.google.gson.Gson
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.WeworkRobotResult
import com.idormy.sms.forwarder.entity.setting.WeworkRobotSetting
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack
import com.xuexiang.xhttp2.exception.ApiException
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class WeworkRobotUtils private constructor() {
companion object {
private val TAG: String = WeworkRobotUtils::class.java.simpleName
fun sendMsg(
setting: WeworkRobotSetting,
msgInfo: MsgInfo,
rule: Rule?,
logId: Long?,
) {
val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString())
}
val requestUrl = setting.webHook
Log.i(TAG, "requestUrl:$requestUrl")
val msgMap: MutableMap<String, Any> = mutableMapOf()
msgMap["msgtype"] = "text"
val textText: MutableMap<String, Any> = mutableMapOf()
textText["content"] = content
msgMap["text"] = textText
val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl)
.upJson(requestMsg)
.keepJson(true)
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage)
SendUtils.updateLogs(logId, 0, e.displayMessage)
}
override fun onSuccess(response: String) {
Log.i(TAG, response)
val resp = Gson().fromJson(response, WeworkRobotResult::class.java)
if (resp?.errcode == 0L) {
SendUtils.updateLogs(logId, 2, response)
} else {
SendUtils.updateLogs(logId, 0, response)
}
}
})
}
fun sendMsg(setting: WeworkRobotSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null)
}
}
}
Loading…
Cancel
Save