Last active
October 4, 2022 05:33
-
-
Save PimCoumans/1f605b96e6598837c842e08408fb0028 to your computer and use it in GitHub Desktop.
Finding your external Synology URL though the undocumented QuickConnect API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
// Based on example by Thomas Theunen: https://thomastheunen.eu/2017/07/04/diving-into-synology-quickconnect-and-creating-a-javascript-library/ | |
struct QuickConnect { | |
private static let endpointURL = URL(string: "https://global.quickconnect.to/Serv.php")! | |
enum Error: Swift.Error { | |
case noAddressFound | |
case noResponse | |
case invalidData(decodingError: Swift.Error, jsonString: String) | |
} | |
private struct IDRequestParameters: Encodable { | |
let version = 1 | |
let command = "get_server_info" | |
let stop_when_error = false | |
let stop_when_success = false | |
let id: String | |
let serverID: String | |
} | |
private struct ServerResponse: Decodable { | |
struct Service: Decodable { | |
let pingpong: String | |
let pingpongDesc: [String] | |
let port: Int | |
} | |
let service: Service | |
func url(https: Bool) -> URL? { | |
guard let ipAddress = service.pingpongDesc.first, service.pingpong == "CONNECTED" else { | |
return nil | |
} | |
return URL(string: "\(https ? "https" : "http")://\(ipAddress)") | |
} | |
} | |
private static let encoder: JSONEncoder = { | |
let encoder = JSONEncoder() | |
return encoder | |
}() | |
private static let decoder: JSONDecoder = { | |
let decoder = JSONDecoder() | |
decoder.keyDecodingStrategy = .convertFromSnakeCase | |
return decoder | |
}() | |
static func externalAddress(for quickConnectID: String, handler: @escaping (Result<URL>) -> Swift.Void) { | |
let parameters = [ | |
IDRequestParameters(id: "dsm_portal_https", serverID: quickConnectID), | |
IDRequestParameters(id: "dsm_portal", serverID: quickConnectID) | |
] | |
var request = URLRequest(url: endpointURL) | |
request.httpMethod = "POST" | |
request.httpBody = try? encoder.encode(parameters) | |
URLSession.shared.dataTask(with: request) { (data, response, error) in | |
do { | |
guard let data = data else { | |
throw error ?? Error.noResponse | |
} | |
let response: [ServerResponse] | |
do { | |
response = try decoder.decode([ServerResponse].self, from: data) | |
} catch { | |
let jsonString = String(data: data, encoding: .utf8)! | |
throw Error.invalidData(decodingError: error, jsonString: jsonString) | |
} | |
if let address = response.first?.url(https: true) { | |
DispatchQueue.main.async { | |
handler(.success(address)) | |
} | |
} else if let address = response.last?.url(https: false) { | |
DispatchQueue.main.async { | |
handler(.success(address)) | |
} | |
} else { | |
throw Error.noAddressFound | |
} | |
} | |
catch { | |
DispatchQueue.main.async { | |
handler(.failure(error)) | |
} | |
} | |
}.resume() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment