mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-20 02:00:55 +07:00
fixed telemt=mtproxy algoritm
This commit is contained in:
@@ -362,6 +362,17 @@ void TelemtConfigModel::removeAdditionalSecret(int idx) {
|
||||
emit dataChanged(index(0), index(0), QList<int>{AdditionalSecretsRole});
|
||||
}
|
||||
|
||||
QVariantList TelemtConfigModel::additionalSecretsList() const {
|
||||
QVariantList out;
|
||||
out.reserve(m_protocolConfig.additionalSecrets.size());
|
||||
for (const auto &s : m_protocolConfig.additionalSecrets) {
|
||||
if (!s.isEmpty()) {
|
||||
out.append(s);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void TelemtConfigModel::setEnabled(bool enabled) {
|
||||
m_protocolConfig.isEnabled = enabled;
|
||||
emit dataChanged(index(0), index(0), QList<int>{IsEnabledRole});
|
||||
|
||||
@@ -88,6 +88,9 @@ public slots:
|
||||
|
||||
Q_INVOKABLE void removeAdditionalSecret(int idx);
|
||||
|
||||
/// Current additional secrets list from in-memory config (for QML snapshot vs. unsaved adds).
|
||||
Q_INVOKABLE QVariantList additionalSecretsList() const;
|
||||
|
||||
Q_INVOKABLE QString generateQrCode(const QString &text);
|
||||
|
||||
Q_INVOKABLE void setEnabled(bool enabled);
|
||||
|
||||
@@ -20,6 +20,7 @@ PageType {
|
||||
id: root
|
||||
|
||||
property int containerStatus: 1
|
||||
// Last status-query error code (0 = none). 305 = SshTimeoutError → server unreachable.
|
||||
property int statusErrorCode: 0
|
||||
property bool isUpdating: false
|
||||
property bool isCheckingStatus: false
|
||||
@@ -189,6 +190,27 @@ PageType {
|
||||
})
|
||||
}
|
||||
|
||||
property var telemtPersistedAdditionalHex: []
|
||||
|
||||
function telemtRefreshPersistedAdditionalSecrets() {
|
||||
var list = TelemtConfigModel.additionalSecretsList()
|
||||
var a = []
|
||||
for (var i = 0; i < list.length; ++i) {
|
||||
a.push(String(list[i]))
|
||||
}
|
||||
root.telemtPersistedAdditionalHex = a
|
||||
}
|
||||
|
||||
function telemtIsPersistedAdditionalHex(hex) {
|
||||
var h = String(hex)
|
||||
for (var j = 0; j < root.telemtPersistedAdditionalHex.length; ++j) {
|
||||
if (String(root.telemtPersistedAdditionalHex[j]) === h) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function statusText() {
|
||||
if (isCheckingStatus) {
|
||||
return qsTr("Checking...")
|
||||
@@ -220,6 +242,10 @@ PageType {
|
||||
root.savedTlsDomain = TelemtConfigModel.getTlsDomain()
|
||||
root.savedPublicHost = TelemtConfigModel.getPublicHost()
|
||||
|
||||
Qt.callLater(function () {
|
||||
root.telemtRefreshPersistedAdditionalSecrets()
|
||||
})
|
||||
|
||||
Qt.callLater(root.telemtOnPageShown)
|
||||
}
|
||||
|
||||
@@ -277,6 +303,7 @@ PageType {
|
||||
root.savedTransportMode = TelemtConfigModel.getTransportMode()
|
||||
root.savedTlsDomain = TelemtConfigModel.getTlsDomain()
|
||||
root.savedPublicHost = TelemtConfigModel.getPublicHost()
|
||||
root.telemtRefreshPersistedAdditionalSecrets()
|
||||
PageController.showNotificationMessage(message)
|
||||
if (closePage) {
|
||||
PageController.closePage()
|
||||
@@ -821,6 +848,7 @@ PageType {
|
||||
reuseItems: false
|
||||
|
||||
delegate: ColumnLayout {
|
||||
id: settingsRoot
|
||||
width: settingsListView.width
|
||||
spacing: 0
|
||||
|
||||
@@ -831,6 +859,18 @@ PageType {
|
||||
root.savedTlsDomain, TelemtConfigModel.defaultTlsDomain())
|
||||
}
|
||||
|
||||
function telemtEffectiveHostForLinks() {
|
||||
return root.savedPublicHost !== "" ? root.savedPublicHost : ServersUiController.serverHostName(ServersUiController.processedServerId)
|
||||
}
|
||||
|
||||
function telemtTmeLinkForAdditional(baseHex) {
|
||||
return "https://t.me/proxy?server=" + telemtEffectiveHostForLinks() + "&port=" + port + "&secret=" + telemtActiveSecretForBaseHex(baseHex)
|
||||
}
|
||||
|
||||
function telemtTgLinkForAdditional(baseHex) {
|
||||
return "tg://proxy?server=" + telemtEffectiveHostForLinks() + "&port=" + port + "&secret=" + telemtActiveSecretForBaseHex(baseHex)
|
||||
}
|
||||
|
||||
SwitcherType {
|
||||
id: enableTelemtSwitch
|
||||
Layout.fillWidth: true
|
||||
@@ -1046,6 +1086,17 @@ PageType {
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.bottomMargin: 8
|
||||
text: qsTr("The promoted channel is set in @MTProxyBot. Paste the proxy tag here: exactly 32 hexadecimal characters (0-9, A-F), as in the bot message — or leave empty.")
|
||||
color: AmneziaStyle.color.mutedGray
|
||||
font.pixelSize: 12
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: tagTextField
|
||||
enabled: fieldsEditable
|
||||
@@ -1275,41 +1326,224 @@ PageType {
|
||||
|
||||
Repeater {
|
||||
model: additionalSecrets
|
||||
delegate: RowLayout {
|
||||
delegate: ColumnLayout {
|
||||
id: addSecretDelegate
|
||||
property bool linksExpanded: false
|
||||
readonly property bool linksPanelAllowed: root.telemtIsPersistedAdditionalHex(modelData)
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.bottomMargin: 4
|
||||
Layout.bottomMargin: 8
|
||||
spacing: 0
|
||||
|
||||
onLinksPanelAllowedChanged: {
|
||||
if (!linksPanelAllowed) {
|
||||
linksExpanded = false
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: collapsedBar.implicitHeight + 16
|
||||
color: AmneziaStyle.color.onyxBlack
|
||||
radius: 8
|
||||
border.color: AmneziaStyle.color.slateGray
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
id: collapsedBar
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: 12
|
||||
anchors.rightMargin: 8
|
||||
spacing: 8
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: Math.max(hexCaption.implicitHeight, 24)
|
||||
|
||||
RowLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 8
|
||||
|
||||
CaptionTextType {
|
||||
id: hexCaption
|
||||
Layout.fillWidth: true
|
||||
text: modelData
|
||||
color: AmneziaStyle.color.paleGray
|
||||
elide: Text.ElideMiddle
|
||||
font.pixelSize: 13
|
||||
}
|
||||
ImageButtonType {
|
||||
implicitWidth: 32
|
||||
implicitHeight: 32
|
||||
hoverEnabled: true
|
||||
image: "qrc:/images/controls/copy.svg"
|
||||
imageColor: AmneziaStyle.color.mutedGray
|
||||
onClicked: { GC.copyToClipBoard(modelData)
|
||||
PageController.showNotificationMessage(qsTr("Copied")) }
|
||||
|
||||
Image {
|
||||
width: 24
|
||||
height: 24
|
||||
visible: addSecretDelegate.linksPanelAllowed
|
||||
source: "qrc:/images/controls/chevron-down.svg"
|
||||
sourceSize.width: 24
|
||||
sourceSize.height: 24
|
||||
rotation: addSecretDelegate.linksExpanded ? 180 : 0
|
||||
Behavior on rotation {
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
visible: addSecretDelegate.linksPanelAllowed
|
||||
enabled: addSecretDelegate.linksPanelAllowed
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: addSecretDelegate.linksExpanded = !addSecretDelegate.linksExpanded
|
||||
}
|
||||
}
|
||||
|
||||
ImageButtonType {
|
||||
implicitWidth: 32
|
||||
implicitHeight: 32
|
||||
hoverEnabled: true
|
||||
visible: ServersUiController.isProcessedServerHasWriteAccess()
|
||||
image: "qrc:/images/controls/trash.svg"
|
||||
imageColor: AmneziaStyle.color.vibrantRed
|
||||
onClicked: {
|
||||
TelemtConfigModel.removeAdditionalSecret(index)
|
||||
if (containerStatus === 1) {
|
||||
root.telemtScheduleUpdate(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 8
|
||||
spacing: 8
|
||||
visible: addSecretDelegate.linksPanelAllowed && addSecretDelegate.linksExpanded
|
||||
|
||||
CaptionTextType {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Use Telegram connection link")
|
||||
color: AmneziaStyle.color.mutedGray
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: expTmeRow.implicitHeight + 16
|
||||
color: AmneziaStyle.color.onyxBlack
|
||||
radius: 8
|
||||
border.color: AmneziaStyle.color.slateGray
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
id: expTmeRow
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: 12
|
||||
anchors.rightMargin: 8
|
||||
spacing: 4
|
||||
|
||||
CaptionTextType {
|
||||
Layout.fillWidth: true
|
||||
text: settingsRoot.telemtTmeLinkForAdditional(modelData)
|
||||
color: AmneziaStyle.color.goldenApricot
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
font.pixelSize: 13
|
||||
}
|
||||
|
||||
ImageButtonType {
|
||||
implicitWidth: 36
|
||||
implicitHeight: 36
|
||||
hoverEnabled: true
|
||||
image: "qrc:/images/controls/qr-code.svg"
|
||||
imageColor: AmneziaStyle.color.paleGray
|
||||
onClicked: {
|
||||
ExportController.generateQrFromString(settingsRoot.telemtTmeLinkForAdditional(modelData))
|
||||
PageController.goToShareConnectionPage(
|
||||
qsTr("Telegram connection link"),
|
||||
qsTr("Telemt connection link"),
|
||||
"", "", "")
|
||||
}
|
||||
}
|
||||
|
||||
ImageButtonType {
|
||||
implicitWidth: 36
|
||||
implicitHeight: 36
|
||||
hoverEnabled: true
|
||||
image: "qrc:/images/controls/copy.svg"
|
||||
imageColor: AmneziaStyle.color.paleGray
|
||||
onClicked: {
|
||||
GC.copyToClipBoard(settingsRoot.telemtTmeLinkForAdditional(modelData))
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: expTgRow.implicitHeight + 16
|
||||
color: AmneziaStyle.color.onyxBlack
|
||||
radius: 8
|
||||
border.color: AmneziaStyle.color.slateGray
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
id: expTgRow
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: 12
|
||||
anchors.rightMargin: 8
|
||||
spacing: 4
|
||||
|
||||
CaptionTextType {
|
||||
Layout.fillWidth: true
|
||||
text: settingsRoot.telemtTgLinkForAdditional(modelData)
|
||||
color: AmneziaStyle.color.goldenApricot
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
font.pixelSize: 13
|
||||
}
|
||||
|
||||
ImageButtonType {
|
||||
implicitWidth: 36
|
||||
implicitHeight: 36
|
||||
hoverEnabled: true
|
||||
image: "qrc:/images/controls/qr-code.svg"
|
||||
imageColor: AmneziaStyle.color.paleGray
|
||||
onClicked: {
|
||||
ExportController.generateQrFromString(settingsRoot.telemtTgLinkForAdditional(modelData))
|
||||
PageController.goToShareConnectionPage(
|
||||
qsTr("Telegram connection link"),
|
||||
qsTr("Telemt connection link"),
|
||||
"", "", "")
|
||||
}
|
||||
}
|
||||
|
||||
ImageButtonType {
|
||||
implicitWidth: 36
|
||||
implicitHeight: 36
|
||||
hoverEnabled: true
|
||||
image: "qrc:/images/controls/copy.svg"
|
||||
imageColor: AmneziaStyle.color.paleGray
|
||||
onClicked: {
|
||||
GC.copyToClipBoard(settingsRoot.telemtTgLinkForAdditional(modelData))
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
@@ -1321,7 +1555,6 @@ PageType {
|
||||
text: qsTr("Add additional secret")
|
||||
clickedFunc: function () {
|
||||
TelemtConfigModel.addAdditionalSecret()
|
||||
root.telemtScheduleUpdate(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1677,18 +1910,66 @@ PageType {
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
visible: ServersUiController.isProcessedServerHasWriteAccess()
|
||||
enabled: fieldsEditable
|
||||
enabled: fieldsEditable && !root.telemtNetworkBlocked
|
||||
text: qsTr("Save")
|
||||
clickedFunc: function () {
|
||||
if (root.telemtNetworkBlocked) {
|
||||
PageController.showErrorMessage(qsTr("No internet connection. Connect to the internet to change Telemt settings."))
|
||||
return
|
||||
}
|
||||
publicHostTextField.errorText = ""
|
||||
tagTextField.errorText = ""
|
||||
tlsDomainTextField.errorText = ""
|
||||
natInternalIpTextField.errorText = ""
|
||||
natExternalIpTextField.errorText = ""
|
||||
portTextField.errorText = ""
|
||||
|
||||
var portValue = portTextField.textField.text === ""
|
||||
? TelemtConfigModel.defaultPort()
|
||||
: portTextField.textField.text
|
||||
|
||||
var errorLines = []
|
||||
var bullet = "- "
|
||||
if (!portTextField.textField.acceptableInput && portTextField.textField.text !== "") {
|
||||
portTextField.errorText = qsTr("The port must be in the range of 1 to 65535")
|
||||
var portErr = qsTr("The port must be in the range of 1 to 65535")
|
||||
portTextField.errorText = portErr
|
||||
errorLines.push(bullet + portErr)
|
||||
}
|
||||
if (!TelemtConfigModel.isValidPublicHost(publicHostTextField.textField.text)) {
|
||||
var hostErr = qsTr("Enter a valid IP address or domain name")
|
||||
publicHostTextField.errorText = hostErr
|
||||
errorLines.push(bullet + hostErr)
|
||||
}
|
||||
var tagNormalized = TelemtConfigModel.sanitizeMtProxyTagFieldText(tagTextField.textField.text)
|
||||
tagTextField.textField.text = tagNormalized
|
||||
if (!TelemtConfigModel.isValidMtProxyTag(tagNormalized)) {
|
||||
var tagErr = qsTr("Proxy tag must be exactly 32 hexadecimal characters (0-9, A-F), or leave empty.")
|
||||
tagTextField.errorText = tagErr
|
||||
errorLines.push(bullet + tagErr)
|
||||
}
|
||||
var domainValueForSave = tlsDomainTextField.textField.text === ""
|
||||
? TelemtConfigModel.defaultTlsDomain()
|
||||
: tlsDomainTextField.textField.text
|
||||
if (!TelemtConfigModel.isValidFakeTlsDomain(domainValueForSave)) {
|
||||
var tlsErr = qsTr("Enter a valid domain name")
|
||||
tlsDomainTextField.errorText = tlsErr
|
||||
errorLines.push(bullet + tlsErr)
|
||||
}
|
||||
var natIpErr = qsTr("Enter a valid IPv4 address")
|
||||
if (!TelemtConfigModel.isValidOptionalIpv4(natInternalIpTextField.textField.text)) {
|
||||
natInternalIpTextField.errorText = natIpErr
|
||||
errorLines.push(bullet + qsTr("NAT internal IP: enter a valid IPv4 address"))
|
||||
}
|
||||
if (!TelemtConfigModel.isValidOptionalIpv4(natExternalIpTextField.textField.text)) {
|
||||
natExternalIpTextField.errorText = natIpErr
|
||||
errorLines.push(bullet + qsTr("NAT external IP: enter a valid IPv4 address"))
|
||||
}
|
||||
if (errorLines.length > 0) {
|
||||
PageController.showErrorMessage(errorLines.join("\n"))
|
||||
return
|
||||
}
|
||||
TelemtConfigModel.setPort(portValue)
|
||||
TelemtConfigModel.setTag(tagTextField.textField.text)
|
||||
TelemtConfigModel.setTag(tagNormalized)
|
||||
TelemtConfigModel.setPublicHost(publicHostTextField.textField.text)
|
||||
TelemtConfigModel.setTransportMode(transportMode)
|
||||
var domainValue = tlsDomainTextField.textField.text === ""
|
||||
|
||||
Reference in New Issue
Block a user