/// <summary> /// Registers custom actions found in the action directory /// </summary> private static void RegisterCustomActions() { Logger.WriteLine(LogLevel.Verbose, "discovering and registering custom actions"); foreach (string path in Directory.EnumerateFiles(Path.Combine(AppDirectory, "Actions"), "*", SearchOption.AllDirectories)) { CustomAction action = DeserializeAction(path); if (action != null) { CustomActions[Path.GetFileNameWithoutExtension(path)] = action; } } }
/// <summary> /// Watches the action directory for changes and performs the pertinent tasks /// </summary> private static void WatchActionDirectory() { FileSystemWatcher watcher = new FileSystemWatcher(Path.Combine(AppDirectory, "Actions")) { IncludeSubdirectories = true, EnableRaisingEvents = true, NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Size }; watcher.Deleted += delegate(object sender, FileSystemEventArgs args) { string key = Path.GetFileNameWithoutExtension(args.Name); Logger.WriteLine(LogLevel.Verbose, "action has been deleted: {0}", key); if (CustomActions.ContainsKey(key)) { CustomActions.Remove(key); } if (Preferences.ActionType == ActionType.CustomAction && Preferences.ActionName == key) { Preferences tempPreferences = new Preferences(); Preferences.ActionType = tempPreferences.ActionType; Preferences.ActionName = tempPreferences.ActionName; UnregisterHotKeys(); RegisterHotKeys(); Preferences.Save(); } UpdatePreferencesDialog(); }; watcher.Changed += delegate(object sender, FileSystemEventArgs args) { string key = Path.GetFileNameWithoutExtension(args.Name); Logger.WriteLine(LogLevel.Verbose, "action has been updated: {0}", key); if (CustomActions.ContainsKey(key)) { CustomActions.Remove(key); } CustomAction action = DeserializeAction(args.FullPath); if (action != null) { CustomActions[key] = action; } UpdatePreferencesDialog(); }; watcher.Renamed += delegate(object sender, RenamedEventArgs args) { string key = Path.GetFileNameWithoutExtension(args.Name), oldKey = Path.GetFileNameWithoutExtension(args.OldName); Logger.WriteLine(LogLevel.Verbose, "action has been renamed: {0} -> {1}", oldKey, key); if (CustomActions.ContainsKey(oldKey)) { CustomActions.Add(key, CustomActions[oldKey]); CustomActions.Remove(oldKey); } if (Preferences.ActionType == ActionType.CustomAction && Preferences.ActionName == oldKey) { Preferences.ActionName = key; Logger.WriteLine(LogLevel.Informational, "new user action set: {0} -> {1}", oldKey, key); Preferences.Save(); } UpdatePreferencesDialog(); }; watcher.Created += delegate(object sender, FileSystemEventArgs args) { string key = Path.GetFileNameWithoutExtension(args.Name); Logger.WriteLine(LogLevel.Verbose, "created action: {0}", key); if (!CustomActions.ContainsKey(key)) { Logger.WriteLine(LogLevel.Verbose, "unregistering previous conflicting action"); CustomAction action = DeserializeAction(args.FullPath); if (action != null) { CustomActions[key] = action; } UpdatePreferencesDialog(); } ; }; new Thread(new ThreadStart(() => { try { watcher.WaitForChanged(WatcherChangeTypes.All); Logger.WriteLine(LogLevel.Verbose, "watching action directory"); } catch { Logger.WriteLine(LogLevel.Warning, "failed to watch action directory"); } })).Start(); }
public static CustomAction ToCustomAction(string json) { SharexUploader uploader = JsonConvert.DeserializeObject <SharexUploader>(json); if (String.IsNullOrWhiteSpace(uploader.FileFormName)) { App.Logger.WriteLine(LogLevel.Error, "invalid ShareX uploader: no FileFormName field found"); return(null); } CustomAction customAction = new CustomAction() { ActionID = json.GetHashCode().ToString("x"), Method = uploader.RequestType, URL = uploader.RequestURL, Name = uploader.FileFormName, Headers = uploader.Headers }; App.Logger.WriteLine(LogLevel.Verbose, "trying to build match for custom action"); if (!String.IsNullOrWhiteSpace(uploader.URL)) { Regex expr = new Regex(@"\$(?:(xml|json)\:(.+?))|(?:regex\:([0-9]+)\,?([0-9]+)?)\$", RegexOptions.Compiled); MatchCollection matches = expr.Matches(uploader.URL); // select 1 for each distinct guard type in this template - if the result count is greater than 1 this uploader is mixing guards, which is not supported if ((from Match m in matches group m by m.Groups[1].Value into _ select 1).ToArray().Length > 1) { App.Logger.WriteLine(LogLevel.Error, "unsupported uploader: distinct guard types are being mixed up"); return(null); } // try to convert matches customAction.Match = new CustomActionMatch(); switch (matches[0].Groups[0].Value) { case "json": customAction.Match.Type = CustomActionMatchType.JSON; customAction.Match.Template = expr.Replace(uploader.URL, new MatchEvaluator((Match match) => { return("{" + match.Groups[2] + "}"); })); break; case "xml": customAction.Match.Type = CustomActionMatchType.XML; customAction.Match.Template = expr.Replace(uploader.URL, new MatchEvaluator((Match match) => { return("{" + match.Groups[2] + "}"); })); break; case "regex": customAction.Match.Type = CustomActionMatchType.Regex; customAction.Match.Matches = uploader.RegexList; customAction.Match.Template = expr.Replace(uploader.URL, new MatchEvaluator((Match match) => { return("{" + match.Groups[1] + " " + match.Groups[2] + "}"); })); break; } } else { App.Logger.WriteLine(LogLevel.Warning, "no URL template found on ShareX uploader - assuming redirection"); } return(customAction); }