Remove relaybaton due to esni is blocked in China

This commit is contained in:
世界 2020-08-01 08:31:51 +08:00
parent 13b1e06fd4
commit ee5d3fa381
14 changed files with 33 additions and 929 deletions

View File

@ -1,58 +0,0 @@
#!/usr/bin/env bash
DEPS=$ANDROID_HOME/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin
ANDROID_ARM_CC=$DEPS/armv7a-linux-androideabi16-clang
ANDROID_ARM_STRIP=$DEPS/arm-linux-androideabi-strip
ANDROID_ARM64_CC=$DEPS/aarch64-linux-android21-clang
ANDROID_ARM64_STRIP=$DEPS/aarch64-linux-android-strip
ANDROID_X86_CC=$DEPS/i686-linux-android16-clang
ANDROID_X86_STRIP=$DEPS/i686-linux-android-strip
ANDROID_X86_64_CC=$DEPS/x86_64-linux-android21-clang
ANDROID_X86_64_STRIP=$DEPS/x86_64-linux-android-strip
git clone https://github.com/cloudflare/tls-tris -b pwu/esni tls
BASEDIR=$(realpath tls/_dev)
GOENV="$(go env GOHOSTOS)_$(go env GOHOSTARCH)"
BUILD_DIR=${BASEDIR}/GOROOT make -f $BASEDIR/Makefile >&2
export GOROOT="$BASEDIR/GOROOT/$GOENV"
export GO111MOD=on
export CGO_ENABLED=1
export GOOS=android
PKG="github.com/iyouport-org/relaybaton/main"
OUTPUT="relaybaton"
LIB_OUTPUT="lib$OUTPUT.so"
AAR_OUTPUT="$OUTPUT.aar"
go get -v $PKG
ROOT="relaybaton/src/main/jniLibs"
DIR="$ROOT/armeabi-v7a"
mkdir -p $DIR
env CC=$ANDROID_ARM_CC GOARCH=arm GOARM=7 go build -o $DIR/$LIB_OUTPUT -v $PKG
$ANDROID_ARM_STRIP $DIR/$LIB_OUTPUT
DIR="$ROOT/arm64-v8a"
mkdir -p $DIR
env CC=$ANDROID_ARM64_CC GOARCH=arm64 go build -o $DIR/$LIB_OUTPUT -v $PKG
$ANDROID_ARM64_STRIP $DIR/$LIB_OUTPUT
DIR="$ROOT/x86"
mkdir -p $DIR
env CC=$ANDROID_X86_CC GOARCH=386 go build -o $DIR/$LIB_OUTPUT -v $PKG
$ANDROID_X86_STRIP $DIR/$LIB_OUTPUT
DIR="$ROOT/x86_64"
mkdir -p $DIR
env CC=$ANDROID_X86_64_CC GOARCH=amd64 go build -o $DIR/$LIB_OUTPUT -v $PKG
$ANDROID_X86_64_STRIP $DIR/$LIB_OUTPUT

View File

@ -7,8 +7,8 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
def verName = "6.3.0.0-preview-3"
def verCode = 60
def verName = "6.3.0.0-rc03"
def verCode = 61
def serviceAccountCredentialsFile = rootProject.file("service_account_credentials.json")
@ -518,4 +518,4 @@ android {
}
}
}
}

View File

@ -16,7 +16,6 @@ object V2RayConfig {
const val VMESS1_PROTOCOL = "vmess1://"
const val SS_PROTOCOL: String = "ss://"
const val SSR_PROTOCOL: String = "ssr://"
const val RB_PROTOCOL: String = "rb://"
const val SOCKS_PROTOCOL: String = "socks://"
const val BROADCAST_ACTION_SERVICE = "com.v2ray.ang.action.service"

View File

@ -3267,117 +3267,6 @@ public class AndroidUtilities {
builder.show();
}
public static void showRelayBatonAlert(Context activity, final SharedConfig.RelayBatonProxy info) {
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
final Runnable dismissRunnable = builder.getDismissRunnable();
builder.setApplyTopPadding(false);
builder.setApplyBottomPadding(false);
LinearLayout linearLayout = new LinearLayout(activity);
builder.setCustomView(linearLayout);
linearLayout.setOrientation(LinearLayout.VERTICAL);
for (int a = 0; a < 5; a++) {
String text = null;
String detail = null;
if (a == 0) {
text = info.bean.getServer();
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
} else if (a == 1) {
text = "" + info.bean.getUsername();
detail = LocaleController.getString("UseProxyPort", R.string.UseProxyUsername);
} else if (a == 2) {
text = info.bean.getPassword();
detail = LocaleController.getString("UseProxyPassword", R.string.UseProxyPassword);
} else if (a == 3) {
text = info.bean.getEsni() ? "Y" : "N";
detail = LocaleController.getString("ESNI", R.string.ESNI);
} else {
text = LocaleController.getString("Checking", R.string.Checking);
detail = LocaleController.getString("Checking", R.string.Checking);
}
if (TextUtils.isEmpty(text)) {
continue;
}
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
cell.setTextAndValue(text, detail, true);
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
AtomicInteger count = new AtomicInteger();
if (a == 4) {
RequestTimeDelegate callback = new RequestTimeDelegate() {
@Override
public void run(long time) {
int c = count.getAndIncrement();
String colorKey;
if (time != -1) {
info.stop();
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else if (c < 3) {
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", t -> AndroidUtilities.runOnUIThread(() -> run(t), 500));
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else {
info.stop();
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
colorKey = Theme.key_windowBackgroundWhiteRedText4;
}
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
}
};
UIUtil.runOnIoDispatcher(() -> {
try {
info.start();
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", time -> AndroidUtilities.runOnUIThread(() -> callback.run(time)));
} catch (Exception e) {
FileLog.e(e);
AlertUtil.showToast(e);
}
});
}
}
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
pickerBottomLayout.cancelButton.setOnClickListener(view -> {
info.stop();
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
SharedConfig.addProxy(info);
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
pickerBottomLayout.doneButton.setOnClickListener(v -> {
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
builder.show();
}
@SuppressLint("PrivateApi")
public static String getSystemProperty(String key) {
try {

View File

@ -41,7 +41,6 @@ import java.util.LinkedList;
import cn.hutool.core.util.StrUtil;
import okhttp3.HttpUrl;
import tw.nekomimi.nekogram.ProxyManager;
import tw.nekomimi.nekogram.RelayBatonLoader;
import tw.nekomimi.nekogram.ShadowsocksLoader;
import tw.nekomimi.nekogram.ShadowsocksRLoader;
import tw.nekomimi.nekogram.VmessLoader;
@ -865,121 +864,6 @@ public class SharedConfig {
}
public static class RelayBatonProxy extends ExternalSocks5Proxy {
public RelayBatonLoader.Bean bean;
public RelayBatonLoader loader;
public RelayBatonProxy(String rbLink) {
this(RelayBatonLoader.Bean.Companion.parse(rbLink));
}
public RelayBatonProxy(RelayBatonLoader.Bean bean) {
this.bean = bean;
if (BuildVars.isMini) {
throw new RuntimeException(LocaleController.getString("MiniVersionAlert", R.string.MiniVersionAlert));
}
}
@Override
public String getAddress() {
return bean.getServer();
}
@Override
public boolean isStarted() {
return loader != null;
}
@Override
public void start() {
if (loader != null) return;
port = ProxyManager.mkPort();
RelayBatonLoader loader = new RelayBatonLoader();
loader.initConfig(bean, port);
loader.start();
this.loader = loader;
if (SharedConfig.proxyEnabled && SharedConfig.currentProxy == this) {
ConnectionsManager.setProxySettings(true, address, port, username, password, secret);
}
}
@Override
public void stop() {
if (loader != null) {
RelayBatonLoader loader = this.loader;
this.loader = null;
loader.stop();
}
}
@Override
public String toUrl() {
return bean.toString();
}
@Override
public String getRemarks() {
return bean.getRemarks();
}
@Override
public void setRemarks(String remarks) {
bean.setRemarks(remarks);
}
@Override
public String getType() {
return "RB";
}
@Override
public JSONObject toJsonInternal() throws JSONException {
JSONObject obj = new JSONObject();
obj.put("type", "shadowsocksr");
obj.put("link", toUrl());
return obj;
}
@Override
public int hashCode() {
return bean.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
return super.equals(obj) || (obj instanceof RelayBatonProxy && bean.equals(((RelayBatonProxy) obj).bean));
}
}
public static LinkedList<ProxyInfo> proxyList = new LinkedList<>();
public static LinkedList<ProxyInfo> getProxyList() {

View File

@ -89,7 +89,6 @@ import cn.hutool.core.util.StrUtil;
import kotlin.Unit;
import okhttp3.HttpUrl;
import tw.nekomimi.nekogram.BottomBuilder;
import tw.nekomimi.nekogram.RelayBatonSettingsActivity;
import tw.nekomimi.nekogram.ShadowsocksRSettingsActivity;
import tw.nekomimi.nekogram.ShadowsocksSettingsActivity;
import tw.nekomimi.nekogram.SubSettingsActivity;
@ -777,8 +776,6 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
presentFragment(new ShadowsocksRSettingsActivity((SharedConfig.ShadowsocksRProxy) info));
}
} else if (info instanceof SharedConfig.RelayBatonProxy) {
presentFragment(new RelayBatonSettingsActivity((SharedConfig.RelayBatonProxy) info));
} else {
presentFragment(new ProxySettingsActivity(info));
}
@ -844,7 +841,6 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
LocaleController.getString("AddProxyVmess", R.string.AddProxyVmess),
Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ? null : LocaleController.getString("AddProxySS", R.string.AddProxySS),
Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ? null : LocaleController.getString("AddProxySSR", R.string.AddProxySSR),
LocaleController.getString("AddProxyRB", R.string.AddProxyRB),
LocaleController.getString("ImportProxyFromClipboard", R.string.ImportProxyFromClipboard),
LocaleController.getString("ScanQRCode", R.string.ScanQRCode)
@ -872,10 +868,6 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
} else if (i == 5) {
presentFragment(new RelayBatonSettingsActivity());
} else if (i == 6) {
ProxyUtil.importFromClipboard(getParentActivity());
} else {

View File

@ -1,191 +0,0 @@
package tw.nekomimi.nekogram
import android.annotation.SuppressLint
import com.v2ray.ang.V2RayConfig
import kotlinx.coroutines.runBlocking
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import org.telegram.messenger.ApplicationLoader
import org.telegram.messenger.FileLog
import tw.nekomimi.nekogram.utils.FileUtil
import java.io.File
import kotlin.concurrent.thread
import kotlin.properties.Delegates
class RelayBatonLoader {
companion object {
@SuppressLint("AuthLeak")
const val publicServer = "rb://anonymous:nya@net.neko.services"
}
lateinit var bean: Bean
var port by Delegates.notNull<Int>()
var rbProcess: GuardedProcessPool? = null
fun initConfig(bean: Bean, port: Int) {
this.bean = bean
this.port = port
}
fun start() {
stop()
val cacheCfg = File(ApplicationLoader.applicationContext.cacheDir, "config.toml")
cacheCfg.writeText(bean.toToml(port))
val geoip = File(ApplicationLoader.applicationContext.cacheDir, "GeoLite2-Country.mmdb")
if (!geoip.isFile) {
geoip.createNewFile()
geoip.outputStream().use { out ->
ApplicationLoader.applicationContext.assets.open("GeoLite2-Country.mmdb").use {
it.copyTo(out)
}
}
}
rbProcess = GuardedProcessPool {
FileLog.e(it)
}.apply {
runCatching {
start(listOf(FileUtil.extLib("relaybaton").path, "client")) {
cacheCfg.delete()
}
}.onFailure {
cacheCfg.delete()
FileLog.e(it)
}
}
}
fun stop() {
if (rbProcess != null) {
val proc = rbProcess!!
thread {
runCatching {
runBlocking { proc.close(this) }
}
}
rbProcess = null
}
}
data class Bean(
var server: String = "",
var username: String = "",
var password: String = "",
var esni: Boolean = true,
var remarks: String? = null
) {
override fun equals(other: Any?): Boolean {
return super.equals(other) || (other is Bean && hash == other.hash)
}
val hash = (server + username + password).hashCode()
fun toToml(port: Int) = """
[log]
file="./log.txt"
level="error"
[dns]
type="dot"
server="cloudflare-dns.com"
addr="1.0.0.1:853"
local_resolve=false
[clients]
port=$port
[[clients.client]]
id="1"
server="$server"
username="$username"
password="$password"
esni=$esni
timeout=15
[routes]
geoip_file="GeoLite2-Country.mmdb"
[[routes.route]]
type="default"
cond=""
target="1"
"""
companion object {
fun parse(url: String): Bean {
// ss-android style
val link = url.replace(V2RayConfig.RB_PROTOCOL, "https://").toHttpUrlOrNull() ?: error("invalid relaybaton link $url")
return Bean(
link.host,
link.username,
link.password,
link.queryParameter("esni").takeIf { it in arrayOf("true", "false") }?.toBoolean() ?: true,
link.fragment
)
}
}
override fun toString(): String {
val url = HttpUrl.Builder()
.scheme("https")
.username(username)
.password(password)
.host(server)
if (!remarks.isNullOrBlank()) url.fragment(remarks)
if (!esni) url.addQueryParameter("esni","false")
return url.build().toString().replace("https://", V2RayConfig.RB_PROTOCOL)
}
}
}

View File

@ -1,375 +0,0 @@
/*
* This is the source code of Telegram for Android v. 5.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2018.
*/
package tw.nekomimi.nekogram;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.os.Build;
import android.text.InputType;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarMenuItem;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Cells.TextCheckCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Components.EditTextBoldCursor;
import org.telegram.ui.Components.LayoutHelper;
import java.util.ArrayList;
import cn.hutool.core.util.StrUtil;
public class RelayBatonSettingsActivity extends BaseFragment {
private EditTextBoldCursor[] inputFields;
private EditTextBoldCursor serverField;
private EditTextBoldCursor usernameField;
private EditTextBoldCursor passwordField;
private TextCheckCell esniField;
private EditTextBoldCursor remarksField;
private ScrollView scrollView;
private LinearLayout linearLayout2;
private LinearLayout inputFieldsContainer;
private TextInfoPrivacyCell bottomCell;
private SharedConfig.RelayBatonProxy currentProxyInfo;
private RelayBatonLoader.Bean currentBean;
private boolean ignoreOnTextChange;
private static final int done_button = 1;
public class TypeCell extends FrameLayout {
private TextView textView;
private ImageView checkImage;
private boolean needDivider;
public TypeCell(Context context) {
super(context);
setWillNotDraw(false);
textView = new TextView(context);
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
textView.setLines(1);
textView.setMaxLines(1);
textView.setSingleLine(true);
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 23 + 48 : 21, 0, LocaleController.isRTL ? 21 : 23, 0));
checkImage = new ImageView(context);
checkImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.SRC_IN));
checkImage.setImageResource(R.drawable.sticker_added);
addView(checkImage, LayoutHelper.createFrame(19, 14, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
}
public void setValue(String name, boolean checked, boolean divider) {
textView.setText(name);
checkImage.setVisibility(checked ? VISIBLE : INVISIBLE);
needDivider = divider;
}
public void setTypeChecked(boolean value) {
checkImage.setVisibility(value ? VISIBLE : INVISIBLE);
}
@Override
protected void onDraw(Canvas canvas) {
if (needDivider) {
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
}
}
}
public RelayBatonSettingsActivity() {
super();
currentBean = new RelayBatonLoader.Bean();
}
public RelayBatonSettingsActivity(SharedConfig.RelayBatonProxy proxyInfo) {
super();
currentProxyInfo = proxyInfo;
currentBean = proxyInfo.bean;
}
@Override
public void onResume() {
super.onResume();
AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid);
}
@Override
public View createView(Context context) {
actionBar.setTitle(LocaleController.getString("ProxyDetails", R.string.ProxyDetails));
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(false);
if (AndroidUtilities.isTablet()) {
actionBar.setOccupyStatusBar(false);
}
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
@Override
public void onItemClick(int id) {
if (id == -1) {
finishFragment();
} else if (id == done_button) {
if (getParentActivity() == null) {
return;
}
if (StrUtil.isBlank(serverField.getText())) {
serverField.requestFocus();
AndroidUtilities.showKeyboard(serverField);
return;
}
if (StrUtil.isBlank(usernameField.getText())) {
usernameField.requestFocus();
AndroidUtilities.showKeyboard(usernameField);
return;
}
if (StrUtil.isBlank(passwordField.getText())) {
passwordField.requestFocus();
AndroidUtilities.showKeyboard(passwordField);
return;
}
currentBean.setServer(serverField.getText().toString());
currentBean.setUsername(usernameField.getText().toString());
currentBean.setPassword(passwordField.getText().toString());
currentBean.setEsni(esniField.isChecked());
currentBean.setRemarks(remarksField.getText().toString());
if (currentProxyInfo == null) {
currentProxyInfo = new SharedConfig.RelayBatonProxy(currentBean);
SharedConfig.addProxy(currentProxyInfo);
SharedConfig.setCurrentProxy(currentProxyInfo);
} else {
currentProxyInfo.proxyCheckPingId = 0;
currentProxyInfo.availableCheckTime = 0;
currentProxyInfo.ping = 0;
SharedConfig.saveProxyList();
SharedConfig.setProxyEnable(false);
}
finishFragment();
}
}
});
ActionBarMenuItem doneItem = actionBar.createMenu().addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56));
doneItem.setContentDescription(LocaleController.getString("Done", R.string.Done));
fragmentView = new FrameLayout(context);
FrameLayout frameLayout = (FrameLayout) fragmentView;
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
scrollView = new ScrollView(context);
scrollView.setFillViewport(true);
AndroidUtilities.setScrollViewEdgeEffectColor(scrollView, Theme.getColor(Theme.key_actionBarDefault));
frameLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
linearLayout2 = new LinearLayout(context);
linearLayout2.setOrientation(LinearLayout.VERTICAL);
scrollView.addView(linearLayout2, new ScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
inputFieldsContainer = new LinearLayout(context);
inputFieldsContainer.setOrientation(LinearLayout.VERTICAL);
inputFieldsContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// bring to front for transitions
inputFieldsContainer.setElevation(AndroidUtilities.dp(1f));
inputFieldsContainer.setOutlineProvider(null);
}
linearLayout2.addView(inputFieldsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
inputFields = new EditTextBoldCursor[4];
for (int a = 0; a < 4; a++) {
FrameLayout container = new FrameLayout(context);
EditTextBoldCursor cursor = mkCursor();
inputFields[a] = cursor;
cursor.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
switch (a) {
case 0:
serverField = cursor;
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
cursor.setHintText(LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress));
cursor.setText(currentBean.getServer());
break;
case 1:
usernameField = cursor;
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
cursor.setHintText(LocaleController.getString("UseProxyUsername", R.string.UseProxyUsername));
cursor.setText(currentBean.getUsername());
break;
case 2:
passwordField = cursor;
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
cursor.setHintText(LocaleController.getString("UseProxyPassword", R.string.UseProxyPassword));
cursor.setText(currentBean.getPassword());
break;
case 3:
remarksField = cursor;
cursor.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
cursor.setHintText(LocaleController.getString("ProxyRemarks", R.string.ProxyRemarks));
cursor.setText(currentBean.getRemarks());
break;
}
cursor.setSelection(cursor.length());
cursor.setPadding(0, 0, 0, 0);
container.addView(cursor, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 17, a == 0 ? 12 : 0, 17, 0));
}
inputFieldsContainer.addView((View) serverField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
inputFieldsContainer.addView((View) usernameField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
inputFieldsContainer.addView((View) passwordField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
FrameLayout container = new FrameLayout(context);
esniField = new TextCheckCell(context);
esniField.setBackground(Theme.getSelectorDrawable(false));
esniField.setTextAndCheck(LocaleController.getString("ESNI", R.string.ESNI), currentBean.getEsni(), false);
esniField.setOnClickListener((v) -> esniField.setChecked(!esniField.isChecked()));
container.addView(esniField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
inputFieldsContainer.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
inputFieldsContainer.addView((View) remarksField.getParent(), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64));
bottomCell = new TextInfoPrivacyCell(context);
bottomCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
bottomCell.setText(LocaleController.getString("ProxyInfoSS", R.string.ProxyInfoSS));
linearLayout2.addView(bottomCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
return fragmentView;
}
EditTextBoldCursor mkCursor() {
EditTextBoldCursor cursor = new EditTextBoldCursor(getParentActivity());
cursor.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
cursor.setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText));
cursor.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
cursor.setBackground(null);
cursor.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
cursor.setCursorSize(AndroidUtilities.dp(20));
cursor.setCursorWidth(1.5f);
cursor.setSingleLine(true);
cursor.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
cursor.setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
cursor.setTransformHintToHeader(true);
cursor.setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
return cursor;
}
@Override
protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
if (isOpen && !backward && currentProxyInfo == null) {
serverField.requestFocus();
AndroidUtilities.showKeyboard(serverField);
}
}
@Override
public ArrayList<ThemeDescription> getThemeDescriptions() {
final ThemeDescription.ThemeDescriptionDelegate delegate = () -> {
if (inputFields != null) {
for (int i = 0; i < inputFields.length; i++) {
inputFields[i].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField),
Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated),
Theme.getColor(Theme.key_windowBackgroundWhiteRedText3));
}
}
};
ArrayList<ThemeDescription> arrayList = new ArrayList<>();
arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray));
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault));
arrayList.add(new ThemeDescription(scrollView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault));
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon));
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle));
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector));
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch));
arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder));
arrayList.add(new ThemeDescription(inputFieldsContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
arrayList.add(new ThemeDescription(linearLayout2, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider));
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteBlueText4));
arrayList.add(new ThemeDescription(null, 0, null, null, null, null, delegate, Theme.key_windowBackgroundWhiteGrayText2));
if (inputFields != null) {
for (int a = 0; a < inputFields.length; a++) {
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_HINTTEXTCOLOR | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader));
arrayList.add(new ThemeDescription(inputFields[a], ThemeDescription.FLAG_CURSORCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputField));
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteInputFieldActivated));
arrayList.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteRedText3));
}
} else {
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
arrayList.add(new ThemeDescription(null, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText));
}
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow));
arrayList.add(new ThemeDescription(bottomCell, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4));
arrayList.add(new ThemeDescription(bottomCell, ThemeDescription.FLAG_LINKCOLOR, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText));
return arrayList;
}
}

View File

@ -3,27 +3,20 @@ package tw.nekomimi.nekogram.sub;
import androidx.annotation.NonNull;
import org.dizitart.no2.Document;
import org.dizitart.no2.NitriteId;
import org.dizitart.no2.mapper.Mappable;
import org.dizitart.no2.mapper.NitriteMapper;
import org.dizitart.no2.objects.Id;
import org.dizitart.no2.objects.Index;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.xml.transform.ErrorListener;
import cn.hutool.core.util.StrUtil;
import tw.nekomimi.nekogram.RelayBatonLoader;
import tw.nekomimi.nekogram.utils.HttpUtil;
import tw.nekomimi.nekogram.utils.ProxyUtil;
@ -46,13 +39,13 @@ public class SubInfo implements Mappable {
if (name.length() < 10) return name;
return name.substring(0,10) + "...";
return name.substring(0, 10) + "...";
}
public List<String> reloadProxies() throws AllTriesFailed {
HashMap<String,Exception> exceptions = new HashMap<>();
HashMap<String, Exception> exceptions = new HashMap<>();
for (String url : urls) {
@ -64,7 +57,7 @@ public class SubInfo implements Mappable {
} catch (Exception e) {
exceptions.put(url,e);
exceptions.put(url, e);
}
@ -76,13 +69,15 @@ public class SubInfo implements Mappable {
public static class AllTriesFailed extends IOException {
public AllTriesFailed(HashMap<String,Exception> exceptions) {
public AllTriesFailed(HashMap<String, Exception> exceptions) {
this.exceptions = exceptions;
}
public HashMap<String,Exception> exceptions;
public HashMap<String, Exception> exceptions;
@NonNull @Override public String toString() {
@NonNull
@Override
public String toString() {
StringBuilder errors = new StringBuilder();
@ -126,7 +121,7 @@ public class SubInfo implements Mappable {
document.put("id", id);
document.put("name", name);
document.put("urls", urls);
document.put("proxies",proxies);
document.put("proxies", proxies);
document.put("lastFetch", lastFetch);
document.put("enable", enable);
document.put("internal", internal);
@ -142,12 +137,11 @@ public class SubInfo implements Mappable {
urls = (List<String>) document.get("urls");
proxies = (List<String>) document.get("proxies");
lastFetch = document.get("lastFetch",Long.class);
enable = document.get("enable",Boolean.class);
internal = document.get("internal",Boolean.class);
lastFetch = document.get("lastFetch", Long.class);
enable = document.get("enable", Boolean.class);
internal = document.get("internal", Boolean.class);
}
}

View File

@ -19,7 +19,6 @@ import com.google.zxing.*
import com.google.zxing.common.GlobalHistogramBinarizer
import com.google.zxing.qrcode.QRCodeReader
import com.google.zxing.qrcode.QRCodeWriter
import com.v2ray.ang.V2RayConfig.RB_PROTOCOL
import com.v2ray.ang.V2RayConfig.SSR_PROTOCOL
import com.v2ray.ang.V2RayConfig.SS_PROTOCOL
import com.v2ray.ang.V2RayConfig.VMESS1_PROTOCOL
@ -74,13 +73,13 @@ object ProxyUtil {
it.forEach { line ->
if (line.startsWith("tg://proxy") ||
line.startsWith("tg://socks") ||
line.startsWith("https://t.me/proxy") ||
line.startsWith("https://t.me/socks") ||
line.startsWith(VMESS_PROTOCOL) ||
line.startsWith(VMESS1_PROTOCOL) ||
line.startsWith(SS_PROTOCOL) ||
line.startsWith(SSR_PROTOCOL) /*||
line.startsWith("tg://socks") ||
line.startsWith("https://t.me/proxy") ||
line.startsWith("https://t.me/socks") ||
line.startsWith(VMESS_PROTOCOL) ||
line.startsWith(VMESS1_PROTOCOL) ||
line.startsWith(SS_PROTOCOL) ||
line.startsWith(SSR_PROTOCOL) /*||
line.startsWith(RB_PROTOCOL)*/) {
runCatching { proxies.add(SharedConfig.parseProxyInfo(line).toUrl()) }
@ -111,13 +110,13 @@ object ProxyUtil {
it.forEach { line ->
if (line.startsWith("tg://proxy") ||
line.startsWith("tg://socks") ||
line.startsWith("https://t.me/proxy") ||
line.startsWith("https://t.me/socks") ||
line.startsWith(VMESS_PROTOCOL) ||
line.startsWith(VMESS1_PROTOCOL) ||
line.startsWith(SS_PROTOCOL) ||
line.startsWith(SSR_PROTOCOL) /*||
line.startsWith("tg://socks") ||
line.startsWith("https://t.me/proxy") ||
line.startsWith("https://t.me/socks") ||
line.startsWith(VMESS_PROTOCOL) ||
line.startsWith(VMESS1_PROTOCOL) ||
line.startsWith(SS_PROTOCOL) ||
line.startsWith(SSR_PROTOCOL) /*||
line.startsWith(RB_PROTOCOL)*/) {
runCatching { proxies.add(SharedConfig.parseProxyInfo(line)) }.onFailure {
@ -176,9 +175,9 @@ object ProxyUtil {
return
} else if (!error){
} else if (!error) {
AlertUtil.showSimpleAlert(ctx, LocaleController.getString("ImportedProxies",R.string.ImportedProxies) + "\n\n" + proxies.joinToString("\n") { it.title })
AlertUtil.showSimpleAlert(ctx, LocaleController.getString("ImportedProxies", R.string.ImportedProxies) + "\n\n" + proxies.joinToString("\n") { it.title })
}
@ -213,13 +212,9 @@ object ProxyUtil {
AndroidUtilities.showShadowsocksRAlert(ctx, SharedConfig.ShadowsocksRProxy(link))
} else if (link.startsWith(RB_PROTOCOL)) {
AndroidUtilities.showRelayBatonAlert(ctx, SharedConfig.RelayBatonProxy(link))
} else {
val url = link.replace("tg://","https://t.me/").toHttpUrlOrNull()!!
val url = link.replace("tg://", "https://t.me/").toHttpUrlOrNull()!!
AndroidUtilities.showProxyAlert(ctx,
url.queryParameter("server"),
@ -238,7 +233,7 @@ object ProxyUtil {
FileLog.e(it)
if (BuildVars.LOGS_ENABLED){
if (BuildVars.LOGS_ENABLED) {
AlertUtil.showSimpleAlert(ctx, it)

View File

@ -168,9 +168,6 @@
<string name="SSRObfs">Obfs</string>
<string name="SSRObfsParam">Obfs Param</string>
<string name="ProxyInfoRB">RelayBaton Proxy Settings</string>
<string name="ESNI">Encrypted SNI</string>
<string name="ProxyRemarks">Remarks</string>
<string name="RetestPing">Retest ping for all servers</string>
<string name="ReorderByPing">Reorder servers by ping</string>

View File

@ -1 +0,0 @@
/build

View File

@ -1,16 +0,0 @@
plugins {
id 'com.android.library'
}
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
ndkVersion "21.1.6352462"
defaultConfig {
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"
}
}

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.nekohasekai.relaybaton">
</manifest>