diff --git a/AGENTS.md b/AGENTS.md index 0ce8b64b..46abf31d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -28,14 +28,14 @@ Optional repository **secrets** for signing/notarization: `APPLE_ID`, `APPLE_APP ## Architecture Overview -Jared is a macOS iMessage bot. It polls the local Messages SQLite database (`~/Library/Messages/chat.db`) every ~5 seconds for new rows, constructs `Message` objects, and routes them through a plugin system. +Jared is a macOS iMessage bot. It polls the local Messages SQLite database (`~/Library/Messages/chat.db`) every ~5 seconds for new rows, constructs `Message` objects, and routes them through a module system. **Data flow:** ``` DatabaseHandler (SQLite polling) → Router.route(message:) → MessageDelegate.didProcess() [webhooks notified of every message] - → Route comparisons matched → route.call(message) [plugin handler invoked] + → Route comparisons matched → route.call(message) [module handler invoked] ``` **Outgoing messages** are sent via AppleScript (`.scpt` files bundled in the app). Different scripts handle group chats vs. 1:1 conversations. @@ -44,25 +44,16 @@ DatabaseHandler (SQLite polling) | File/Target | Role | |---|---| -| `JaredFramework/` | Public API framework; shared with plugins. Defines `Message`, `Route`, `RoutingModule`, `MessageSender`, entities, etc. | +| `JaredFramework/` | Public API framework. Defines `Message`, `Route`, `RoutingModule`, `MessageSender`, entities, etc. | | `Jared/DatabaseHandler.swift` | Polls `chat.db`, constructs `Message` objects, feeds them to `Router` | | `Jared/Router.swift` | Matches incoming messages against all registered `Route`s | -| `Jared/PluginManager.swift` | Loads `.bundle` plugin files from `~/Library/Application Support/Jared/Plugins/`, manages `RoutingModule` list | +| `Jared/PluginManager.swift` | Manages the list of built-in `RoutingModule`s | | `Jared/CoreModule.swift` | Built-in commands: `/ping`, `/send`, `/schedule`, `/name`, `/whoami`, `/barf`, etc. | | `Jared/InternalModule.swift` | `/help`, `/reload`, `/enable`, `/disable` commands | | `Jared/WebHookManager.swift` | Implements both `MessageDelegate` (notify on all messages) and `RoutingModule` (webhook-defined routes) | | `Jared/JaredWebServer.swift` | REST API web server | | `JaredUI/` | SwiftUI/AppKit macOS app wrapper (thin — mostly wires up the core) | -## Plugin System - -Plugins are `.bundle` files implementing `RoutingModule`. A plugin must: -1. Set `JaredFrameworkVersion = "J3.0.0"` in its `Info.plist` — version must match exactly or the plugin is silently rejected (`PluginManager.loadBundle`). -2. Have a `principalClass` that conforms to `RoutingModule`. -3. Be placed in `~/Library/Application Support/Jared/Plugins/`. - -See `Documentation/SampleModule/` for a reference implementation. - ## Route Comparisons `Route` uses a `[Compare: [String]]` dictionary. Available comparison types (case-insensitive matching): @@ -99,7 +90,7 @@ Route names in `config.routes` are lowercased keys matching `Route.name.lowercas Tests are in `JaredTests/`. Mocks live in `JaredTests/Mocks/`: - `JaredMock` — stub `MessageSender` -- `MockPluginManager` — tracks route call counts via `callCounts[routeName]` +- `MockPluginManager` — stub `PluginController` that tracks route call counts via `callCounts[routeName]` - `MockRouter` — captures routed messages - `URLProtocolMock` — intercepts URLSession for webhook tests diff --git a/Documentation/SampleModule/EmoteModule.xcodeproj/project.pbxproj b/Documentation/SampleModule/EmoteModule.xcodeproj/project.pbxproj deleted file mode 100644 index 48720887..00000000 --- a/Documentation/SampleModule/EmoteModule.xcodeproj/project.pbxproj +++ /dev/null @@ -1,430 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7F84B62D1CC5075D0059A82B /* JaredFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F84B62C1CC5075D0059A82B /* JaredFramework.framework */; }; - B36710E124DF68CC00DA1C5D /* JaredFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F84B62C1CC5075D0059A82B /* JaredFramework.framework */; }; - B39A66091CC2018A003E26B0 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = B39A66081CC2018A003E26B0 /* main.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 7F84B62C1CC5075D0059A82B /* JaredFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JaredFramework.framework; sourceTree = ""; }; - B36710D824DF681300DA1C5D /* EmoteTest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EmoteTest.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - B39A65FE1CC20181003E26B0 /* EmoteModule.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EmoteModule.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - B39A66011CC20181003E26B0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - B39A66081CC2018A003E26B0 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - B36710D524DF681300DA1C5D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - B36710E124DF68CC00DA1C5D /* JaredFramework.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B39A65FB1CC20181003E26B0 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 7F84B62D1CC5075D0059A82B /* JaredFramework.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - B36710E024DF68CC00DA1C5D /* Frameworks */ = { - isa = PBXGroup; - children = ( - ); - name = Frameworks; - sourceTree = ""; - }; - B39A65F51CC20181003E26B0 = { - isa = PBXGroup; - children = ( - 7F84B62C1CC5075D0059A82B /* JaredFramework.framework */, - B39A66001CC20181003E26B0 /* EmoteModule */, - B39A65FF1CC20181003E26B0 /* Products */, - B36710E024DF68CC00DA1C5D /* Frameworks */, - ); - sourceTree = ""; - }; - B39A65FF1CC20181003E26B0 /* Products */ = { - isa = PBXGroup; - children = ( - B39A65FE1CC20181003E26B0 /* EmoteModule.bundle */, - B36710D824DF681300DA1C5D /* EmoteTest.xctest */, - ); - name = Products; - sourceTree = ""; - }; - B39A66001CC20181003E26B0 /* EmoteModule */ = { - isa = PBXGroup; - children = ( - B39A66011CC20181003E26B0 /* Info.plist */, - B39A66081CC2018A003E26B0 /* main.swift */, - ); - path = EmoteModule; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - B36710D724DF681300DA1C5D /* EmoteTest */ = { - isa = PBXNativeTarget; - buildConfigurationList = B36710DF24DF681400DA1C5D /* Build configuration list for PBXNativeTarget "EmoteTest" */; - buildPhases = ( - B36710D424DF681300DA1C5D /* Sources */, - B36710D524DF681300DA1C5D /* Frameworks */, - B36710D624DF681300DA1C5D /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = EmoteTest; - productName = EmoteTest; - productReference = B36710D824DF681300DA1C5D /* EmoteTest.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - B39A65FD1CC20181003E26B0 /* EmoteModule */ = { - isa = PBXNativeTarget; - buildConfigurationList = B39A66041CC20181003E26B0 /* Build configuration list for PBXNativeTarget "EmoteModule" */; - buildPhases = ( - B39A65FA1CC20181003E26B0 /* Sources */, - B39A65FB1CC20181003E26B0 /* Frameworks */, - B39A65FC1CC20181003E26B0 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = EmoteModule; - productName = EmoteModule; - productReference = B39A65FE1CC20181003E26B0 /* EmoteModule.bundle */; - productType = "com.apple.product-type.bundle"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - B39A65F61CC20181003E26B0 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1160; - LastUpgradeCheck = 1020; - ORGANIZATIONNAME = "Zeke Snider"; - TargetAttributes = { - B36710D724DF681300DA1C5D = { - CreatedOnToolsVersion = 11.6; - DevelopmentTeam = C7LJ587XF3; - ProvisioningStyle = Automatic; - }; - B39A65FD1CC20181003E26B0 = { - CreatedOnToolsVersion = 7.3; - }; - }; - }; - buildConfigurationList = B39A65F91CC20181003E26B0 /* Build configuration list for PBXProject "EmoteModule" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = B39A65F51CC20181003E26B0; - productRefGroup = B39A65FF1CC20181003E26B0 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - B39A65FD1CC20181003E26B0 /* EmoteModule */, - B36710D724DF681300DA1C5D /* EmoteTest */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - B36710D624DF681300DA1C5D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B39A65FC1CC20181003E26B0 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - B36710D424DF681300DA1C5D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B39A65FA1CC20181003E26B0 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B39A66091CC2018A003E26B0 /* main.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - B36710DD24DF681400DA1C5D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = C7LJ587XF3; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = EmoteTest/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.zekesnider.EmoteTest; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - B36710DE24DF681400DA1C5D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = C7LJ587XF3; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = EmoteTest/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.zekesnider.EmoteTest; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - B39A66021CC20181003E26B0 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - B39A66031CC20181003E26B0 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - }; - name = Release; - }; - B39A66051CC20181003E26B0 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CLANG_ENABLE_MODULES = YES; - COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/EmoteModule", - "$(PROJECT_DIR)", - ); - INFOPLIST_FILE = EmoteModule/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = self.edu.zeke.EmoteModule; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_OBJC_BRIDGING_HEADER = ""; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - WRAPPER_EXTENSION = bundle; - }; - name = Debug; - }; - B39A66061CC20181003E26B0 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CLANG_ENABLE_MODULES = YES; - COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/EmoteModule", - "$(PROJECT_DIR)", - ); - INFOPLIST_FILE = EmoteModule/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = self.edu.zeke.EmoteModule; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_OBJC_BRIDGING_HEADER = ""; - SWIFT_VERSION = 5.0; - WRAPPER_EXTENSION = bundle; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - B36710DF24DF681400DA1C5D /* Build configuration list for PBXNativeTarget "EmoteTest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B36710DD24DF681400DA1C5D /* Debug */, - B36710DE24DF681400DA1C5D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B39A65F91CC20181003E26B0 /* Build configuration list for PBXProject "EmoteModule" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B39A66021CC20181003E26B0 /* Debug */, - B39A66031CC20181003E26B0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B39A66041CC20181003E26B0 /* Build configuration list for PBXNativeTarget "EmoteModule" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B39A66051CC20181003E26B0 /* Debug */, - B39A66061CC20181003E26B0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = B39A65F61CC20181003E26B0 /* Project object */; -} diff --git a/Documentation/SampleModule/EmoteModule.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Documentation/SampleModule/EmoteModule.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1427db5e..00000000 --- a/Documentation/SampleModule/EmoteModule.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Documentation/SampleModule/EmoteModule.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Documentation/SampleModule/EmoteModule.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/Documentation/SampleModule/EmoteModule.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Documentation/SampleModule/EmoteModule/Info.plist b/Documentation/SampleModule/EmoteModule/Info.plist deleted file mode 100644 index 144b5184..00000000 --- a/Documentation/SampleModule/EmoteModule/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleDisplayName - EmoteModule - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - JaredFrameworkVersion - J3.0.0 - NSHumanReadableCopyright - Copyright © 2016 Zeke Snider. All rights reserved. - NSPrincipalClass - EmoteModule - - diff --git a/Documentation/SampleModule/EmoteModule/main.swift b/Documentation/SampleModule/EmoteModule/main.swift deleted file mode 100644 index e52b537c..00000000 --- a/Documentation/SampleModule/EmoteModule/main.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// main.swift -// EmoteModule -// -// Created by Zeke Snider on 4/16/16. -// Copyright © 2016 Zeke Snider. All rights reserved. -// - -import Foundation -import JaredFramework - -public class EmoteModule: RoutingModule { - var sender: MessageSender - - public var routes: [Route] = [] - public var description = "A Description" - - required public init(sender: MessageSender) { - self.sender = sender - - let testRoute = Route(name: "test function", comparisons: [.startsWith: ["/moduletest"]], call: {[weak self] in self?.test(message: $0)}, description: "TEST") - routes = [testRoute] - } - - public func test(message: Message) -> Void { - sender.send("This command was loaded from a modularized bundle.", to: message.RespondTo()) - } -} - - diff --git a/Documentation/SampleModule/JaredFramework.framework/Headers b/Documentation/SampleModule/JaredFramework.framework/Headers deleted file mode 120000 index a177d2a6..00000000 --- a/Documentation/SampleModule/JaredFramework.framework/Headers +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/Headers \ No newline at end of file diff --git a/Documentation/SampleModule/JaredFramework.framework/JaredFramework b/Documentation/SampleModule/JaredFramework.framework/JaredFramework deleted file mode 120000 index 5188b38e..00000000 --- a/Documentation/SampleModule/JaredFramework.framework/JaredFramework +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/JaredFramework \ No newline at end of file diff --git a/Documentation/SampleModule/JaredFramework.framework/Modules b/Documentation/SampleModule/JaredFramework.framework/Modules deleted file mode 120000 index 5736f318..00000000 --- a/Documentation/SampleModule/JaredFramework.framework/Modules +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/Modules \ No newline at end of file diff --git a/Documentation/SampleModule/JaredFramework.framework/Resources b/Documentation/SampleModule/JaredFramework.framework/Resources deleted file mode 120000 index 953ee36f..00000000 --- a/Documentation/SampleModule/JaredFramework.framework/Resources +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/Resources \ No newline at end of file diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Headers/JaredFramework-Swift.h b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Headers/JaredFramework-Swift.h deleted file mode 100644 index da278c8b..00000000 --- a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Headers/JaredFramework-Swift.h +++ /dev/null @@ -1,209 +0,0 @@ -// Generated by Apple Swift version 5.2.4 (swiftlang-1103.0.32.9 clang-1103.0.32.53) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wgcc-compat" - -#if !defined(__has_include) -# define __has_include(x) 0 -#endif -#if !defined(__has_attribute) -# define __has_attribute(x) 0 -#endif -#if !defined(__has_feature) -# define __has_feature(x) 0 -#endif -#if !defined(__has_warning) -# define __has_warning(x) 0 -#endif - -#if __has_include() -# include -#endif - -#pragma clang diagnostic ignored "-Wauto-import" -#include -#include -#include -#include - -#if !defined(SWIFT_TYPEDEFS) -# define SWIFT_TYPEDEFS 1 -# if __has_include() -# include -# elif !defined(__cplusplus) -typedef uint_least16_t char16_t; -typedef uint_least32_t char32_t; -# endif -typedef float swift_float2 __attribute__((__ext_vector_type__(2))); -typedef float swift_float3 __attribute__((__ext_vector_type__(3))); -typedef float swift_float4 __attribute__((__ext_vector_type__(4))); -typedef double swift_double2 __attribute__((__ext_vector_type__(2))); -typedef double swift_double3 __attribute__((__ext_vector_type__(3))); -typedef double swift_double4 __attribute__((__ext_vector_type__(4))); -typedef int swift_int2 __attribute__((__ext_vector_type__(2))); -typedef int swift_int3 __attribute__((__ext_vector_type__(3))); -typedef int swift_int4 __attribute__((__ext_vector_type__(4))); -typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); -typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); -typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); -#endif - -#if !defined(SWIFT_PASTE) -# define SWIFT_PASTE_HELPER(x, y) x##y -# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) -#endif -#if !defined(SWIFT_METATYPE) -# define SWIFT_METATYPE(X) Class -#endif -#if !defined(SWIFT_CLASS_PROPERTY) -# if __has_feature(objc_class_property) -# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ -# else -# define SWIFT_CLASS_PROPERTY(...) -# endif -#endif - -#if __has_attribute(objc_runtime_name) -# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) -#else -# define SWIFT_RUNTIME_NAME(X) -#endif -#if __has_attribute(swift_name) -# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) -#else -# define SWIFT_COMPILE_NAME(X) -#endif -#if __has_attribute(objc_method_family) -# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) -#else -# define SWIFT_METHOD_FAMILY(X) -#endif -#if __has_attribute(noescape) -# define SWIFT_NOESCAPE __attribute__((noescape)) -#else -# define SWIFT_NOESCAPE -#endif -#if __has_attribute(ns_consumed) -# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed)) -#else -# define SWIFT_RELEASES_ARGUMENT -#endif -#if __has_attribute(warn_unused_result) -# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -#else -# define SWIFT_WARN_UNUSED_RESULT -#endif -#if __has_attribute(noreturn) -# define SWIFT_NORETURN __attribute__((noreturn)) -#else -# define SWIFT_NORETURN -#endif -#if !defined(SWIFT_CLASS_EXTRA) -# define SWIFT_CLASS_EXTRA -#endif -#if !defined(SWIFT_PROTOCOL_EXTRA) -# define SWIFT_PROTOCOL_EXTRA -#endif -#if !defined(SWIFT_ENUM_EXTRA) -# define SWIFT_ENUM_EXTRA -#endif -#if !defined(SWIFT_CLASS) -# if __has_attribute(objc_subclassing_restricted) -# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA -# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA -# else -# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA -# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA -# endif -#endif -#if !defined(SWIFT_RESILIENT_CLASS) -# if __has_attribute(objc_class_stub) -# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub)) -# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME) -# else -# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) -# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME) -# endif -#endif - -#if !defined(SWIFT_PROTOCOL) -# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA -# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA -#endif - -#if !defined(SWIFT_EXTENSION) -# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) -#endif - -#if !defined(OBJC_DESIGNATED_INITIALIZER) -# if __has_attribute(objc_designated_initializer) -# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) -# else -# define OBJC_DESIGNATED_INITIALIZER -# endif -#endif -#if !defined(SWIFT_ENUM_ATTR) -# if defined(__has_attribute) && __has_attribute(enum_extensibility) -# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility))) -# else -# define SWIFT_ENUM_ATTR(_extensibility) -# endif -#endif -#if !defined(SWIFT_ENUM) -# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type -# if __has_feature(generalized_swift_name) -# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type -# else -# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility) -# endif -#endif -#if !defined(SWIFT_UNAVAILABLE) -# define SWIFT_UNAVAILABLE __attribute__((unavailable)) -#endif -#if !defined(SWIFT_UNAVAILABLE_MSG) -# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) -#endif -#if !defined(SWIFT_AVAILABILITY) -# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) -#endif -#if !defined(SWIFT_WEAK_IMPORT) -# define SWIFT_WEAK_IMPORT __attribute__((weak_import)) -#endif -#if !defined(SWIFT_DEPRECATED) -# define SWIFT_DEPRECATED __attribute__((deprecated)) -#endif -#if !defined(SWIFT_DEPRECATED_MSG) -# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) -#endif -#if __has_feature(attribute_diagnose_if_objc) -# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) -#else -# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) -#endif -#if !defined(IBSegueAction) -# define IBSegueAction -#endif -#if __has_feature(modules) -#if __has_warning("-Watimport-in-framework-header") -#pragma clang diagnostic ignored "-Watimport-in-framework-header" -#endif -#endif - -#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" -#pragma clang diagnostic ignored "-Wduplicate-method-arg" -#if __has_warning("-Wpragma-clang-attribute") -# pragma clang diagnostic ignored "-Wpragma-clang-attribute" -#endif -#pragma clang diagnostic ignored "-Wunknown-pragmas" -#pragma clang diagnostic ignored "-Wnullability" - -#if __has_attribute(external_source_symbol) -# pragma push_macro("any") -# undef any -# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="JaredFramework",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol)) -# pragma pop_macro("any") -#endif - -#if __has_attribute(external_source_symbol) -# pragma clang attribute pop -#endif -#pragma clang diagnostic pop diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Headers/JaredFramework.h b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Headers/JaredFramework.h deleted file mode 100644 index a8c36c59..00000000 --- a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Headers/JaredFramework.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// JaredFramework.h -// JaredFramework -// -// Created by Jared Derulo on 4/18/16. -// Copyright © 2016 Zeke Snider. All rights reserved. -// - -#import - -//! Project version number for JaredFramework. -FOUNDATION_EXPORT double JaredFrameworkVersionNumber; - -//! Project version string for JaredFramework. -FOUNDATION_EXPORT const unsigned char JaredFrameworkVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/JaredFramework b/Documentation/SampleModule/JaredFramework.framework/Versions/A/JaredFramework deleted file mode 100755 index cdcaec26..00000000 Binary files a/Documentation/SampleModule/JaredFramework.framework/Versions/A/JaredFramework and /dev/null differ diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/Project/x86_64-apple-macos.swiftsourceinfo b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/Project/x86_64-apple-macos.swiftsourceinfo deleted file mode 100644 index cf4eea66..00000000 Binary files a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/Project/x86_64-apple-macos.swiftsourceinfo and /dev/null differ diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/Project/x86_64.swiftsourceinfo b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/Project/x86_64.swiftsourceinfo deleted file mode 100644 index cf4eea66..00000000 Binary files a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/Project/x86_64.swiftsourceinfo and /dev/null differ diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64-apple-macos.swiftdoc b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64-apple-macos.swiftdoc deleted file mode 100644 index 926c0f11..00000000 Binary files a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64-apple-macos.swiftdoc and /dev/null differ diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64-apple-macos.swiftmodule b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64-apple-macos.swiftmodule deleted file mode 100644 index 292f5aa8..00000000 Binary files a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64-apple-macos.swiftmodule and /dev/null differ diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64.swiftdoc b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64.swiftdoc deleted file mode 100644 index 926c0f11..00000000 Binary files a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64.swiftdoc and /dev/null differ diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64.swiftmodule b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64.swiftmodule deleted file mode 100644 index 292f5aa8..00000000 Binary files a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/JaredFramework.swiftmodule/x86_64.swiftmodule and /dev/null differ diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/module.modulemap b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/module.modulemap deleted file mode 100644 index ee1f7fa0..00000000 --- a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Modules/module.modulemap +++ /dev/null @@ -1,11 +0,0 @@ -framework module JaredFramework { - umbrella header "JaredFramework.h" - - export * - module * { export * } -} - -module JaredFramework.Swift { - header "JaredFramework-Swift.h" - requires objc -} diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Resources/Configuration.plist b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Resources/Configuration.plist deleted file mode 100644 index 54e75a04..00000000 --- a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Resources/Configuration.plist +++ /dev/null @@ -1,50 +0,0 @@ - - - - - actionType - - 2000 - love - 2001 - like - 2002 - dislike - 2003 - laugh - 2004 - exclaim - 2005 - question - - sendStyle - - com.apple.messages.effect.CKSpotlightEffect - spotlight - com.apple.messages.effect.CKSparklesEffect - celebration - com.apple.messages.effect.CKShootingStarEffect - shootingStar - com.apple.messages.effect.CKLasersEffect - lasers - com.apple.messages.effect.CKHeartEffect - love - com.apple.messages.effect.CKHappyBirthdayEffect - balloons - com.apple.messages.effect.CKFireworksEffect - fireworks - com.apple.messages.effect.CKConfettiEffect - confetti - com.apple.MobileSMS.expressivesend.loud - loud - com.apple.MobileSMS.expressivesend.invisibleink - invisibleInk - com.apple.MobileSMS.expressivesend.gentle - gentle - com.apple.messages.effect.CKEchoEffect - echo - com.apple.MobileSMS.expressivesend.impact - slam - - - diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Resources/Info.plist b/Documentation/SampleModule/JaredFramework.framework/Versions/A/Resources/Info.plist deleted file mode 100644 index bca51c09..00000000 --- a/Documentation/SampleModule/JaredFramework.framework/Versions/A/Resources/Info.plist +++ /dev/null @@ -1,48 +0,0 @@ - - - - - BuildMachineOSBuild - 19F101 - CFBundleDevelopmentRegion - en - CFBundleExecutable - JaredFramework - CFBundleIdentifier - com.jaredapp.JaredFramework - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - JaredFramework - CFBundlePackageType - FMWK - CFBundleShortVersionString - 3.0 - CFBundleSignature - ???? - CFBundleSupportedPlatforms - - MacOSX - - CFBundleVersion - 1 - DTCompiler - com.apple.compilers.llvm.clang.1_0 - DTPlatformBuild - 11E708 - DTPlatformVersion - GM - DTSDKBuild - 19G68 - DTSDKName - macosx10.15 - DTXcode - 1160 - DTXcodeBuild - 11E708 - LSMinimumSystemVersion - 10.13 - NSHumanReadableCopyright - Copyright © 2016 Zeke Snider. All rights reserved. - - diff --git a/Documentation/SampleModule/JaredFramework.framework/Versions/Current b/Documentation/SampleModule/JaredFramework.framework/Versions/Current deleted file mode 120000 index 8c7e5a66..00000000 --- a/Documentation/SampleModule/JaredFramework.framework/Versions/Current +++ /dev/null @@ -1 +0,0 @@ -A \ No newline at end of file diff --git a/Documentation/SampleModule/readme.md b/Documentation/SampleModule/readme.md deleted file mode 100644 index 6f85ce50..00000000 --- a/Documentation/SampleModule/readme.md +++ /dev/null @@ -1,12 +0,0 @@ -# Sample Module - -This is a sample project to demonstrate how a third party plugin can be built. The main project requirements are: - -* The project must be configured to build a bundle target -* `JaredFramework.framework` must be linked and included -* In `Info.plist` set `JaredFrameworkVersion` to the correct version -* In `Info.plist` set `Principal class` to be the the subclass of `RoutingModule` that should be used. - -To create the routing module you must subclass `RoutingModule`. Routes can be defined and added to the `routes` member variable. Action handler methods must accept a `Message` variable and return void. Your initializer will receive a `MessageSender` object, and you can use it at any time to send messages. You can construct a `RecipientEntity` yourself, or you can just call `message.RespondTo()` to respond to the incoming message. - -If you use `self` for callbacks, be very careful to use a weak reference, [to avoid memory leaks](https://zeke.dev/automatic-reference-counting-with-self/). \ No newline at end of file diff --git a/Documentation/n8n.md b/Documentation/n8n.md index f80c87e4..35077dc6 100644 --- a/Documentation/n8n.md +++ b/Documentation/n8n.md @@ -39,7 +39,7 @@ Replace `YOUR-WORKFLOW-ID` with the path from your n8n Webhook node trigger URL. ### Step 2 — Reload Jared -Either send `/reload` in any iMessage conversation, or click **Reload Plugins** in the Jared menu bar icon. +Either send `/reload` in any iMessage conversation, or click **Reload Configuration** in the Jared menu bar icon. ### Step 3 — Import the starter workflow diff --git a/Documentation/plugins.md b/Documentation/plugins.md deleted file mode 100644 index 80c2b597..00000000 --- a/Documentation/plugins.md +++ /dev/null @@ -1,12 +0,0 @@ -# Plugins - -Plugins allow you to add additional routing modules to Jared by using native Swift code. - -If you would like to develop your own Jared plugins, you need to build a .bundle to be loaded by Jared. You must include JaredFramework.framework in your project and define a public subclass of RoutingModule. The bundle must set this class as the principle class in `Info.plist`. `Info.plist` must also contain a string for `JaredFrameworkVersion`, the current version number is `J3.0.0`. - -To include JaredFramework you have 3 options: -1. Manually include it in the project (Grab it from the [release](https://github.com/ZekeSnider/Jared/releases/latest) page) -2. Use [Carthage](https://github.com/Carthage/Carthage) -3. Use [CocoaPods](https://cocoapods.org) (coming soon) - -Take a look at the [Sample project](/Documentation/SampleModule) to see how the project should be configured. The README there contains instructions for how to build a plugin. Also look at the modules in contained in the main project for examples of more complicated routings. \ No newline at end of file diff --git a/Documentation/readme.md b/Documentation/readme.md index 0ba02727..5534f8e0 100644 --- a/Documentation/readme.md +++ b/Documentation/readme.md @@ -3,8 +3,6 @@ Welcome to the Jared documentation hub. Here you'll find a glossary of Jared's API documentation. + [Routes](routes.md) -+ [Plugins](plugins.md) -+ [Sample Plugin](SampleModule) + [Webhooks](webhooks.md) + [n8n Integration](n8n.md) + [REST API](restapi.md) diff --git a/Documentation/routes.md b/Documentation/routes.md index 515114c7..4ae0d94d 100644 --- a/Documentation/routes.md +++ b/Documentation/routes.md @@ -1,6 +1,6 @@ # Routes -By using either native plugins, or a webhook configuration, you can define routes which are used to define triggers for messages. +By using a webhook configuration, you can define routes which are used to define triggers for messages. ## Parameters @@ -16,7 +16,7 @@ By using either native plugins, or a webhook configuration, you can define route `parameterSyntax`: A string that describes how to exercise your route. `description`: A string that describes the purpose of this route -`call`: A callback method to execute when the route is triggered. This is only required for native plugins. If you're using webhooks, your webhook endpoint will be called automatically. +`call`: A callback method to execute when the route is triggered. When using webhooks, your webhook endpoint is called automatically. ## Example The following is an example configuration of one of Jared's built in routes, `/send`. diff --git a/Jared/ConfigurationHelper.swift b/Jared/ConfigurationHelper.swift index 93d759f1..6db0d01d 100644 --- a/Jared/ConfigurationHelper.swift +++ b/Jared/ConfigurationHelper.swift @@ -46,15 +46,6 @@ struct ConfigurationHelper { return supportDir } - static func getPluginDirectory() -> URL { - let supportDir = getSupportDirectory() - .appendingPathComponent("Plugins") - - try! fileManager.createDirectory(at: supportDir, withIntermediateDirectories: true, attributes: nil) - - return supportDir - } - private static func createConfigFileIfNotExists(at path: URL, using fileManager: FileManager) { guard !fileManager.fileExists(atPath: path.path) else { return } guard let source = Bundle.main.resourceURL?.appendingPathComponent("config.json") else { diff --git a/Jared/PluginManager.swift b/Jared/PluginManager.swift index e488ce16..bdc6cc0a 100644 --- a/Jared/PluginManager.swift +++ b/Jared/PluginManager.swift @@ -10,10 +10,7 @@ import Foundation import JaredFramework class PluginManager: RouteProvider, PluginController, ConfigurationApplier { - var FrameworkVersion: String = "J3.0.0" private var modules: [RoutingModule] = [] - private var bundles: [Bundle] = [] - var pluginDir: URL var disabled = false var config: ConfigurationFile var webhooks: [String]? @@ -21,16 +18,14 @@ class PluginManager: RouteProvider, PluginController, ConfigurationApplier { var sender: MessageSender public var router: Router! private var configWatcher: ConfigurationWatcher? - - init (sender: MessageSender, configuration: ConfigurationFile, pluginDir: URL) { + + init(sender: MessageSender, configuration: ConfigurationFile) { self.sender = sender - self.pluginDir = pluginDir self.config = configuration - + webHookManager = WebHookManager(webhooks: configuration.webhooks, sender: sender) router = Router(pluginManager: self, messageDelegates: [webHookManager]) - - loadPlugins() + addInternalModules() } @@ -56,62 +51,8 @@ class PluginManager: RouteProvider, PluginController, ConfigurationApplier { modules.append(webHookManager) } - func loadPlugins() { - //Loop through all files in our plugin directory - let filemanager = FileManager.default - let files = filemanager.enumerator(at: pluginDir, includingPropertiesForKeys: [], - options: [.skipsHiddenFiles, .skipsPackageDescendants], errorHandler: nil) - - while let file = files?.nextObject() as? URL { - if let bundle = validateBundle(file) { - loadBundle(bundle) - } - } - } - - private func validateBundle(_ file: URL) -> Bundle? { - //Only unpackage bundles - guard file.pathExtension == "bundle" else { - return nil - } - - guard let myBundle = Bundle(url: file) else { - return nil - } - - return myBundle - } - - func loadBundle(_ myBundle: Bundle) { - //Check version of the framework that this plugin is using - //TODO: Add better version comparison (2.1.0 should be compatible with 2.0.0) - guard myBundle.infoDictionary?["JaredFrameworkVersion"] as? String == self.FrameworkVersion else { - return - } - - //Cast the class to RoutingModule protocol - guard let principleClass = myBundle.principalClass as? RoutingModule.Type else { - return - } - - //Initialize it - let module: RoutingModule = principleClass.init(sender: sender) - bundles.append(myBundle) - - //Add it to our modules - modules.append(module) - } - - func reload() { + func reload() { modules.removeAll() - - for bundle in bundles { - bundle.unload() - } - - bundles.removeAll() - - loadPlugins() addInternalModules() } diff --git a/Jared/en.lproj/Localizable.strings b/Jared/en.lproj/Localizable.strings index bdb91c33..c3c26237 100644 --- a/Jared/en.lproj/Localizable.strings +++ b/Jared/en.lproj/Localizable.strings @@ -49,8 +49,8 @@ "helpDescription" = "Get help on commands"; /* reload */ -"reloadDescription" = "Reload plugins"; -"reloadMessage" = "Successfully reloaded plugins."; +"reloadDescription" = "Reload configuration"; +"reloadMessage" = "Successfully reloaded configuration."; "commandPrefix" = "Command: "; "parametersPrefix" = "Parameters: "; diff --git a/JaredUI/AppDelegate.swift b/JaredUI/AppDelegate.swift index 555d8c5c..d5f92131 100644 --- a/JaredUI/AppDelegate.swift +++ b/JaredUI/AppDelegate.swift @@ -29,7 +29,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { let config = ConfigurationHelper.getConfiguration() sender = Jared() - pluginManager = PluginManager(sender: sender, configuration: config, pluginDir: ConfigurationHelper.getPluginDirectory()) + pluginManager = PluginManager(sender: sender, configuration: config) let webServer = JaredWebServer(sender: sender, configuration: config.webServer) server = webServer let configuredPort = config.webServer.port diff --git a/JaredUI/MenuBarManager.swift b/JaredUI/MenuBarManager.swift index 36cd193f..0498222b 100644 --- a/JaredUI/MenuBarManager.swift +++ b/JaredUI/MenuBarManager.swift @@ -61,7 +61,7 @@ class MenuBarManager { sleepItem.state = UserDefaults.standard.bool(forKey: JaredConstants.preventSystemSleep) ? .on : .off menu.addItem(sleepItem) - let reloadItem = NSMenuItem(title: "Reload Plugins", action: #selector(reloadPlugins), keyEquivalent: "r") + let reloadItem = NSMenuItem(title: "Reload Configuration", action: #selector(reloadConfiguration), keyEquivalent: "r") reloadItem.target = self menu.addItem(reloadItem) @@ -89,7 +89,7 @@ class MenuBarManager { UserDefaults.standard.set(!current, forKey: JaredConstants.preventSystemSleep) } - @objc private func reloadPlugins() { + @objc private func reloadConfiguration() { pluginManager.reload() } diff --git a/JaredUI/ViewController.swift b/JaredUI/ViewController.swift index 11859e74..6a134b02 100644 --- a/JaredUI/ViewController.swift +++ b/JaredUI/ViewController.swift @@ -226,17 +226,13 @@ class ViewController: NSViewController, DiskAccessDelegate { let container = NSView() container.translatesAutoresizingMaskIntoConstraints = false - let reloadBtn = toolButton("Reload plugins", icon: "arrow.clockwise", action: #selector(ReloadButtonPressed(_:))) - let pluginsBtn = toolButton("Open plugins folder", icon: "folder", action: #selector(OpenPluginsButtonAction(_:))) + let reloadBtn = toolButton("Reload Configuration", icon: "arrow.clockwise", action: #selector(ReloadButtonPressed(_:))) container.addSubview(reloadBtn) - container.addSubview(pluginsBtn) NSLayoutConstraint.activate([ container.heightAnchor.constraint(equalToConstant: 56), reloadBtn.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 20), reloadBtn.centerYAnchor.constraint(equalTo: container.centerYAnchor), - pluginsBtn.leadingAnchor.constraint(equalTo: reloadBtn.trailingAnchor, constant: 8), - pluginsBtn.centerYAnchor.constraint(equalTo: container.centerYAnchor), ]) return container } @@ -503,12 +499,6 @@ class ViewController: NSViewController, DiskAccessDelegate { } } - @IBAction func OpenPluginsButtonAction(_ sender: Any) { - let appsupport = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0] - let pluginDir = appsupport.appendingPathComponent("Jared").appendingPathComponent("Plugins") - NSWorkspace.shared.selectFile(nil, inFileViewerRootedAtPath: pluginDir.path) - } - @IBAction func ReloadButtonPressed(_ sender: Any) { (NSApplication.shared.delegate as? AppDelegate)?.pluginManager.reload() } diff --git a/readme.md b/readme.md index bb3636df..20baff44 100644 --- a/readme.md +++ b/readme.md @@ -84,11 +84,6 @@ See [config-sample.json](Documentation/config-sample.json) for an example. ## Extensions Jared Provides a variety of APIs to allow you to easily add your own commands, automate messages, and more. For all API documentation, see the [documentation hub](/Documentation). -### Plugins -Additional routes can be added via modularized plugins, written in native Swift code. Plugins are loaded dynamically from the `~/Library/Application Support/Jared/Plugins` folder. To install a module, drag it in there and then send `/reload` to Jared, or click `Reload Plugins` in the UI. - -For more information on developing your own plugins, see the [plugin documentation](Documentation/plugins.md). If you developed any plugins, please send me a link so I can add a link here! I will be working on a few extra modules of my own as well, and will add them here when they are complete. - ### Webhooks Jared supports webhooks for sending your server information about incoming and outgoing messages. Your server can respond to these requests to send messages, or use the REST API to send messages at any time. To configure webhooks, add them to the `config.json` mentioned above. For more info on the webhooks API, check out the [webhook documentation](Documentation/webhooks.md). @@ -96,6 +91,6 @@ Jared supports webhooks for sending your server information about incoming and o Jared contains a web server with a REST API that can be enabled. This allows you make HTTP requests to send messages to any recipient. For more information, [check out the REST API documentation](Documentation/restapi.md). ## How Jared works -Jared reads from the Messages database on a set interval and queries for new messages. It provides a routing framework for actioning on messages, and uses AppleScript to send outgoing messages. It's also multi-threaded so it can take care of multiple requests at once. Jared allows expansion via `.bundle` plugin files, webhooks, and a REST API. This allows commands to be added without modifying the main Jared code base. +Jared reads from the Messages database on a set interval and queries for new messages. It provides a routing framework for actioning on messages, and uses AppleScript to send outgoing messages. It's also multi-threaded so it can take care of multiple requests at once. Jared allows expansion via webhooks and a REST API. I've tried using private APIs such as MessagesKit to send/receive messages to no avail so far. If you have any leads on this front I'd love to hear about it.