Browse Source
feat: add Bot/Hermes input commands (/steer, /queue, /cancel) with real-time streaming and multiline formatting
main
feat: add Bot/Hermes input commands (/steer, /queue, /cancel) with real-time streaming and multiline formatting
main
4 changed files with 251 additions and 23 deletions
-
83src/BotCommandProcessor.swift
-
146src/InputBoxManager.swift
-
27src/TextProcessor.swift
-
4src/VoiceCommandExecutor.swift
@ -0,0 +1,83 @@ |
|||
import Foundation |
|||
|
|||
public struct BotCommandResult { |
|||
public let command: String // "/steer", "/queue", "/cancel" |
|||
public let body: String |
|||
|
|||
public var formattedText: String { |
|||
let cleanBody = body.trimmingCharacters(in: .whitespacesAndNewlines) |
|||
if cleanBody.isEmpty { |
|||
return command |
|||
} |
|||
return "\(command)\n\(cleanBody)" |
|||
} |
|||
} |
|||
|
|||
public final class BotCommandProcessor { |
|||
private static let leadingPunct = CharacterSet(charactersIn: " .,،؛:!؟?\\\"'«»()[]{}—-_") |
|||
|
|||
// Pattern 1: Steer (/steer) |
|||
// Matches: "اسلش اس", "اسلش استیر", "اسلش steer", "slash s", "slash steer", "/s", "/steer" |
|||
private static let steerRegex: NSRegularExpression = { |
|||
let p = "^(?:(?:اسلش|اصلش|slash|\\/)\\s*(?:استیر|steer|اس|s)|\\/(?:steer|s))(?=[.,،؛!؟?:\\s]|$)[.,،؛!؟?:\\s]*(.*)$" |
|||
return try! NSRegularExpression(pattern: p, options: [.caseInsensitive, .dotMatchesLineSeparators]) |
|||
}() |
|||
|
|||
// Pattern 2: Queue (/queue) |
|||
// Matches: "اسلش کیو", "اسلش کوئری", "اسلش queue", "slash q", "slash queue", "/q", "/queue" |
|||
private static let queueRegex: NSRegularExpression = { |
|||
let p = "^(?:(?:اسلش|اصلش|slash|\\/)\\s*(?:کوئری|کیو|queue|q)|\\/(?:queue|q))(?=[.,،؛!؟?:\\s]|$)[.,،؛!؟?:\\s]*(.*)$" |
|||
return try! NSRegularExpression(pattern: p, options: [.caseInsensitive, .dotMatchesLineSeparators]) |
|||
}() |
|||
|
|||
// Pattern 3: Cancel (/cancel) |
|||
// Matches: "اسلش سی", "اسلش کنسل", "اسلش کنسله", "slash c", "slash cancel", "/c", "/cancel" |
|||
private static let cancelRegex: NSRegularExpression = { |
|||
let p = "^(?:(?:اسلش|اصلش|slash|\\/)\\s*(?:کنسله|کنسل|cancel|سی|c)|\\/(?:cancel|c))(?=[.,،؛!؟?:\\s]|$)[.,،؛!؟?:\\s]*(.*)$" |
|||
return try! NSRegularExpression(pattern: p, options: [.caseInsensitive, .dotMatchesLineSeparators]) |
|||
}() |
|||
|
|||
public static func parse(text: String) -> BotCommandResult? { |
|||
let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) |
|||
guard !trimmed.isEmpty else { return nil } |
|||
|
|||
let range = NSRange(location: 0, length: (trimmed as NSString).length) |
|||
|
|||
// 1. Check Steer |
|||
if let match = steerRegex.firstMatch(in: trimmed, options: [], range: range) { |
|||
let body = extractGroup(from: trimmed, match: match, groupIndex: 1) |
|||
return BotCommandResult(command: "/steer", body: body) |
|||
} |
|||
|
|||
// 2. Check Queue |
|||
if let match = queueRegex.firstMatch(in: trimmed, options: [], range: range) { |
|||
let body = extractGroup(from: trimmed, match: match, groupIndex: 1) |
|||
return BotCommandResult(command: "/queue", body: body) |
|||
} |
|||
|
|||
// 3. Check Cancel |
|||
if let match = cancelRegex.firstMatch(in: trimmed, options: [], range: range) { |
|||
let body = extractGroup(from: trimmed, match: match, groupIndex: 1) |
|||
return BotCommandResult(command: "/cancel", body: body) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
private static func extractGroup(from str: String, match: NSTextCheckingResult, groupIndex: Int) -> String { |
|||
guard groupIndex < match.numberOfRanges else { return "" } |
|||
let r = match.range(at: groupIndex) |
|||
guard r.location != NSNotFound else { return "" } |
|||
let rawGroup = (str as NSString).substring(with: r) |
|||
return rawGroup.trimmingCharacters(in: leadingPunct) |
|||
} |
|||
|
|||
public static func isBotCommand(text: String) -> Bool { |
|||
return parse(text: text) != nil |
|||
} |
|||
|
|||
public static func formatIfBotCommand(text: String) -> String? { |
|||
guard let res = parse(text: text) else { return nil } |
|||
return res.formattedText |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue