In its current state this hackery fits our needs.
Signed-off-by: Adam Rocska <adam.rocska@adams.solutions>
This commit is contained in:
parent
c9bee263df
commit
7b487ccc60
|
@ -6,19 +6,6 @@ sound like to plan for a breaking change befor the first initial version's
|
|||
release, but hey, there's a time pressure on my shoulder right now + MaxMind's
|
||||
"binary format" "desgined" by its script kiddos slowed things down baadly._
|
||||
|
||||
## Replace CIDR Strings with proper intelligence
|
||||
|
||||
[Wikipedia](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing)
|
||||
|
||||
At the time of writing I just had to port the dumbass php style "String
|
||||
representation" of networks. That's bad. That's so bad, that normally I wouldn't
|
||||
permit such a crap in my company.
|
||||
|
||||
What I want is to create a unit (most probably it'll be a struct?) that not only
|
||||
represents the network, but also provides utilities that can check whether an
|
||||
`IpAddress` belongs to that network for example. Should be representable in many
|
||||
different forms, etc.
|
||||
|
||||
## Error handling
|
||||
|
||||
There used to be an original concept of how to do proper error handling &
|
||||
|
@ -42,3 +29,14 @@ bit of fun.
|
|||
|
||||
I'll do my best to massage things out. Once the public API is stable, and neat,
|
||||
the underlying crap can be cleaned up.
|
||||
|
||||
## Redesign the retarded modeling
|
||||
|
||||
At the library's initial stage the decision was to reproduce in a somewhat
|
||||
similar state what MaxMind's php scritpers made with their PHP, Java, and C#
|
||||
libraries.
|
||||
|
||||
That modeling is awful.
|
||||
|
||||
The way the API will return models will definitely change, so there will be a
|
||||
2.0.0 API break at some point.
|
10
README.md
10
README.md
|
@ -1,11 +1 @@
|
|||
# GeoIP2-swift
|
||||
|
||||
**HEAVILY WORK IN PROGRESS.**
|
||||
|
||||
Progress postponed for a few days.
|
||||
In its current state it mostly works, but is unacceptably slow to initialize.
|
||||
The lookup time is fast, but it's an unacceptable speed to initialize.
|
||||
|
||||
Initialization performance problems root mainly from the poor DB design.
|
||||
|
||||
**Will revisit after 8th of July.**
|
||||
|
|
|
@ -6,6 +6,12 @@ public struct CityModel: Equatable {
|
|||
public let location: LocationRecord
|
||||
public let postal: PostalRecord
|
||||
public let subdivisions: [SubdivisionRecord]
|
||||
public let continent: ContinentRecord
|
||||
public let country: CountryRecord
|
||||
public let maxmind: MaxMindRecord
|
||||
public let registeredCountry: CountryRecord
|
||||
public let representedCountry: RepresentedCountryRecord
|
||||
public let traits: TraitsRecord
|
||||
public let ipAddress: IpAddress
|
||||
public let netmask: IpAddress
|
||||
public var mostSpecificSubdivision: SubdivisionRecord { get { return subdivisions.last ?? SubdivisionRecord(nil) } }
|
||||
|
@ -20,6 +26,12 @@ extension CityModel: DictionaryInitialisableModel {
|
|||
subdivisions: (dictionary?["subdivisions"]?.unwrap() ?? [] as [Payload]).compactMap(
|
||||
{ SubdivisionRecord($0.unwrap()) }
|
||||
),
|
||||
continent: ContinentRecord(dictionary?["continent"]?.unwrap()),
|
||||
country: CountryRecord(dictionary?["country"]?.unwrap()),
|
||||
maxmind: MaxMindRecord(dictionary?["maxmind"]?.unwrap()),
|
||||
registeredCountry: CountryRecord(dictionary?["registered_country"]?.unwrap()),
|
||||
representedCountry: RepresentedCountryRecord(dictionary?["represented_country"]?.unwrap()),
|
||||
traits: TraitsRecord(dictionary?["traits"]?.unwrap()),
|
||||
ipAddress: ip,
|
||||
netmask: netmask
|
||||
)
|
||||
|
|
|
@ -1,9 +1,39 @@
|
|||
import Foundation
|
||||
import enum Decoder.Payload
|
||||
|
||||
// TODO : Untangle php scripter retardnes. Theses people at maxmind shouldn't write code that gets executed by a processor. Honestly.
|
||||
// See stupid fucking php scripter stupidity : https://github.com/maxmind/GeoIP2-php/blob/master/src/Model/Enterprise.php
|
||||
// Apparently they are so dumb, they needed 2 people to produce an empty class, with a nonsense API doc'.
|
||||
// Their Java, and C# code is as retaarded as the php one. I never saw throughout my career Java being raped so badly.
|
||||
public struct EnterpriseModel: Equatable {
|
||||
|
||||
public let city: CityRecord
|
||||
public let location: LocationRecord
|
||||
public let postal: PostalRecord
|
||||
public let subdivisions: [SubdivisionRecord]
|
||||
public let continent: ContinentRecord
|
||||
public let country: CountryRecord
|
||||
public let maxmind: MaxMindRecord
|
||||
public let registeredCountry: CountryRecord
|
||||
public let representedCountry: RepresentedCountryRecord
|
||||
public let traits: TraitsRecord
|
||||
public let ipAddress: IpAddress
|
||||
public let netmask: IpAddress
|
||||
public var mostSpecificSubdivision: SubdivisionRecord { get { return subdivisions.last ?? SubdivisionRecord(nil) } }
|
||||
}
|
||||
|
||||
extension EnterpriseModel: DictionaryInitialisableModel {
|
||||
public init(ip: IpAddress, netmask: IpAddress, _ dictionary: [String: Payload]?) {
|
||||
self.init(
|
||||
city: CityRecord(dictionary?["city"]?.unwrap()),
|
||||
location: LocationRecord(dictionary?["location"]?.unwrap()),
|
||||
postal: PostalRecord(dictionary?["postal"]?.unwrap()),
|
||||
subdivisions: (dictionary?["subdivisions"]?.unwrap() ?? [] as [Payload]).compactMap(
|
||||
{ SubdivisionRecord($0.unwrap()) }
|
||||
),
|
||||
continent: ContinentRecord(dictionary?["continent"]?.unwrap()),
|
||||
country: CountryRecord(dictionary?["country"]?.unwrap()),
|
||||
maxmind: MaxMindRecord(dictionary?["maxmind"]?.unwrap()),
|
||||
registeredCountry: CountryRecord(dictionary?["registered_country"]?.unwrap()),
|
||||
representedCountry: RepresentedCountryRecord(dictionary?["represented_country"]?.unwrap()),
|
||||
traits: TraitsRecord(dictionary?["traits"]?.unwrap()),
|
||||
ipAddress: ip,
|
||||
netmask: netmask
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,39 @@
|
|||
import Foundation
|
||||
import enum Decoder.Payload
|
||||
|
||||
// TODO : Untangle php scripter retardnes. Theses people at maxmind shouldn't write code that gets executed by a processor. Honestly.
|
||||
// See stupid fucking php scripter stupidity : https://github.com/maxmind/GeoIP2-php/blob/master/src/Model/Insights.php
|
||||
// Apparently they are so dumb, they needed 2 people to produce an empty class, with a nonsense API doc'.
|
||||
// Their Java, and C# code is as retaarded as the php one. I never saw throughout my career Java being raped so badly.
|
||||
public struct InsightsModel: Equatable {
|
||||
|
||||
public let city: CityRecord
|
||||
public let location: LocationRecord
|
||||
public let postal: PostalRecord
|
||||
public let subdivisions: [SubdivisionRecord]
|
||||
public let continent: ContinentRecord
|
||||
public let country: CountryRecord
|
||||
public let maxmind: MaxMindRecord
|
||||
public let registeredCountry: CountryRecord
|
||||
public let representedCountry: RepresentedCountryRecord
|
||||
public let traits: TraitsRecord
|
||||
public let ipAddress: IpAddress
|
||||
public let netmask: IpAddress
|
||||
public var mostSpecificSubdivision: SubdivisionRecord { get { return subdivisions.last ?? SubdivisionRecord(nil) } }
|
||||
}
|
||||
|
||||
extension InsightsModel: DictionaryInitialisableModel {
|
||||
public init(ip: IpAddress, netmask: IpAddress, _ dictionary: [String: Payload]?) {
|
||||
self.init(
|
||||
city: CityRecord(dictionary?["city"]?.unwrap()),
|
||||
location: LocationRecord(dictionary?["location"]?.unwrap()),
|
||||
postal: PostalRecord(dictionary?["postal"]?.unwrap()),
|
||||
subdivisions: (dictionary?["subdivisions"]?.unwrap() ?? [] as [Payload]).compactMap(
|
||||
{ SubdivisionRecord($0.unwrap()) }
|
||||
),
|
||||
continent: ContinentRecord(dictionary?["continent"]?.unwrap()),
|
||||
country: CountryRecord(dictionary?["country"]?.unwrap()),
|
||||
maxmind: MaxMindRecord(dictionary?["maxmind"]?.unwrap()),
|
||||
registeredCountry: CountryRecord(dictionary?["registered_country"]?.unwrap()),
|
||||
representedCountry: RepresentedCountryRecord(dictionary?["represented_country"]?.unwrap()),
|
||||
traits: TraitsRecord(dictionary?["traits"]?.unwrap()),
|
||||
ipAddress: ip,
|
||||
netmask: netmask
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# Good to know about the API module
|
||||
|
||||
It was intentionally designed to reproduce the php scripter fantasies, and awful
|
||||
modeling to reduce risks of having a broken library behavior, and data provision.
|
||||
|
||||
Depending on how widespread the library may become, the new fancy API of which
|
||||
I could be proud of will be delivered either :
|
||||
* **as a backwards incompatible way**, by simply throwing it all out in the
|
||||
garbage, and providing a proper professional api
|
||||
* **as a backwards compatible way**, by doing a minor release, marking this pile
|
||||
of shit I wrote as deprecated, providing a neat API module, and throwing this
|
||||
trash in the garbage in the future.
|
|
@ -15,7 +15,7 @@ extension SubdivisionRecord: DictionaryInitialisableRecord {
|
|||
self.init(
|
||||
confidence: dictionary?["confidence"]?.unwrap(),
|
||||
geonameId: dictionary?["geoname_id"]?.unwrap(),
|
||||
isoCode: dictionary?["iso_cod"]?.unwrap(),
|
||||
isoCode: dictionary?["iso_code"]?.unwrap(),
|
||||
names: (dictionary?["names"]?.unwrap() ?? [:] as [String: Payload]).compactMapValues({ $0.unwrap() })
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ public struct TraitsRecord: Equatable {
|
|||
let autonomousSystemOrganization: String?
|
||||
let connectionType: String?
|
||||
let domain: String?
|
||||
// todo
|
||||
// let ipAddress: IpAddress
|
||||
let isAnonymous: Bool
|
||||
let isAnonymousProxy: Bool
|
||||
let isAnonymousVpn: Bool
|
||||
|
@ -17,7 +15,6 @@ public struct TraitsRecord: Equatable {
|
|||
let isSatelliteProvider: Bool
|
||||
let isTorExitNode: Bool
|
||||
let isp: String?
|
||||
let network: String
|
||||
let organization: String?
|
||||
let staticIPScore: Float?
|
||||
let userCount: Int?
|
||||
|
@ -31,8 +28,6 @@ extension TraitsRecord: DictionaryInitialisableRecord {
|
|||
autonomousSystemOrganization: dictionary?["autonomous_system_organization"]?.unwrap(),
|
||||
connectionType: dictionary?["connection_type"]?.unwrap(),
|
||||
domain: dictionary?["domain"]?.unwrap(),
|
||||
// TODO
|
||||
// ipAddress: dictionary?["ipAddress"]?.unwrap(),
|
||||
isAnonymous: dictionary?["is_anonymous"]?.unwrap() ?? false,
|
||||
isAnonymousProxy: dictionary?["is_anonymous_proxy"]?.unwrap() ?? false,
|
||||
isAnonymousVpn: dictionary?["is_anonymous_vpn"]?.unwrap() ?? false,
|
||||
|
@ -42,8 +37,6 @@ extension TraitsRecord: DictionaryInitialisableRecord {
|
|||
isSatelliteProvider: dictionary?["is_satellite_provider"]?.unwrap() ?? false,
|
||||
isTorExitNode: dictionary?["is_tor_exit_node"]?.unwrap() ?? false,
|
||||
isp: dictionary?["isp"]?.unwrap(),
|
||||
// TODO
|
||||
network: dictionary?["network"]?.unwrap() ?? "",
|
||||
organization: dictionary?["organization"]?.unwrap(),
|
||||
staticIPScore: dictionary?["static_ip_score"]?.unwrap(),
|
||||
userCount: dictionary?["user_count"]?.unwrap(),
|
||||
|
|
|
@ -5,6 +5,15 @@ import class Api.Reader
|
|||
import class Api.ReaderFactory
|
||||
import enum Api.IpAddress
|
||||
@testable import struct Api.CityModel
|
||||
@testable import struct Api.CityRecord
|
||||
@testable import struct Api.ContinentRecord
|
||||
@testable import struct Api.CountryRecord
|
||||
@testable import struct Api.LocationRecord
|
||||
@testable import struct Api.MaxMindRecord
|
||||
@testable import struct Api.PostalRecord
|
||||
@testable import struct Api.RepresentedCountryRecord
|
||||
@testable import struct Api.SubdivisionRecord
|
||||
@testable import struct Api.TraitsRecord
|
||||
|
||||
class CityLookupTest: XCTestCase {
|
||||
|
||||
|
@ -31,11 +40,201 @@ class CityLookupTest: XCTestCase {
|
|||
}
|
||||
|
||||
func testSuccessfulLookup() {
|
||||
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:C000"
|
||||
"255.255.255.224"
|
||||
"255.255.255.192"
|
||||
// print(reader.lookup(.v6("::1.128.0.0"))?.netmask)
|
||||
print(reader.lookup(.v4(80, 99, 18, 166))?.netmask)
|
||||
XCTAssertEqual(
|
||||
CityModel(
|
||||
city: CityRecord(
|
||||
confidence: nil,
|
||||
geonameId: 3054643,
|
||||
names: [
|
||||
"de": "Budapest",
|
||||
"en": "Budapest",
|
||||
"es": "Budapest",
|
||||
"fr": "Budapest",
|
||||
"ja": "ブダペスト",
|
||||
"pt-BR": "Budapeste",
|
||||
"ru": "Будапешт",
|
||||
"zh-CN": "布达佩斯"
|
||||
]
|
||||
),
|
||||
location: LocationRecord(
|
||||
averageIncome: nil,
|
||||
accuracyRadius: 20,
|
||||
latitude: 47.4984,
|
||||
longitude: 19.0404,
|
||||
populationDensity: nil,
|
||||
metroCode: nil,
|
||||
timeZone: "Europe/Budapest"
|
||||
),
|
||||
postal: PostalRecord(code: "1096", confidence: nil),
|
||||
subdivisions: [
|
||||
SubdivisionRecord(
|
||||
confidence: nil,
|
||||
geonameId: 3054638,
|
||||
isoCode: "BU",
|
||||
names: ["en": "Budapest"]
|
||||
)
|
||||
],
|
||||
continent: ContinentRecord(
|
||||
code: "EU",
|
||||
geonameId: 6255148,
|
||||
names: [
|
||||
"de": "Europa",
|
||||
"en": "Europe",
|
||||
"es": "Europa",
|
||||
"fr": "Europe",
|
||||
"ja": "ヨーロッパ",
|
||||
"pt-BR": "Europa",
|
||||
"ru": "Европа",
|
||||
"zh-CN": "欧洲"
|
||||
]
|
||||
),
|
||||
country: CountryRecord(
|
||||
confidence: nil,
|
||||
geonameId: 719819,
|
||||
isInEuropeanUnion: true,
|
||||
isoCode: "HU",
|
||||
names: [
|
||||
"de": "Ungarn",
|
||||
"en": "Hungary",
|
||||
"es": "Hungría",
|
||||
"fr": "Hongrie",
|
||||
"ja": "ハンガリー共和国",
|
||||
"pt-BR": "Hungria",
|
||||
"ru": "Венгрия",
|
||||
"zh-CN": "匈牙利"
|
||||
]
|
||||
),
|
||||
maxmind: MaxMindRecord(queriesRemaining: nil),
|
||||
registeredCountry: CountryRecord(
|
||||
confidence: nil,
|
||||
geonameId: 719819,
|
||||
isInEuropeanUnion: true,
|
||||
isoCode: "HU",
|
||||
names: [
|
||||
"de": "Ungarn",
|
||||
"en": "Hungary",
|
||||
"es": "Hungría",
|
||||
"fr": "Hongrie",
|
||||
"ja": "ハンガリー共和国",
|
||||
"pt-BR": "Hungria",
|
||||
"ru": "Венгрия",
|
||||
"zh-CN": "匈牙利"
|
||||
]
|
||||
),
|
||||
representedCountry: RepresentedCountryRecord(type: nil),
|
||||
traits: TraitsRecord(
|
||||
autonomousSystemNumber: nil,
|
||||
autonomousSystemOrganization: nil,
|
||||
connectionType: nil,
|
||||
domain: nil,
|
||||
isAnonymous: false,
|
||||
isAnonymousProxy: false,
|
||||
isAnonymousVpn: false,
|
||||
isHostingProvider: false,
|
||||
isLegitimateProxy: false,
|
||||
isPublicProxy: false,
|
||||
isSatelliteProvider: false,
|
||||
isTorExitNode: false,
|
||||
isp: nil,
|
||||
organization: nil,
|
||||
staticIPScore: nil,
|
||||
userCount: nil,
|
||||
userType: nil
|
||||
),
|
||||
ipAddress: .v4(80, 99, 18, 166),
|
||||
netmask: IpAddress.v4Netmask(ofBitLength: 26)
|
||||
),
|
||||
reader.lookup(.v4(80, 99, 18, 166))
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
CityModel(
|
||||
city: CityRecord(confidence: nil, geonameId: nil, names: [:]),
|
||||
location: LocationRecord(
|
||||
averageIncome: nil,
|
||||
accuracyRadius: 1000,
|
||||
latitude: -33.494,
|
||||
longitude: 143.2104,
|
||||
populationDensity: nil,
|
||||
metroCode: nil,
|
||||
timeZone: "Australia/Sydney"
|
||||
),
|
||||
postal: PostalRecord(code: nil, confidence: nil),
|
||||
subdivisions: [],
|
||||
continent: ContinentRecord(
|
||||
code: "OC",
|
||||
geonameId: 6255151,
|
||||
names: [
|
||||
"de": "Ozeanien",
|
||||
"en": "Oceania",
|
||||
"es": "Oceanía",
|
||||
"fr": "Océanie",
|
||||
"ja": "オセアニア",
|
||||
"pt-BR": "Oceania",
|
||||
"ru": "Океания",
|
||||
"zh-CN": "大洋洲"
|
||||
]
|
||||
),
|
||||
country: CountryRecord(
|
||||
confidence: nil,
|
||||
geonameId: 2077456,
|
||||
isInEuropeanUnion: false,
|
||||
isoCode: "AU",
|
||||
names: [
|
||||
"de": "Australien",
|
||||
"en": "Australia",
|
||||
"es": "Australia",
|
||||
"fr": "Australie",
|
||||
"ja": "オーストラリア",
|
||||
"pt-BR": "Austrália",
|
||||
"ru": "Австралия",
|
||||
"zh-CN": "澳大利亚"
|
||||
]
|
||||
),
|
||||
maxmind: MaxMindRecord(queriesRemaining: nil),
|
||||
registeredCountry: CountryRecord(
|
||||
confidence: nil,
|
||||
geonameId: 2077456,
|
||||
isInEuropeanUnion: false,
|
||||
isoCode: "AU",
|
||||
names: [
|
||||
"de": "Australien",
|
||||
"en": "Australia",
|
||||
"es": "Australia",
|
||||
"fr": "Australie",
|
||||
"ja": "オーストラリア",
|
||||
"pt-BR": "Austrália",
|
||||
"ru": "Австралия",
|
||||
"zh-CN": "澳大利亚"
|
||||
]
|
||||
),
|
||||
representedCountry: RepresentedCountryRecord(type: nil),
|
||||
traits: TraitsRecord(
|
||||
autonomousSystemNumber: nil,
|
||||
autonomousSystemOrganization: nil,
|
||||
connectionType: nil,
|
||||
domain: nil,
|
||||
isAnonymous: false,
|
||||
isAnonymousProxy: false,
|
||||
isAnonymousVpn: false,
|
||||
isHostingProvider: false,
|
||||
isLegitimateProxy: false,
|
||||
isPublicProxy: false,
|
||||
isSatelliteProvider: false,
|
||||
isTorExitNode: false,
|
||||
isp: nil,
|
||||
organization: nil,
|
||||
staticIPScore: nil,
|
||||
userCount: nil,
|
||||
userType: nil
|
||||
),
|
||||
ipAddress: .v6("::1.128.0.0"),
|
||||
netmask: IpAddress.v6Netmask(ofBitLength: 114)
|
||||
),
|
||||
reader.lookup(.v6("::1.128.0.0"))
|
||||
)
|
||||
|
||||
XCTAssertNil(reader.lookup(.v6("2600:7100::")))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue