Textual-Plugin/Arxius.swift

225 lines
7.6 KiB
Swift
Executable File

import Foundation
@objc
class Plugin: NSObject, THOPluginProtocol {
var apikey = ""
var theClient:IRCClient? = nil
var currentAlbum = ""
var uploadQueue:[URL] = []
var isUploading = false
var task:URLSessionDataTask?
@objc
let subscribedUserInputCommands = ["arxiuskey", "upload", "cancel"]
@objc func pluginLoadedIntoMemory() {
if (apikey.count < 1) {
if let key = TPCPreferencesUserDefaults.shared().value(forKey: "arxiusAPIKey") {
apikey = key as! String
}
}
}
@objc
func userInputCommandInvoked(on client: IRCClient, command commandString: String, messageString: String) {
theClient = client
performBlock(onMainThread: {
switch commandString {
case "ARXIUSKEY":
if (messageString.count == 32) {
apikey = messageString
TPCPreferencesUserDefaults.shared().setValue(apikey, forKey: "arxiusAPIKey")
debug("Your API key is set")
}
else if (messageString.count == 0 && apikey.count > 0) {
apikey = ""
TPCPreferencesUserDefaults.shared().removeObject(forKey: "arxiusAPIKey")
debug("Your API key is unset")
}
else if (messageString.count == 0) {
debug("Enter your API key like this: /arxiuskey abcd1234abcd1234abcd1234abcd1234")
}
else {
debug("That's not a valid API key")
}
case "UPLOAD":
let dialog = NSOpenPanel();
dialog.title = "Select files to upload";
dialog.showsResizeIndicator = true;
dialog.showsHiddenFiles = false;
dialog.canChooseDirectories = false;
dialog.canCreateDirectories = true;
dialog.allowsMultipleSelection = true;
if (dialog.runModal() == NSApplication.ModalResponse.OK) {
let files = dialog.urls
if (files.count > 0) {
for file in files {
let path = file.absoluteURL
uploadQueue.append(path)
}
makeAlbumIfNeeded()
}
}
case "CANCEL":
task?.cancel()
uploadQueue = []
debug("Upload cancelled")
break
default:
break
}
})
}
func debug(_ message: Any) {
self.theClient!.printDebugInformation("\u{02}[Arxius]\u{02} \(message)", in: self.theClient!.lastSelectedChannel!)
}
func startUploading() {
uploadFiles()
}
func uploadFiles() {
if (uploadQueue.count > 0) {
upload()
}
else {
currentAlbum = ""
}
}
func upload() {
let file = uploadQueue[0]
uploadQueue.remove(at: 0)
let url = URL(string: "https://arxius.io/")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
var parameters: [String:String] = [:]
if (apikey.count > 0) {
parameters["apikey"] = apikey
}
if (currentAlbum.count > 0) {
parameters["album"] = currentAlbum
}
var last = false
if (uploadQueue.count < 1) {
last = true
parameters["last"] = "true"
}
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
do {
let fileData = try Data(contentsOf: file)
request.httpBody = createBody(parameters: parameters, boundary: boundary, data: fileData, mimeType: "application/octet-stream", filename: file.lastPathComponent)
task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, let response = response as? HTTPURLResponse, error == nil else {
return
}
guard (200 ... 299) ~= response.statusCode else {
return
}
if (last) {
if let link = String(data: data, encoding: .utf8) {
self.debug("Upload complete: \(link)")
}
}
}
task!.resume()
debug("Uploading: \(file.path)")
uploadFiles()
}
catch {}
}
func makeAlbumIfNeeded() {
if (uploadQueue.count > 1) {
let url = URL(string: "https://arxius.io/api/create/album")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
var parameters: [String:String] = [:]
if (apikey.count > 0) {
parameters["apikey"] = apikey
}
request.httpBody = parameters.percentEscaped().data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, let response = response as? HTTPURLResponse, error == nil else {
return
}
guard (200 ... 299) ~= response.statusCode else {
return
}
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String: Any]
if (json.index(forKey: "album") != nil) {
let album = json["album"] as! String
self.currentAlbum = album
self.debug("Created album: \(album)")
self.startUploading()
}
else {
self.debug("Error creating album")
}
} catch {}
}
task.resume()
}
else {
self.startUploading()
}
}
func createBody(parameters: [String: String],
boundary: String,
data: Data,
mimeType: String,
filename: String) -> Data {
let body = NSMutableData()
let boundaryPrefix = "--\(boundary)\r\n"
for (key, value) in parameters {
body.appendString(boundaryPrefix)
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
body.appendString(boundaryPrefix)
body.appendString("Content-Disposition: form-data; name=\"file\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimeType)\r\n\r\n")
body.append(data)
body.appendString("\r\n")
body.appendString("--".appending(boundary.appending("--")))
return body as Data
}
}