ClashX.Meta/ClashX/General/Managers/ConfigFileManager.swift

146 lines
4.7 KiB
Swift
Raw Normal View History

//
// ConfigFileFactory.swift
// ClashX
//
// Created by CYC on 2018/8/5.
2018-08-08 13:47:38 +08:00
// Copyright © 2018 yichengchen. All rights reserved.
//
import Foundation
import AppKit
import SwiftyJSON
2018-10-07 21:03:16 +08:00
import Yams
2018-12-09 22:00:15 +08:00
class ConfigFileManager {
static let shared = ConfigFileManager()
var witness:Witness?
func watchConfigFile(configName:String) {
let path = "\(kConfigFolderPath)/\(configName).yml"
witness = Witness(paths: [path], flags: .FileEvents, latency: 0.3) { events in
2018-08-19 11:14:16 +08:00
for event in events {
if event.flags.contains(.ItemModified) || event.flags.contains(.ItemCreated){
NSUserNotificationCenter.default
.postConfigFileChangeDetectionNotice()
NotificationCenter.default
.post(Notification(name: kConfigFileChange))
2018-08-19 11:14:16 +08:00
break
}
}
}
}
2018-10-14 22:48:51 +08:00
static func saveToClashConfigFile(config:[String:Any]) {
// save to ~/.config/clash/config.yml
2018-09-22 17:18:25 +08:00
_ = self.backupAndRemoveConfigFile(showAlert: false)
var config = config
var finalConfigString = ""
do {
if let proxyConfig = config["Proxy"] {
finalConfigString += try
Yams.dump(object: ["Proxy":proxyConfig],allowUnicode:true)
config["Proxy"] = nil
}
if let proxyGroupConfig = config["Proxy Group"] {
finalConfigString += try
Yams.dump(object: ["Proxy Group":proxyGroupConfig]
,allowUnicode:true)
config["Proxy Group"] = nil
}
if let rule = config["Rule"] {
finalConfigString += try
Yams.dump(object: ["Rule":rule],allowUnicode:true)
config["Rule"] = nil
}
finalConfigString = try Yams.dump(object: config,allowUnicode:true) + finalConfigString
2018-12-09 22:00:15 +08:00
try finalConfigString.write(toFile: kDefaultConfigFilePath, atomically: true, encoding: .utf8)
} catch {
return
}
}
2018-09-27 23:07:05 +08:00
@discardableResult
static func backupAndRemoveConfigFile(showAlert:Bool = false) -> Bool {
2018-12-09 22:00:15 +08:00
let path = kDefaultConfigFilePath
2018-10-14 23:42:53 +08:00
if (FileManager.default.fileExists(atPath: path)) {
2018-10-14 23:42:53 +08:00
if (showAlert) {
if !self.showReplacingConfigFileAlert() {return false}
}
2018-10-14 22:48:51 +08:00
let newPath = "\(kConfigFolderPath)config_\(Date().timeIntervalSince1970).yml"
try? FileManager.default.moveItem(atPath: path, toPath: newPath)
}
return true
}
2018-10-14 22:48:51 +08:00
static func copySampleConfigIfNeed() {
2018-12-09 22:00:15 +08:00
if !FileManager.default.fileExists(atPath: kDefaultConfigFilePath) {
2018-10-14 23:42:53 +08:00
_ = replaceConfigWithSampleConfig()
2018-10-14 22:48:51 +08:00
}
}
static func replaceConfigWithSampleConfig() -> Bool {
if (!backupAndRemoveConfigFile(showAlert: true)) {
return false
}
2018-10-14 22:48:51 +08:00
let path = Bundle.main.path(forResource: "sampleConfig", ofType: "yml")!
2018-12-09 22:00:15 +08:00
try? FileManager.default.copyItem(atPath: path, toPath: kDefaultConfigFilePath)
NSUserNotificationCenter.default.postGenerateSimpleConfigNotice()
return true
}
2018-10-07 21:03:16 +08:00
}
2018-12-09 22:00:15 +08:00
extension ConfigFileManager {
2018-10-27 12:22:45 +08:00
static func checkFinalRuleAndShowAlert() {
ApiRequest.getRules() {
rules in
let hasFinal = rules.reversed().contains(){$0.type == "MATCH"}
2018-10-27 12:22:45 +08:00
if !hasFinal {
showNoFinalRuleAlert()
}
}
}
2018-10-07 21:03:16 +08:00
}
2018-12-09 22:00:15 +08:00
extension ConfigFileManager {
static func showReplacingConfigFileAlert() -> Bool{
let alert = NSAlert()
alert.messageText = """
2018-10-02 12:20:18 +08:00
Can't recognize your config file. We will backup and replace your config file in your config folder.
Otherwise the functions of ClashX will not work properly. You may need to restart ClashX or reload Config manually.
"""
alert.alertStyle = .warning
alert.addButton(withTitle: "Replace")
alert.addButton(withTitle: "Cancel")
return alert.runModal() == .alertFirstButtonReturn
}
2018-10-07 21:03:16 +08:00
2018-10-27 12:22:45 +08:00
static func showNoFinalRuleAlert() {
let alert = NSAlert()
alert.messageText = """
No FINAL rule were found in clash configs,This might caused by incorrect upgradation during earily version of clashX or error setting of FINAL rule.Please check your config file.
NO FINAL rule would cause traffic send to DIRECT which no match any rules.
""".localized()
alert.alertStyle = .warning
alert.addButton(withTitle: "OK")
alert.runModal()
}
}