mirror of
https://github.com/MGislv/NekoX.git
synced 2024-06-30 10:14:04 +00:00
Support add clash url as subscription
This commit is contained in:
parent
bc2261efd9
commit
06df6a63dd
|
@ -1,8 +1,8 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
def verName = "7.4.2-rc06"
|
||||
def verCode = 186
|
||||
def verName = "7.4.2-rc07"
|
||||
def verCode = 188
|
||||
|
||||
def officialVer = "7.4.2"
|
||||
def officialCode = 2227
|
||||
|
@ -85,6 +85,7 @@ dependencies {
|
|||
implementation 'cn.hutool:hutool-crypto:5.5.8'
|
||||
implementation 'cn.hutool:hutool-http:5.5.8'
|
||||
|
||||
implementation 'org.yaml:snakeyaml:1.27'
|
||||
implementation 'com.jakewharton:process-phoenix:2.0.0'
|
||||
|
||||
implementation project(":openpgp-api")
|
||||
|
@ -138,7 +139,7 @@ pwd = pwd ?: System.getenv("ALIAS_PASS")
|
|||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion '30.0.3'
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
ndkVersion '21.3.6528147'
|
||||
|
||||
defaultConfig.applicationId = "nekox.messenger"
|
||||
|
||||
|
|
|
@ -32,16 +32,17 @@ import org.telegram.messenger.R
|
|||
init {
|
||||
add(NoPlugin)
|
||||
addAll(ApplicationLoader.applicationContext.packageManager.queryIntentContentProviders(
|
||||
Intent(PluginContract.ACTION_NATIVE_PLUGIN), PackageManager.GET_META_DATA).map { NativePlugin(it) })
|
||||
Intent(PluginContract.ACTION_NATIVE_PLUGIN), PackageManager.GET_META_DATA)
|
||||
.map { NativePlugin(it) })
|
||||
}
|
||||
|
||||
val lookup = mutableMapOf<String, Plugin>().apply {
|
||||
for (plugin in this@PluginList) {
|
||||
fun check(old: Plugin?) = check(old == null || old === plugin) { LocaleController.formatString("SSPluginConflictingName",R.string.SSPluginConflictingName,plugin.id) }
|
||||
check(put(plugin.id, plugin))
|
||||
for (alias in plugin.idAliases) check(put(alias, plugin))
|
||||
}
|
||||
}
|
||||
|
||||
val lookupNames get() = lookup.values.map {
|
||||
if (it.label.isNotBlank() && it.id.isNotBlank()) {
|
||||
"${it.label} (${it.id})"
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
|||
import cn.hutool.core.codec.Base64
|
||||
import com.github.shadowsocks.plugin.PluginConfiguration
|
||||
import com.github.shadowsocks.plugin.PluginManager
|
||||
import com.github.shadowsocks.plugin.PluginOptions
|
||||
import com.v2ray.ang.V2RayConfig.SS_PROTOCOL
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.HttpUrl
|
||||
|
@ -106,16 +107,29 @@ class ShadowsocksLoader {
|
|||
|
||||
val pl = PluginConfiguration(plugin)
|
||||
|
||||
if (pl.selected.contains("v2ray") && pl.selected != "v2ray") {
|
||||
if (pl.selected.contains("v2ray") && pl.selected != "v2ray-plugin") {
|
||||
|
||||
pl.pluginsOptions["v2ray"] = pl.getOptions()
|
||||
pl.pluginsOptions["v2ray-plugin"] = pl.getOptions().apply { id = "v2ray-plugin" }
|
||||
pl.pluginsOptions.remove(pl.selected)
|
||||
pl.selected = "v2ray"
|
||||
pl.selected = "v2ray-plugin"
|
||||
|
||||
// reslove v2ray plugin
|
||||
|
||||
}
|
||||
|
||||
if (pl.selected == "obfs") {
|
||||
|
||||
pl.pluginsOptions["obfs-local"] = pl.getOptions().apply { id = "obfs-local" }
|
||||
pl.pluginsOptions.remove(pl.selected)
|
||||
pl.selected = "obfs-local"
|
||||
|
||||
// reslove clash obfs
|
||||
|
||||
}
|
||||
|
||||
plugin = pl.toString()
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
@ -150,6 +164,23 @@ class ShadowsocksLoader {
|
|||
|
||||
companion object {
|
||||
|
||||
fun parseJson(ssObj: JSONObject): Bean {
|
||||
var pluginStr = ""
|
||||
val pId = ssObj.optString("plugin")
|
||||
if (!pId.isNullOrBlank()) {
|
||||
val plugin = PluginOptions(pId, ssObj.optString("plugin_opts"))
|
||||
pluginStr = plugin.toString(false)
|
||||
}
|
||||
return Bean(
|
||||
ssObj.getString("server"),
|
||||
ssObj.getInt("server_port"),
|
||||
ssObj.getString("password"),
|
||||
ssObj.getString("method"),
|
||||
pluginStr,
|
||||
ssObj.optString("remarks")
|
||||
)
|
||||
}
|
||||
|
||||
fun parse(url: String): Bean {
|
||||
|
||||
if (url.contains("@")) {
|
||||
|
@ -157,7 +188,7 @@ class ShadowsocksLoader {
|
|||
// ss-android style
|
||||
|
||||
val link = url.replace(SS_PROTOCOL, "https://").toHttpUrlOrNull()
|
||||
?: error("invalid ss-android link $url")
|
||||
?: error("invalid ss-android link $url")
|
||||
|
||||
if (link.password.isNotBlank()) {
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ class ShadowsocksRLoader {
|
|||
var remarks: String? = null
|
||||
) {
|
||||
|
||||
val hash = (host + remotePort + password + protocol + obfs + method).hashCode()
|
||||
val hash get() = (host + remotePort + password + protocol + obfs + method).hashCode()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return super.equals(other) || (other is Bean && hash == other.hash)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@file:Suppress("UNCHECKED_CAST")
|
||||
|
||||
package tw.nekomimi.nekogram.utils
|
||||
|
||||
import android.Manifest
|
||||
|
@ -20,20 +22,28 @@ import android.widget.ImageView
|
|||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.setPadding
|
||||
import com.github.shadowsocks.plugin.PluginOptions
|
||||
import com.google.zxing.*
|
||||
import com.google.zxing.common.GlobalHistogramBinarizer
|
||||
import com.google.zxing.qrcode.QRCodeReader
|
||||
import com.google.zxing.qrcode.QRCodeWriter
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import com.v2ray.ang.V2RayConfig
|
||||
import com.v2ray.ang.V2RayConfig.SSR_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.SS_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.TROJAN_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.VMESS1_PROTOCOL
|
||||
import com.v2ray.ang.V2RayConfig.VMESS_PROTOCOL
|
||||
import com.v2ray.ang.dto.AngConfig
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.telegram.messenger.*
|
||||
import org.telegram.messenger.browser.Browser
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import tw.nekomimi.nekogram.BottomBuilder
|
||||
import tw.nekomimi.nekogram.ShadowsocksLoader
|
||||
import tw.nekomimi.nekogram.ShadowsocksRLoader
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil.showToast
|
||||
import java.io.File
|
||||
import java.net.NetworkInterface
|
||||
|
@ -66,17 +76,113 @@ object ProxyUtil {
|
|||
fun parseProxies(_text: String): MutableList<String> {
|
||||
|
||||
val text = runCatching {
|
||||
|
||||
String(Base64.decode(_text, Base64.NO_PADDING))
|
||||
|
||||
}.recover {
|
||||
|
||||
_text
|
||||
|
||||
}.getOrThrow()
|
||||
|
||||
val proxies = mutableListOf<String>()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
try {
|
||||
// sip008
|
||||
val ssArray = JSONArray(text)
|
||||
for (index in 0..ssArray.length()) {
|
||||
proxies.add(ShadowsocksLoader.Bean.parseJson(ssArray.getJSONObject(index)).toString())
|
||||
}
|
||||
return proxies
|
||||
} catch (ignored: JSONException) {
|
||||
}
|
||||
|
||||
if (text.contains("proxies:\n")) {
|
||||
// clash
|
||||
|
||||
for (proxy in (Yaml().loadAs(text, Map::class.java)["proxies"] as List<Map<String, Any?>>)) {
|
||||
val type = proxy["type"] as String
|
||||
when (type) {
|
||||
"ss" -> {
|
||||
var pluginStr = ""
|
||||
if (proxy.contains("plugin")) {
|
||||
val opts = PluginOptions()
|
||||
opts.id = proxy["plugin"] as String
|
||||
opts.putAll(proxy["plugin-opts"] as Map<String, String?>)
|
||||
pluginStr = opts.toString(false)
|
||||
}
|
||||
proxies.add(ShadowsocksLoader.Bean(
|
||||
proxy["server"] as String,
|
||||
proxy["port"] as Int,
|
||||
proxy["password"] as String,
|
||||
proxy["cipher"] as String,
|
||||
pluginStr,
|
||||
proxy["name"] as String
|
||||
).toString())
|
||||
}
|
||||
"vmess" -> {
|
||||
val opts = AngConfig.VmessBean()
|
||||
for (opt in proxy) {
|
||||
when (opt.key) {
|
||||
"name" -> opts.remarks = opt.value as String
|
||||
"server" -> opts.address = opt.value as String
|
||||
"port" -> opts.port = opt.value as Int
|
||||
"uuid" -> opts.id = opt.value as String
|
||||
"alterId" -> opts.alterId = opt.value as Int
|
||||
"cipher" -> opts.security = opt.value as String
|
||||
"network" -> opts.network = opt.value as String
|
||||
"tls" -> opts.streamSecurity = if (opt.value?.toString() == "true") "tls" else opts.streamSecurity
|
||||
"ws-path" -> opts.path = opt.value as String
|
||||
"servername" -> opts.requestHost = opt.value as String
|
||||
"h2-opts" -> for (h2Opt in (opt.value as Map<String, Any>)) {
|
||||
when (h2Opt.key) {
|
||||
"host" -> opts.requestHost = (h2Opt.value as List<String>).first()
|
||||
"path" -> opts.path = h2Opt.value as String
|
||||
}
|
||||
}
|
||||
"http-opts" -> for (httpOpt in (opt.value as Map<String, Any>)) {
|
||||
when (httpOpt.key) {
|
||||
"path" -> opts.path = (httpOpt.value as List<String>).first()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
proxies.add(opts.toString())
|
||||
}
|
||||
"trojan" -> {
|
||||
val opts = AngConfig.VmessBean()
|
||||
opts.configType = V2RayConfig.EConfigType.Trojan
|
||||
for (opt in proxy) {
|
||||
when (opt.key) {
|
||||
"name" -> opts.remarks = opt.value as String
|
||||
"server" -> opts.address = opt.value as String
|
||||
"port" -> opts.port = opt.value as Int
|
||||
"password" -> opts.id = opt.value as String
|
||||
"sni" -> opts.requestHost = opt.value as String
|
||||
}
|
||||
}
|
||||
proxies.add(opts.toString())
|
||||
}
|
||||
"ssr" -> {
|
||||
val opts = ShadowsocksRLoader.Bean()
|
||||
for (opt in proxy) {
|
||||
when (opt.key) {
|
||||
"name" -> opts.remarks = opt.value as String
|
||||
"server" -> opts.host = opt.value as String
|
||||
"port" -> opts.remotePort = opt.value as Int
|
||||
"cipher" -> opts.method = opt.value as String
|
||||
"password" -> opts.password = opt.value as String
|
||||
"obfs" -> opts.obfs = opt.value as String
|
||||
"protocol" -> opts.protocol = opt.value as String
|
||||
"obfs-param" -> opts.obfs_param = opt.value as String
|
||||
"protocol-param" -> opts.protocol_param = opt.value as String
|
||||
}
|
||||
}
|
||||
proxies.add(opts.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
return proxies
|
||||
}
|
||||
}
|
||||
|
||||
text.split('\n').map { it.split(" ") }.forEach {
|
||||
|
||||
it.forEach { line ->
|
||||
|
|
|
@ -16,7 +16,7 @@ buildscript {
|
|||
}
|
||||
}
|
||||
|
||||
static String detectNdkVersion() {
|
||||
/*static String detectNdkVersion() {
|
||||
|
||||
def version = "21.3.6528147"
|
||||
|
||||
|
@ -40,7 +40,7 @@ ext {
|
|||
|
||||
ndkVersion = detectNdkVersion()
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
|
|
|
@ -7,7 +7,7 @@ plugins {
|
|||
|
||||
android {
|
||||
|
||||
ndkVersion = rootProject.extra.get("ndkVersion").toString()
|
||||
ndkVersion = "21.3.6528147"
|
||||
|
||||
compileSdkVersion(30)
|
||||
defaultConfig {
|
||||
|
|
|
@ -4,8 +4,8 @@ plugins {
|
|||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion '30.0.2'
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
buildToolsVersion '30.0.3'
|
||||
ndkVersion "21.3.6528147"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
|
|
Loading…
Reference in New Issue
Block a user