mirror of
https://github.com/MatsuriDayo/NekoBoxForAndroid.git
synced 2025-12-20 07:00:05 +08:00
anytls share link
This commit is contained in:
parent
56f90f2ea1
commit
a1b5813e55
@ -30,11 +30,11 @@ import io.nekohasekai.sagernet.fmt.tuic.toUri
|
|||||||
import io.nekohasekai.sagernet.fmt.v2ray.*
|
import io.nekohasekai.sagernet.fmt.v2ray.*
|
||||||
import io.nekohasekai.sagernet.fmt.wireguard.WireGuardBean
|
import io.nekohasekai.sagernet.fmt.wireguard.WireGuardBean
|
||||||
import io.nekohasekai.sagernet.ktx.app
|
import io.nekohasekai.sagernet.ktx.app
|
||||||
import io.nekohasekai.sagernet.ktx.applyDefaultValues
|
|
||||||
import io.nekohasekai.sagernet.ui.profile.*
|
import io.nekohasekai.sagernet.ui.profile.*
|
||||||
import moe.matsuri.nb4a.SingBoxOptions.MultiplexOptions
|
import moe.matsuri.nb4a.SingBoxOptions.MultiplexOptions
|
||||||
import moe.matsuri.nb4a.proxy.anytls.AnyTLSBean
|
import moe.matsuri.nb4a.proxy.anytls.AnyTLSBean
|
||||||
import moe.matsuri.nb4a.proxy.anytls.AnyTLSSettingsActivity
|
import moe.matsuri.nb4a.proxy.anytls.AnyTLSSettingsActivity
|
||||||
|
import moe.matsuri.nb4a.proxy.anytls.toUri
|
||||||
import moe.matsuri.nb4a.proxy.config.ConfigBean
|
import moe.matsuri.nb4a.proxy.config.ConfigBean
|
||||||
import moe.matsuri.nb4a.proxy.config.ConfigSettingActivity
|
import moe.matsuri.nb4a.proxy.config.ConfigSettingActivity
|
||||||
import moe.matsuri.nb4a.proxy.neko.*
|
import moe.matsuri.nb4a.proxy.neko.*
|
||||||
@ -98,10 +98,8 @@ data class ProxyEntity(
|
|||||||
|
|
||||||
val chainName by lazy { app.getString(R.string.proxy_chain) }
|
val chainName by lazy { app.getString(R.string.proxy_chain) }
|
||||||
|
|
||||||
private val placeHolderBean = SOCKSBean().applyDefaultValues()
|
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val CREATOR = object : Serializable.CREATOR<ProxyEntity>() {
|
val CREATOR = object : CREATOR<ProxyEntity>() {
|
||||||
|
|
||||||
override fun newInstance(): ProxyEntity {
|
override fun newInstance(): ProxyEntity {
|
||||||
return ProxyEntity()
|
return ProxyEntity()
|
||||||
@ -241,7 +239,6 @@ data class ProxyEntity(
|
|||||||
is SSHBean -> false
|
is SSHBean -> false
|
||||||
is WireGuardBean -> false
|
is WireGuardBean -> false
|
||||||
is ShadowTLSBean -> false
|
is ShadowTLSBean -> false
|
||||||
is AnyTLSBean -> false
|
|
||||||
is NekoBean -> nekoBean!!.haveStandardLink()
|
is NekoBean -> nekoBean!!.haveStandardLink()
|
||||||
is ConfigBean -> false
|
is ConfigBean -> false
|
||||||
else -> true
|
else -> true
|
||||||
@ -259,6 +256,7 @@ data class ProxyEntity(
|
|||||||
is NaiveBean -> toUri()
|
is NaiveBean -> toUri()
|
||||||
is HysteriaBean -> toUri()
|
is HysteriaBean -> toUri()
|
||||||
is TuicBean -> toUri()
|
is TuicBean -> toUri()
|
||||||
|
is AnyTLSBean -> toUri()
|
||||||
is NekoBean -> shareLink()
|
is NekoBean -> shareLink()
|
||||||
else -> toUniversalLink()
|
else -> toUniversalLink()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import io.nekohasekai.sagernet.fmt.tuic.parseTuic
|
|||||||
import io.nekohasekai.sagernet.fmt.trojan_go.parseTrojanGo
|
import io.nekohasekai.sagernet.fmt.trojan_go.parseTrojanGo
|
||||||
import io.nekohasekai.sagernet.fmt.v2ray.parseV2Ray
|
import io.nekohasekai.sagernet.fmt.v2ray.parseV2Ray
|
||||||
import moe.matsuri.nb4a.plugin.NekoPluginManager
|
import moe.matsuri.nb4a.plugin.NekoPluginManager
|
||||||
|
import moe.matsuri.nb4a.proxy.anytls.parseAnytls
|
||||||
import moe.matsuri.nb4a.proxy.neko.NekoJSInterface
|
import moe.matsuri.nb4a.proxy.neko.NekoJSInterface
|
||||||
import moe.matsuri.nb4a.proxy.neko.parseShareLink
|
import moe.matsuri.nb4a.proxy.neko.parseShareLink
|
||||||
import moe.matsuri.nb4a.utils.JavaUtil.gson
|
import moe.matsuri.nb4a.utils.JavaUtil.gson
|
||||||
@ -203,6 +204,13 @@ suspend fun parseProxies(text: String): List<AbstractBean> {
|
|||||||
}.onFailure {
|
}.onFailure {
|
||||||
Logs.w(it)
|
Logs.w(it)
|
||||||
}
|
}
|
||||||
|
} else if (startsWith("anytls://")) {
|
||||||
|
Logs.d("Try parse anytls link: $this")
|
||||||
|
runCatching {
|
||||||
|
entities.add(parseAnytls(this))
|
||||||
|
}.onFailure {
|
||||||
|
Logs.w(it)
|
||||||
|
}
|
||||||
} else { // Neko Plugins
|
} else { // Neko Plugins
|
||||||
NekoPluginManager.getProtocols().forEach { obj ->
|
NekoPluginManager.getProtocols().forEach { obj ->
|
||||||
obj.protocolConfig.optJSONArray("links")?.forEach { _, any ->
|
obj.protocolConfig.optJSONArray("links")?.forEach { _, any ->
|
||||||
@ -228,12 +236,12 @@ suspend fun parseProxies(text: String): List<AbstractBean> {
|
|||||||
for (link in linksByLine) {
|
for (link in linksByLine) {
|
||||||
link.parseLink(entitiesByLine)
|
link.parseLink(entitiesByLine)
|
||||||
}
|
}
|
||||||
var isBadLink = false
|
// var isBadLink = false
|
||||||
if (entities.onEach { it.initializeDefaultValues() }.size == entitiesByLine.onEach { it.initializeDefaultValues() }.size) run test@{
|
if (entities.onEach { it.initializeDefaultValues() }.size == entitiesByLine.onEach { it.initializeDefaultValues() }.size) run test@{
|
||||||
entities.forEachIndexed { index, bean ->
|
entities.forEachIndexed { index, bean ->
|
||||||
val lineBean = entitiesByLine[index]
|
val lineBean = entitiesByLine[index]
|
||||||
if (bean == lineBean && bean.displayName() != lineBean.displayName()) {
|
if (bean == lineBean && bean.displayName() != lineBean.displayName()) {
|
||||||
isBadLink = true
|
// isBadLink = true
|
||||||
return@test
|
return@test
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1661,8 +1661,8 @@ class ConfigurationFragment @JvmOverloads constructor(
|
|||||||
try {
|
try {
|
||||||
currentName = entity.displayName()!!
|
currentName = entity.displayName()!!
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_standard_qr -> showCode(entity.toStdLink()!!)
|
R.id.action_standard_qr -> showCode(entity.toStdLink())
|
||||||
R.id.action_standard_clipboard -> export(entity.toStdLink()!!)
|
R.id.action_standard_clipboard -> export(entity.toStdLink())
|
||||||
R.id.action_universal_qr -> showCode(entity.requireBean().toUniversalLink())
|
R.id.action_universal_qr -> showCode(entity.requireBean().toUniversalLink())
|
||||||
R.id.action_universal_clipboard -> export(
|
R.id.action_universal_clipboard -> export(
|
||||||
entity.requireBean().toUniversalLink()
|
entity.requireBean().toUniversalLink()
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
package moe.matsuri.nb4a.proxy.anytls
|
package moe.matsuri.nb4a.proxy.anytls
|
||||||
|
|
||||||
import io.nekohasekai.sagernet.ktx.blankAsNull
|
import io.nekohasekai.sagernet.ktx.blankAsNull
|
||||||
|
import io.nekohasekai.sagernet.ktx.linkBuilder
|
||||||
|
import io.nekohasekai.sagernet.ktx.toLink
|
||||||
|
import io.nekohasekai.sagernet.ktx.urlSafe
|
||||||
import moe.matsuri.nb4a.SingBoxOptions
|
import moe.matsuri.nb4a.SingBoxOptions
|
||||||
import moe.matsuri.nb4a.utils.listByLineOrComma
|
import moe.matsuri.nb4a.utils.listByLineOrComma
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
|
|
||||||
fun buildSingBoxOutboundAnyTLSBean(bean: AnyTLSBean): SingBoxOptions.Outbound_AnyTLSOptions {
|
fun buildSingBoxOutboundAnyTLSBean(bean: AnyTLSBean): SingBoxOptions.Outbound_AnyTLSOptions {
|
||||||
return SingBoxOptions.Outbound_AnyTLSOptions().apply {
|
return SingBoxOptions.Outbound_AnyTLSOptions().apply {
|
||||||
@ -35,3 +39,43 @@ fun buildSingBoxOutboundAnyTLSBean(bean: AnyTLSBean): SingBoxOptions.Outbound_An
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun AnyTLSBean.toUri(): String {
|
||||||
|
val builder = linkBuilder()
|
||||||
|
.host(serverAddress)
|
||||||
|
.port(serverPort)
|
||||||
|
.username(password)
|
||||||
|
if (!name.isNullOrBlank()) {
|
||||||
|
builder.encodedFragment(name.urlSafe())
|
||||||
|
}
|
||||||
|
if (allowInsecure) {
|
||||||
|
builder.addQueryParameter("insecure", "1")
|
||||||
|
}
|
||||||
|
if (!sni.isNullOrBlank()) {
|
||||||
|
builder.addQueryParameter("sni", sni)
|
||||||
|
}
|
||||||
|
if (!utlsFingerprint.isNullOrBlank()) {
|
||||||
|
builder.addQueryParameter("fp", utlsFingerprint)
|
||||||
|
}
|
||||||
|
return builder.toLink("anytls")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseAnytls(url: String): AnyTLSBean {
|
||||||
|
// https://github.com/anytls/anytls-go/blob/main/docs/uri_scheme.md
|
||||||
|
val link = url.replace("anytls://", "https://").toHttpUrlOrNull() ?: error(
|
||||||
|
"invalid anytls link $url"
|
||||||
|
)
|
||||||
|
return AnyTLSBean().apply {
|
||||||
|
serverAddress = link.host
|
||||||
|
serverPort = link.port
|
||||||
|
name = link.fragment
|
||||||
|
password = link.username
|
||||||
|
sni = link.queryParameter("sni") ?: ""
|
||||||
|
link.queryParameter("insecure")?.also {
|
||||||
|
allowInsecure = it == "1" || it == "true"
|
||||||
|
}
|
||||||
|
link.queryParameter("fp")?.let {
|
||||||
|
utlsFingerprint = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user