mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 17:37:40 +08:00
优化:单个转发规则支持绑定多个发送通道,且支持执行逻辑(全部执行/失败即止/成功即止) #247
优化:转发日志列表以原始信息为主,聚合展示转发日志(一对多)
This commit is contained in:
parent
b4870207d1
commit
b79d3d8493
@ -17,10 +17,7 @@ import com.gyf.cactus.ext.cactus
|
|||||||
import com.idormy.sms.forwarder.activity.MainActivity
|
import com.idormy.sms.forwarder.activity.MainActivity
|
||||||
import com.idormy.sms.forwarder.core.Core
|
import com.idormy.sms.forwarder.core.Core
|
||||||
import com.idormy.sms.forwarder.database.AppDatabase
|
import com.idormy.sms.forwarder.database.AppDatabase
|
||||||
import com.idormy.sms.forwarder.database.repository.FrpcRepository
|
import com.idormy.sms.forwarder.database.repository.*
|
||||||
import com.idormy.sms.forwarder.database.repository.LogsRepository
|
|
||||||
import com.idormy.sms.forwarder.database.repository.RuleRepository
|
|
||||||
import com.idormy.sms.forwarder.database.repository.SenderRepository
|
|
||||||
import com.idormy.sms.forwarder.entity.SimInfo
|
import com.idormy.sms.forwarder.entity.SimInfo
|
||||||
import com.idormy.sms.forwarder.receiver.CactusReceiver
|
import com.idormy.sms.forwarder.receiver.CactusReceiver
|
||||||
import com.idormy.sms.forwarder.service.BatteryService
|
import com.idormy.sms.forwarder.service.BatteryService
|
||||||
@ -48,6 +45,7 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
|
|||||||
val applicationScope = CoroutineScope(SupervisorJob())
|
val applicationScope = CoroutineScope(SupervisorJob())
|
||||||
val database by lazy { AppDatabase.getInstance(this) }
|
val database by lazy { AppDatabase.getInstance(this) }
|
||||||
val frpcRepository by lazy { FrpcRepository(database.frpcDao()) }
|
val frpcRepository by lazy { FrpcRepository(database.frpcDao()) }
|
||||||
|
val msgRepository by lazy { MsgRepository(database.msgDao()) }
|
||||||
val logsRepository by lazy { LogsRepository(database.logsDao()) }
|
val logsRepository by lazy { LogsRepository(database.logsDao()) }
|
||||||
val ruleRepository by lazy { RuleRepository(database.ruleDao()) }
|
val ruleRepository by lazy { RuleRepository(database.ruleDao()) }
|
||||||
val senderRepository by lazy { SenderRepository(database.senderDao()) }
|
val senderRepository by lazy { SenderRepository(database.senderDao()) }
|
||||||
|
@ -269,7 +269,7 @@ class MainActivity : BaseActivity<ActivityMainBinding?>(),
|
|||||||
.negativeText(R.string.lab_no)
|
.negativeText(R.string.lab_no)
|
||||||
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||||
AppDatabase.getInstance(this)
|
AppDatabase.getInstance(this)
|
||||||
.logsDao()
|
.msgDao()
|
||||||
.deleteAll(logsType)
|
.deleteAll(logsType)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
@ -9,7 +9,6 @@ import androidx.recyclerview.widget.DiffUtil
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.idormy.sms.forwarder.adapter.LogsPagingAdapter.MyViewHolder
|
import com.idormy.sms.forwarder.adapter.LogsPagingAdapter.MyViewHolder
|
||||||
import com.idormy.sms.forwarder.database.entity.LogsAndRuleAndSender
|
import com.idormy.sms.forwarder.database.entity.LogsAndRuleAndSender
|
||||||
import com.idormy.sms.forwarder.database.entity.Sender
|
|
||||||
import com.idormy.sms.forwarder.databinding.AdapterLogsCardViewListItemBinding
|
import com.idormy.sms.forwarder.databinding.AdapterLogsCardViewListItemBinding
|
||||||
import com.xuexiang.xutil.data.DateUtils
|
import com.xuexiang.xutil.data.DateUtils
|
||||||
|
|
||||||
@ -23,12 +22,12 @@ class LogsPagingAdapter(private val itemClickListener: OnItemClickListener) : Pa
|
|||||||
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
||||||
val item = getItem(position)
|
val item = getItem(position)
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
holder.binding.tvFrom.text = item.logs.from
|
holder.binding.tvFrom.text = item.msg.from
|
||||||
holder.binding.tvTime.text = DateUtils.getFriendlyTimeSpanByNow(item.logs.time)
|
holder.binding.tvTime.text = DateUtils.getFriendlyTimeSpanByNow(item.logs.time)
|
||||||
holder.binding.tvContent.text = item.logs.content
|
holder.binding.tvContent.text = item.msg.content
|
||||||
holder.binding.ivSenderImage.setImageResource(Sender.getImageId(item.relation.sender.type))
|
//holder.binding.ivSenderImage.setImageResource(Sender.getImageId(item.sender.type))
|
||||||
holder.binding.ivStatusImage.setImageResource(item.logs.statusImageId)
|
//holder.binding.ivStatusImage.setImageResource(item.logs.statusImageId)
|
||||||
holder.binding.ivSimImage.setImageResource(item.logs.simImageId)
|
holder.binding.ivSimImage.setImageResource(item.msg.simImageId)
|
||||||
|
|
||||||
holder.binding.cardView.setOnClickListener { view: View? ->
|
holder.binding.cardView.setOnClickListener { view: View? ->
|
||||||
itemClickListener.onItemClicked(view, item)
|
itemClickListener.onItemClicked(view, item)
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
package com.idormy.sms.forwarder.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.paging.PagingDataAdapter
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.idormy.sms.forwarder.App
|
||||||
|
import com.idormy.sms.forwarder.R
|
||||||
|
import com.idormy.sms.forwarder.adapter.MsgPagingAdapter.MyViewHolder
|
||||||
|
import com.idormy.sms.forwarder.database.entity.LogsDetail
|
||||||
|
import com.idormy.sms.forwarder.database.entity.MsgAndLogs
|
||||||
|
import com.idormy.sms.forwarder.databinding.AdapterLogsCardViewListItemBinding
|
||||||
|
import com.xuexiang.xutil.data.DateUtils
|
||||||
|
|
||||||
|
class MsgPagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<MsgAndLogs, MyViewHolder>(diffCallback) {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
||||||
|
val binding = AdapterLogsCardViewListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
return MyViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
||||||
|
val item = getItem(position)
|
||||||
|
if (item != null) {
|
||||||
|
holder.binding.tvFrom.text = item.msg.from
|
||||||
|
holder.binding.tvTime.text = DateUtils.getFriendlyTimeSpanByNow(item.msg.time)
|
||||||
|
holder.binding.tvContent.text = item.msg.content
|
||||||
|
//holder.binding.ivSenderImage.setImageResource(Sender.getImageId(item.sender.type))
|
||||||
|
//holder.binding.ivStatusImage.setImageResource(item.msg.statusImageId)
|
||||||
|
holder.binding.ivSimImage.setImageResource(item.msg.simImageId)
|
||||||
|
|
||||||
|
holder.binding.layoutLogs.removeAllViews()
|
||||||
|
for (logs in item.logsList) {
|
||||||
|
val layoutSenderItem = View.inflate(App.context, R.layout.item_logs, null) as LinearLayout
|
||||||
|
val ivSenderImage = layoutSenderItem.findViewById<ImageView>(R.id.iv_sender_image)
|
||||||
|
val ivSenderStatus = layoutSenderItem.findViewById<ImageView>(R.id.iv_sender_status)
|
||||||
|
val tvSenderName = layoutSenderItem.findViewById<TextView>(R.id.tv_sender_name)
|
||||||
|
ivSenderImage.setImageResource(logs.senderImageId)
|
||||||
|
ivSenderStatus.setImageResource(logs.statusImageId)
|
||||||
|
tvSenderName.text = logs.senderName
|
||||||
|
layoutSenderItem.setOnClickListener { view: View? ->
|
||||||
|
itemClickListener.onLogsClicked(view, logs)
|
||||||
|
}
|
||||||
|
holder.binding.layoutLogs.addView(layoutSenderItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.binding.cardView.setOnClickListener { view: View? ->
|
||||||
|
itemClickListener.onItemClicked(view, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyViewHolder(val binding: AdapterLogsCardViewListItemBinding) : RecyclerView.ViewHolder(binding.root)
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onItemClicked(view: View?, item: MsgAndLogs)
|
||||||
|
fun onLogsClicked(view: View?, item: LogsDetail)
|
||||||
|
fun onItemRemove(view: View?, id: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
var diffCallback: DiffUtil.ItemCallback<MsgAndLogs> = object : DiffUtil.ItemCallback<MsgAndLogs>() {
|
||||||
|
override fun areItemsTheSame(oldItem: MsgAndLogs, newItem: MsgAndLogs): Boolean {
|
||||||
|
return oldItem.msg.id == newItem.msg.id
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("DiffUtilEquals")
|
||||||
|
override fun areContentsTheSame(oldItem: MsgAndLogs, newItem: MsgAndLogs): Boolean {
|
||||||
|
return oldItem.msg === newItem.msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,15 +4,19 @@ import android.annotation.SuppressLint
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
import androidx.paging.PagingDataAdapter
|
import androidx.paging.PagingDataAdapter
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.idormy.sms.forwarder.App
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.adapter.RulePagingAdapter.MyViewHolder
|
import com.idormy.sms.forwarder.adapter.RulePagingAdapter.MyViewHolder
|
||||||
import com.idormy.sms.forwarder.database.entity.RuleAndSender
|
import com.idormy.sms.forwarder.database.entity.Rule
|
||||||
import com.idormy.sms.forwarder.databinding.AdapterRulesCardViewListItemBinding
|
import com.idormy.sms.forwarder.databinding.AdapterRulesCardViewListItemBinding
|
||||||
|
|
||||||
class RulePagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<RuleAndSender, MyViewHolder>(diffCallback) {
|
class RulePagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<Rule, MyViewHolder>(diffCallback) {
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
||||||
val binding = AdapterRulesCardViewListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
val binding = AdapterRulesCardViewListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
@ -22,16 +26,22 @@ class RulePagingAdapter(private val itemClickListener: OnItemClickListener) : Pa
|
|||||||
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
||||||
val item = getItem(position)
|
val item = getItem(position)
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
holder.binding.ivRuleImage.setImageResource(item.rule.imageId)
|
holder.binding.ivRuleImage.setImageResource(item.imageId)
|
||||||
holder.binding.ivRuleStatus.setImageResource(item.rule.statusImageId)
|
holder.binding.ivRuleStatus.setImageResource(item.statusImageId)
|
||||||
holder.binding.tvRuleMatch.text = item.rule.ruleMatch
|
holder.binding.tvRuleMatch.text = item.ruleMatch
|
||||||
holder.binding.ivSenderImage.setImageResource(item.sender.imageId)
|
|
||||||
holder.binding.ivSenderStatus.setImageResource(item.sender.statusImageId)
|
holder.binding.layoutSenders.removeAllViews()
|
||||||
holder.binding.tvSenderName.text = item.sender.name
|
for (sender in item.senderList) {
|
||||||
|
val layoutSenderItem = View.inflate(App.context, R.layout.item_sender, null) as LinearLayout
|
||||||
|
val ivSenderImage = layoutSenderItem.findViewById<ImageView>(R.id.iv_sender_image)
|
||||||
|
val ivSenderStatus = layoutSenderItem.findViewById<ImageView>(R.id.iv_sender_status)
|
||||||
|
val tvSenderName = layoutSenderItem.findViewById<TextView>(R.id.tv_sender_name)
|
||||||
|
ivSenderImage.setImageResource(sender.imageId)
|
||||||
|
ivSenderStatus.setImageResource(sender.statusImageId)
|
||||||
|
tvSenderName.text = sender.name
|
||||||
|
holder.binding.layoutSenders.addView(layoutSenderItem)
|
||||||
|
}
|
||||||
|
|
||||||
/*holder.binding.cardView.setOnClickListener { view: View? ->
|
|
||||||
itemClickListener.onItemClicked(view, item)
|
|
||||||
}*/
|
|
||||||
holder.binding.ivCopy.setImageResource(R.drawable.ic_copy)
|
holder.binding.ivCopy.setImageResource(R.drawable.ic_copy)
|
||||||
holder.binding.ivEdit.setImageResource(R.drawable.ic_edit)
|
holder.binding.ivEdit.setImageResource(R.drawable.ic_edit)
|
||||||
holder.binding.ivDelete.setImageResource(R.drawable.ic_delete)
|
holder.binding.ivDelete.setImageResource(R.drawable.ic_delete)
|
||||||
@ -49,19 +59,19 @@ class RulePagingAdapter(private val itemClickListener: OnItemClickListener) : Pa
|
|||||||
|
|
||||||
class MyViewHolder(val binding: AdapterRulesCardViewListItemBinding) : RecyclerView.ViewHolder(binding.root)
|
class MyViewHolder(val binding: AdapterRulesCardViewListItemBinding) : RecyclerView.ViewHolder(binding.root)
|
||||||
interface OnItemClickListener {
|
interface OnItemClickListener {
|
||||||
fun onItemClicked(view: View?, item: RuleAndSender)
|
fun onItemClicked(view: View?, item: Rule)
|
||||||
fun onItemRemove(view: View?, id: Int)
|
fun onItemRemove(view: View?, id: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
var diffCallback: DiffUtil.ItemCallback<RuleAndSender> = object : DiffUtil.ItemCallback<RuleAndSender>() {
|
var diffCallback: DiffUtil.ItemCallback<Rule> = object : DiffUtil.ItemCallback<Rule>() {
|
||||||
override fun areItemsTheSame(oldItem: RuleAndSender, newItem: RuleAndSender): Boolean {
|
override fun areItemsTheSame(oldItem: Rule, newItem: Rule): Boolean {
|
||||||
return oldItem.rule.id == newItem.rule.id
|
return oldItem.id == newItem.id
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("DiffUtilEquals")
|
@SuppressLint("DiffUtilEquals")
|
||||||
override fun areContentsTheSame(oldItem: RuleAndSender, newItem: RuleAndSender): Boolean {
|
override fun areContentsTheSame(oldItem: Rule, newItem: Rule): Boolean {
|
||||||
return oldItem.rule === newItem.rule
|
return oldItem === newItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,16 +7,14 @@ import androidx.core.content.ContextCompat
|
|||||||
import androidx.work.Configuration
|
import androidx.work.Configuration
|
||||||
import com.idormy.sms.forwarder.App
|
import com.idormy.sms.forwarder.App
|
||||||
import com.idormy.sms.forwarder.BuildConfig
|
import com.idormy.sms.forwarder.BuildConfig
|
||||||
import com.idormy.sms.forwarder.database.repository.FrpcRepository
|
import com.idormy.sms.forwarder.database.repository.*
|
||||||
import com.idormy.sms.forwarder.database.repository.LogsRepository
|
|
||||||
import com.idormy.sms.forwarder.database.repository.RuleRepository
|
|
||||||
import com.idormy.sms.forwarder.database.repository.SenderRepository
|
|
||||||
import com.idormy.sms.forwarder.service.ForegroundService
|
import com.idormy.sms.forwarder.service.ForegroundService
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
object Core : Configuration.Provider {
|
object Core : Configuration.Provider {
|
||||||
lateinit var app: Application
|
lateinit var app: Application
|
||||||
val frpc: FrpcRepository by lazy { (app as App).frpcRepository }
|
val frpc: FrpcRepository by lazy { (app as App).frpcRepository }
|
||||||
|
val msg: MsgRepository by lazy { (app as App).msgRepository }
|
||||||
val logs: LogsRepository by lazy { (app as App).logsRepository }
|
val logs: LogsRepository by lazy { (app as App).logsRepository }
|
||||||
val rule: RuleRepository by lazy { (app as App).ruleRepository }
|
val rule: RuleRepository by lazy { (app as App).ruleRepository }
|
||||||
val sender: SenderRepository by lazy { (app as App).senderRepository }
|
val sender: SenderRepository by lazy { (app as App).senderRepository }
|
||||||
|
@ -7,26 +7,22 @@ import androidx.room.RoomDatabase
|
|||||||
import androidx.room.TypeConverters
|
import androidx.room.TypeConverters
|
||||||
import androidx.room.migration.Migration
|
import androidx.room.migration.Migration
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
import com.idormy.sms.forwarder.database.dao.FrpcDao
|
import com.idormy.sms.forwarder.database.dao.*
|
||||||
import com.idormy.sms.forwarder.database.dao.LogsDao
|
import com.idormy.sms.forwarder.database.entity.*
|
||||||
import com.idormy.sms.forwarder.database.dao.RuleDao
|
import com.idormy.sms.forwarder.database.ext.ConvertersDate
|
||||||
import com.idormy.sms.forwarder.database.dao.SenderDao
|
|
||||||
import com.idormy.sms.forwarder.database.entity.Frpc
|
|
||||||
import com.idormy.sms.forwarder.database.entity.Logs
|
|
||||||
import com.idormy.sms.forwarder.database.entity.Rule
|
|
||||||
import com.idormy.sms.forwarder.database.entity.Sender
|
|
||||||
import com.idormy.sms.forwarder.database.ext.Converters
|
|
||||||
import com.idormy.sms.forwarder.utils.DATABASE_NAME
|
import com.idormy.sms.forwarder.utils.DATABASE_NAME
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
entities = [Frpc::class, Logs::class, Rule::class, Sender::class],
|
entities = [Frpc::class, Msg::class, Logs::class, Rule::class, Sender::class],
|
||||||
version = 11,
|
views = [LogsDetail::class],
|
||||||
|
version = 15,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
)
|
)
|
||||||
@TypeConverters(Converters::class)
|
@TypeConverters(ConvertersDate::class)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract fun frpcDao(): FrpcDao
|
abstract fun frpcDao(): FrpcDao
|
||||||
|
abstract fun msgDao(): MsgDao
|
||||||
abstract fun logsDao(): LogsDao
|
abstract fun logsDao(): LogsDao
|
||||||
abstract fun ruleDao(): RuleDao
|
abstract fun ruleDao(): RuleDao
|
||||||
abstract fun senderDao(): SenderDao
|
abstract fun senderDao(): SenderDao
|
||||||
@ -96,6 +92,10 @@ custom_domains = smsf.demo.com
|
|||||||
MIGRATION_8_9,
|
MIGRATION_8_9,
|
||||||
MIGRATION_9_10,
|
MIGRATION_9_10,
|
||||||
MIGRATION_10_11,
|
MIGRATION_10_11,
|
||||||
|
MIGRATION_11_12,
|
||||||
|
MIGRATION_12_13,
|
||||||
|
MIGRATION_13_14,
|
||||||
|
MIGRATION_14_15,
|
||||||
)
|
)
|
||||||
|
|
||||||
/*if (BuildConfig.DEBUG) {
|
/*if (BuildConfig.DEBUG) {
|
||||||
@ -281,9 +281,89 @@ CREATE TABLE "Sender" (
|
|||||||
//转发日志添加SIM卡槽ID
|
//转发日志添加SIM卡槽ID
|
||||||
private val MIGRATION_10_11 = object : Migration(10, 11) {
|
private val MIGRATION_10_11 = object : Migration(10, 11) {
|
||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
database.execSQL("Alter table Logs add column sub_id INTEGER NOT NULL DEFAULT 0 ")
|
database.execSQL("Alter table Logs add column sub_id INTEGER NOT NULL DEFAULT 0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//单个转发规则可绑定多个发送通道
|
||||||
|
private val MIGRATION_11_12 = object : Migration(11, 12) {
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("Alter table Logs add column sender_id INTEGER NOT NULL DEFAULT 0")
|
||||||
|
database.execSQL("Update Logs Set sender_id = (Select sender_id from Rule where Logs.rule_id = Rule.id)")
|
||||||
|
database.execSQL("Alter table Rule add column sender_list TEXT NOT NULL DEFAULT ''")
|
||||||
|
database.execSQL("Update Rule set sender_list = sender_id")
|
||||||
|
database.execSQL("CREATE INDEX \"index_Rule_sender_ids\" ON \"Rule\" ( \"sender_list\" ASC)")
|
||||||
|
//删除字段:sender_id
|
||||||
|
/*database.execSQL("Create table Rule_t as Select id,type,filed,check,value,sender_list,sms_template,regex_replace,sim_slot,status,time from Rule where 1 = 1")
|
||||||
|
database.execSQL("Drop table Rule")
|
||||||
|
database.execSQL("Alter table Rule_t rename to Rule")
|
||||||
|
database.execSQL("CREATE UNIQUE INDEX \"index_Rule_id\" ON \"Rule\" ( \"id\" ASC)")*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//转发规则添加发送通道逻辑
|
||||||
|
private val MIGRATION_12_13 = object : Migration(12, 13) {
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("Alter table Rule add column sender_logic TEXT NOT NULL DEFAULT 'ALL'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//分割Logs表
|
||||||
|
private val MIGRATION_13_14 = object : Migration(13, 14) {
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
//database.execSQL("Create table Msg as Select id,type,`from`,content,(case when sim_info like 'SIM1%' then '0' when sim_info like 'SIM2%' then '1' else '-1' end) as sim_slot,sim_info,sub_id,time from Logs where 1 = 1")
|
||||||
|
database.execSQL(
|
||||||
|
"""
|
||||||
|
CREATE TABLE "Msg" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"type" TEXT NOT NULL DEFAULT 'sms',
|
||||||
|
"from" TEXT NOT NULL DEFAULT '',
|
||||||
|
"content" TEXT NOT NULL DEFAULT '',
|
||||||
|
"sim_slot" INTEGER NOT NULL DEFAULT -1,
|
||||||
|
"sim_info" TEXT NOT NULL DEFAULT '',
|
||||||
|
"sub_id" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"time" INTEGER NOT NULL
|
||||||
|
)
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
database.execSQL("INSERT INTO Msg (id,type,`from`,content,sim_slot,sim_info,sub_id,time) Select id,type,`from`,content,(case when sim_info like 'SIM1%' then '0' when sim_info like 'SIM2%' then '1' else '-1' end) as sim_slot,sim_info,sub_id,time from Logs where 1 = 1")
|
||||||
|
database.execSQL("CREATE UNIQUE INDEX \"index_Msg_id\" ON \"Msg\" ( \"id\" ASC)")
|
||||||
|
database.execSQL("ALTER TABLE Logs RENAME TO Logs_old")
|
||||||
|
//database.execSQL("Create table Logs_new as Select id,id as msg_id,rule_id,sender_id,forward_status,forward_response,time from Logs where 1 = 1")
|
||||||
|
database.execSQL(
|
||||||
|
"""
|
||||||
|
CREATE TABLE "Logs" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"type" TEXT NOT NULL DEFAULT 'sms',
|
||||||
|
"msg_id" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"rule_id" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"sender_id" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"forward_status" INTEGER NOT NULL DEFAULT 1,
|
||||||
|
"forward_response" TEXT NOT NULL DEFAULT '',
|
||||||
|
"time" INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY ("msg_id") REFERENCES "Msg" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
FOREIGN KEY ("rule_id") REFERENCES "Rule" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
FOREIGN KEY ("sender_id") REFERENCES "Sender" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
database.execSQL("INSERT INTO Logs (id,type,msg_id,rule_id,sender_id,forward_status,forward_response,time) SELECT id,type,id as msg_id,rule_id,sender_id,forward_status,forward_response,time FROM Logs_old")
|
||||||
|
database.execSQL("DROP TABLE Logs_old")
|
||||||
|
database.execSQL("CREATE UNIQUE INDEX \"index_Logs_id\" ON \"Logs\" ( \"id\" ASC)")
|
||||||
|
database.execSQL("CREATE INDEX \"index_Logs_msg_id\" ON \"Logs\" ( \"msg_id\" ASC)")
|
||||||
|
database.execSQL("CREATE INDEX \"index_Logs_rule_id\" ON \"Logs\" ( \"rule_id\" ASC)")
|
||||||
|
database.execSQL("CREATE INDEX \"index_Logs_sender_id\" ON \"Logs\" ( \"sender_id\" ASC)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义数据库迁移配置
|
||||||
|
private val MIGRATION_14_15 = object : Migration(14, 15) {
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
// 这里新建一个视图(视图名称要用两个半角的间隔号括起来)
|
||||||
|
database.execSQL("CREATE VIEW `LogsDetail` AS SELECT LOGS.id,LOGS.type,LOGS.msg_id,LOGS.rule_id,LOGS.sender_id,LOGS.forward_status,LOGS.forward_response,LOGS.TIME,Rule.filed AS rule_filed,Rule.`check` AS rule_check,Rule.value AS rule_value,Rule.sim_slot AS rule_sim_slot,Sender.type AS sender_type,Sender.NAME AS sender_name FROM LOGS LEFT JOIN Rule ON LOGS.rule_id = Rule.id LEFT JOIN Sender ON LOGS.sender_id = Sender.id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.idormy.sms.forwarder.database.dao
|
||||||
|
|
||||||
|
import androidx.paging.PagingSource
|
||||||
|
import androidx.room.*
|
||||||
|
import com.idormy.sms.forwarder.database.entity.Msg
|
||||||
|
import com.idormy.sms.forwarder.database.entity.MsgAndLogs
|
||||||
|
import io.reactivex.Completable
|
||||||
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface MsgDao {
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||||
|
suspend fun insert(msg: Msg): Long
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(msg: Msg): Completable
|
||||||
|
|
||||||
|
@Query("DELETE FROM Msg where id=:id")
|
||||||
|
fun delete(id: Long)
|
||||||
|
|
||||||
|
@Query("DELETE FROM Msg where type=:type")
|
||||||
|
fun deleteAll(type: String): Completable
|
||||||
|
|
||||||
|
@Query("DELETE FROM Msg where time<:time")
|
||||||
|
fun deleteTimeAgo(time: Long)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun update(msg: Msg): Completable
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Msg where id=:id")
|
||||||
|
fun get(id: Long): Single<Msg>
|
||||||
|
|
||||||
|
@Query("SELECT count(*) FROM Msg where type=:type")
|
||||||
|
fun count(type: String): Single<Int>
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
@Query("SELECT * FROM Msg WHERE type = :type ORDER BY id DESC")
|
||||||
|
fun pagingSource(type: String): PagingSource<Int, MsgAndLogs>
|
||||||
|
|
||||||
|
}
|
@ -25,6 +25,9 @@ interface RuleDao {
|
|||||||
@Query("SELECT * FROM Rule where id=:id")
|
@Query("SELECT * FROM Rule where id=:id")
|
||||||
fun get(id: Long): Single<Rule>
|
fun get(id: Long): Single<Rule>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Rule where id=:id")
|
||||||
|
fun getOne(id: Long): Rule
|
||||||
|
|
||||||
@Query("SELECT count(*) FROM Rule where type=:type and status=:status")
|
@Query("SELECT count(*) FROM Rule where type=:type and status=:status")
|
||||||
fun count(type: String, status: Int): Single<Int>
|
fun count(type: String, status: Int): Single<Int>
|
||||||
|
|
||||||
@ -40,7 +43,7 @@ interface RuleDao {
|
|||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Rule where type=:type ORDER BY id DESC")
|
@Query("SELECT * FROM Rule where type=:type ORDER BY id DESC")
|
||||||
fun pagingSource(type: String): PagingSource<Int, RuleAndSender>
|
fun pagingSource(type: String): PagingSource<Int, Rule>
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Rule where type=:type and status=:status and (sim_slot='ALL' or sim_slot=:simSlot)")
|
@Query("SELECT * FROM Rule where type=:type and status=:status and (sim_slot='ALL' or sim_slot=:simSlot)")
|
||||||
|
@ -25,6 +25,9 @@ interface SenderDao {
|
|||||||
@Query("SELECT * FROM Sender where id=:id")
|
@Query("SELECT * FROM Sender where id=:id")
|
||||||
fun get(id: Long): Single<Sender>
|
fun get(id: Long): Single<Sender>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Sender where id=:id")
|
||||||
|
fun getOne(id: Long): Sender
|
||||||
|
|
||||||
@Query("SELECT count(*) FROM Sender where type=:type and status=:status")
|
@Query("SELECT count(*) FROM Sender where type=:type and status=:status")
|
||||||
fun count(type: String, status: Int): Single<Int>
|
fun count(type: String, status: Int): Single<Int>
|
||||||
|
|
||||||
|
@ -10,45 +10,47 @@ import java.util.*
|
|||||||
@Entity(
|
@Entity(
|
||||||
tableName = "Logs",
|
tableName = "Logs",
|
||||||
foreignKeys = [
|
foreignKeys = [
|
||||||
|
ForeignKey(
|
||||||
|
entity = Msg::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["msg_id"],
|
||||||
|
onDelete = ForeignKey.CASCADE, //级联操作
|
||||||
|
onUpdate = ForeignKey.CASCADE //级联操作
|
||||||
|
),
|
||||||
ForeignKey(
|
ForeignKey(
|
||||||
entity = Rule::class,
|
entity = Rule::class,
|
||||||
parentColumns = ["id"],
|
parentColumns = ["id"],
|
||||||
childColumns = ["rule_id"],
|
childColumns = ["rule_id"],
|
||||||
onDelete = ForeignKey.CASCADE, //级联操作
|
onDelete = ForeignKey.CASCADE, //级联操作
|
||||||
onUpdate = ForeignKey.CASCADE //级联操作
|
onUpdate = ForeignKey.CASCADE //级联操作
|
||||||
)
|
),
|
||||||
|
ForeignKey(
|
||||||
|
entity = Sender::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["sender_id"],
|
||||||
|
onDelete = ForeignKey.CASCADE, //级联操作
|
||||||
|
onUpdate = ForeignKey.CASCADE //级联操作
|
||||||
|
),
|
||||||
],
|
],
|
||||||
indices = [
|
indices = [
|
||||||
Index(value = ["id"], unique = true),
|
Index(value = ["id"], unique = true),
|
||||||
Index(value = ["rule_id"])
|
Index(value = ["msg_id"]),
|
||||||
|
Index(value = ["rule_id"]),
|
||||||
|
Index(value = ["sender_id"]),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
data class Logs(
|
data class Logs(
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
@ColumnInfo(name = "id") var id: Long,
|
@ColumnInfo(name = "id") var id: Long,
|
||||||
@ColumnInfo(name = "type", defaultValue = "sms") var type: String,
|
@ColumnInfo(name = "type", defaultValue = "sms") var type: String,
|
||||||
@ColumnInfo(name = "from", defaultValue = "") var from: String,
|
@ColumnInfo(name = "msg_id", defaultValue = "0") var msgId: Long = 0,
|
||||||
@ColumnInfo(name = "content", defaultValue = "") var content: String,
|
|
||||||
@ColumnInfo(name = "rule_id", defaultValue = "0") var ruleId: Long = 0,
|
@ColumnInfo(name = "rule_id", defaultValue = "0") var ruleId: Long = 0,
|
||||||
@ColumnInfo(name = "sim_info", defaultValue = "") var simInfo: String = "",
|
@ColumnInfo(name = "sender_id", defaultValue = "0") var senderId: Long = 0,
|
||||||
@ColumnInfo(name = "sub_id", defaultValue = "0") var subId: Int = 0,
|
|
||||||
@ColumnInfo(name = "forward_status", defaultValue = "1") var forwardStatus: Int = 1,
|
@ColumnInfo(name = "forward_status", defaultValue = "1") var forwardStatus: Int = 1,
|
||||||
@ColumnInfo(name = "forward_response", defaultValue = "") var forwardResponse: String = "",
|
@ColumnInfo(name = "forward_response", defaultValue = "") var forwardResponse: String = "",
|
||||||
@ColumnInfo(name = "time") var time: Date = Date(),
|
@ColumnInfo(name = "time") var time: Date = Date(),
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
|
|
||||||
val simImageId: Int
|
|
||||||
get() {
|
|
||||||
if (simInfo.isNotEmpty()) {
|
|
||||||
if (simInfo.replace("-", "").startsWith("SIM2")) {
|
|
||||||
return R.drawable.ic_sim2 //mipmap
|
|
||||||
} else if (simInfo.replace("-", "").startsWith("SIM1")) {
|
|
||||||
return R.drawable.ic_sim1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return R.drawable.ic_sim
|
|
||||||
}
|
|
||||||
|
|
||||||
val statusImageId: Int
|
val statusImageId: Int
|
||||||
get() {
|
get() {
|
||||||
if (forwardStatus == 1) {
|
if (forwardStatus == 1) {
|
||||||
|
@ -9,10 +9,24 @@ import kotlinx.parcelize.Parcelize
|
|||||||
data class LogsAndRuleAndSender(
|
data class LogsAndRuleAndSender(
|
||||||
@Embedded val logs: Logs,
|
@Embedded val logs: Logs,
|
||||||
|
|
||||||
|
@Relation(
|
||||||
|
entity = Msg::class,
|
||||||
|
parentColumn = "msg_id",
|
||||||
|
entityColumn = "id"
|
||||||
|
)
|
||||||
|
val msg: Msg,
|
||||||
|
|
||||||
@Relation(
|
@Relation(
|
||||||
entity = Rule::class,
|
entity = Rule::class,
|
||||||
parentColumn = "rule_id",
|
parentColumn = "rule_id",
|
||||||
entityColumn = "id"
|
entityColumn = "id"
|
||||||
)
|
)
|
||||||
val relation: RuleAndSender,
|
val rule: Rule,
|
||||||
|
|
||||||
|
@Relation(
|
||||||
|
entity = Sender::class,
|
||||||
|
parentColumn = "sender_id",
|
||||||
|
entityColumn = "id"
|
||||||
|
)
|
||||||
|
val sender: Sender,
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.idormy.sms.forwarder.database.entity
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.DatabaseView
|
||||||
|
import com.idormy.sms.forwarder.R
|
||||||
|
import com.idormy.sms.forwarder.utils.*
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
@DatabaseView("SELECT LOGS.id,LOGS.type,LOGS.msg_id,LOGS.rule_id,LOGS.sender_id,LOGS.forward_status,LOGS.forward_response,LOGS.TIME,Rule.filed AS rule_filed,Rule.`check` AS rule_check,Rule.value AS rule_value,Rule.sim_slot AS rule_sim_slot,Sender.type AS sender_type,Sender.NAME AS sender_name FROM LOGS LEFT JOIN Rule ON LOGS.rule_id = Rule.id LEFT JOIN Sender ON LOGS.sender_id = Sender.id")
|
||||||
|
data class LogsDetail(
|
||||||
|
@ColumnInfo(name = "id") var id: Long,
|
||||||
|
@ColumnInfo(name = "type", defaultValue = "sms") var type: String,
|
||||||
|
@ColumnInfo(name = "msg_id", defaultValue = "0") var msgId: Long = 0,
|
||||||
|
@ColumnInfo(name = "rule_id", defaultValue = "0") var ruleId: Long = 0,
|
||||||
|
@ColumnInfo(name = "sender_id", defaultValue = "0") var senderId: Long = 0,
|
||||||
|
@ColumnInfo(name = "forward_status", defaultValue = "1") var forwardStatus: Int = 1,
|
||||||
|
@ColumnInfo(name = "forward_response", defaultValue = "") var forwardResponse: String = "",
|
||||||
|
@ColumnInfo(name = "time") var time: Date = Date(),
|
||||||
|
@ColumnInfo(name = "rule_filed", defaultValue = "") var ruleFiled: String,
|
||||||
|
@ColumnInfo(name = "rule_check", defaultValue = "") var ruleCheck: String,
|
||||||
|
@ColumnInfo(name = "rule_value", defaultValue = "") var ruleValue: String,
|
||||||
|
@ColumnInfo(name = "rule_sim_slot", defaultValue = "") var ruleSimSlot: String,
|
||||||
|
@ColumnInfo(name = "sender_type", defaultValue = "1") var senderType: Int = 1,
|
||||||
|
@ColumnInfo(name = "sender_name", defaultValue = "") var senderName: String,
|
||||||
|
) : Parcelable {
|
||||||
|
|
||||||
|
val statusImageId: Int
|
||||||
|
get() {
|
||||||
|
if (forwardStatus == 1) {
|
||||||
|
return R.drawable.ic_round_warning
|
||||||
|
} else if (forwardStatus == 2) {
|
||||||
|
return R.drawable.ic_round_check
|
||||||
|
}
|
||||||
|
return R.drawable.ic_round_cancel
|
||||||
|
}
|
||||||
|
|
||||||
|
val senderImageId: Int
|
||||||
|
get() = when (senderType) {
|
||||||
|
TYPE_DINGTALK_GROUP_ROBOT -> R.drawable.icon_dingtalk
|
||||||
|
TYPE_EMAIL -> R.drawable.icon_email
|
||||||
|
TYPE_BARK -> R.drawable.icon_bark
|
||||||
|
TYPE_WEBHOOK -> R.drawable.icon_webhook
|
||||||
|
TYPE_WEWORK_ROBOT -> R.drawable.icon_wework_robot
|
||||||
|
TYPE_WEWORK_AGENT -> R.drawable.icon_wework_agent
|
||||||
|
TYPE_SERVERCHAN -> R.drawable.icon_serverchan
|
||||||
|
TYPE_TELEGRAM -> R.drawable.icon_telegram
|
||||||
|
TYPE_FEISHU -> R.drawable.icon_feishu
|
||||||
|
TYPE_PUSHPLUS -> R.drawable.icon_pushplus
|
||||||
|
TYPE_GOTIFY -> R.drawable.icon_gotify
|
||||||
|
TYPE_SMS -> R.drawable.icon_sms
|
||||||
|
TYPE_DINGTALK_INNER_ROBOT -> R.drawable.icon_dingtalk_inner
|
||||||
|
TYPE_FEISHU_APP -> R.drawable.icon_feishu_app
|
||||||
|
TYPE_URL_SCHEME -> R.drawable.icon_url_scheme
|
||||||
|
else -> R.drawable.icon_sms
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.idormy.sms.forwarder.database.entity
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.Index
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import com.idormy.sms.forwarder.R
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
@Entity(
|
||||||
|
tableName = "Msg",
|
||||||
|
indices = [
|
||||||
|
Index(value = ["id"], unique = true)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
data class Msg(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ColumnInfo(name = "id") var id: Long,
|
||||||
|
@ColumnInfo(name = "type", defaultValue = "sms") var type: String,
|
||||||
|
@ColumnInfo(name = "from", defaultValue = "") var from: String,
|
||||||
|
@ColumnInfo(name = "content", defaultValue = "") var content: String,
|
||||||
|
@ColumnInfo(name = "sim_slot", defaultValue = "-1") var simSlot: Int = -1, //卡槽id:-1=获取失败、0=卡槽1、1=卡槽2
|
||||||
|
@ColumnInfo(name = "sim_info", defaultValue = "") var simInfo: String = "",
|
||||||
|
@ColumnInfo(name = "sub_id", defaultValue = "0") var subId: Int = 0,
|
||||||
|
@ColumnInfo(name = "time") var time: Date = Date(),
|
||||||
|
) : Parcelable {
|
||||||
|
|
||||||
|
val simImageId: Int
|
||||||
|
get() {
|
||||||
|
if (simInfo.isNotEmpty()) {
|
||||||
|
if (simInfo.replace("-", "").startsWith("SIM2")) {
|
||||||
|
return R.drawable.ic_sim2 //mipmap
|
||||||
|
} else if (simInfo.replace("-", "").startsWith("SIM1")) {
|
||||||
|
return R.drawable.ic_sim1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return R.drawable.ic_sim
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.idormy.sms.forwarder.database.entity
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.room.Embedded
|
||||||
|
import androidx.room.Relation
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data class MsgAndLogs(
|
||||||
|
@Embedded val msg: Msg,
|
||||||
|
|
||||||
|
@Relation(
|
||||||
|
parentColumn = "id",
|
||||||
|
entityColumn = "msg_id"
|
||||||
|
)
|
||||||
|
val logsList: List<LogsDetail>
|
||||||
|
) : Parcelable
|
@ -4,6 +4,7 @@ import android.os.Parcelable
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
|
import com.idormy.sms.forwarder.database.ext.ConvertersSenderList
|
||||||
import com.idormy.sms.forwarder.entity.MsgInfo
|
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||||
import com.idormy.sms.forwarder.utils.*
|
import com.idormy.sms.forwarder.utils.*
|
||||||
import com.xuexiang.xui.utils.ResUtils.getString
|
import com.xuexiang.xui.utils.ResUtils.getString
|
||||||
@ -26,9 +27,11 @@ import java.util.regex.PatternSyntaxException
|
|||||||
],
|
],
|
||||||
indices = [
|
indices = [
|
||||||
Index(value = ["id"], unique = true),
|
Index(value = ["id"], unique = true),
|
||||||
Index(value = ["sender_id"])
|
Index(value = ["sender_id"]),
|
||||||
|
Index(value = ["sender_list"])
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@TypeConverters(ConvertersSenderList::class)
|
||||||
data class Rule(
|
data class Rule(
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
@ColumnInfo(name = "id") var id: Long,
|
@ColumnInfo(name = "id") var id: Long,
|
||||||
@ -42,6 +45,8 @@ data class Rule(
|
|||||||
@ColumnInfo(name = "sim_slot", defaultValue = "ALL") var simSlot: String = "",
|
@ColumnInfo(name = "sim_slot", defaultValue = "ALL") var simSlot: String = "",
|
||||||
@ColumnInfo(name = "status", defaultValue = "1") var status: Int = 1,
|
@ColumnInfo(name = "status", defaultValue = "1") var status: Int = 1,
|
||||||
@ColumnInfo(name = "time") var time: Date = Date(),
|
@ColumnInfo(name = "time") var time: Date = Date(),
|
||||||
|
@ColumnInfo(name = "sender_list", defaultValue = "") var senderList: List<Sender>,
|
||||||
|
@ColumnInfo(name = "sender_logic", defaultValue = "ALL") var senderLogic: String = "ALL",
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -87,6 +92,14 @@ data class Rule(
|
|||||||
else -> R.drawable.icon_on
|
else -> R.drawable.icon_on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSenderLogicCheckId(): Int {
|
||||||
|
return when (senderLogic) {
|
||||||
|
SENDER_LOGIC_UNTIL_FAIL -> R.id.rb_sender_logic_until_fail
|
||||||
|
SENDER_LOGIC_UNTIL_SUCCESS -> R.id.rb_sender_logic_until_success
|
||||||
|
else -> R.id.rb_sender_logic_all
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getSimSlotCheckId(): Int {
|
fun getSimSlotCheckId(): Int {
|
||||||
return when (simSlot) {
|
return when (simSlot) {
|
||||||
CHECK_SIM_SLOT_1 -> R.id.rb_sim_slot_1
|
CHECK_SIM_SLOT_1 -> R.id.rb_sim_slot_1
|
||||||
|
@ -4,7 +4,7 @@ import androidx.room.TypeConverter
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class Converters {
|
class ConvertersDate {
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun fromTimestamp(value: Long?): Date? {
|
fun fromTimestamp(value: Long?): Date? {
|
||||||
return value?.let { Date(it) }
|
return value?.let { Date(it) }
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.idormy.sms.forwarder.database.ext
|
||||||
|
|
||||||
|
import androidx.room.TypeConverter
|
||||||
|
import com.idormy.sms.forwarder.core.Core
|
||||||
|
import com.idormy.sms.forwarder.database.entity.Sender
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
class ConvertersSenderList {
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun stringToObject(value: String): List<Sender> {
|
||||||
|
var senderList: MutableList<Sender> = mutableListOf()
|
||||||
|
value.split(",").map { it.trim() }.forEach {
|
||||||
|
val sender = Core.sender.getOne(it.toLong())
|
||||||
|
senderList.add(sender)
|
||||||
|
}
|
||||||
|
return senderList
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun objectToString(list: List<Sender>): String {
|
||||||
|
var senderList = ArrayList<Long>()
|
||||||
|
list.forEach {
|
||||||
|
senderList += it.id
|
||||||
|
}
|
||||||
|
return senderList.joinToString(",")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.idormy.sms.forwarder.database.repository
|
||||||
|
|
||||||
|
import androidx.annotation.WorkerThread
|
||||||
|
import com.idormy.sms.forwarder.database.dao.MsgDao
|
||||||
|
import com.idormy.sms.forwarder.database.entity.Msg
|
||||||
|
|
||||||
|
class MsgRepository(private val msgDao: MsgDao) {
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
fun delete(id: Long) {
|
||||||
|
msgDao.delete(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
fun deleteTimeAgo(time: Long) {
|
||||||
|
msgDao.deleteTimeAgo(time)
|
||||||
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
suspend fun insert(msg: Msg): Long = msgDao.insert(msg)
|
||||||
|
|
||||||
|
}
|
@ -24,6 +24,9 @@ class RuleRepository(
|
|||||||
@WorkerThread
|
@WorkerThread
|
||||||
fun get(id: Long) = ruleDao.get(id)
|
fun get(id: Long) = ruleDao.get(id)
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
fun getOne(id: Long) = ruleDao.getOne(id)
|
||||||
|
|
||||||
suspend fun getRuleAndSender(type: String, status: Int, simSlot: String) = ruleDao.getRuleAndSender(type, status, simSlot)
|
suspend fun getRuleAndSender(type: String, status: Int, simSlot: String) = ruleDao.getRuleAndSender(type, status, simSlot)
|
||||||
|
|
||||||
fun getRuleList(type: String, status: Int, simSlot: String) = ruleDao.getRuleList(type, status, simSlot)
|
fun getRuleList(type: String, status: Int, simSlot: String) = ruleDao.getRuleList(type, status, simSlot)
|
||||||
|
@ -20,6 +20,8 @@ class SenderRepository(private val senderDao: SenderDao) {
|
|||||||
|
|
||||||
fun get(id: Long) = senderDao.get(id)
|
fun get(id: Long) = senderDao.get(id)
|
||||||
|
|
||||||
|
fun getOne(id: Long) = senderDao.getOne(id)
|
||||||
|
|
||||||
fun update(sender: Sender) = senderDao.update(sender)
|
fun update(sender: Sender) = senderDao.update(sender)
|
||||||
|
|
||||||
val count: Flow<Long> = senderDao.getOnCount()
|
val count: Flow<Long> = senderDao.getOnCount()
|
||||||
|
@ -17,6 +17,11 @@ class BaseViewModelFactory(private val context: Context?) : ViewModelProvider.Fa
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return FrpcViewModel(frpcDao) as T
|
return FrpcViewModel(frpcDao) as T
|
||||||
}
|
}
|
||||||
|
modelClass.isAssignableFrom(MsgViewModel::class.java) -> {
|
||||||
|
val msgDao = AppDatabase.getInstance(context).msgDao()
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return MsgViewModel(msgDao) as T
|
||||||
|
}
|
||||||
modelClass.isAssignableFrom(LogsViewModel::class.java) -> {
|
modelClass.isAssignableFrom(LogsViewModel::class.java) -> {
|
||||||
val logDao = AppDatabase.getInstance(context).logsDao()
|
val logDao = AppDatabase.getInstance(context).logsDao()
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.idormy.sms.forwarder.database.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.cachedIn
|
||||||
|
import com.idormy.sms.forwarder.database.dao.MsgDao
|
||||||
|
import com.idormy.sms.forwarder.database.entity.MsgAndLogs
|
||||||
|
import com.idormy.sms.forwarder.database.ext.ioThread
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class MsgViewModel(private val dao: MsgDao) : ViewModel() {
|
||||||
|
private var type: String = "sms"
|
||||||
|
|
||||||
|
fun setType(type: String): MsgViewModel {
|
||||||
|
this.type = type
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
val allMsg: Flow<PagingData<MsgAndLogs>> = Pager(
|
||||||
|
config = PagingConfig(
|
||||||
|
pageSize = 10,
|
||||||
|
enablePlaceholders = false,
|
||||||
|
initialLoadSize = 10
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
dao.pagingSource(type)
|
||||||
|
}.flow.cachedIn(viewModelScope)
|
||||||
|
|
||||||
|
fun delete(id: Long) = ioThread {
|
||||||
|
dao.delete(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,7 +8,6 @@ import androidx.paging.PagingData
|
|||||||
import androidx.paging.cachedIn
|
import androidx.paging.cachedIn
|
||||||
import com.idormy.sms.forwarder.database.dao.RuleDao
|
import com.idormy.sms.forwarder.database.dao.RuleDao
|
||||||
import com.idormy.sms.forwarder.database.entity.Rule
|
import com.idormy.sms.forwarder.database.entity.Rule
|
||||||
import com.idormy.sms.forwarder.database.entity.RuleAndSender
|
|
||||||
import com.idormy.sms.forwarder.database.ext.ioThread
|
import com.idormy.sms.forwarder.database.ext.ioThread
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@ -20,7 +19,7 @@ class RuleViewModel(private val dao: RuleDao) : ViewModel() {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
val allRules: Flow<PagingData<RuleAndSender>> = Pager(
|
val allRules: Flow<PagingData<Rule>> = Pager(
|
||||||
config = PagingConfig(
|
config = PagingConfig(
|
||||||
pageSize = 10,
|
pageSize = 10,
|
||||||
enablePlaceholders = false,
|
enablePlaceholders = false,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.idormy.sms.forwarder.fragment
|
package com.idormy.sms.forwarder.fragment
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -9,21 +11,20 @@ import androidx.lifecycle.lifecycleScope
|
|||||||
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
|
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
|
||||||
import com.alibaba.android.vlayout.VirtualLayoutManager
|
import com.alibaba.android.vlayout.VirtualLayoutManager
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.adapter.LogsPagingAdapter
|
import com.idormy.sms.forwarder.adapter.MsgPagingAdapter
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
import com.idormy.sms.forwarder.database.entity.LogsAndRuleAndSender
|
import com.idormy.sms.forwarder.database.entity.LogsDetail
|
||||||
|
import com.idormy.sms.forwarder.database.entity.MsgAndLogs
|
||||||
import com.idormy.sms.forwarder.database.entity.Rule
|
import com.idormy.sms.forwarder.database.entity.Rule
|
||||||
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
|
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
|
||||||
import com.idormy.sms.forwarder.database.viewmodel.LogsViewModel
|
import com.idormy.sms.forwarder.database.viewmodel.MsgViewModel
|
||||||
import com.idormy.sms.forwarder.databinding.FragmentLogsBinding
|
import com.idormy.sms.forwarder.databinding.FragmentLogsBinding
|
||||||
import com.idormy.sms.forwarder.utils.EVENT_UPDATE_LOGS_TYPE
|
import com.idormy.sms.forwarder.utils.EVENT_UPDATE_LOGS_TYPE
|
||||||
import com.idormy.sms.forwarder.utils.FORWARD_STATUS_MAP
|
import com.idormy.sms.forwarder.utils.FORWARD_STATUS_MAP
|
||||||
import com.idormy.sms.forwarder.utils.SendUtils
|
|
||||||
import com.idormy.sms.forwarder.utils.XToastUtils
|
import com.idormy.sms.forwarder.utils.XToastUtils
|
||||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||||
import com.scwang.smartrefresh.layout.api.RefreshLayout
|
import com.scwang.smartrefresh.layout.api.RefreshLayout
|
||||||
import com.xuexiang.xpage.annotation.Page
|
import com.xuexiang.xpage.annotation.Page
|
||||||
import com.xuexiang.xrouter.utils.TextUtils
|
|
||||||
import com.xuexiang.xui.utils.ResUtils
|
import com.xuexiang.xui.utils.ResUtils
|
||||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||||
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
|
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
|
||||||
@ -36,11 +37,11 @@ import java.util.*
|
|||||||
|
|
||||||
@Suppress("PropertyName")
|
@Suppress("PropertyName")
|
||||||
@Page(name = "转发日志")
|
@Page(name = "转发日志")
|
||||||
class LogsFragment : BaseFragment<FragmentLogsBinding?>(), LogsPagingAdapter.OnItemClickListener {
|
class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnItemClickListener {
|
||||||
|
|
||||||
val TAG: String = LogsFragment::class.java.simpleName
|
val TAG: String = LogsFragment::class.java.simpleName
|
||||||
private var adapter = LogsPagingAdapter(this)
|
private var adapter = MsgPagingAdapter(this)
|
||||||
private val viewModel by viewModels<LogsViewModel> { BaseViewModelFactory(context) }
|
private val viewModel by viewModels<MsgViewModel> { BaseViewModelFactory(context) }
|
||||||
private var currentType: String = "sms"
|
private var currentType: String = "sms"
|
||||||
|
|
||||||
override fun viewBindingInflate(
|
override fun viewBindingInflate(
|
||||||
@ -90,7 +91,7 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), LogsPagingAdapter.OnI
|
|||||||
binding!!.refreshLayout.setOnRefreshListener { refreshLayout: RefreshLayout ->
|
binding!!.refreshLayout.setOnRefreshListener { refreshLayout: RefreshLayout ->
|
||||||
//adapter.refresh()
|
//adapter.refresh()
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
viewModel.setType(currentType).allLogs.collectLatest { adapter.submitData(it) }
|
viewModel.setType(currentType).allMsg.collectLatest { adapter.submitData(it) }
|
||||||
}
|
}
|
||||||
refreshLayout.finishRefresh()
|
refreshLayout.finishRefresh()
|
||||||
}
|
}
|
||||||
@ -98,38 +99,58 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), LogsPagingAdapter.OnI
|
|||||||
binding!!.refreshLayout.autoRefresh()
|
binding!!.refreshLayout.autoRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClicked(view: View?, item: LogsAndRuleAndSender) {
|
override fun onItemClicked(view: View?, item: MsgAndLogs) {
|
||||||
val ruleStr = StringBuilder()
|
Log.d(TAG, "item: $item")
|
||||||
ruleStr.append(Rule.getRuleMatch(item.relation.rule.filed, item.relation.rule.check, item.relation.rule.value, item.relation.rule.simSlot)).append(item.relation.sender.name)
|
|
||||||
val detailStr = StringBuilder()
|
val detailStr = StringBuilder()
|
||||||
detailStr.append(ResUtils.getString(R.string.from)).append(item.logs.from).append("\n\n")
|
detailStr.append(ResUtils.getString(R.string.from)).append(item.msg.from).append("\n\n")
|
||||||
detailStr.append(ResUtils.getString(R.string.msg)).append(item.logs.content).append("\n\n")
|
detailStr.append(ResUtils.getString(R.string.msg)).append(item.msg.content).append("\n\n")
|
||||||
if (!TextUtils.isEmpty(item.logs.simInfo)) detailStr.append(ResUtils.getString(R.string.slot)).append(item.logs.simInfo).append("\n\n")
|
if (!TextUtils.isEmpty(item.msg.simInfo)) detailStr.append(ResUtils.getString(R.string.slot)).append(item.msg.simInfo).append("\n\n")
|
||||||
detailStr.append(ResUtils.getString(R.string.rule)).append(ruleStr.toString()).append("\n\n")
|
|
||||||
@SuppressLint("SimpleDateFormat") val utcFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
@SuppressLint("SimpleDateFormat") val utcFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||||
detailStr.append(ResUtils.getString(R.string.time)).append(DateUtils.date2String(item.logs.time, utcFormatter)).append("\n\n")
|
detailStr.append(ResUtils.getString(R.string.time)).append(DateUtils.date2String(item.msg.time, utcFormatter))
|
||||||
detailStr.append(ResUtils.getString(R.string.result)).append(FORWARD_STATUS_MAP[item.logs.forwardStatus]).append("\n--------------------\n").append(item.logs.forwardResponse)
|
|
||||||
|
|
||||||
MaterialDialog.Builder(requireContext())
|
MaterialDialog.Builder(requireContext())
|
||||||
.iconRes(item.logs.simImageId)
|
.iconRes(item.msg.simImageId)
|
||||||
.title(R.string.details)
|
.title(R.string.details)
|
||||||
.content(detailStr.toString())
|
.content(detailStr.toString())
|
||||||
.cancelable(true)
|
.cancelable(true)
|
||||||
.positiveText(R.string.del)
|
.positiveText(R.string.del)
|
||||||
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||||
viewModel.delete(item.logs.id)
|
viewModel.delete(item.msg.id)
|
||||||
XToastUtils.success(R.string.delete_log_toast)
|
XToastUtils.success(R.string.delete_log_toast)
|
||||||
}
|
}
|
||||||
.negativeText(R.string.resend)
|
|
||||||
.onNegative { _: MaterialDialog?, _: DialogAction? ->
|
|
||||||
XToastUtils.toast(R.string.resend_toast)
|
|
||||||
SendUtils.resendMsg(item, false)
|
|
||||||
}
|
|
||||||
.neutralText(R.string.rematch)
|
.neutralText(R.string.rematch)
|
||||||
.neutralColor(ResUtils.getColors(R.color.red))
|
.neutralColor(ResUtils.getColors(R.color.red))
|
||||||
.onNeutral { _: MaterialDialog?, _: DialogAction? ->
|
.onNeutral { _: MaterialDialog?, _: DialogAction? ->
|
||||||
XToastUtils.toast(R.string.rematch_toast)
|
XToastUtils.toast(R.string.rematch_toast)
|
||||||
SendUtils.resendMsg(item, true)
|
//SendUtils.resendMsg(item, true)
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLogsClicked(view: View?, item: LogsDetail) {
|
||||||
|
Log.d(TAG, "item: $item")
|
||||||
|
val ruleStr = StringBuilder()
|
||||||
|
ruleStr.append(Rule.getRuleMatch(item.ruleFiled, item.ruleCheck, item.ruleValue, item.ruleSimSlot)).append(item.senderName)
|
||||||
|
val detailStr = StringBuilder()
|
||||||
|
detailStr.append(ResUtils.getString(R.string.rule)).append(ruleStr.toString()).append("\n\n")
|
||||||
|
@SuppressLint("SimpleDateFormat") val utcFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||||
|
detailStr.append(ResUtils.getString(R.string.time)).append(DateUtils.date2String(item.time, utcFormatter)).append("\n\n")
|
||||||
|
detailStr.append(ResUtils.getString(R.string.result)).append(FORWARD_STATUS_MAP[item.forwardStatus]).append("\n--------------------\n").append(item.forwardResponse)
|
||||||
|
|
||||||
|
MaterialDialog.Builder(requireContext())
|
||||||
|
.title(R.string.details)
|
||||||
|
.content(detailStr.toString())
|
||||||
|
.cancelable(true)
|
||||||
|
.positiveText(R.string.del)
|
||||||
|
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||||
|
viewModel.delete(item.id)
|
||||||
|
XToastUtils.success(R.string.delete_log_toast)
|
||||||
|
}
|
||||||
|
.negativeText(R.string.resend)
|
||||||
|
.onNegative { _: MaterialDialog?, _: DialogAction? ->
|
||||||
|
XToastUtils.toast(R.string.resend_toast)
|
||||||
|
//SendUtils.resendMsg(item, false)
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.idormy.sms.forwarder.fragment
|
package com.idormy.sms.forwarder.fragment
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -52,8 +53,11 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
|
|
||||||
//当前发送通道
|
//当前发送通道
|
||||||
var senderId = 0L
|
var senderId = 0L
|
||||||
|
var senderListSelected: MutableList<Sender> = mutableListOf()
|
||||||
|
private var senderItemMap = HashMap<Long, LinearLayout>(2)
|
||||||
|
|
||||||
//发送通道列表
|
//发送通道列表
|
||||||
|
var senderListAll: MutableList<Sender> = mutableListOf()
|
||||||
private val senderSpinnerList = ArrayList<SenderAdapterItem>()
|
private val senderSpinnerList = ArrayList<SenderAdapterItem>()
|
||||||
private lateinit var senderSpinnerAdapter: SenderSpinnerAdapter<*>
|
private lateinit var senderSpinnerAdapter: SenderSpinnerAdapter<*>
|
||||||
|
|
||||||
@ -264,17 +268,11 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialDialog.Builder(requireContext())
|
MaterialDialog.Builder(requireContext()).title(R.string.delete_rule_title).content(R.string.delete_rule_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||||
.title(R.string.delete_rule_title)
|
viewModel.delete(ruleId)
|
||||||
.content(R.string.delete_rule_tips)
|
XToastUtils.success(R.string.delete_rule_toast)
|
||||||
.positiveText(R.string.lab_yes)
|
popToBack()
|
||||||
.negativeText(R.string.lab_no)
|
}.show()
|
||||||
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
|
||||||
viewModel.delete(ruleId)
|
|
||||||
XToastUtils.success(R.string.delete_rule_toast)
|
|
||||||
popToBack()
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
R.id.btn_save -> {
|
R.id.btn_save -> {
|
||||||
@ -295,73 +293,62 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
|
|
||||||
//初始化发送通道下拉框
|
//初始化发送通道下拉框
|
||||||
private fun initSenderSpinner() {
|
private fun initSenderSpinner() {
|
||||||
AppDatabase.getInstance(requireContext())
|
AppDatabase.getInstance(requireContext()).senderDao().getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<List<Sender>> {
|
||||||
.senderDao()
|
override fun onSubscribe(d: Disposable) {}
|
||||||
.getAll()
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(object : SingleObserver<List<Sender>> {
|
|
||||||
override fun onSubscribe(d: Disposable) {}
|
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSuccess(senderList: List<Sender>) {
|
||||||
|
if (senderList.isEmpty()) {
|
||||||
|
XToastUtils.error(R.string.add_sender_first)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(senderList: List<Sender>) {
|
senderListAll = senderList as MutableList<Sender>
|
||||||
if (senderList.isEmpty()) {
|
for (sender in senderList) {
|
||||||
XToastUtils.error(R.string.add_sender_first)
|
val name = if (sender.name.length > 20) sender.name.substring(0, 19) else sender.name
|
||||||
return
|
senderSpinnerList.add(SenderAdapterItem(name, sender.imageId, sender.id, sender.status))
|
||||||
}
|
}
|
||||||
|
senderSpinnerAdapter = SenderSpinnerAdapter(senderSpinnerList)
|
||||||
|
//.setTextColor(ResUtils.getColor(R.color.green))
|
||||||
|
//.setTextSize(12F)
|
||||||
|
.setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
|
||||||
|
binding!!.spSender.setAdapter(senderSpinnerAdapter)
|
||||||
|
|
||||||
for (sender in senderList) {
|
if (senderListSelected.isNotEmpty()) {
|
||||||
val name = if (sender.name.length > 20) sender.name.substring(0, 19) else sender.name
|
for (sender in senderListSelected) {
|
||||||
senderSpinnerList.add(SenderAdapterItem(name, sender.imageId, sender.id, sender.status))
|
for (senderItem in senderSpinnerList) {
|
||||||
}
|
if (sender.id == senderItem.id) {
|
||||||
senderSpinnerAdapter = SenderSpinnerAdapter(senderSpinnerList)
|
addSenderItemLinearLayout(senderItemMap, binding!!.layoutSenders, senderItem)
|
||||||
//.setTextColor(ResUtils.getColor(R.color.green))
|
|
||||||
//.setTextSize(12F)
|
|
||||||
.setIsFilterKey(true)
|
|
||||||
.setFilterColor("#EF5362")
|
|
||||||
.setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
|
|
||||||
binding!!.spSender.setAdapter(senderSpinnerAdapter)
|
|
||||||
|
|
||||||
if (senderId > 0) {
|
|
||||||
for (sender in senderSpinnerList) {
|
|
||||||
if (sender.id == senderId) {
|
|
||||||
binding!!.ivSenderImage.setImageDrawable(sender.icon)
|
|
||||||
binding!!.ivSenderStatus.setImageDrawable(
|
|
||||||
ResUtils.getDrawable(
|
|
||||||
when (sender.status) {
|
|
||||||
STATUS_OFF -> R.drawable.icon_off
|
|
||||||
else -> R.drawable.icon_on
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
binding!!.tvSenderName.text = sender.title
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
binding!!.spSender.setOnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
|
binding!!.spSender.setOnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
|
||||||
try {
|
try {
|
||||||
//val sender = senderSpinnerList[position]
|
|
||||||
val sender = senderSpinnerAdapter.getItemSource(position) as SenderAdapterItem
|
val sender = senderSpinnerAdapter.getItemSource(position) as SenderAdapterItem
|
||||||
sender.id.also {
|
senderId = sender.id!!
|
||||||
senderId = it ?: 0L
|
if (senderId > 0L) {
|
||||||
}
|
senderListSelected.forEach {
|
||||||
binding!!.ivSenderImage.setImageDrawable(sender.icon)
|
if (senderId == it.id) {
|
||||||
binding!!.ivSenderStatus.setImageDrawable(
|
XToastUtils.warning(getString(R.string.sender_contains_tips))
|
||||||
ResUtils.getDrawable(
|
return@setOnItemClickListener
|
||||||
when (sender.status) {
|
|
||||||
STATUS_OFF -> R.drawable.icon_off
|
|
||||||
else -> R.drawable.icon_on
|
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
)
|
senderListAll.forEach {
|
||||||
binding!!.tvSenderName.text = sender.title
|
if (senderId == it.id) {
|
||||||
if (STATUS_OFF == sender.status) {
|
senderListSelected.add(it)
|
||||||
XToastUtils.warning(getString(R.string.sender_disabled_tips))
|
addSenderItemLinearLayout(senderItemMap, binding!!.layoutSenders, sender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STATUS_OFF == sender.status) {
|
||||||
|
XToastUtils.warning(getString(R.string.sender_disabled_tips))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
XToastUtils.error(e.message.toString())
|
XToastUtils.error(e.message.toString())
|
||||||
@ -369,6 +356,60 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态增删header
|
||||||
|
*
|
||||||
|
* @param senderItemMap 管理item的map,用于删除指定header
|
||||||
|
* @param layoutSenders 需要挂载item的LinearLayout
|
||||||
|
* @param sender SenderAdapterItem
|
||||||
|
*/
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
private fun addSenderItemLinearLayout(
|
||||||
|
senderItemMap: MutableMap<Long, LinearLayout>, layoutSenders: LinearLayout, sender: SenderAdapterItem
|
||||||
|
) {
|
||||||
|
val layoutSenderItem = View.inflate(requireContext(), R.layout.item_add_sender, null) as LinearLayout
|
||||||
|
val ivRemoveSender = layoutSenderItem.findViewById<ImageView>(R.id.iv_remove_sender)
|
||||||
|
val ivSenderImage = layoutSenderItem.findViewById<ImageView>(R.id.iv_sender_image)
|
||||||
|
val ivSenderStatus = layoutSenderItem.findViewById<ImageView>(R.id.iv_sender_status)
|
||||||
|
val tvSenderName = layoutSenderItem.findViewById<TextView>(R.id.tv_sender_name)
|
||||||
|
|
||||||
|
ivSenderImage.setImageDrawable(sender.icon)
|
||||||
|
ivSenderStatus.setImageDrawable(ResUtils.getDrawable(if (STATUS_OFF == sender.status) R.drawable.icon_off else R.drawable.icon_on))
|
||||||
|
val senderItemId = sender.id as Long
|
||||||
|
tvSenderName.text = "ID-$senderItemId:${sender.title}"
|
||||||
|
|
||||||
|
ivRemoveSender.tag = senderItemId
|
||||||
|
ivRemoveSender.setOnClickListener { view2: View ->
|
||||||
|
val tagId = view2.tag as Long
|
||||||
|
layoutSenders.removeView(senderItemMap[tagId])
|
||||||
|
senderItemMap.remove(tagId)
|
||||||
|
//senderListSelected.removeIf { it.id == tagId }
|
||||||
|
for (it in senderListSelected) {
|
||||||
|
if (it.id == tagId) {
|
||||||
|
senderListSelected -= it
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d(TAG, senderListSelected.count().toString())
|
||||||
|
Log.d(TAG, senderListSelected.toString())
|
||||||
|
if (senderListSelected.isEmpty()) senderId = 0L
|
||||||
|
if (senderListSelected.count() > 1) {
|
||||||
|
binding!!.layoutSenderLogic.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding!!.layoutSenderLogic.visibility = View.GONE
|
||||||
|
binding!!.rgSenderLogic.check(R.id.rb_sender_logic_all)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layoutSenders.addView(layoutSenderItem)
|
||||||
|
senderItemMap[senderItemId] = layoutSenderItem
|
||||||
|
if (senderListSelected.count() > 1) {
|
||||||
|
binding!!.layoutSenderLogic.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding!!.layoutSenderLogic.visibility = View.GONE
|
||||||
|
binding!!.rgSenderLogic.check(R.id.rb_sender_logic_all)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//初始化APP下拉列表
|
//初始化APP下拉列表
|
||||||
private fun initAppSpinner() {
|
private fun initAppSpinner() {
|
||||||
if (ruleType != "app") return
|
if (ruleType != "app") return
|
||||||
@ -377,9 +418,7 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
if (!SettingUtils.enableLoadUserAppList && !SettingUtils.enableLoadSystemAppList) return
|
if (!SettingUtils.enableLoadUserAppList && !SettingUtils.enableLoadSystemAppList) return
|
||||||
|
|
||||||
val get = GlobalScope.async(Dispatchers.IO) {
|
val get = GlobalScope.async(Dispatchers.IO) {
|
||||||
if ((SettingUtils.enableLoadUserAppList && App.UserAppList.isEmpty())
|
if ((SettingUtils.enableLoadUserAppList && App.UserAppList.isEmpty()) || (SettingUtils.enableLoadSystemAppList && App.SystemAppList.isEmpty())) {
|
||||||
|| (SettingUtils.enableLoadSystemAppList && App.SystemAppList.isEmpty())
|
|
||||||
) {
|
|
||||||
App.UserAppList.clear()
|
App.UserAppList.clear()
|
||||||
App.SystemAppList.clear()
|
App.SystemAppList.clear()
|
||||||
val appInfoList = AppUtils.getAppsInfo()
|
val appInfoList = AppUtils.getAppsInfo()
|
||||||
@ -417,9 +456,7 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
appListSpinnerAdapter = AppListSpinnerAdapter(appListSpinnerList)
|
appListSpinnerAdapter = AppListSpinnerAdapter(appListSpinnerList)
|
||||||
//.setTextColor(ResUtils.getColor(R.color.green))
|
//.setTextColor(ResUtils.getColor(R.color.green))
|
||||||
//.setTextSize(12F)
|
//.setTextSize(12F)
|
||||||
.setIsFilterKey(true)
|
.setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
|
||||||
.setFilterColor("#EF5362")
|
|
||||||
.setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
|
|
||||||
binding!!.spApp.setAdapter(appListSpinnerAdapter)
|
binding!!.spApp.setAdapter(appListSpinnerAdapter)
|
||||||
binding!!.spApp.setOnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
|
binding!!.spApp.setOnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
|
||||||
try {
|
try {
|
||||||
@ -439,53 +476,53 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
|
|
||||||
//初始化表单
|
//初始化表单
|
||||||
private fun initForm() {
|
private fun initForm() {
|
||||||
AppDatabase.getInstance(requireContext())
|
AppDatabase.getInstance(requireContext()).ruleDao().get(ruleId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Rule> {
|
||||||
.ruleDao()
|
override fun onSubscribe(d: Disposable) {}
|
||||||
.get(ruleId)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(object : SingleObserver<Rule> {
|
|
||||||
override fun onSubscribe(d: Disposable) {}
|
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSuccess(rule: Rule) {
|
||||||
|
Log.d(TAG, rule.senderList.toString())
|
||||||
|
rule.senderList.forEach {
|
||||||
|
senderId = it.id
|
||||||
|
senderListSelected.add(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(rule: Rule) {
|
if (isClone) {
|
||||||
senderId = rule.senderId
|
titleBar?.setSubTitle(getString(R.string.clone_rule))
|
||||||
|
binding!!.btnDel.setText(R.string.discard)
|
||||||
if (isClone) {
|
} else {
|
||||||
titleBar?.setSubTitle(getString(R.string.clone_rule))
|
titleBar?.setSubTitle(getString(R.string.edit_rule))
|
||||||
binding!!.btnDel.setText(R.string.discard)
|
|
||||||
} else {
|
|
||||||
titleBar?.setSubTitle(getString(R.string.edit_rule))
|
|
||||||
}
|
|
||||||
Log.d(TAG, rule.toString())
|
|
||||||
|
|
||||||
binding!!.rgSimSlot.check(rule.getSimSlotCheckId())
|
|
||||||
binding!!.rgFiled.check(rule.getFiledCheckId())
|
|
||||||
val checkId = rule.getCheckCheckId()
|
|
||||||
if (checkId == R.id.rb_is || checkId == R.id.rb_contain || checkId == R.id.rb_not_contain) {
|
|
||||||
binding!!.rgCheck.check(checkId)
|
|
||||||
} else {
|
|
||||||
binding!!.rgCheck2.check(checkId)
|
|
||||||
}
|
|
||||||
binding!!.etValue.setText(rule.value)
|
|
||||||
binding!!.sbSmsTemplate.isChecked = !TextUtils.isEmpty(rule.smsTemplate.trim())
|
|
||||||
binding!!.etSmsTemplate.setText(rule.smsTemplate.trim())
|
|
||||||
binding!!.sbRegexReplace.isChecked = !TextUtils.isEmpty(rule.regexReplace.trim())
|
|
||||||
binding!!.etRegexReplace.setText(rule.regexReplace.trim())
|
|
||||||
binding!!.sbStatus.isChecked = rule.statusChecked
|
|
||||||
|
|
||||||
//初始化发送通道下拉框
|
|
||||||
initSenderSpinner()
|
|
||||||
}
|
}
|
||||||
})
|
Log.d(TAG, rule.toString())
|
||||||
|
|
||||||
|
binding!!.rgSenderLogic.check(rule.getSenderLogicCheckId())
|
||||||
|
binding!!.rgSimSlot.check(rule.getSimSlotCheckId())
|
||||||
|
binding!!.rgFiled.check(rule.getFiledCheckId())
|
||||||
|
val checkId = rule.getCheckCheckId()
|
||||||
|
if (checkId == R.id.rb_is || checkId == R.id.rb_contain || checkId == R.id.rb_not_contain) {
|
||||||
|
binding!!.rgCheck.check(checkId)
|
||||||
|
} else {
|
||||||
|
binding!!.rgCheck2.check(checkId)
|
||||||
|
}
|
||||||
|
binding!!.etValue.setText(rule.value)
|
||||||
|
binding!!.sbSmsTemplate.isChecked = !TextUtils.isEmpty(rule.smsTemplate.trim())
|
||||||
|
binding!!.etSmsTemplate.setText(rule.smsTemplate.trim())
|
||||||
|
binding!!.sbRegexReplace.isChecked = !TextUtils.isEmpty(rule.regexReplace.trim())
|
||||||
|
binding!!.etRegexReplace.setText(rule.regexReplace.trim())
|
||||||
|
binding!!.sbStatus.isChecked = rule.statusChecked
|
||||||
|
|
||||||
|
//初始化发送通道下拉框
|
||||||
|
initSenderSpinner()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//提交前检查表单
|
//提交前检查表单
|
||||||
private fun checkForm(): Rule {
|
private fun checkForm(): Rule {
|
||||||
if (senderId <= 0L) {
|
if (senderListSelected.isEmpty() || senderId == 0L) {
|
||||||
throw Exception(getString(R.string.new_sender_first))
|
throw Exception(getString(R.string.new_sender_first))
|
||||||
}
|
}
|
||||||
val filed = when (binding!!.rgFiled.checkedRadioButtonId) {
|
val filed = when (binding!!.rgFiled.checkedRadioButtonId) {
|
||||||
@ -522,6 +559,12 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
throw Exception(String.format(getString(R.string.invalid_regex_replace), lineNum))
|
throw Exception(String.format(getString(R.string.invalid_regex_replace), lineNum))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val senderLogic = when (binding!!.rgSenderLogic.checkedRadioButtonId) {
|
||||||
|
R.id.rb_sender_logic_until_fail -> SENDER_LOGIC_UNTIL_FAIL
|
||||||
|
R.id.rb_sender_logic_until_success -> SENDER_LOGIC_UNTIL_SUCCESS
|
||||||
|
else -> SENDER_LOGIC_ALL
|
||||||
|
}
|
||||||
|
|
||||||
val simSlot = when (binding!!.rgSimSlot.checkedRadioButtonId) {
|
val simSlot = when (binding!!.rgSimSlot.checkedRadioButtonId) {
|
||||||
R.id.rb_sim_slot_1 -> CHECK_SIM_SLOT_1
|
R.id.rb_sim_slot_1 -> CHECK_SIM_SLOT_1
|
||||||
R.id.rb_sim_slot_2 -> CHECK_SIM_SLOT_2
|
R.id.rb_sim_slot_2 -> CHECK_SIM_SLOT_2
|
||||||
@ -532,7 +575,7 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
// throw Exception(getString(R.string.invalid_rule_status))
|
// throw Exception(getString(R.string.invalid_rule_status))
|
||||||
//}
|
//}
|
||||||
|
|
||||||
return Rule(ruleId, ruleType, filed, check, value, senderId, smsTemplate, regexReplace, simSlot, status)
|
return Rule(ruleId, ruleType, filed, check, value, senderId, smsTemplate, regexReplace, simSlot, status, Date(), senderListSelected, senderLogic)
|
||||||
}
|
}
|
||||||
|
|
||||||
//检查多重匹配规则是否正确
|
//检查多重匹配规则是否正确
|
||||||
@ -589,73 +632,48 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
etContent.visibility = View.GONE
|
etContent.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialDialog.Builder(requireContext())
|
MaterialDialog.Builder(requireContext()).iconRes(android.R.drawable.ic_dialog_email).title(R.string.rule_tester).customView(dialogTest, true).cancelable(false).autoDismiss(false).neutralText(R.string.action_back).neutralColor(ResUtils.getColors(R.color.darkGrey)).onNeutral { dialog: MaterialDialog?, _: DialogAction? ->
|
||||||
.iconRes(android.R.drawable.ic_dialog_email)
|
dialog?.dismiss()
|
||||||
.title(R.string.rule_tester)
|
}.positiveText(R.string.action_test).onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||||
.customView(dialogTest, true)
|
try {
|
||||||
.cancelable(false)
|
val simSlot = when (if (ruleType == "app") -1 else rgSimSlot.checkedRadioButtonId) {
|
||||||
.autoDismiss(false)
|
R.id.rb_sim_slot_1 -> 0
|
||||||
.neutralText(R.string.action_back)
|
R.id.rb_sim_slot_2 -> 1
|
||||||
.neutralColor(ResUtils.getColors(R.color.darkGrey))
|
else -> -1
|
||||||
.onNeutral { dialog: MaterialDialog?, _: DialogAction? ->
|
|
||||||
dialog?.dismiss()
|
|
||||||
}
|
|
||||||
.positiveText(R.string.action_test)
|
|
||||||
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
|
||||||
try {
|
|
||||||
val simSlot = when (if (ruleType == "app") -1 else rgSimSlot.checkedRadioButtonId) {
|
|
||||||
R.id.rb_sim_slot_1 -> 0
|
|
||||||
R.id.rb_sim_slot_2 -> 1
|
|
||||||
else -> -1
|
|
||||||
}
|
|
||||||
|
|
||||||
val testSim = "SIM" + (simSlot + 1)
|
|
||||||
val ruleSim: String = rule.simSlot
|
|
||||||
if (ruleSim != "ALL" && ruleSim != testSim) {
|
|
||||||
throw java.lang.Exception(getString(R.string.card_slot_does_not_match))
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取卡槽信息
|
|
||||||
val simInfo = when (simSlot) {
|
|
||||||
0 -> "SIM1_" + SettingUtils.extraSim1
|
|
||||||
1 -> "SIM2_" + SettingUtils.extraSim2
|
|
||||||
else -> etTitle.text.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
val msgInfo = MsgInfo(ruleType, etFrom.text.toString(), etContent.text.toString(), Date(), simInfo, simSlot)
|
|
||||||
if (!rule.checkMsg(msgInfo)) {
|
|
||||||
throw java.lang.Exception(getString(R.string.unmatched_rule))
|
|
||||||
}
|
|
||||||
|
|
||||||
AppDatabase.getInstance(requireContext())
|
|
||||||
.senderDao()
|
|
||||||
.get(senderId)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(object : SingleObserver<Sender> {
|
|
||||||
override fun onSubscribe(d: Disposable) {}
|
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSuccess(sender: Sender) {
|
|
||||||
Thread {
|
|
||||||
try {
|
|
||||||
SendUtils.sendMsgSender(msgInfo, rule, sender, 0L)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
if (Looper.myLooper() == null) Looper.prepare()
|
|
||||||
XToastUtils.error(e.message.toString())
|
|
||||||
Looper.loop()
|
|
||||||
}
|
|
||||||
}.start()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
} catch (e: Exception) {
|
|
||||||
XToastUtils.error(e.message.toString())
|
|
||||||
}
|
}
|
||||||
}.show()
|
|
||||||
|
val testSim = "SIM" + (simSlot + 1)
|
||||||
|
val ruleSim: String = rule.simSlot
|
||||||
|
if (ruleSim != "ALL" && ruleSim != testSim) {
|
||||||
|
throw java.lang.Exception(getString(R.string.card_slot_does_not_match))
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取卡槽信息
|
||||||
|
val simInfo = when (simSlot) {
|
||||||
|
0 -> "SIM1_" + SettingUtils.extraSim1
|
||||||
|
1 -> "SIM2_" + SettingUtils.extraSim2
|
||||||
|
else -> etTitle.text.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
val msgInfo = MsgInfo(ruleType, etFrom.text.toString(), etContent.text.toString(), Date(), simInfo, simSlot)
|
||||||
|
if (!rule.checkMsg(msgInfo)) {
|
||||||
|
throw java.lang.Exception(getString(R.string.unmatched_rule))
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread {
|
||||||
|
try {
|
||||||
|
SendUtils.sendMsgSender(msgInfo, rule)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
if (Looper.myLooper() == null) Looper.prepare()
|
||||||
|
XToastUtils.error(e.message.toString())
|
||||||
|
Looper.loop()
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
XToastUtils.error(e.message.toString())
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package com.idormy.sms.forwarder.fragment
|
package com.idormy.sms.forwarder.fragment
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -11,7 +10,7 @@ import com.alibaba.android.vlayout.VirtualLayoutManager
|
|||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.adapter.RulePagingAdapter
|
import com.idormy.sms.forwarder.adapter.RulePagingAdapter
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
import com.idormy.sms.forwarder.database.entity.RuleAndSender
|
import com.idormy.sms.forwarder.database.entity.Rule
|
||||||
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
|
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
|
||||||
import com.idormy.sms.forwarder.database.viewmodel.RuleViewModel
|
import com.idormy.sms.forwarder.database.viewmodel.RuleViewModel
|
||||||
import com.idormy.sms.forwarder.databinding.FragmentRulesBinding
|
import com.idormy.sms.forwarder.databinding.FragmentRulesBinding
|
||||||
@ -92,22 +91,21 @@ class RulesFragment : BaseFragment<FragmentRulesBinding?>(), RulePagingAdapter.O
|
|||||||
binding!!.refreshLayout.autoRefresh()
|
binding!!.refreshLayout.autoRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClicked(view: View?, item: RuleAndSender) {
|
override fun onItemClicked(view: View?, item: Rule) {
|
||||||
Log.e(TAG, item.toString())
|
|
||||||
when (view?.id) {
|
when (view?.id) {
|
||||||
R.id.iv_copy -> {
|
R.id.iv_copy -> {
|
||||||
PageOption.to(RulesEditFragment::class.java)
|
PageOption.to(RulesEditFragment::class.java)
|
||||||
.setNewActivity(true)
|
.setNewActivity(true)
|
||||||
.putLong(KEY_RULE_ID, item.rule.id)
|
.putLong(KEY_RULE_ID, item.id)
|
||||||
.putString(KEY_RULE_TYPE, item.rule.type)
|
.putString(KEY_RULE_TYPE, item.type)
|
||||||
.putBoolean(KEY_RULE_CLONE, true)
|
.putBoolean(KEY_RULE_CLONE, true)
|
||||||
.open(this)
|
.open(this)
|
||||||
}
|
}
|
||||||
R.id.iv_edit -> {
|
R.id.iv_edit -> {
|
||||||
PageOption.to(RulesEditFragment::class.java)
|
PageOption.to(RulesEditFragment::class.java)
|
||||||
.setNewActivity(true)
|
.setNewActivity(true)
|
||||||
.putLong(KEY_RULE_ID, item.rule.id)
|
.putLong(KEY_RULE_ID, item.id)
|
||||||
.putString(KEY_RULE_TYPE, item.rule.type)
|
.putString(KEY_RULE_TYPE, item.type)
|
||||||
.open(this)
|
.open(this)
|
||||||
}
|
}
|
||||||
R.id.iv_delete -> {
|
R.id.iv_delete -> {
|
||||||
@ -117,7 +115,7 @@ class RulesFragment : BaseFragment<FragmentRulesBinding?>(), RulePagingAdapter.O
|
|||||||
.positiveText(R.string.lab_yes)
|
.positiveText(R.string.lab_yes)
|
||||||
.negativeText(R.string.lab_no)
|
.negativeText(R.string.lab_no)
|
||||||
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||||
viewModel.delete(item.rule.id)
|
viewModel.delete(item.id)
|
||||||
XToastUtils.success(R.string.delete_rule_toast)
|
XToastUtils.success(R.string.delete_rule_toast)
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
|
@ -64,7 +64,7 @@ class BatteryService : Service() {
|
|||||||
Log.d(TAG, "自动删除N天前的转发记录")
|
Log.d(TAG, "自动删除N天前的转发记录")
|
||||||
val cal = Calendar.getInstance()
|
val cal = Calendar.getInstance()
|
||||||
cal.add(Calendar.DAY_OF_MONTH, 0 - SettingUtils.autoCleanLogsDays)
|
cal.add(Calendar.DAY_OF_MONTH, 0 - SettingUtils.autoCleanLogsDays)
|
||||||
Core.logs.deleteTimeAgo(cal.timeInMillis)
|
Core.msg.deleteTimeAgo(cal.timeInMillis)
|
||||||
}
|
}
|
||||||
|
|
||||||
//电量发生变化
|
//电量发生变化
|
||||||
|
@ -12,6 +12,9 @@ object Worker {
|
|||||||
const val sendLogId = "send_log_id"
|
const val sendLogId = "send_log_id"
|
||||||
const val sendSbnId = "send_sbn_id"
|
const val sendSbnId = "send_sbn_id"
|
||||||
const val updateLogs = "update_logs"
|
const val updateLogs = "update_logs"
|
||||||
|
const val ruleId = "rule_id"
|
||||||
|
const val senderIndex = "sender_index"
|
||||||
|
const val msgId = "msg_id"
|
||||||
}
|
}
|
||||||
|
|
||||||
//初始化相关
|
//初始化相关
|
||||||
@ -103,6 +106,11 @@ const val CHECK_REGEX = "regex"
|
|||||||
const val CHECK_SIM_SLOT_ALL = "ALL"
|
const val CHECK_SIM_SLOT_ALL = "ALL"
|
||||||
const val CHECK_SIM_SLOT_1 = "SIM1"
|
const val CHECK_SIM_SLOT_1 = "SIM1"
|
||||||
const val CHECK_SIM_SLOT_2 = "SIM2"
|
const val CHECK_SIM_SLOT_2 = "SIM2"
|
||||||
|
|
||||||
|
//发送通道执行逻辑:ALL=全部执行, UntilFail=失败即终止, UntilSuccess=成功即终止
|
||||||
|
const val SENDER_LOGIC_ALL = "ALL"
|
||||||
|
const val SENDER_LOGIC_UNTIL_FAIL = "UntilFail"
|
||||||
|
const val SENDER_LOGIC_UNTIL_SUCCESS = "UntilSuccess"
|
||||||
val TYPE_MAP = object : HashMap<String, String>() {
|
val TYPE_MAP = object : HashMap<String, String>() {
|
||||||
init {
|
init {
|
||||||
put("sms", getString(R.string.rule_sms))
|
put("sms", getString(R.string.rule_sms))
|
||||||
|
@ -187,9 +187,11 @@ class PhoneUtils private constructor() {
|
|||||||
Log.d(TAG, "selectionArgs = $selectionArgs")
|
Log.d(TAG, "selectionArgs = $selectionArgs")
|
||||||
|
|
||||||
//为了兼容性这里全部取出后手动分页
|
//为了兼容性这里全部取出后手动分页
|
||||||
val cursor = Core.app.contentResolver.query(
|
val cursor = (if (limit == 1) Core.app.contentResolver.query(
|
||||||
|
CallLog.Calls.CONTENT_URI, null, selection, selectionArgs.toTypedArray(), CallLog.Calls.DEFAULT_SORT_ORDER + " limit $limit offset $offset"
|
||||||
|
) else Core.app.contentResolver.query(
|
||||||
CallLog.Calls.CONTENT_URI, null, selection, selectionArgs.toTypedArray(), CallLog.Calls.DEFAULT_SORT_ORDER // + " limit $limit offset $offset"
|
CallLog.Calls.CONTENT_URI, null, selection, selectionArgs.toTypedArray(), CallLog.Calls.DEFAULT_SORT_ORDER // + " limit $limit offset $offset"
|
||||||
) ?: return callInfoList
|
)) ?: return callInfoList
|
||||||
Log.i(TAG, "cursor count:" + cursor.count)
|
Log.i(TAG, "cursor count:" + cursor.count)
|
||||||
|
|
||||||
// 避免超过总数后循环取出
|
// 避免超过总数后循环取出
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
|
package com.idormy.sms.forwarder.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.preference.PreferenceManager
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by aykutasil on 8.12.2016.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
class PrefsHelper private constructor() {
|
||||||
|
|
||||||
|
lateinit var preference: SharedPreferences
|
||||||
|
|
||||||
|
val prefEditor: SharedPreferences.Editor
|
||||||
|
get() = preference.edit()
|
||||||
|
|
||||||
|
constructor(context: Context, prefName: String) : this() {
|
||||||
|
preference = context.getSharedPreferences(prefName, Context.MODE_PRIVATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(context: Context) : this() {
|
||||||
|
preference = getDefaultPreference(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val DEFAULT_STRING_VALUE: String? = null
|
||||||
|
private const val DEFAULT_INT_VALUE = 0
|
||||||
|
private const val DEFAULT_BOOLEAN_VALUE = false
|
||||||
|
|
||||||
|
fun getDefaultPreference(context: Context): SharedPreferences {
|
||||||
|
return PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writePrefString(context: Context, key: String, value: String?) {
|
||||||
|
PrefsHelper(context).prefEditor.putString(key, value).commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readPrefString(context: Context, key: String): String? {
|
||||||
|
return PrefsHelper(context).preference.getString(key, DEFAULT_STRING_VALUE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writePrefInt(context: Context, key: String, value: Int) {
|
||||||
|
PrefsHelper(context).prefEditor.putInt(key, value).commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readPrefInt(context: Context, key: String): Int {
|
||||||
|
return PrefsHelper(context).preference.getInt(key, DEFAULT_INT_VALUE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writePrefBool(context: Context, key: String, value: Boolean) {
|
||||||
|
PrefsHelper(context).prefEditor.putBoolean(key, value).commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readPrefBool(context: Context, key: String): Boolean {
|
||||||
|
return PrefsHelper(context).preference.getBoolean(key, DEFAULT_BOOLEAN_VALUE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearPreference(context: Context) {
|
||||||
|
PrefsHelper(context).preference.edit().clear().apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,11 +9,11 @@ import com.google.gson.Gson
|
|||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.database.entity.LogsAndRuleAndSender
|
import com.idormy.sms.forwarder.database.entity.LogsAndRuleAndSender
|
||||||
import com.idormy.sms.forwarder.database.entity.Rule
|
import com.idormy.sms.forwarder.database.entity.Rule
|
||||||
import com.idormy.sms.forwarder.database.entity.Sender
|
|
||||||
import com.idormy.sms.forwarder.entity.MsgInfo
|
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||||
import com.idormy.sms.forwarder.entity.result.SendResponse
|
import com.idormy.sms.forwarder.entity.result.SendResponse
|
||||||
import com.idormy.sms.forwarder.entity.setting.*
|
import com.idormy.sms.forwarder.entity.setting.*
|
||||||
import com.idormy.sms.forwarder.utils.sender.*
|
import com.idormy.sms.forwarder.utils.sender.*
|
||||||
|
import com.idormy.sms.forwarder.workers.SendLogicWorker
|
||||||
import com.idormy.sms.forwarder.workers.SendWorker
|
import com.idormy.sms.forwarder.workers.SendWorker
|
||||||
import com.idormy.sms.forwarder.workers.UpdateLogsWorker
|
import com.idormy.sms.forwarder.workers.UpdateLogsWorker
|
||||||
import com.xuexiang.xui.utils.ResUtils
|
import com.xuexiang.xui.utils.ResUtils
|
||||||
@ -24,13 +24,6 @@ import java.util.*
|
|||||||
object SendUtils {
|
object SendUtils {
|
||||||
private const val TAG = "SendUtils"
|
private const val TAG = "SendUtils"
|
||||||
|
|
||||||
//批量发送消息
|
|
||||||
/*fun sendMsgList(infoList: List<MsgInfo>, type: String) {
|
|
||||||
for (msgInfo in infoList) {
|
|
||||||
sendMsg(msgInfo, type)
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//发送消息
|
//发送消息
|
||||||
fun sendMsg(msgInfo: MsgInfo) {
|
fun sendMsg(msgInfo: MsgInfo) {
|
||||||
val request = OneTimeWorkRequestBuilder<SendWorker>()
|
val request = OneTimeWorkRequestBuilder<SendWorker>()
|
||||||
@ -53,9 +46,9 @@ object SendUtils {
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Date()
|
Date()
|
||||||
}
|
}
|
||||||
val simInfo: String = item.logs.simInfo
|
val simInfo: String = item.msg.simInfo
|
||||||
val simSlot: Int = if (simInfo.startsWith("SIM2")) 2 else 1
|
val simSlot: Int = if (simInfo.startsWith("SIM2")) 2 else 1
|
||||||
val msgInfo = MsgInfo(item.logs.type, item.logs.from, item.logs.content, date, simInfo, simSlot)
|
val msgInfo = MsgInfo(item.msg.type, item.msg.from, item.msg.content, date, simInfo, simSlot)
|
||||||
Log.d(TAG, "resendMsg msgInfo:$msgInfo")
|
Log.d(TAG, "resendMsg msgInfo:$msgInfo")
|
||||||
|
|
||||||
if (rematch) {
|
if (rematch) {
|
||||||
@ -63,72 +56,73 @@ object SendUtils {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMsgSender(msgInfo, item.relation.rule, item.relation.sender, item.logs.id)
|
//sendMsgSender(msgInfo, item.rule, item.sender, item.logs.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
//匹配发送通道发送消息
|
//匹配发送通道发送消息
|
||||||
fun sendMsgSender(msgInfo: MsgInfo, rule: Rule, sender: Sender, logId: Long) {
|
fun sendMsgSender(msgInfo: MsgInfo, rule: Rule, senderIndex: Int = 0, logId: Long = 0L, msgId: Long = 0L) {
|
||||||
try {
|
try {
|
||||||
|
val sender = rule.senderList[senderIndex]
|
||||||
when (sender.type) {
|
when (sender.type) {
|
||||||
TYPE_DINGTALK_GROUP_ROBOT -> {
|
TYPE_DINGTALK_GROUP_ROBOT -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, DingtalkGroupRobotSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, DingtalkGroupRobotSetting::class.java)
|
||||||
DingtalkGroupRobotUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
DingtalkGroupRobotUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_EMAIL -> {
|
TYPE_EMAIL -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, EmailSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, EmailSetting::class.java)
|
||||||
EmailUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
EmailUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_BARK -> {
|
TYPE_BARK -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, BarkSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, BarkSetting::class.java)
|
||||||
BarkUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
BarkUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_WEBHOOK -> {
|
TYPE_WEBHOOK -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, WebhookSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, WebhookSetting::class.java)
|
||||||
WebhookUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
WebhookUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_WEWORK_ROBOT -> {
|
TYPE_WEWORK_ROBOT -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, WeworkRobotSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, WeworkRobotSetting::class.java)
|
||||||
WeworkRobotUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
WeworkRobotUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_WEWORK_AGENT -> {
|
TYPE_WEWORK_AGENT -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, WeworkAgentSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, WeworkAgentSetting::class.java)
|
||||||
WeworkAgentUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
WeworkAgentUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_SERVERCHAN -> {
|
TYPE_SERVERCHAN -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, ServerchanSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, ServerchanSetting::class.java)
|
||||||
ServerchanUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
ServerchanUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_TELEGRAM -> {
|
TYPE_TELEGRAM -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, TelegramSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, TelegramSetting::class.java)
|
||||||
TelegramUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
TelegramUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_SMS -> {
|
TYPE_SMS -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, SmsSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, SmsSetting::class.java)
|
||||||
SmsUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
SmsUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_FEISHU -> {
|
TYPE_FEISHU -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, FeishuSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, FeishuSetting::class.java)
|
||||||
FeishuUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
FeishuUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_PUSHPLUS -> {
|
TYPE_PUSHPLUS -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, PushplusSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, PushplusSetting::class.java)
|
||||||
PushplusUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
PushplusUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_GOTIFY -> {
|
TYPE_GOTIFY -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, GotifySetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, GotifySetting::class.java)
|
||||||
GotifyUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
GotifyUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_DINGTALK_INNER_ROBOT -> {
|
TYPE_DINGTALK_INNER_ROBOT -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, DingtalkInnerRobotSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, DingtalkInnerRobotSetting::class.java)
|
||||||
DingtalkInnerRobotUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
DingtalkInnerRobotUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_FEISHU_APP -> {
|
TYPE_FEISHU_APP -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, FeishuAppSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, FeishuAppSetting::class.java)
|
||||||
FeishuAppUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
FeishuAppUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
TYPE_URL_SCHEME -> {
|
TYPE_URL_SCHEME -> {
|
||||||
val settingVo = Gson().fromJson(sender.jsonSetting, UrlSchemeSetting::class.java)
|
val settingVo = Gson().fromJson(sender.jsonSetting, UrlSchemeSetting::class.java)
|
||||||
UrlSchemeUtils.sendMsg(settingVo, msgInfo, rule, logId)
|
UrlSchemeUtils.sendMsg(settingVo, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
updateLogs(logId, 0, "未知发送通道")
|
updateLogs(logId, 0, "未知发送通道")
|
||||||
@ -140,6 +134,24 @@ object SendUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun senderLogic(status: Int, msgInfo: MsgInfo, rule: Rule?, senderIndex: Int = 0, msgId: Long = 0L) {
|
||||||
|
if (rule == null) return
|
||||||
|
//发送通道执行逻辑:ALL=全部执行, UntilFail=失败即终止, UntilSuccess=成功即终止
|
||||||
|
if (senderIndex < rule.senderList.count() - 1 && ((status == 2 && rule.senderLogic == SENDER_LOGIC_UNTIL_FAIL) || (status == 0 && rule.senderLogic == SENDER_LOGIC_UNTIL_SUCCESS))) {
|
||||||
|
val request = OneTimeWorkRequestBuilder<SendLogicWorker>()
|
||||||
|
.setInputData(
|
||||||
|
workDataOf(
|
||||||
|
Worker.sendMsgInfo to Gson().toJson(msgInfo),
|
||||||
|
Worker.ruleId to rule.id,
|
||||||
|
Worker.senderIndex to senderIndex + 1,
|
||||||
|
Worker.msgId to msgId,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
WorkManager.getInstance(XUtil.getContext()).enqueue(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//更新转发日志状态
|
//更新转发日志状态
|
||||||
fun updateLogs(logId: Long?, status: Int, response: String) {
|
fun updateLogs(logId: Long?, status: Int, response: String) {
|
||||||
|
|
||||||
|
@ -25,7 +25,9 @@ class BarkUtils {
|
|||||||
setting: BarkSetting,
|
setting: BarkSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
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)
|
||||||
@ -86,18 +88,19 @@ class BarkUtils {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
Log.i(TAG, response)
|
Log.i(TAG, response)
|
||||||
|
|
||||||
val resp = Gson().fromJson(response, BarkResult::class.java)
|
val resp = Gson().fromJson(response, BarkResult::class.java)
|
||||||
if (resp?.code == 200L) {
|
val status = if (resp?.code == 200L) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -105,7 +108,7 @@ class BarkUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: BarkSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: BarkSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,7 +30,9 @@ class DingtalkGroupRobotUtils private constructor() {
|
|||||||
setting: DingtalkGroupRobotSetting,
|
setting: DingtalkGroupRobotSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
val content: String = if (rule != null) {
|
val content: String = if (rule != null) {
|
||||||
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
|
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
|
||||||
@ -97,18 +99,18 @@ class DingtalkGroupRobotUtils private constructor() {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
Log.i(TAG, response)
|
Log.i(TAG, response)
|
||||||
|
|
||||||
val resp = Gson().fromJson(response, DingtalkResult::class.java)
|
val resp = Gson().fromJson(response, DingtalkResult::class.java)
|
||||||
if (resp?.errcode == 0L) {
|
val status = if (resp?.errcode == 0L) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -116,7 +118,7 @@ class DingtalkGroupRobotUtils private constructor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: DingtalkGroupRobotSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: DingtalkGroupRobotSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -36,12 +36,14 @@ class DingtalkInnerRobotUtils private constructor() {
|
|||||||
setting: DingtalkInnerRobotSetting,
|
setting: DingtalkInnerRobotSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
var accessToken: String by SharedPreference("accessToken_" + setting.agentID, "")
|
var accessToken: String by SharedPreference("accessToken_" + setting.agentID, "")
|
||||||
var expiresIn: Long by SharedPreference("expiresIn_" + setting.agentID, 0L)
|
var expiresIn: Long by SharedPreference("expiresIn_" + setting.agentID, 0L)
|
||||||
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
|
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
|
||||||
return sendTextMsg(setting, msgInfo, rule, logId)
|
return sendTextMsg(setting, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
val requestUrl = "https://api.dingtalk.com/v1.0/oauth2/accessToken"
|
val requestUrl = "https://api.dingtalk.com/v1.0/oauth2/accessToken"
|
||||||
@ -93,7 +95,9 @@ class DingtalkInnerRobotUtils private constructor() {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
@ -103,9 +107,10 @@ class DingtalkInnerRobotUtils private constructor() {
|
|||||||
if (!TextUtils.isEmpty(resp?.accessToken)) {
|
if (!TextUtils.isEmpty(resp?.accessToken)) {
|
||||||
accessToken = resp.accessToken.toString()
|
accessToken = resp.accessToken.toString()
|
||||||
expiresIn = System.currentTimeMillis() + ((resp.expireIn ?: 7200) - 120) * 1000L //提前2分钟过期
|
expiresIn = System.currentTimeMillis() + ((resp.expireIn ?: 7200) - 120) * 1000L //提前2分钟过期
|
||||||
sendTextMsg(setting, msgInfo, rule, logId)
|
sendTextMsg(setting, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
} else {
|
} else {
|
||||||
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
|
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
|
||||||
|
SendUtils.senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +123,9 @@ class DingtalkInnerRobotUtils private constructor() {
|
|||||||
setting: DingtalkInnerRobotSetting,
|
setting: DingtalkInnerRobotSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
val requestUrl = "https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend"
|
val requestUrl = "https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend"
|
||||||
Log.d(TAG, "requestUrl:$requestUrl")
|
Log.d(TAG, "requestUrl:$requestUrl")
|
||||||
@ -197,25 +204,25 @@ class DingtalkInnerRobotUtils private constructor() {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
Log.i(TAG, response)
|
Log.i(TAG, response)
|
||||||
|
|
||||||
val resp = Gson().fromJson(response, DingtalkInnerRobotResult::class.java)
|
val resp = Gson().fromJson(response, DingtalkInnerRobotResult::class.java)
|
||||||
if (!TextUtils.isEmpty(resp?.processQueryKey)) {
|
val status = if (!TextUtils.isEmpty(resp?.processQueryKey)) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: DingtalkInnerRobotSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: DingtalkInnerRobotSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,9 @@ class EmailUtils {
|
|||||||
setting: EmailSetting,
|
setting: EmailSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
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)
|
||||||
@ -134,18 +136,21 @@ class EmailUtils {
|
|||||||
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())
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.message.toString())
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
||||||
|
SendUtils.senderLogic(2, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: EmailSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: EmailSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -28,13 +28,15 @@ class FeishuAppUtils private constructor() {
|
|||||||
setting: FeishuAppSetting,
|
setting: FeishuAppSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var accessToken: String by SharedPreference("feishu_access_token_" + setting.appId, "")
|
var accessToken: String by SharedPreference("feishu_access_token_" + setting.appId, "")
|
||||||
var expiresIn: Long by SharedPreference("feishu_expires_in_" + setting.appId, 0L)
|
var expiresIn: Long by SharedPreference("feishu_expires_in_" + setting.appId, 0L)
|
||||||
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
|
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
|
||||||
return sendTextMsg(setting, msgInfo, rule, logId)
|
return sendTextMsg(setting, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
val requestUrl = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
|
val requestUrl = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
|
||||||
@ -51,7 +53,9 @@ class FeishuAppUtils private constructor() {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
@ -61,9 +65,10 @@ class FeishuAppUtils private constructor() {
|
|||||||
if (!TextUtils.isEmpty(resp?.tenant_access_token)) {
|
if (!TextUtils.isEmpty(resp?.tenant_access_token)) {
|
||||||
accessToken = resp.tenant_access_token.toString()
|
accessToken = resp.tenant_access_token.toString()
|
||||||
expiresIn = System.currentTimeMillis() + ((resp.expire ?: 7010) - 120) * 1000L //提前2分钟过期
|
expiresIn = System.currentTimeMillis() + ((resp.expire ?: 7010) - 120) * 1000L //提前2分钟过期
|
||||||
sendTextMsg(setting, msgInfo, rule, logId)
|
sendTextMsg(setting, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
} else {
|
} else {
|
||||||
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
|
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
|
||||||
|
SendUtils.senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +81,9 @@ class FeishuAppUtils private constructor() {
|
|||||||
setting: FeishuAppSetting,
|
setting: FeishuAppSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
val requestUrl = "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=user_id"
|
val requestUrl = "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=user_id"
|
||||||
Log.d(TAG, "requestUrl:$requestUrl")
|
Log.d(TAG, "requestUrl:$requestUrl")
|
||||||
@ -117,7 +124,9 @@ class FeishuAppUtils private constructor() {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
@ -126,18 +135,16 @@ class FeishuAppUtils private constructor() {
|
|||||||
//Log.d(TAG, "cipherSuite=" + response.handshake().cipherSuite().toString())
|
//Log.d(TAG, "cipherSuite=" + response.handshake().cipherSuite().toString())
|
||||||
|
|
||||||
val resp = Gson().fromJson(response, FeishuAppResult::class.java)
|
val resp = Gson().fromJson(response, FeishuAppResult::class.java)
|
||||||
if (resp?.code == 0L) {
|
val status = if (resp?.code == 0L) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: FeishuAppSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: FeishuAppSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun jsonInnerStr(string: String?): String {
|
private fun jsonInnerStr(string: String?): String {
|
||||||
|
@ -83,7 +83,9 @@ class FeishuUtils private constructor() {
|
|||||||
setting: FeishuSetting,
|
setting: FeishuSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
val from: String = msgInfo.from
|
val from: String = msgInfo.from
|
||||||
val title: String = if (rule != null) {
|
val title: String = if (rule != null) {
|
||||||
@ -144,18 +146,18 @@ class FeishuUtils private constructor() {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
Log.i(TAG, response)
|
Log.i(TAG, response)
|
||||||
|
|
||||||
val resp = Gson().fromJson(response, FeishuResult::class.java)
|
val resp = Gson().fromJson(response, FeishuResult::class.java)
|
||||||
if (resp?.code == 0L) {
|
val status = if (resp?.code == 0L) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -181,7 +183,7 @@ class FeishuUtils private constructor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: FeishuSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: FeishuSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,7 +23,9 @@ class GotifyUtils {
|
|||||||
setting: GotifySetting,
|
setting: GotifySetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
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)
|
||||||
@ -64,18 +66,18 @@ class GotifyUtils {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
val status = if (resp?.id != null) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -83,7 +85,7 @@ class GotifyUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: GotifySetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: GotifySetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,7 +27,9 @@ class PushplusUtils private constructor() {
|
|||||||
setting: PushplusSetting,
|
setting: PushplusSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
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)
|
||||||
@ -79,18 +81,18 @@ class PushplusUtils private constructor() {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
Log.i(TAG, response)
|
Log.i(TAG, response)
|
||||||
|
|
||||||
val resp = Gson().fromJson(response, PushplusResult::class.java)
|
val resp = Gson().fromJson(response, PushplusResult::class.java)
|
||||||
if (resp?.code == 200L) {
|
val status = if (resp?.code == 200L) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -98,7 +100,7 @@ class PushplusUtils private constructor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: PushplusSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: PushplusSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,7 +24,9 @@ class ServerchanUtils {
|
|||||||
setting: ServerchanSetting,
|
setting: ServerchanSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
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)
|
||||||
@ -58,18 +60,17 @@ class ServerchanUtils {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
val status = if (resp?.code == 0L) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -77,7 +78,7 @@ class ServerchanUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: ServerchanSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: ServerchanSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,16 +26,20 @@ class SmsUtils {
|
|||||||
setting: SmsSetting,
|
setting: SmsSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
//仅当无网络时启用 && 判断是否真实有网络
|
//仅当无网络时启用 && 判断是否真实有网络
|
||||||
if (setting.onlyNoNetwork == true && NetworkUtils.isHaveInternet() && NetworkUtils.isAvailableByPing()) {
|
if (setting.onlyNoNetwork == true && NetworkUtils.isHaveInternet() && NetworkUtils.isAvailableByPing()) {
|
||||||
SendUtils.updateLogs(logId, 0, ResUtils.getString(R.string.OnlyNoNetwork))
|
SendUtils.updateLogs(logId, 0, ResUtils.getString(R.string.OnlyNoNetwork))
|
||||||
|
SendUtils.senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ActivityCompat.checkSelfPermission(XUtil.getContext(), Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
|
if (ActivityCompat.checkSelfPermission(XUtil.getContext(), Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
|
||||||
SendUtils.updateLogs(logId, 0, ResUtils.getString(R.string.no_sms_sending_permission))
|
SendUtils.updateLogs(logId, 0, ResUtils.getString(R.string.no_sms_sending_permission))
|
||||||
|
SendUtils.senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,13 +66,15 @@ class SmsUtils {
|
|||||||
val res: String? = PhoneUtils.sendSms(mSubscriptionId, mobiles, content)
|
val res: String? = PhoneUtils.sendSms(mSubscriptionId, mobiles, content)
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
SendUtils.updateLogs(logId, 2, ResUtils.getString(R.string.request_succeeded))
|
SendUtils.updateLogs(logId, 2, ResUtils.getString(R.string.request_succeeded))
|
||||||
|
SendUtils.senderLogic(2, msgInfo, rule, senderIndex, msgId)
|
||||||
} else {
|
} else {
|
||||||
SendUtils.updateLogs(logId, 0, res)
|
SendUtils.updateLogs(logId, 0, res)
|
||||||
|
SendUtils.senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: SmsSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: SmsSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,7 +30,9 @@ class TelegramUtils private constructor() {
|
|||||||
setting: TelegramSetting,
|
setting: TelegramSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
if (setting.method == null || setting.method == "POST") {
|
if (setting.method == null || setting.method == "POST") {
|
||||||
msgInfo.content = htmlEncode(msgInfo.content)
|
msgInfo.content = htmlEncode(msgInfo.content)
|
||||||
@ -116,18 +118,18 @@ class TelegramUtils private constructor() {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
Log.i(TAG, response)
|
Log.i(TAG, response)
|
||||||
|
|
||||||
val resp = Gson().fromJson(response, TelegramResult::class.java)
|
val resp = Gson().fromJson(response, TelegramResult::class.java)
|
||||||
if (resp?.ok == true) {
|
val status = if (resp?.ok == true) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -135,7 +137,7 @@ class TelegramUtils private constructor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: TelegramSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: TelegramSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun htmlEncode(source: String?): String {
|
private fun htmlEncode(source: String?): String {
|
||||||
|
@ -26,7 +26,9 @@ class UrlSchemeUtils private constructor() {
|
|||||||
setting: UrlSchemeSetting,
|
setting: UrlSchemeSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
val from: String = msgInfo.from
|
val from: String = msgInfo.from
|
||||||
val content: String = if (rule != null) {
|
val content: String = if (rule != null) {
|
||||||
@ -62,16 +64,18 @@ class UrlSchemeUtils private constructor() {
|
|||||||
try {
|
try {
|
||||||
XUtil.getContext().startActivity(intent)
|
XUtil.getContext().startActivity(intent)
|
||||||
SendUtils.updateLogs(logId, 2, "调用成功")
|
SendUtils.updateLogs(logId, 2, "调用成功")
|
||||||
|
SendUtils.senderLogic(2, msgInfo, rule, senderIndex, msgId)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Log.e(TAG, e.message.toString())
|
Log.e(TAG, e.message.toString())
|
||||||
SendUtils.updateLogs(logId, 0, e.message.toString())
|
SendUtils.updateLogs(logId, 0, e.message.toString())
|
||||||
|
SendUtils.senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: UrlSchemeSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: UrlSchemeSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,7 +32,9 @@ class WebhookUtils {
|
|||||||
setting: WebhookSetting,
|
setting: WebhookSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
val from: String = msgInfo.from
|
val from: String = msgInfo.from
|
||||||
val content: String = if (rule != null) {
|
val content: String = if (rule != null) {
|
||||||
@ -183,12 +185,15 @@ class WebhookUtils {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
SendUtils.senderLogic(2, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -203,7 +208,7 @@ class WebhookUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: WebhookSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: WebhookSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -36,13 +36,15 @@ class WeworkAgentUtils private constructor() {
|
|||||||
setting: WeworkAgentSetting,
|
setting: WeworkAgentSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var accessToken: String by SharedPreference("access_token_" + setting.agentID, "")
|
var accessToken: String by SharedPreference("access_token_" + setting.agentID, "")
|
||||||
var expiresIn: Long by SharedPreference("expires_in_" + setting.agentID, 0L)
|
var expiresIn: Long by SharedPreference("expires_in_" + setting.agentID, 0L)
|
||||||
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
|
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
|
||||||
return sendTextMsg(setting, msgInfo, rule, logId)
|
return sendTextMsg(setting, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
var getTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
|
var getTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
|
||||||
@ -90,7 +92,9 @@ class WeworkAgentUtils private constructor() {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
@ -100,9 +104,10 @@ class WeworkAgentUtils private constructor() {
|
|||||||
if (resp?.errcode == 0L) {
|
if (resp?.errcode == 0L) {
|
||||||
accessToken = resp.access_token.toString()
|
accessToken = resp.access_token.toString()
|
||||||
expiresIn = System.currentTimeMillis() + ((resp.expires_in ?: 7200) - 120) * 1000L //提前2分钟过期
|
expiresIn = System.currentTimeMillis() + ((resp.expires_in ?: 7200) - 120) * 1000L //提前2分钟过期
|
||||||
sendTextMsg(setting, msgInfo, rule, logId)
|
sendTextMsg(setting, msgInfo, rule, senderIndex, logId, msgId)
|
||||||
} else {
|
} else {
|
||||||
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
|
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
|
||||||
|
SendUtils.senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +120,9 @@ class WeworkAgentUtils private constructor() {
|
|||||||
setting: WeworkAgentSetting,
|
setting: WeworkAgentSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
val content: String = if (rule != null) {
|
val content: String = if (rule != null) {
|
||||||
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
|
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
|
||||||
@ -181,25 +188,25 @@ class WeworkAgentUtils private constructor() {
|
|||||||
|
|
||||||
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)
|
val status = 0
|
||||||
|
SendUtils.updateLogs(logId, status, e.displayMessage)
|
||||||
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
Log.i(TAG, response)
|
Log.i(TAG, response)
|
||||||
|
|
||||||
val resp = Gson().fromJson(response, DingtalkResult::class.java)
|
val resp = Gson().fromJson(response, DingtalkResult::class.java)
|
||||||
if (resp?.errcode == 0L) {
|
val status = if (resp?.errcode == 0L) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: WeworkAgentSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: WeworkAgentSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,9 @@ class WeworkRobotUtils private constructor() {
|
|||||||
setting: WeworkRobotSetting,
|
setting: WeworkRobotSetting,
|
||||||
msgInfo: MsgInfo,
|
msgInfo: MsgInfo,
|
||||||
rule: Rule?,
|
rule: Rule?,
|
||||||
logId: Long?,
|
senderIndex: Int = 0,
|
||||||
|
logId: Long = 0L,
|
||||||
|
msgId: Long = 0L
|
||||||
) {
|
) {
|
||||||
val content: String = if (rule != null) {
|
val content: String = if (rule != null) {
|
||||||
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
|
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
|
||||||
@ -58,17 +60,16 @@ class WeworkRobotUtils private constructor() {
|
|||||||
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)
|
||||||
|
SendUtils.senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(response: String) {
|
override fun onSuccess(response: String) {
|
||||||
Log.i(TAG, response)
|
Log.i(TAG, response)
|
||||||
|
|
||||||
val resp = Gson().fromJson(response, WeworkRobotResult::class.java)
|
val resp = Gson().fromJson(response, WeworkRobotResult::class.java)
|
||||||
if (resp?.errcode == 0L) {
|
val status = if (resp?.errcode == 0L) 2 else 0
|
||||||
SendUtils.updateLogs(logId, 2, response)
|
SendUtils.updateLogs(logId, status, response)
|
||||||
} else {
|
SendUtils.senderLogic(status, msgInfo, rule, senderIndex, msgId)
|
||||||
SendUtils.updateLogs(logId, 0, response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -76,7 +77,7 @@ class WeworkRobotUtils private constructor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendMsg(setting: WeworkRobotSetting, msgInfo: MsgInfo) {
|
fun sendMsg(setting: WeworkRobotSetting, msgInfo: MsgInfo) {
|
||||||
sendMsg(setting, msgInfo, null, null)
|
sendMsg(setting, msgInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.idormy.sms.forwarder.workers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.work.CoroutineWorker
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.idormy.sms.forwarder.core.Core
|
||||||
|
import com.idormy.sms.forwarder.database.entity.Logs
|
||||||
|
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||||
|
import com.idormy.sms.forwarder.utils.SendUtils
|
||||||
|
import com.idormy.sms.forwarder.utils.Worker
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class SendLogicWorker(
|
||||||
|
context: Context,
|
||||||
|
workerParams: WorkerParameters,
|
||||||
|
) : CoroutineWorker(context, workerParams) {
|
||||||
|
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
|
||||||
|
|
||||||
|
val msgInfoJson = inputData.getString(Worker.sendMsgInfo)
|
||||||
|
val msgInfo = Gson().fromJson(msgInfoJson, MsgInfo::class.java)
|
||||||
|
val ruleId = inputData.getLong(Worker.ruleId, 0L)
|
||||||
|
val senderIndex = inputData.getInt(Worker.senderIndex, 0)
|
||||||
|
val msgId = inputData.getLong(Worker.msgId, 0L)
|
||||||
|
|
||||||
|
val rule = Core.rule.getOne(ruleId)
|
||||||
|
val sender = rule.senderList[senderIndex]
|
||||||
|
val log = Logs(0, rule.type, msgId, rule.id, sender.id)
|
||||||
|
val logId = Core.logs.insert(log)
|
||||||
|
SendUtils.sendMsgSender(msgInfo, rule, senderIndex, logId, msgId)
|
||||||
|
|
||||||
|
return@withContext Result.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,7 +9,8 @@ import androidx.work.workDataOf
|
|||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.idormy.sms.forwarder.core.Core
|
import com.idormy.sms.forwarder.core.Core
|
||||||
import com.idormy.sms.forwarder.database.entity.Logs
|
import com.idormy.sms.forwarder.database.entity.Logs
|
||||||
import com.idormy.sms.forwarder.database.entity.RuleAndSender
|
import com.idormy.sms.forwarder.database.entity.Msg
|
||||||
|
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.utils.*
|
import com.idormy.sms.forwarder.utils.*
|
||||||
import com.xuexiang.xutil.security.CipherUtils
|
import com.xuexiang.xutil.security.CipherUtils
|
||||||
@ -55,7 +56,6 @@ class SendWorker(
|
|||||||
Log.e("SendWorker", "免打扰(禁用转发)时间段")
|
Log.e("SendWorker", "免打扰(禁用转发)时间段")
|
||||||
return@withContext Result.failure(workDataOf("send" to "failed"))
|
return@withContext Result.failure(workDataOf("send" to "failed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val msgInfoJson = inputData.getString(Worker.sendMsgInfo)
|
val msgInfoJson = inputData.getString(Worker.sendMsgInfo)
|
||||||
@ -75,18 +75,22 @@ class SendWorker(
|
|||||||
|
|
||||||
//【注意】卡槽id:-1=获取失败、0=卡槽1、1=卡槽2,但是 Rule 表里存的是 SIM1/SIM2
|
//【注意】卡槽id:-1=获取失败、0=卡槽1、1=卡槽2,但是 Rule 表里存的是 SIM1/SIM2
|
||||||
val simSlot = "SIM" + (msgInfo.simSlot + 1)
|
val simSlot = "SIM" + (msgInfo.simSlot + 1)
|
||||||
val ruleList: List<RuleAndSender> = Core.rule.getRuleAndSender(msgInfo.type, 1, simSlot)
|
val ruleList: List<Rule> = Core.rule.getRuleList(msgInfo.type, 1, simSlot)
|
||||||
if (ruleList.isEmpty()) {
|
if (ruleList.isEmpty()) {
|
||||||
return@withContext Result.failure(workDataOf("send" to "failed"))
|
return@withContext Result.failure(workDataOf("send" to "failed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val msg = Msg(0, msgInfo.type, msgInfo.from, msgInfo.content, msgInfo.simSlot, msgInfo.simInfo, msgInfo.subId)
|
||||||
|
val msgId = Core.msg.insert(msg)
|
||||||
|
|
||||||
for (rule in ruleList) {
|
for (rule in ruleList) {
|
||||||
if (!rule.rule.checkMsg(msgInfo)) continue
|
Log.d("SendWorker", rule.toString())
|
||||||
val log = Logs(
|
if (!rule.checkMsg(msgInfo)) continue
|
||||||
0, msgInfo.type, msgInfo.from, msgInfo.content, rule.rule.id, msgInfo.simInfo, msgInfo.subId
|
|
||||||
)
|
val sender = rule.senderList[0]
|
||||||
|
val log = Logs(0, msgInfo.type, msgId, rule.id, sender.id)
|
||||||
val logId = Core.logs.insert(log)
|
val logId = Core.logs.insert(log)
|
||||||
SendUtils.sendMsgSender(msgInfo, rule.rule, rule.sender, logId)
|
SendUtils.sendMsgSender(msgInfo, rule, 0, logId, msgId)
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -20,30 +20,9 @@
|
|||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:layout_weight="1"
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_sender_image"
|
|
||||||
android:layout_width="@dimen/card_view_image_size"
|
|
||||||
android:layout_height="@dimen/card_view_image_size"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_status_image"
|
|
||||||
android:layout_width="16dp"
|
|
||||||
android:layout_height="16dp"
|
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginTop="-16dp"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@ -85,6 +64,20 @@
|
|||||||
android:maxLines="3"
|
android:maxLines="3"
|
||||||
android:textSize="11sp" />
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginTop="3dp"
|
||||||
|
android:layout_marginBottom="3dp"
|
||||||
|
android:background="?attr/xui_config_color_separator_light" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_Logs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"></LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@ -40,57 +41,31 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_rule_match"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="start"
|
|
||||||
android:maxEms="8"
|
|
||||||
android:maxLines="3"
|
|
||||||
android:textSize="11sp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="@dimen/card_view_image_size"
|
android:layout_width="0dp"
|
||||||
android:layout_height="@dimen/card_view_image_size"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_weight="1"
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_sender_image"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_sender_status"
|
|
||||||
android:layout_width="10dp"
|
|
||||||
android:layout_height="10dp"
|
|
||||||
android:layout_marginStart="14dp"
|
|
||||||
android:layout_marginTop="-10dp"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_sender_name"
|
android:id="@+id/tv_rule_match"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:gravity="center"
|
android:gravity="start"
|
||||||
android:maxEms="6"
|
android:maxEms="8"
|
||||||
android:maxLines="1"
|
android:maxLines="3"
|
||||||
android:textSize="9sp"
|
android:textSize="11sp" />
|
||||||
tools:ignore="SmallSp" />
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_Senders"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:orientation="horizontal"></LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -23,65 +23,84 @@
|
|||||||
style="@style/ruleBarStyle"
|
style="@style/ruleBarStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/select_sender"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="50dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:layout_marginStart="5dp"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_horizontal"
|
android:paddingBottom="5dp">
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_sender_image"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/iv_sender_status"
|
|
||||||
android:layout_width="10dp"
|
|
||||||
android:layout_height="10dp"
|
|
||||||
android:layout_marginStart="14dp"
|
|
||||||
android:layout_marginTop="-10dp"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_sender_name"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ellipsize="end"
|
android:text="@string/select_sender"
|
||||||
android:gravity="center"
|
android:textStyle="bold" />
|
||||||
android:maxEms="6"
|
|
||||||
android:maxLines="1"
|
<com.xuexiang.xui.widget.spinner.editspinner.EditSpinner
|
||||||
android:textSize="9sp"
|
android:id="@+id/sp_sender"
|
||||||
tools:ignore="SmallSp" />
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
app:es_hint="@string/choose_sender"
|
||||||
|
app:es_maxLength="20"
|
||||||
|
app:es_maxLine="1" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.spinner.editspinner.EditSpinner
|
<View
|
||||||
android:id="@+id/sp_sender"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="0dp"
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/xui_config_color_separator_light" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_Senders"
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:orientation="vertical"></LinearLayout>
|
||||||
android:layout_weight="1"
|
|
||||||
app:es_hint="@string/choose_sender"
|
<LinearLayout
|
||||||
app:es_maxLength="20"
|
android:id="@+id/layout_sender_logic"
|
||||||
app:es_maxLine="1" />
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/sender_logic"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/rg_sender_logic"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rb_sender_logic_all"
|
||||||
|
style="@style/rg_rb_style_wrap"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/sender_logic_all" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rb_sender_logic_until_fail"
|
||||||
|
style="@style/rg_rb_style_wrap"
|
||||||
|
android:text="@string/sender_logic_until_fail" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rb_sender_logic_until_success"
|
||||||
|
style="@style/rg_rb_style_wrap"
|
||||||
|
android:text="@string/sender_logic_until_success" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -65,7 +65,6 @@
|
|||||||
android:id="@+id/rg_method"
|
android:id="@+id/rg_method"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<RadioButton
|
<RadioButton
|
||||||
@ -73,25 +72,41 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:checked="true"
|
android:checked="true"
|
||||||
android:text="@string/post" />
|
android:scaleX="0.7"
|
||||||
|
android:scaleY="0.7"
|
||||||
|
android:text="@string/post"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:translationX="18dp" />
|
||||||
|
|
||||||
<RadioButton
|
<RadioButton
|
||||||
android:id="@+id/rb_method_get"
|
android:id="@+id/rb_method_get"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/get" />
|
android:scaleX="0.7"
|
||||||
|
android:scaleY="0.7"
|
||||||
|
android:text="@string/get"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:translationX="18dp" />
|
||||||
|
|
||||||
<RadioButton
|
<RadioButton
|
||||||
android:id="@+id/rb_method_put"
|
android:id="@+id/rb_method_put"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/put" />
|
android:scaleX="0.7"
|
||||||
|
android:scaleY="0.7"
|
||||||
|
android:text="@string/put"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:translationX="18dp" />
|
||||||
|
|
||||||
<RadioButton
|
<RadioButton
|
||||||
android:id="@+id/rb_method_patch"
|
android:id="@+id/rb_method_patch"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/patch" />
|
android:scaleX="0.7"
|
||||||
|
android:scaleY="0.7"
|
||||||
|
android:text="@string/patch"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:translationX="18dp" />
|
||||||
|
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
|
|
||||||
|
70
app/src/main/res/layout/item_add_sender.xml
Normal file
70
app/src/main/res/layout/item_add_sender.xml
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/xui_config_color_white"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingStart="5dp"
|
||||||
|
android:paddingEnd="5dp"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sender_image"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sender_status"
|
||||||
|
android:layout_width="10dp"
|
||||||
|
android:layout_height="10dp"
|
||||||
|
android:layout_marginStart="14dp"
|
||||||
|
android:layout_marginTop="-10dp"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_sender_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:minHeight="?attr/ms_item_height_size"
|
||||||
|
android:paddingStart="?attr/ms_padding_left_size"
|
||||||
|
android:paddingTop="?attr/ms_padding_top_size"
|
||||||
|
android:paddingEnd="?attr/ms_padding_left_size"
|
||||||
|
android:paddingBottom="?attr/ms_padding_top_size"
|
||||||
|
android:singleLine="true"
|
||||||
|
tools:ignore="PrivateResource" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_remove_sender"
|
||||||
|
android:layout_width="18dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
android:contentDescription="@string/sender_del"
|
||||||
|
android:src="@drawable/icon_delete"
|
||||||
|
app:tint="@color/design_default_color_error" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/xui_config_color_separator_light" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
44
app/src/main/res/layout/item_logs.xml
Normal file
44
app/src/main/res/layout/item_logs.xml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sender_image"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sender_status"
|
||||||
|
android:layout_width="10dp"
|
||||||
|
android:layout_height="10dp"
|
||||||
|
android:layout_marginStart="14dp"
|
||||||
|
android:layout_marginTop="-10dp"
|
||||||
|
tools:ignore="ContentDescription,VisualLintBounds" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_sender_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxEms="10"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textSize="9sp"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
44
app/src/main/res/layout/item_sender.xml
Normal file
44
app/src/main/res/layout/item_sender.xml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sender_image"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_sender_status"
|
||||||
|
android:layout_width="10dp"
|
||||||
|
android:layout_height="10dp"
|
||||||
|
android:layout_marginStart="14dp"
|
||||||
|
android:layout_marginTop="-10dp"
|
||||||
|
tools:ignore="ContentDescription,VisualLintBounds" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_sender_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxEms="10"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textSize="9sp"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -223,6 +223,10 @@
|
|||||||
<string name="test_package_name">测试模拟的APP包名</string>
|
<string name="test_package_name">测试模拟的APP包名</string>
|
||||||
<string name="test_inform_title">测试模拟的通知标题</string>
|
<string name="test_inform_title">测试模拟的通知标题</string>
|
||||||
<string name="test_inform_content">测试模拟的通知内容</string>
|
<string name="test_inform_content">测试模拟的通知内容</string>
|
||||||
|
<string name="sender_logic">执行逻辑</string>
|
||||||
|
<string name="sender_logic_all">全部执行</string>
|
||||||
|
<string name="sender_logic_until_fail">失败即止</string>
|
||||||
|
<string name="sender_logic_until_success">成功即止</string>
|
||||||
<string name="match_sim_slot">匹配卡槽</string>
|
<string name="match_sim_slot">匹配卡槽</string>
|
||||||
<string name="match_field">匹配字段</string>
|
<string name="match_field">匹配字段</string>
|
||||||
<string name="phone_number">手机号</string>
|
<string name="phone_number">手机号</string>
|
||||||
@ -841,6 +845,7 @@
|
|||||||
<string name="frpc_failed_to_run">Frpc运行失败</string>
|
<string name="frpc_failed_to_run">Frpc运行失败</string>
|
||||||
<string name="successfully_deleted">删除成功</string>
|
<string name="successfully_deleted">删除成功</string>
|
||||||
<string name="sender_disabled_tips">【注意】该发送通道已经禁用,其关联的规则即便匹配上也不会发送!</string>
|
<string name="sender_disabled_tips">【注意】该发送通道已经禁用,其关联的规则即便匹配上也不会发送!</string>
|
||||||
|
<string name="sender_contains_tips">【注意】该发送通道已经在列表中,无需重复添加!</string>
|
||||||
<string name="local_call">本地呼叫:</string>
|
<string name="local_call">本地呼叫:</string>
|
||||||
<string name="remote_sms">远程发短信:</string>
|
<string name="remote_sms">远程发短信:</string>
|
||||||
<string name="clear">清除</string>
|
<string name="clear">清除</string>
|
||||||
@ -942,4 +947,6 @@
|
|||||||
<string name="copy_public_key">复制公钥</string>
|
<string name="copy_public_key">复制公钥</string>
|
||||||
<string name="sm4_key">SM4密钥</string>
|
<string name="sm4_key">SM4密钥</string>
|
||||||
<string name="sm4_key_tips">客户端/服务端交互采用SM4加解密</string>
|
<string name="sm4_key_tips">客户端/服务端交互采用SM4加解密</string>
|
||||||
|
|
||||||
|
<string name="sender_del">删除发送通道</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user