|
|
|
@ -1,10 +1,10 @@
|
|
|
|
|
import SwiftCSV
|
|
|
|
|
//import SwiftCSV
|
|
|
|
|
|
|
|
|
|
final class IP2Country {
|
|
|
|
|
var countryNamesCache: [String:String] = [:]
|
|
|
|
|
|
|
|
|
|
private lazy var ipv4Table = try! CSV(name: "GeoLite2-Country-Blocks-IPv4", extension: "csv", bundle: .main, delimiter: ",", encoding: .utf8, loadColumns: true)!
|
|
|
|
|
private lazy var countryNamesTable = try! CSV(name: "GeoLite2-Country-Locations-English", extension: "csv", bundle: .main, delimiter: ",", encoding: .utf8, loadColumns: true)!
|
|
|
|
|
// private lazy var ipv4Table = try! CSV(name: "GeoLite2-Country-Blocks-IPv4", extension: "csv", bundle: .main, delimiter: ",", encoding: .utf8, loadColumns: true)!
|
|
|
|
|
// private lazy var countryNamesTable = try! CSV(name: "GeoLite2-Country-Locations-English", extension: "csv", bundle: .main, delimiter: ",", encoding: .utf8, loadColumns: true)!
|
|
|
|
|
|
|
|
|
|
private static let workQueue = DispatchQueue(label: "IP2Country.workQueue", qos: .utility) // It's important that this is a serial queue
|
|
|
|
|
|
|
|
|
@ -25,22 +25,23 @@ final class IP2Country {
|
|
|
|
|
private func cacheCountry(for ip: String) -> String {
|
|
|
|
|
var truncatedIP = ip
|
|
|
|
|
func getCountryInternal() -> String {
|
|
|
|
|
if let country = countryNamesCache[ip] { return country }
|
|
|
|
|
if let ipv4TableIndex = ipv4Table.namedColumns["network"]!.firstIndex(where: { $0.starts(with: truncatedIP) }) {
|
|
|
|
|
let countryID = ipv4Table.namedColumns["registered_country_geoname_id"]![ipv4TableIndex]
|
|
|
|
|
if let countryNamesTableIndex = countryNamesTable.namedColumns["geoname_id"]!.firstIndex(of: countryID) {
|
|
|
|
|
let country = countryNamesTable.namedColumns["country_name"]![countryNamesTableIndex]
|
|
|
|
|
countryNamesCache[ip] = country
|
|
|
|
|
return country
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if truncatedIP.contains(".") && !truncatedIP.hasSuffix(".") { // The fuzziest we want to go is xxx.x
|
|
|
|
|
truncatedIP.removeLast()
|
|
|
|
|
if truncatedIP.hasSuffix(".") { truncatedIP.removeLast() }
|
|
|
|
|
return getCountryInternal()
|
|
|
|
|
} else {
|
|
|
|
|
return "Unknown Country"
|
|
|
|
|
}
|
|
|
|
|
return "Mars"
|
|
|
|
|
// if let country = countryNamesCache[ip] { return country }
|
|
|
|
|
// if let ipv4TableIndex = ipv4Table.namedColumns["network"]!.firstIndex(where: { $0.starts(with: truncatedIP) }) {
|
|
|
|
|
// let countryID = ipv4Table.namedColumns["registered_country_geoname_id"]![ipv4TableIndex]
|
|
|
|
|
// if let countryNamesTableIndex = countryNamesTable.namedColumns["geoname_id"]!.firstIndex(of: countryID) {
|
|
|
|
|
// let country = countryNamesTable.namedColumns["country_name"]![countryNamesTableIndex]
|
|
|
|
|
// countryNamesCache[ip] = country
|
|
|
|
|
// return country
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// if truncatedIP.contains(".") && !truncatedIP.hasSuffix(".") { // The fuzziest we want to go is xxx.x
|
|
|
|
|
// truncatedIP.removeLast()
|
|
|
|
|
// if truncatedIP.hasSuffix(".") { truncatedIP.removeLast() }
|
|
|
|
|
// return getCountryInternal()
|
|
|
|
|
// } else {
|
|
|
|
|
// return "Unknown Country"
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
return getCountryInternal()
|
|
|
|
|
}
|
|
|
|
|