92 lines
3.0 KiB
Swift
92 lines
3.0 KiB
Swift
import Foundation
|
|
|
|
struct QLog {
|
|
private init() {}
|
|
static func m(_ message: String) { write("", message) }
|
|
static func Info(_ message: String) { write("[INFO] ", message) }
|
|
#if DEBUG
|
|
static func Debug(_ message: String) { write("[DEBUG] ", message) }
|
|
#else
|
|
static func Debug(_ _: String) {}
|
|
#endif
|
|
static func Error(_ message: String) { write("[ERROR] ", message) }
|
|
static func Warning(_ message: String) { write("[WARN] ", message) }
|
|
private static func write(_ tag: String, _ message: String) {
|
|
print(String(format: "%1.3f %@%@", Date().timeIntervalSince1970, tag, message))
|
|
}
|
|
}
|
|
|
|
extension Collection {
|
|
subscript(ifExist i: Index?) -> Iterator.Element? {
|
|
guard let i = i else { return nil }
|
|
return indices.contains(i) ? self[i] : nil
|
|
}
|
|
}
|
|
|
|
var listOfSLDs: [String : [String : Bool]] = {
|
|
let path = Bundle.main.url(forResource: "third-level", withExtension: "txt")
|
|
let content = try! String(contentsOf: path!)
|
|
var res: [String : [String : Bool]] = [:]
|
|
content.enumerateLines { line, _ in
|
|
let dom = line.split(separator: ".")
|
|
let tld = String(dom.first!)
|
|
let sld = String(dom.last!)
|
|
if res[tld] == nil { res[tld] = [:] }
|
|
res[tld]![sld] = true
|
|
}
|
|
return res
|
|
}()
|
|
|
|
extension String {
|
|
/// Check if string is equal to `domain` or ends with `.domain`
|
|
func isSubdomain(of domain: String) -> Bool { self == domain || self.hasSuffix("." + domain) }
|
|
/// Split string into top level domain part and host part
|
|
func splitDomainAndHost() -> (domain: String, host: String?) {
|
|
let lastChr = last?.asciiValue ?? 0
|
|
guard lastChr > UInt8(ascii: "9") || lastChr < UInt8(ascii: "0") else { // IP address
|
|
return (domain: "# IP connection", host: self)
|
|
}
|
|
var parts = components(separatedBy: ".")
|
|
guard let tld = parts.popLast(), let sld = parts.popLast() else {
|
|
return (domain: self, host: nil) // no subdomains, just plain SLD
|
|
}
|
|
var ending = sld + "." + tld
|
|
if listOfSLDs[tld]?[sld] ?? false, let rld = parts.popLast() {
|
|
ending = rld + "." + ending
|
|
}
|
|
return (domain: ending, host: parts.joined(separator: "."))
|
|
|
|
// var allDots = enumerated().compactMap { $1 == "." ? $0 : nil }
|
|
// let d1 = allDots.popLast() // we dont care about TLD
|
|
// guard let d2 = allDots.popLast() else {
|
|
// return (domain: self, host: nil) // no subdomains, just plain SLD
|
|
// }
|
|
// // TODO: check third level domains
|
|
//// let d3 = allDots.popLast()
|
|
// return (String(suffix(count - d2 - 1)), String(prefix(d2)))
|
|
}
|
|
}
|
|
|
|
extension Timer {
|
|
@discardableResult static func repeating(_ interval: TimeInterval, call selector: Selector, on target: Any, userInfo: Any? = nil) -> Timer {
|
|
Timer.scheduledTimer(timeInterval: interval, target: target, selector: selector,
|
|
userInfo: userInfo, repeats: true)
|
|
}
|
|
}
|
|
|
|
extension DateFormatter {
|
|
convenience init(withFormat: String) {
|
|
self.init()
|
|
dateFormat = withFormat
|
|
}
|
|
func with(format: String) -> Self {
|
|
dateFormat = format
|
|
return self
|
|
}
|
|
func string(from ts: Timestamp) -> String {
|
|
string(from: Date.init(timeIntervalSince1970: Double(ts)))
|
|
}
|
|
}
|
|
|
|
func TimestampNow() -> Timestamp { Timestamp(Date().timeIntervalSince1970) }
|