Created
March 31, 2021 21:54
-
-
Save titandiaz/b8916f8a41185885734a308dc986cb02 to your computer and use it in GitHub Desktop.
time tracker
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 Cocoa | |
protocol ApplicationTimeTrackerDelegate: AnyObject { | |
func timeTracker(_ tracker: ApplicationTimeTracker, didUpdateFrontmostApplication: Application, withTotalSeconds: UInt) | |
func timeTracker(_ tracker: ApplicationTimeTracker, didFinishTrackingApplication: Application, withTotalSeconds: UInt) | |
} | |
class ApplicationTimeTracker: NSObject { | |
private var trackings: [BundleIdentifier: Tracking] = [:] | |
private var applications: [String: Application] = [:] | |
private var observation: NSKeyValueObservation? | |
private weak var delegate: ApplicationTimeTrackerDelegate? | |
var gameTimer: Timer? | |
init(delegate: ApplicationTimeTrackerDelegate, workspace: NSWorkspace = NSWorkspace.shared) { | |
self.delegate = delegate | |
super.init() | |
self.observation = workspace.observe(\.frontmostApplication, options: [.old, .new]) { [weak self] (workspace, change) in | |
let oldApp = change.oldValue ?? nil | |
let newApp = change.newValue ?? nil | |
self?.switchTracking(from: oldApp, to: newApp) | |
} | |
} | |
} | |
extension ApplicationTimeTracker { | |
private func switchTracking(from oldApp: NSRunningApplication?, to newApp: NSRunningApplication?) { | |
if let oldApp = oldApp { | |
self.updateTracking(for: oldApp, started: false) | |
} | |
if let newApp = newApp { | |
// self.updateTracking(for: newApp, started: true) | |
var gameTimer: Timer? | |
gameTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in | |
self.updateTracking(for: newApp, started: true) | |
} | |
} | |
} | |
private func updateTracking(for app: NSRunningApplication, started: Bool) { | |
let originApp = app | |
guard let bundleIdentifier = app.bundleIdentifier else { print("Nothing to do here ¯\\_(ツ)_/¯"); return } | |
let app = applications[bundleIdentifier] ?? Application(id: bundleIdentifier, icon: app.icon!, name: app.localizedName ?? "🥴", date: app.launchDate ?? Date() ) | |
var tracking: Tracking | |
if started { | |
tracking = trackings[bundleIdentifier] ?? Tracking(startTs: Date().timeIntervalSince1970, totalSeconds: 0) | |
tracking.startTs = Date().timeIntervalSince1970 | |
defer { | |
self.delegate?.timeTracker(self, didUpdateFrontmostApplication: app, withTotalSeconds: tracking.totalSeconds) | |
} | |
} else { | |
guard let appTracking = trackings[bundleIdentifier] else { print("What are you doing here?"); return } | |
tracking = appTracking | |
tracking.totalSeconds += max(1, UInt(round(Date().timeIntervalSince1970 - tracking.startTs))) | |
do { | |
self.delegate?.timeTracker(self, didFinishTrackingApplication: app, withTotalSeconds: tracking.totalSeconds) | |
} | |
} | |
self.trackings[bundleIdentifier] = tracking | |
self.applications[bundleIdentifier] = app | |
//start ******* metodos para obtener info de los navegadores | |
func getBrowserURL(_ appName: String) -> String? { | |
guard let scriptText = getScriptText(appName) else { return nil } | |
var error: NSDictionary? | |
guard let script = NSAppleScript(source: scriptText) else { return nil } | |
guard let outputString = script.executeAndReturnError(&error).stringValue else { | |
if let error = error { | |
print("Get Browser URL request failed with error: \(error.description)") | |
} | |
return nil | |
} | |
// clean url output - remove protocol & unnecessary "www." | |
if let url = URL(string: outputString), | |
var host = url.host { | |
if host.hasPrefix("www.") { | |
host = String(host.dropFirst(4)) | |
} | |
let resultURL = "\(host)\(url.path)" | |
return resultURL | |
} | |
return nil | |
} | |
func getBrowserTitle(_ appName: String) -> String? { | |
guard let scriptText = getScriptTextTitle(appName) else { return nil } | |
var error: NSDictionary? | |
guard let script = NSAppleScript(source: scriptText) else { return nil } | |
guard let outputString = script.executeAndReturnError(&error).stringValue else { | |
if let error = error { | |
print("Get Browser URL request failed with error: \(error.description)") | |
} | |
return nil | |
} | |
return outputString | |
} | |
func getScriptText(_ appName: String) -> String? { | |
switch appName { | |
case "Google Chrome": | |
return "tell app \"Google Chrome\" to get the url of the active tab of window 1" | |
case "Safari": | |
return "tell application \"Safari\" to return URL of front document" | |
default: | |
return nil | |
} | |
} | |
func getScriptTextTitle(_ appName: String) -> String? { | |
switch appName { | |
case "Google Chrome": | |
return "tell app \"Google Chrome\" to get the title of the active tab of window 1" | |
case "Safari": | |
return "tell application \"Safari\" to return name of front document" | |
default: | |
return nil | |
} | |
} | |
//end *********** | |
func getInfoBrowser() { | |
let title = getBrowserTitle(originApp.localizedName ?? "not browser") | |
let url = getBrowserURL(originApp.localizedName ?? "not browser") | |
print(url) | |
print(title) | |
} | |
@discardableResult | |
func shell(_ app: String, _ args: String...) -> Int32 { | |
let task = Process() | |
task.launchPath = "/usr/bin/\(app)" | |
task.arguments = args | |
task.launch() | |
task.waitUntilExit() | |
return task.terminationStatus | |
} | |
print(bundleIdentifier) | |
let proToolsApp : NSRunningApplication? = NSRunningApplication | |
.runningApplications(withBundleIdentifier: bundleIdentifier).last as NSRunningApplication? | |
if let pid = proToolsApp?.processIdentifier { | |
var result = [AXUIElement]() | |
var windowList: AnyObject? = nil // [AXUIElement] | |
let appRef = AXUIElementCreateApplication(pid) | |
if AXUIElementCopyAttributeValue(appRef, "AXWindows" as CFString, &windowList) == .success { | |
result = windowList as! [AXUIElement] | |
} | |
var docRef: AnyObject? = nil | |
var filePath: String = "" | |
if result.first != nil { | |
if AXUIElementCopyAttributeValue(result.first!, "AXDocument" as CFString, &docRef) == .success { | |
let result = docRef as! AXUIElement | |
filePath = result as! String | |
} else { | |
print("no hay archivo 1") | |
} | |
} else { | |
print("no hay archivo 2") | |
var gameTimer: Timer? | |
gameTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in | |
var gameTimer: Timer? | |
} | |
} | |
if filePath != "" { | |
let strIndex = filePath.index(filePath.startIndex, offsetBy: 7) | |
let pathFile = filePath[strIndex...] | |
var arrFile = pathFile.components(separatedBy: "/") | |
let file = String(arrFile.popLast()!) | |
let path = arrFile.joined(separator: "/") | |
print(file) | |
shell("git", "-C", String(path), "branch", "--show-current") | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment