Kaynağa Gözat

Add "Conditional Executution" plugin.

Change-Id: I4fd30159ea93503c7354d07739ffdcb6a1dedebb
Reviewed-on: http://gerrit.dmdirc.com/2629
Automatic-Compile: DMDirc Build Manager
Reviewed-by: Chris Smith <chris@dmdirc.com>
Reviewed-by: Greg Holmes <greg@dmdirc.com>
tags/0.8
Shane Mc Cormack 11 yıl önce
ebeveyn
işleme
30395f609d

+ 214
- 0
src/com/dmdirc/addons/conditional_execute/ConditionalExecuteCommand.java Dosyayı Görüntüle

@@ -0,0 +1,214 @@
1
+/*
2
+ * Copyright (c) 2006-2013 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.addons.conditional_execute;
24
+
25
+import com.dmdirc.FrameContainer;
26
+import com.dmdirc.WritableFrameContainer;
27
+import com.dmdirc.commandparser.BaseCommandInfo;
28
+import com.dmdirc.commandparser.CommandArguments;
29
+import com.dmdirc.commandparser.CommandType;
30
+import com.dmdirc.commandparser.commands.Command;
31
+import com.dmdirc.commandparser.commands.context.CommandContext;
32
+import java.util.HashMap;
33
+import java.util.Map;
34
+
35
+/**
36
+ * The ConditionalExecute command allows the user to conditionally execute a
37
+ * command based on external and pre-determined conditions.
38
+ */
39
+public class ConditionalExecuteCommand extends Command {
40
+
41
+    /** Store details about current namespaces. */
42
+    private final Map<String, ConditionalExecuteNamespace> namespaces = new HashMap<String, ConditionalExecuteNamespace>();
43
+
44
+    /** A command info object for this command. */
45
+    public static final BaseCommandInfo INFO = new BaseCommandInfo("conditionalexecute", "conditionalexecute <args> - Conditionally execute a command", CommandType.TYPE_GLOBAL);
46
+
47
+    /** {@inheritDoc} */
48
+    @Override
49
+    public void execute(final FrameContainer origin, final CommandArguments args, final CommandContext context) {
50
+        final String cmdname = args.getWordsAsString(0, 0);
51
+
52
+        ConditionalExecuteNamespace namespace = null;
53
+        final String[] arguments = args.getArguments();
54
+        boolean manipulated = false;
55
+        boolean inverse = false;
56
+
57
+        for (int i = 0; i < arguments.length; i++) {
58
+            final String arg = arguments[i].toLowerCase();
59
+            final String nextArg = i + 1 < arguments.length ? arguments[i + 1] : "";
60
+
61
+            if (arg.equalsIgnoreCase("--help")) {
62
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Usage:");
63
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "");
64
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, cmdname + " <args>");
65
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, cmdname + " --namespace <name> <namespace commands>");
66
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, cmdname + " --namespace <name> [--inverse] </commandToRun <command args>>");
67
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "");
68
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Commands can only be specified if no other non-namespace args are given.");
69
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "");
70
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "When trying to run a command, the namespace will be checked to see if the command can be run.");
71
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "The checks performed are as follows:");
72
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "   1) Does the namespace exist? if not, run the command and create the namespace.");
73
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "   2) Is the namespace inhibited? - Do not run the command.");
74
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "   3) Is the namespace in forced mode? - Run the command.");
75
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "   4) If --inverse is specified, are we under the limit time? Run the command");
76
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "   5) If --inverse is not specified, are we over the limit time? Run the command");
77
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "   6) Do not run the command.");
78
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "");
79
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "General Arguments.");
80
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --list                   - List all current namespaces and their status");
81
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --help                   - Print this help.");
82
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --reset                  - Remove all namespaces.");
83
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "");
84
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Useful things:");
85
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --namespace <name>       - Namespace to modify. If the namespace does not exist, it will be created. Namespaces are not remembered across sessions.");
86
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "");
87
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Arguments related to a namespace:");
88
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --settime <time>         - Set the limit time on this namespace. Time can be either a time in seconds, 'now' for now, or 'nowifless' to set to now only if it is currently less.");
89
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --delay <seconds>        - Increase the 'limit' time on this namespace by <seconds> seconds");
90
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --inhibit                - Prevent any attempts at running commands in this namespace from executing");
91
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --force                  - Any future attempts at running commands in this namespace will always execute");
92
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --allow                  - Disable '--force' or '--inhibit' and resume normal operation.");
93
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --remove                 - Remove this namespace.");
94
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --status                 - Show the status of this namespace.");
95
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "");
96
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Arguments when running a command:");
97
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "  --inverse              - Inverse the match against the 'limit' time.");
98
+                return;
99
+            } else if (arg.equalsIgnoreCase("--list")) {
100
+                if (namespaces.isEmpty()) {
101
+                    sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "There are currently no known namespaces.");
102
+                } else {
103
+                    sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Current namespaces: ");
104
+                    for (final Map.Entry<String, ConditionalExecuteNamespace> e : namespaces.entrySet()) {
105
+                        sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "    " + e.getValue().toString());
106
+                    }
107
+                }
108
+                return;
109
+            } else if (arg.equalsIgnoreCase("--reset")) {
110
+                namespaces.clear();
111
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "All namespaces removed.");
112
+                return;
113
+            } else if (namespace == null) {
114
+                if (arg.equalsIgnoreCase("--namespace")) {
115
+                    if (nextArg.isEmpty()) {
116
+                        sendLine(origin, args.isSilent(), FORMAT_ERROR, "Error: You must specify a namespace.");
117
+                        return;
118
+                    } else {
119
+                        if (!namespaces.containsKey(nextArg.toLowerCase())) {
120
+                            namespaces.put(nextArg.toLowerCase(), new ConditionalExecuteNamespace(nextArg.toLowerCase()));
121
+                        }
122
+                        namespace = namespaces.get(nextArg.toLowerCase());
123
+
124
+                        // Skip the next argument.
125
+                        i++;
126
+                    }
127
+                } else {
128
+                    sendLine(origin, args.isSilent(), FORMAT_ERROR, "Error: You must specify a namespace first.");
129
+                    return;
130
+                }
131
+            } else if (arg.equalsIgnoreCase("--inhibit")) {
132
+                namespace.inhibit();
133
+                manipulated = true;
134
+            } else if (arg.equalsIgnoreCase("--force")) {
135
+                namespace.force();
136
+                manipulated = true;
137
+            } else if (arg.equalsIgnoreCase("--allow")) {
138
+                namespace.reset();
139
+                manipulated = true;
140
+            } else if (arg.equalsIgnoreCase("--settime")) {
141
+                if (nextArg.isEmpty()) {
142
+                    sendLine(origin, args.isSilent(), FORMAT_ERROR, "Error: You must provide a time to use.");
143
+                    return;
144
+                } else if (nextArg.equalsIgnoreCase("now")) {
145
+                    namespace.setLimit(System.currentTimeMillis());
146
+                    i++;
147
+                    manipulated = true;
148
+               } else if (nextArg.equalsIgnoreCase("nowifless")) {
149
+                    if (namespace.getLimitTime() < System.currentTimeMillis()) {
150
+                        namespace.setLimit(System.currentTimeMillis());
151
+                    }
152
+                    i++;
153
+                    manipulated = true;
154
+                } else {
155
+                    try {
156
+                        namespace.setLimit(Long.parseLong(nextArg) * 1000);
157
+                        i++;
158
+                        manipulated = true;
159
+                    } catch (final NumberFormatException nfe) {
160
+                        sendLine(origin, args.isSilent(), FORMAT_ERROR, "Error: Invalid time: " + nextArg);
161
+                        return;
162
+                    }
163
+                }
164
+            } else if (arg.equalsIgnoreCase("--delay")) {
165
+                if (nextArg.isEmpty()) {
166
+                    sendLine(origin, args.isSilent(), FORMAT_ERROR, "Error: You must provide a delay to use.");
167
+                    return;
168
+                } else {
169
+                    try {
170
+                        namespace.changeLimit(Long.parseLong(nextArg) * 1000);
171
+                        i++;
172
+                        manipulated = true;
173
+                    } catch (final NumberFormatException nfe) {
174
+                        sendLine(origin, args.isSilent(), FORMAT_ERROR, "Error: Invalid delay: " + nextArg);
175
+                        return;
176
+                    }
177
+                }
178
+            } else if (arg.equalsIgnoreCase("--remove")) {
179
+                namespaces.remove(namespace.getName());
180
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Removed namespace '" + namespace.getName() + "'");
181
+                return;
182
+            } else if (arg.equalsIgnoreCase("--status")) {
183
+                // Show the current status, incase some manipulations occured prior to this.
184
+                sendLine(origin, args.isSilent(), FORMAT_OUTPUT, namespaces.get(namespace.getName()));
185
+                return;
186
+            } else if (arg.equalsIgnoreCase("--inverse")) {
187
+                inverse = true;
188
+            } else if (manipulated) {
189
+                sendLine(origin, args.isSilent(), FORMAT_ERROR, "You can't run commands and manipulate the namespace at the same time, ignored.");
190
+            } else {
191
+                // Command to run!
192
+                if (namespace.canRun(inverse) && origin instanceof WritableFrameContainer) {
193
+                    ((WritableFrameContainer) origin).getCommandParser().parseCommand(origin, args.getArgumentsAsString(i++));
194
+                }
195
+                return;
196
+            }
197
+        }
198
+
199
+        // If we get here, we either manipulated something, or should show the usage text.
200
+        if (manipulated) {
201
+            sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Namespace updated.");
202
+            sendLine(origin, args.isSilent(), FORMAT_OUTPUT, namespace.toString());
203
+            namespaces.put(namespace.getName(), namespace);
204
+        } else {
205
+            sendLine(origin, args.isSilent(), FORMAT_ERROR, "Usage:");
206
+            sendLine(origin, args.isSilent(), FORMAT_ERROR, "");
207
+            sendLine(origin, args.isSilent(), FORMAT_ERROR, cmdname + " <args>");
208
+            sendLine(origin, args.isSilent(), FORMAT_ERROR, cmdname + " --namespace <name> <namespace commands>");
209
+            sendLine(origin, args.isSilent(), FORMAT_ERROR, cmdname + " --namespace <name> [--inverse] </commandToRun <command args>>");
210
+            sendLine(origin, args.isSilent(), FORMAT_ERROR, "");
211
+            sendLine(origin, args.isSilent(), FORMAT_ERROR, "For more information, see " + cmdname + " --help");
212
+        }
213
+    }
214
+}

+ 167
- 0
src/com/dmdirc/addons/conditional_execute/ConditionalExecuteNamespace.java Dosyayı Görüntüle

@@ -0,0 +1,167 @@
1
+/*
2
+ * Copyright (c) 2006-2013 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.addons.conditional_execute;
24
+
25
+import java.text.DateFormat;
26
+import java.text.SimpleDateFormat;
27
+
28
+/**
29
+ * Class representing a ConditionalExecute Namespace.
30
+ */
31
+public class ConditionalExecuteNamespace {
32
+    /** Name of this namespace. */
33
+    private final String name;
34
+
35
+    /** Are we currently inhibited? */
36
+    private boolean inhibited = false;
37
+
38
+    /** Are we currently forced? */
39
+    private boolean forced = false;
40
+
41
+    /** What is the current limit time? */
42
+    private long limitTime = 0L;
43
+
44
+    /**
45
+     * Create a new ConditionalExecuteNamespace.
46
+     *
47
+     * @param name Name of this Namespace
48
+     */
49
+    public ConditionalExecuteNamespace(final String name) {
50
+        this.name = name;
51
+    }
52
+
53
+    /**
54
+     * Can a command in this namespace be run?
55
+     *
56
+     * This checks as follows:
57
+     *   - Is the namespace inhibited? - return False
58
+     *   - Is the namespace in "force" mode?  - return True
59
+     *   - If inverse is true, are we under the limit time? return True
60
+     *   - If inverse is false, are we over the limit time? return True
61
+     *   - return False
62
+     *
63
+     * @param inverse Check if we are *before* the limit time rather than after?
64
+     * @return True if the command can be run.
65
+     */
66
+    public boolean canRun(final boolean inverse) {
67
+        return !isInhibited() && (isForced() || inverse == System.currentTimeMillis() < limitTime);
68
+    }
69
+
70
+    /** Inhibit this namespace. */
71
+    public void inhibit() {
72
+        this.inhibited = true;
73
+        this.forced = false;
74
+    }
75
+
76
+    /** Force this namespace. */
77
+    public void force() {
78
+        this.inhibited = false;
79
+        this.forced = true;
80
+    }
81
+
82
+    /** UnForce and Uninhibit this namespace. */
83
+    public void reset() {
84
+        this.inhibited = false;
85
+        this.forced = false;
86
+    }
87
+
88
+    /**
89
+     * Change the limit time on this namespace.
90
+     *
91
+     * @param difference Change (in milliseconds) to make to the limit time.
92
+     * @return New limit time.
93
+     */
94
+    public long changeLimit(final long difference) {
95
+        this.limitTime += difference;
96
+        return this.limitTime;
97
+    }
98
+
99
+    /**
100
+     * Set the limit time on this namespace.
101
+     *
102
+     * @param time new Limit time (in milliseconds)
103
+     * @return New limit time.
104
+     */
105
+    public long setLimit(final long time) {
106
+        this.limitTime = time;
107
+        return this.limitTime;
108
+    }
109
+
110
+    /**
111
+     * Are we currently forced?
112
+     *
113
+     * @return Are we currently forced?
114
+     */
115
+    public boolean isForced() {
116
+        return forced;
117
+    }
118
+
119
+    /**
120
+     * Are we currently inhibited?
121
+     *
122
+     * @return Are we currently inhibited?
123
+     */
124
+    public boolean isInhibited() {
125
+        return inhibited;
126
+    }
127
+
128
+    /**
129
+     * Current limit time.
130
+     *
131
+     * @return The current limit time.
132
+     */
133
+    public long getLimitTime() {
134
+        return limitTime;
135
+    }
136
+
137
+    /**
138
+     * Get the name of this namespace.
139
+     *
140
+     * @return The name of this namespace.
141
+     */
142
+    public String getName() {
143
+        return name;
144
+    }
145
+
146
+    /** {@inheritDoc} */
147
+    @Override
148
+    public String toString() {
149
+        final StringBuilder sb = new StringBuilder(getName());
150
+        if (isForced()) {
151
+          sb.append(" - Forced");
152
+        } else if (isInhibited()) {
153
+          sb.append(" - Inhibited");
154
+        } else {
155
+          sb.append(" - Limit Time: ");
156
+          final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
157
+          sb.append(dateFormat.format(limitTime));
158
+        }
159
+        if (canRun(false)) {
160
+            sb.append(" [Can Run]");
161
+        }
162
+        if (canRun(true)) {
163
+            sb.append(" [Can Run Inverse]");
164
+        }
165
+        return sb.toString();
166
+    }
167
+}

