support api for proxy provider [beta] [appcenter] [notarize]

This commit is contained in:
yicheng 2019-12-14 17:52:44 +08:00
parent e1ce6b35db
commit 969124d9e7
9 changed files with 146 additions and 29 deletions

View File

@ -64,6 +64,8 @@
F935B2F42307CD32009E4D33 /* ProxyConfigHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = F935B2F32307CD32009E4D33 /* ProxyConfigHelper.m */; };
F935B2FA23083EE6009E4D33 /* ProxySettingTool.m in Sources */ = {isa = PBXBuildFile; fileRef = F935B2F923083EE6009E4D33 /* ProxySettingTool.m */; };
F935B2FC23085515009E4D33 /* SystemProxyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F935B2FB23085515009E4D33 /* SystemProxyManager.swift */; };
F939724C23A4B33500FE5A3F /* ClashProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F939724B23A4B33500FE5A3F /* ClashProvider.swift */; };
F939724E23A4DB0600FE5A3F /* DateFormatter+.swift in Sources */ = {isa = PBXBuildFile; fileRef = F939724D23A4DB0600FE5A3F /* DateFormatter+.swift */; };
F976275C23634DF8000EDEFE /* LoginServiceKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = F976275B23634DF8000EDEFE /* LoginServiceKit.swift */; };
F977FAAC2366790500C17F1F /* AutoUpgardeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F977FAAB2366790500C17F1F /* AutoUpgardeManager.swift */; };
F977FAAE23669D6400C17F1F /* ConnectionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F977FAAD23669D6400C17F1F /* ConnectionManager.swift */; };
@ -181,6 +183,8 @@
F935B2F823083EE6009E4D33 /* ProxySettingTool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProxySettingTool.h; sourceTree = "<group>"; };
F935B2F923083EE6009E4D33 /* ProxySettingTool.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ProxySettingTool.m; sourceTree = "<group>"; };
F935B2FB23085515009E4D33 /* SystemProxyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemProxyManager.swift; sourceTree = "<group>"; };
F939724B23A4B33500FE5A3F /* ClashProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClashProvider.swift; sourceTree = "<group>"; };
F939724D23A4DB0600FE5A3F /* DateFormatter+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter+.swift"; sourceTree = "<group>"; };
F976275B23634DF8000EDEFE /* LoginServiceKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginServiceKit.swift; sourceTree = "<group>"; };
F977FAAB2366790500C17F1F /* AutoUpgardeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoUpgardeManager.swift; sourceTree = "<group>"; };
F977FAAD23669D6400C17F1F /* ConnectionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionManager.swift; sourceTree = "<group>"; };
@ -232,6 +236,7 @@
F92D0B29236C759100575E15 /* NSTextField+Vibrancy.swift */,
F9E754D1239CC28D00CEE7CC /* NSAlert+Extension.swift */,
F9E8F34523A12B89002DE5E8 /* String+Encode.swift */,
F939724D23A4DB0600FE5A3F /* DateFormatter+.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -281,6 +286,7 @@
499A485722ED715200F6C675 /* RemoteConfigModel.swift */,
F915A4612366ADEF004840BE /* ClashConnection.swift */,
F92D0B23236BC12000575E15 /* SavedProxyModel.swift */,
F939724B23A4B33500FE5A3F /* ClashProvider.swift */,
);
path = Models;
sourceTree = "<group>";
@ -620,6 +626,7 @@
4952C3D02117027C004A4FA8 /* ConfigFileManager.swift in Sources */,
49BC061C212931F4005A0FE7 /* AboutViewController.swift in Sources */,
4949D154213242F600EF85E6 /* Paths.swift in Sources */,
F939724E23A4DB0600FE5A3F /* DateFormatter+.swift in Sources */,
F915A4622366ADEF004840BE /* ClashConnection.swift in Sources */,
F977FAAE23669D6400C17F1F /* ConnectionManager.swift in Sources */,
495340B320DE68C300B0D3FF /* StatusItemView.swift in Sources */,
@ -660,6 +667,7 @@
4960A6DB2136529200B940C9 /* JSBridgeHandler.swift in Sources */,
493AEAE5221AE7230016FE98 /* ProxyMenuItem.swift in Sources */,
499A485E22ED9B7C00F6C675 /* NSTableView+Reload.swift in Sources */,
F939724C23A4B33500FE5A3F /* ClashProvider.swift in Sources */,
49862FA0218418C600A1D5EC /* ClashRule.swift in Sources */,
49C9EF64223E78F5005D8B6A /* ClashProxy.swift in Sources */,
F9E8F34623A12B89002DE5E8 /* String+Encode.swift in Sources */,

