134 lines
4.3 KiB
Swift
Executable File
134 lines
4.3 KiB
Swift
Executable File
import Routing
|
|
import Vapor
|
|
import SQLite
|
|
|
|
private let fm = FileManager.default
|
|
|
|
private let baseFolder = URL(fileURLWithPath: "/caps")
|
|
|
|
private let imageFolder = URL(fileURLWithPath: "/caps/public/images")
|
|
|
|
private let dbFile = "/caps/db.sqlite3"
|
|
|
|
private let tempImageFile = imageFolder.appendingPathComponent("temp.jpg")
|
|
|
|
private var db: Connection!
|
|
|
|
private let id = Expression<Int>("id")
|
|
|
|
private let name = Expression<String>("name")
|
|
|
|
private let table = Table("caps")
|
|
|
|
func loadDatabase() throws {
|
|
db = try Connection(dbFile)
|
|
}
|
|
|
|
private func select(_ cap: Int) -> Table {
|
|
table.filter(id == cap)
|
|
}
|
|
|
|
private func folder(of cap: Int) -> URL {
|
|
imageFolder.appendingPathComponent(String(format: "%04d", cap))
|
|
}
|
|
|
|
private func file(of cap: Int, version: Int) -> URL {
|
|
folder(of: cap).appendingPathComponent(String(format: "%04d-%02d.jpg", cap, version))
|
|
}
|
|
|
|
private func countImages(in folder: URL) throws -> Int {
|
|
try fm.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil).filter({ $0.pathExtension == "jpg" }).count
|
|
}
|
|
|
|
private func count(of cap: Int) throws -> Int {
|
|
let f = folder(of: cap)
|
|
guard fm.fileExists(atPath: f.path) else {
|
|
throw CapError.unknownId
|
|
}
|
|
return try countImages(in: f)
|
|
}
|
|
|
|
/// Register your application's routes here.
|
|
///
|
|
/// [Learn More →](https://docs.vapor.codes/3.0/getting-started/structure/#routesswift)
|
|
public func routes(_ router: Router) throws {
|
|
|
|
// Get the name of a cap
|
|
router.getCatching("name", Int.parameter) { request -> Data in
|
|
let cap = try request.parameters.next(Int.self)
|
|
guard let row = try db.pluck(table.select(name).filter(id == cap)) else {
|
|
throw CapError.unknownId
|
|
}
|
|
return row[name].data(using: .utf8)!
|
|
}
|
|
|
|
// Set the name of a cap
|
|
router.postCatching("name", Int.parameter) { request in
|
|
let cap = try request.parameters.next(Int.self)
|
|
guard let data = request.http.body.data, let string = String(data: data, encoding: .utf8) else {
|
|
throw CapError.invalidBody
|
|
}
|
|
guard let _ = try db.pluck(select(cap)) else {
|
|
try db.run(select(cap).insert(id <- cap, name <- string))
|
|
return
|
|
}
|
|
try db.run(select(cap).update(name <- string))
|
|
}
|
|
|
|
// Upload an image
|
|
router.postCatching("images", Int.parameter) { request -> Data in
|
|
let cap = try request.parameters.next(Int.self)
|
|
guard let data = request.http.body.data else {
|
|
throw CapError.invalidBody
|
|
}
|
|
let c = try count(of: cap)
|
|
let f = file(of: cap, version: c)
|
|
guard !fm.fileExists(atPath: f.path) else {
|
|
throw CapError.dataInconsistency
|
|
}
|
|
try data.write(to: f)
|
|
return "\(c)".data(using: .utf8)!
|
|
}
|
|
|
|
// Get count of a cap
|
|
router.getCatching("count", Int.parameter) { request -> Data in
|
|
let cap = try request.parameters.next(Int.self)
|
|
let c = try count(of: cap)
|
|
return "\(c)".data(using: .utf8)!
|
|
}
|
|
|
|
// Get the count of all caps
|
|
router.getCatching("count", "all") { request -> Data in
|
|
let counts: [(id: Int, count: Int)] = try fm.contentsOfDirectory(at: imageFolder, includingPropertiesForKeys: nil).compactMap { folder in
|
|
guard let id = Int(folder.lastPathComponent) else {
|
|
return nil
|
|
}
|
|
guard let count = try? countImages(in: folder) else {
|
|
return nil
|
|
}
|
|
return (id, count)
|
|
}
|
|
return counts.map { "\($0.id)#\($0.count)"}.joined(separator: ";").data(using: .utf8)!
|
|
}
|
|
|
|
// Set a different version as the main image
|
|
router.getCatching("switch", Int.parameter, Int.parameter) { request in
|
|
let cap = try request.parameters.next(Int.self)
|
|
let version = try request.parameters.next(Int.self)
|
|
guard version > 0 else {
|
|
return
|
|
}
|
|
let file1 = file(of: cap, version: 0)
|
|
guard fm.fileExists(atPath: file1.path) else {
|
|
throw CapError.invalidFile
|
|
}
|
|
let file2 = file(of: cap, version: version)
|
|
guard fm.fileExists(atPath: file2.path) else {
|
|
throw CapError.invalidFile
|
|
}
|
|
try fm.moveItem(at: file1, to: tempImageFile)
|
|
try fm.moveItem(at: file2, to: file1)
|
|
try fm.moveItem(at: tempImageFile, to: file2)
|
|
}
|
|
}
|