+ 43
- 0
src/com/dmdirc/addons/conditional_execute/ConditionalExecutePlugin.java Dosyayı Görüntüle

@@ -0,0 +1,43 @@
1
+/*
2
+ * Copyright (c) 2006-2013 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.addons.conditional_execute;
24
+
25
+import com.dmdirc.interfaces.CommandController;
26
+import com.dmdirc.plugins.implementations.BaseCommandPlugin;
27
+
28
+/**
29
+ * The ConditionalExecute plugin allows the user to run commands only if
30
+ * external conditions have been met.
31
+ */
32
+public final class ConditionalExecutePlugin extends BaseCommandPlugin {
33
+
34
+    /**
35
+     * Creates a new instance of this plugin.
36
+     *
37
+     * @param commandController Command controller to register commands
38
+     */
39
+    public ConditionalExecutePlugin(final CommandController commandController) {
40
+        super(commandController);
41
+        registerCommand(new ConditionalExecuteCommand(), ConditionalExecuteCommand.INFO);
42
+    }
43
+}

+ 27
- 0
src/com/dmdirc/addons/conditional_execute/plugin.config Dosyayı Görüntüle

@@ -0,0 +1,27 @@
1
+# This is a DMDirc configuration file.
2
+
3
+# This section indicates which sections below take key/value
4
+# pairs, rather than a simple list. It should be placed above
5
+# any sections that take key/values.
6
+keysections:
7
+  metadata
8
+  updates
9
+  version
10
+
11
+metadata:
12
+  author=Shane Mc Cormack <shane@dmdirc.com>
13
+  mainclass=com.dmdirc.addons.conditional_execute.ConditionalExecutePlugin
14
+  description=Adds commands to allow conditional command execution.
15
+  name=conditional_execute
16
+  nicename=Conditional Execution Plugin
17
+
18
+updates:
19
+  id=73
20
+
21
+version:
22
+  friendly=0.1
23
+
24
+provides:
25
+  conditionalexecute command
26
+
27
+required-services:

Loading…
İptal
Kaydet