Created
December 16, 2022 23:46
-
-
Save brianmichel/1959ef94b7dbbeccda26a01859dd7fa0 to your computer and use it in GitHub Desktop.
Say goodbye to your meet tabs
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
#!/usr/bin/env swift | |
import AppKit | |
import Foundation | |
import ScriptingBridge | |
@objc public protocol SBObjectProtocol: NSObjectProtocol { | |
func get() -> Any! | |
} | |
@objc public protocol SBApplicationProtocol: SBObjectProtocol { | |
func activate() | |
var delegate: SBApplicationDelegate! { get set } | |
var isRunning: Bool { get } | |
} | |
// MARK: ChromeGenericMethods | |
@objc public protocol ChromeGenericMethods { | |
@objc optional func saveIn(_ in_: URL!, as: String!) // Save an object. | |
@objc optional func close() // Close a window. | |
@objc optional func delete() // Delete an object. | |
@objc optional func duplicateTo(_ to: SBObject!, withProperties: [AnyHashable : Any]!) -> SBObject // Copy object(s) and put the copies at a new location. | |
@objc optional func moveTo(_ to: SBObject!) -> SBObject // Move object(s) to a new location. | |
@objc optional func print() // Print an object. | |
@objc optional func reload() // Reload a tab. | |
@objc optional func goBack() // Go Back (If Possible). | |
@objc optional func goForward() // Go Forward (If Possible). | |
@objc optional func selectAll() // Select all. | |
@objc optional func cutSelection() // Cut selected text (If Possible). | |
@objc optional func copySelection() // Copy text. | |
@objc optional func pasteSelection() // Paste text (If Possible). | |
@objc optional func undo() // Undo the last change. | |
@objc optional func redo() // Redo the last change. | |
@objc optional func stop() // Stop the current tab from loading. | |
@objc optional func viewSource() // View the HTML source of the tab. | |
@objc optional func executeJavascript(_ javascript: String!) -> Any // Execute a piece of javascript. | |
} | |
// MARK: ChromeApplication | |
@objc public protocol ChromeApplication: SBApplicationProtocol { | |
@objc optional func windows() -> SBElementArray | |
@objc optional var name: String { get } // The name of the application. | |
@objc optional var frontmost: Bool { get } // Is this the frontmost (active) application? | |
@objc optional var version: String { get } // The version of the application. | |
@objc optional func `open`(_ x: [URL]!) // Open a document. | |
@objc optional func quit() // Quit the application. | |
@objc optional func exists(_ x: Any!) -> Bool // Verify if an object exists. | |
@objc optional func bookmarkFolders() -> SBElementArray | |
@objc optional var bookmarksBar: ChromeBookmarkFolder { get } // The bookmarks bar bookmark folder. | |
@objc optional var otherBookmarks: ChromeBookmarkFolder { get } // The other bookmarks bookmark folder. | |
} | |
extension SBApplication: ChromeApplication {} | |
// MARK: ChromeWindow | |
@objc public protocol ChromeWindow: SBObjectProtocol, ChromeGenericMethods { | |
@objc optional func tabs() -> SBElementArray | |
@objc optional var givenName: String { get } // The given name of the window. | |
@objc optional var name: String { get } // The full title of the window. | |
@objc optional func id() -> Int // The unique identifier of the window. | |
@objc optional var index: Int { get } // The index of the window, ordered front to back. | |
@objc optional var bounds: NSRect { get } // The bounding rectangle of the window. | |
@objc optional var closeable: Bool { get } // Whether the window has a close box. | |
@objc optional var minimizable: Bool { get } // Whether the window can be minimized. | |
@objc optional var minimized: Bool { get } // Whether the window is currently minimized. | |
@objc optional var resizable: Bool { get } // Whether the window can be resized. | |
@objc optional var visible: Bool { get } // Whether the window is currently visible. | |
@objc optional var zoomable: Bool { get } // Whether the window can be zoomed. | |
@objc optional var zoomed: Bool { get } // Whether the window is currently zoomed. | |
@objc optional var activeTab: ChromeTab { get } // Returns the currently selected tab | |
@objc optional var mode: String { get } // Represents the mode of the window which can be 'normal' or 'incognito', can be set only once during creation of the window. | |
@objc optional var activeTabIndex: Int { get } // The index of the active tab. | |
@objc optional func setGivenName(_ givenName: String!) // The given name of the window. | |
@objc optional func setIndex(_ index: Int) // The index of the window, ordered front to back. | |
@objc optional func setBounds(_ bounds: NSRect) // The bounding rectangle of the window. | |
@objc optional func setMinimized(_ minimized: Bool) // Whether the window is currently minimized. | |
@objc optional func setVisible(_ visible: Bool) // Whether the window is currently visible. | |
@objc optional func setZoomed(_ zoomed: Bool) // Whether the window is currently zoomed. | |
@objc optional func setMode(_ mode: String!) // Represents the mode of the window which can be 'normal' or 'incognito', can be set only once during creation of the window. | |
@objc optional func setActiveTabIndex(_ activeTabIndex: Int) // The index of the active tab. | |
} | |
extension SBObject: ChromeWindow {} | |
// MARK: ChromeTab | |
@objc public protocol ChromeTab: SBObjectProtocol, ChromeGenericMethods { | |
@objc optional func id() -> Int // Unique ID of the tab. | |
@objc optional var title: String { get } // The title of the tab. | |
@objc optional var URL: String { get } // The url visible to the user. | |
@objc optional var loading: Bool { get } // Is loading? | |
@objc optional func setURL(_ URL: String!) // The url visible to the user. | |
} | |
extension SBObject: ChromeTab {} | |
// MARK: ChromeBookmarkFolder | |
@objc public protocol ChromeBookmarkFolder: SBObjectProtocol, ChromeGenericMethods { | |
@objc optional func bookmarkFolders() -> SBElementArray | |
@objc optional func bookmarkItems() -> SBElementArray | |
@objc optional func id() -> NSNumber // Unique ID of the bookmark folder. | |
@objc optional var title: String { get } // The title of the folder. | |
@objc optional var index: NSNumber { get } // Returns the index with respect to its parent bookmark folder. | |
@objc optional func setTitle(_ title: String!) // The title of the folder. | |
} | |
extension SBObject: ChromeBookmarkFolder {} | |
// MARK: ChromeBookmarkItem | |
@objc public protocol ChromeBookmarkItem: SBObjectProtocol, ChromeGenericMethods { | |
@objc optional func id() -> Int // Unique ID of the bookmark item. | |
@objc optional var title: String { get } // The title of the bookmark item. | |
@objc optional var URL: String { get } // The URL of the bookmark. | |
@objc optional var index: NSNumber { get } // Returns the index with respect to its parent bookmark folder. | |
@objc optional func setTitle(_ title: String!) // The title of the bookmark item. | |
@objc optional func setURL(_ URL: String!) // The URL of the bookmark. | |
} | |
extension SBObject: ChromeBookmarkItem {} | |
final class Bridge { | |
private let chromeApplication: ChromeApplication | |
var tabs: [ChromeTab]? { | |
let windows = chromeApplication.windows?().compactMap({ $0 as? ChromeWindow }) | |
let tabs = windows?.compactMap({ window in | |
window.tabs?().compactMap({ $0 as? ChromeTab }) | |
}) | |
return tabs?.flatMap({$0}) | |
} | |
init() { | |
self.chromeApplication = SBApplication(bundleIdentifier: "com.google.Chrome")! | |
} | |
func closeMeets() { | |
tabs? | |
.filter({$0.URL?.hasPrefix("https://meet.google.com") ?? false}) | |
.forEach({ tab in | |
tab.close?() | |
}) | |
} | |
func printAllTabs() { | |
let windows = chromeApplication.windows?().compactMap({ $0 as? ChromeWindow }) | |
let tabs = windows?.compactMap({ window in | |
window.tabs?().compactMap({ $0 as? ChromeTab }) | |
}) | |
let flattened = tabs?.flatMap({$0}) | |
for tab in flattened! { | |
print("Tab: \(String(describing: tab.URL))") | |
} | |
} | |
} | |
let bridge = Bridge() | |
bridge.printAllTabs() | |
bridge.closeMeets() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment