2018-08-05 18:34:12 +08:00
//
// C o n f i g F i l e F a c t o r y . s w i f t
// C l a s h X
//
// C r e a t e d b y C Y C o n 2 0 1 8 / 8 / 5 .
2018-08-08 13:47:38 +08:00
// C o p y r i g h t © 2 0 1 8 年 y i c h e n g c h e n . A l l r i g h t s r e s e r v e d .
2018-08-05 18:34:12 +08:00
//
import Foundation
2018-08-05 23:16:58 +08:00
import AppKit
2018-08-06 14:17:04 +08:00
import SwiftyJSON
2018-10-07 21:03:16 +08:00
import Yams
2018-08-05 18:34:12 +08:00
2018-12-09 22:00:15 +08:00
class ConfigFileManager {
static let shared = ConfigFileManager ( )
2019-07-29 19:01:07 +08:00
private var witness : Witness ?
private var pause = false
func pauseForNextChange ( ) {
pause = true
}
2019-07-28 17:37:59 +08:00
2018-12-09 22:55:01 +08:00
func watchConfigFile ( configName : String ) {
2019-07-28 17:37:59 +08:00
let path = " \( kConfigFolderPath ) \( configName ) .yaml "
2019-07-29 19:01:07 +08:00
witness = Witness ( paths : [ path ] , flags : . FileEvents , latency : 0.3 ) {
[ weak self ] events in
guard let self = self else { return }
guard ! self . pause else {
self . pause = false
return
}
2018-08-19 11:14:16 +08:00
for event in events {
2019-07-28 17:37:59 +08:00
if event . flags . contains ( . ItemModified ) {
2018-12-09 22:55:01 +08:00
NSUserNotificationCenter . default
. postConfigFileChangeDetectionNotice ( )
NotificationCenter . default
. post ( Notification ( name : kConfigFileChange ) )
2018-08-19 11:14:16 +08:00
break
}
}
2018-08-12 00:10:42 +08:00
}
}
2019-07-28 17:37:59 +08:00
2018-09-01 14:19:53 +08:00
2018-09-27 23:07:05 +08:00
@ discardableResult
2018-09-05 19:30:38 +08:00
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
2018-08-05 18:34:12 +08:00
if ( FileManager . default . fileExists ( atPath : path ) ) {
2018-10-14 23:42:53 +08:00
if ( showAlert ) {
if ! self . showReplacingConfigFileAlert ( ) { return false }
}
2019-06-29 18:52:05 +08:00
let newPath = " \( kConfigFolderPath ) config_ \( Date ( ) . timeIntervalSince1970 ) .yaml "
2018-09-01 14:19:53 +08:00
try ? FileManager . default . moveItem ( atPath : path , toPath : newPath )
2018-08-05 18:34:12 +08:00
}
2018-09-05 19:30:38 +08:00
return true
2018-08-05 23:16:58 +08:00
}
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 {
2018-09-05 19:30:38 +08:00
if ( ! backupAndRemoveConfigFile ( showAlert : true ) ) {
2018-09-05 20:19:47 +08:00
return false
2018-09-05 19:30:38 +08:00
}
2019-06-29 18:52:05 +08:00
let path = Bundle . main . path ( forResource : " sampleConfig " , ofType : " yaml " ) !
2018-12-09 22:00:15 +08:00
try ? FileManager . default . copyItem ( atPath : path , toPath : kDefaultConfigFilePath )
2018-08-11 23:07:51 +08:00
NSUserNotificationCenter . default . postGenerateSimpleConfigNotice ( )
2018-09-05 20:19:47 +08:00
return true
2018-08-11 23:07:51 +08:00
}
2018-08-05 23:16:58 +08:00
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
2019-02-19 11:50:23 +08:00
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 {
2018-09-05 19:30:38 +08:00
static func showReplacingConfigFileAlert ( ) -> Bool {
let alert = NSAlert ( )
2019-07-28 12:39:49 +08:00
alert . messageText = NSLocalizedString ( " Can't recognize your config file. We will backup and replace your config file in your config folder. \n \n Otherwise the functions of ClashX will not work properly. You may need to restart ClashX or reload Config manually. " , comment : " " )
2018-09-05 19:30:38 +08:00
alert . alertStyle = . warning
2019-07-28 12:39:49 +08:00
alert . addButton ( withTitle : NSLocalizedString ( " Replace " , comment : " " ) )
alert . addButton ( withTitle : NSLocalizedString ( " Cancel " , comment : " " ) )
2018-09-05 19:30:38 +08:00
return alert . runModal ( ) = = . alertFirstButtonReturn
}
2018-10-07 21:03:16 +08:00
2018-10-19 13:44:37 +08:00
2018-10-27 12:22:45 +08:00
static func showNoFinalRuleAlert ( ) {
let alert = NSAlert ( )
2019-07-28 12:39:49 +08:00
alert . messageText = NSLocalizedString ( " 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. \n \n NO FINAL rule would cause traffic send to DIRECT which no match any rules. " , comment : " " )
2018-10-27 12:22:45 +08:00
alert . alertStyle = . warning
alert . addButton ( withTitle : " OK " )
alert . runModal ( )
}
2018-08-05 18:34:12 +08:00
}