Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import Shout
import Socket
import Keychain
import Foundation
import DependencyInjection
public struct SFTPServiceBackupUploader {
public var upload: (URL, @escaping SFTPUploadResult) -> Void
public func callAsFunction(url: URL, completion: @escaping SFTPUploadResult) {
upload(url, completion)
}
}
extension SFTPServiceBackupUploader {
static let mock = SFTPServiceBackupUploader(
upload: { url, _ in
print("^^^ Requested upload on sftp service")
print("^^^ URL path: \(url.path)")
}
)
static let live = SFTPServiceBackupUploader { url, completion in
DispatchQueue.global().async {
do {
let keychain = try DependencyInjection.Container.shared.resolve() as KeychainHandling
let host = try keychain.get(key: .host)
let password = try keychain.get(key: .pwd)
let username = try keychain.get(key: .username)
let ssh = try SSH(host: host!, port: 22)
try ssh.authenticate(username: username!, password: password!)
let sftp = try ssh.openSftp()
let data = try Data(contentsOf: url)
if (try? sftp.listFiles(in: "backup")) == nil {
try sftp.createDirectory("backup")
}
try sftp.upload(data: data, remotePath: "backup/backup.xxm")
completion(.success(.init(
id: "backup/backup.xxm",
date: Date(),
size: Float(data.count)
)))
} catch {
if let error = error as? SSHError {
print(error.kind)
print(error.message)
print(error.description)
} else if let error = error as? Socket.Error {
print(error.errorCode)
print(error.description)
print(error.errorReason)
print(error.localizedDescription)
} else {
print(error.localizedDescription)
}
completion(.failure(error))
}
}
}
}