View File

@ -546,10 +546,16 @@ extension AppDelegate {
extension AppDelegate {
func registCrashLogger() {
#if DEBUG
return
#endif
Fabric.with([Crashlytics.self])
}
func failLaunchProtect() {
#if DEBUG
return
#endif
let x = UserDefaults.standard
var launch_fail_times: Int = 0
if let xx = x.object(forKey: "launch_fail_times") as? Int { launch_fail_times = xx }

View File

@ -0,0 +1,18 @@
//
// DateFormatter+.swift
// ClashX
//
// Created by Etan Chen on 2019/12/14.
// Copyright © 2019 west2online. All rights reserved.
//
import Cocoa
extension DateFormatter {
static var js: DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: NSCalendar.Identifier.ISO8601.rawValue)
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SZ"
return dateFormatter
}
}

View File

@ -166,6 +166,13 @@ class ApiRequest {
ApiRequest.shared.proxyRespCache = proxies
}
static func requestProxyProviderList(completeHandler: ((ClashProviderResp) -> Void)? = nil) {
req("/providers/proxies").responseData { res in
let provider = ClashProviderResp.create(try? res.result.get())
completeHandler?(provider)
}
}
static func updateAllowLan(allow: Bool, completeHandler: (() -> Void)? = nil) {
req("/configs",
method: .patch,

View File

@ -17,26 +17,31 @@ class MenuItemFactory {
return
}
ApiRequest.requestProxyGroupList() {
proxyInfo in
var menuItems = [NSMenuItem]()
ApiRequest.requestProxyProviderList() {
proxyprovider in
for proxy in proxyInfo.proxyGroups {
var menu: NSMenuItem?
switch proxy.type {
case .select: menu = self.generateSelectorMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
case .urltest, .fallback: menu = generateUrlTestFallBackMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
case .loadBalance:
menu = generateLoadBalanceMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
default: continue
}
ApiRequest.requestProxyGroupList() {
proxyInfo in
proxyInfo.updateProvider(proxyprovider)
if let menu = menu {
menuItems.append(menu)
menu.isEnabled = true
var menuItems = [NSMenuItem]()
for proxy in proxyInfo.proxyGroups {
var menu: NSMenuItem?
switch proxy.type {
case .select: menu = self.generateSelectorMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
case .urltest, .fallback: menu = generateUrlTestFallBackMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
case .loadBalance:
menu = generateLoadBalanceMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
default: continue
}
if let menu = menu {
menuItems.append(menu)
menu.isEnabled = true
}
}
completionHandler(menuItems.reversed())
}
completionHandler(menuItems.reversed())
}
}
@ -152,6 +157,21 @@ class MenuItemFactory {
return menu
}
static func generateProviderMenuItems(_ provider: ClashProvider) -> NSMenuItem? {
let menu = NSMenuItem(title: provider.name, action: nil, keyEquivalent: "")
let submenu = NSMenu(title: provider.name)
for proxy in provider.proxies {
let proxyMenuItem = NSMenuItem(title: proxy.name, action: #selector(empty), keyEquivalent: "")
proxyMenuItem.target = MenuItemFactory.self
proxyMenuItem.submenu = generateHistoryMenu(proxy)
submenu.addItem(proxyMenuItem)
}
menu.submenu = submenu
return menu
}
static func generateSwitchConfigMenuItems() -> [NSMenuItem] {
var items = [NSMenuItem]()
for config in ConfigManager.getConfigFilesList() {

View File

@ -0,0 +1,50 @@
//
// ClashProvider.swift
// ClashX
//
// Created by yichengchen on 2019/12/14.
// Copyright © 2019 west2online. All rights reserved.
//
import Cocoa
class ClashProviderResp: Codable {
let allProviders: [ClashProxyName: ClashProvider]
lazy var providers: [ClashProxyName: ClashProvider] = {
return allProviders.filter({ $0.value.vehicleType != .Compatible })
}()
private init() {
allProviders = [:]
}
static func create(_ data: Data?) -> ClashProviderResp {
guard let data = data else { return ClashProviderResp() }
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(DateFormatter.js)
return (try? decoder.decode(ClashProviderResp.self, from: data)) ?? ClashProviderResp()
}
private enum CodingKeys: String, CodingKey {
case allProviders = "providers"
}
}
class ClashProvider: Codable {
enum ProviderType: String, Codable {
case Proxy
case String
}
enum ProviderVehicleType: String, Codable {
case HTTP
case File
case Compatible
case Unknown
}
let name: String
let proxies: [ClashProxy]
let type: ProviderType
let vehicleType: ProviderVehicleType
}

View File

@ -67,11 +67,12 @@ class ClashProxySpeedHistory: Codable {
}
class ClashProxy: Codable {
var name: ClashProxyName = ""
let name: ClashProxyName
let type: ClashProxyType
let all: [ClashProxyName]?
let history: [ClashProxySpeedHistory]
let now: ClashProxyName?
var providerProxy = false
weak var enclosingResp: ClashProxyResp? = nil
lazy var speedtestAble: [ClashProxyName] = {
@ -79,14 +80,16 @@ class ClashProxy: Codable {
var proxys = [ClashProxyName]()
for proxy in allProxys {
if let p = resp.proxiesMap[proxy], !ClashProxyType.isProxyGroup(p) {
proxys.append(proxy)
if !p.providerProxy {
proxys.append(proxy)
}
}
}
return proxys
}()
private enum CodingKeys: String, CodingKey {
case type, all, history, now
case type, all, history, now, name
}
lazy var maxProxyName: String = {
@ -105,7 +108,7 @@ class ClashProxy: Codable {
class ClashProxyResp {
let proxies: [ClashProxy]
let proxiesMap: [ClashProxyName: ClashProxy]
var proxiesMap: [ClashProxyName: ClashProxy]
init(_ data: Any?) {
guard
@ -122,18 +125,14 @@ class ClashProxyResp {
var proxiesMap = [ClashProxyName: ClashProxy]()
let decoder = JSONDecoder()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: NSCalendar.Identifier.ISO8601.rawValue)
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SZ"
decoder.dateDecodingStrategy = .formatted(dateFormatter)
for (key, value) in proxies {
decoder.dateDecodingStrategy = .formatted(DateFormatter.js)
for value in proxies.values {
guard let data = try? JSONSerialization.data(withJSONObject: value, options: .prettyPrinted) else {
continue
}
guard let proxy = try? decoder.decode(ClashProxy.self, from: data) else {
continue
}
proxy.name = key
proxiesModel.append(proxy)
proxiesMap[proxy.name] = proxy
}
@ -145,6 +144,15 @@ class ClashProxyResp {
}
}
func updateProvider(_ providerResp: ClashProviderResp) {
for provider in providerResp.providers.values {
for proxy in provider.proxies {
proxy.providerProxy = true
proxiesMap[proxy.name] = proxy
}
}
}
lazy var proxiesSortMap: [ClashProxyName: Int] = {
var map = [ClashProxyName: Int]()
for (idx, proxy) in (self.proxiesMap["GLOBAL"]?.all ?? []).enumerated() {

View File

@ -1,7 +1,7 @@
module github.com/yichengchen/clashX/ClashX
require (
github.com/Dreamacro/clash v0.16.1-0.20191212162924-0822b526d5d8
github.com/Dreamacro/clash v0.16.1-0.20191214101333-eae06a4a7d3e
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
)

View File

@ -1,5 +1,5 @@
github.com/Dreamacro/clash v0.16.1-0.20191212162924-0822b526d5d8 h1:GeVCWlqa0YfzWDFAzTRKfhGqL8WolYmY5fHDY1xwUfI=
github.com/Dreamacro/clash v0.16.1-0.20191212162924-0822b526d5d8/go.mod h1:3AN6ikXSGG+ZHpQQMirTGu8t3tokzyLU/NUXb5QYZ9Q=
github.com/Dreamacro/clash v0.16.1-0.20191214101333-eae06a4a7d3e h1:W3sFYmxO8s77tkcLnHQTrVmhWZXohOrEU1Bvxb+HgoE=
github.com/Dreamacro/clash v0.16.1-0.20191214101333-eae06a4a7d3e/go.mod h1:3AN6ikXSGG+ZHpQQMirTGu8t3tokzyLU/NUXb5QYZ9Q=
github.com/Dreamacro/go-shadowsocks2 v0.1.5 h1:BizWSjmwzAyQoslz6YhJYMiAGT99j9cnm9zlxVr+kyI=
github.com/Dreamacro/go-shadowsocks2 v0.1.5/go.mod h1:LSXCjyHesPY3pLjhwff1mQX72ItcBT/N2xNC685cYeU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=