-
Notifications
You must be signed in to change notification settings - Fork 41
Writing plugins
AntiContainer plugins are simple JSON structures describing one of three plugin types.
The redirector and resolver types are relatively easy to master. sandbox plugins are more powerful in what they can do, however require more knowledge about Javascript and require more time to execute.
You should prefer redirector and resolver if possible.
- To write a new plugin open Preferences/Anti-Container and select Create Plugin.
- To install an existing plugin use Install Plugin from the same tab.
Please note: Do not manipulate the anticontainer_plugins folder yourself. If you do, your plugins might still work, but you cannot uninstall those plugins from the interface.
All existing plugins are available as flat files from Github
As noted, plugins are just JSON structures, defining a common set properties.
Each plugin must provide the following information
-
type (String)
- Type of the plugin, either redirector, resolver or sandbox -
prefix (String)
- Human readable (host) prefix, which might used throughout the user interface -
match (String)
- Regular expression which the URL must match in order to have the plugin applied to it.
Additionally you may also specify
-
priority (Number)
- Higher priority plugins have precedence. Use this, e.g. to strip-of url redirector services. -
useServerName (Boolean)
- If the server later proposes a new file name it will taken into account. Per default only the generated name will be used. -
sendInitialReferrer (Boolean)
- When set totrue
the request that fetches the container page will include a http referrer if available from the download job. -
omitReferrer (Boolean)
- When set totrue
the referrer will NOT be changed to the container page URL and left blank. -
keepReferrer (Boolean)
- When set totrue
the referrer will NOT be changed to the container page URL and the original download referrer is kept. (1.2.4) -
generateName (String)
- If the server and URL do not provide a sane file name you may usegenerateServerName
as a last resort. A UUID will be generated and the value of generateSeverName appended, i.e.gSN = ".jpg"
will generate something likeec8030f7-c20a-464f-9b0e-13a3a9e97384.jpg
-
decode (Boolean)
- When set totrue
the fetched string will be URL-decoded before generating the new URL -
static (Boolean)
- When set totrue
this indicates that once the final URL that is retrieved is static. If the download is re-started, for example, non-static URLs are resolved again, while static URLs will be kept from the previous run.static
is implied for redirector plugins, and defaults tofalse
for other plugin types. -
noFilter (Boolean)
- When set totrue
the plugin will not be considered for automatic filter generation.
Any other properties will be ignored.
You may want to provide some information as well.
-
author (String)
- The name of the plugin author to be displayed in the UI. -
ns (String)
- Namespace URI. Theprefix
andns
properties together form a unique id for the plugin. If omitted the default namespace is used. If two plugins share the same unique id, then the latter will replace (as in physically override) the former. -
updateURL (String)
- A url to update the plugin from. This value will be set automatically if the plugin is installed from the web. (future)
A redirector is the most simple plugin. It takes an URL and returns a modified URL without loading any pages.
-
pattern (String)
- A regular expression used for the replacement -
replacement (String)
- The replacement text
Have a look at mozilla's replace() documentation.
{
"type": "redirector",
"priority": 1,
"prefix": "anonym.to",
"match": "^http://(.*?)anonym\\.to/\\?",
"pattern": "^http://(.*?)anonym\\.to/\\?",
"replacement": ""
}
This will match anonym.to URLs simply replacing the first part of the url with nothing (effectively removing it).
A resolver is a plugin that will examine the source text of the original URL target (website) and use a regular expression to match a certain part (the URL) and return it. A builder expression will then be used to generate the new URL.
-
finder (String)
- Regular expression to match a certain part of a site. Use grouping to later access the parts of the match only. -
builder (String)
- A builder string that will assemble the new URL. See below.
See mozilla's RegExp documentation for more information on regular expressions.
-
namer (String)
- A builder string that will be used as a suggestion for the file name. See below for builder strings. (1.2.3, DTA-3)
Builders use a special syntax to assemble the final URL fragment. There is no need that the result of an URL is fully qualified; you may also return relative URLs.
Beside normal string parts there are manipulators, which allow access to the numbered groups of the finder match.
A manipulator has the form:
{func:param1,param2,...,paramN}
Currently there are three manipulators:
-
num (default if
func
is omitted). Concatenates all match groups as given by parameters-
{1}, {num:1}
becomes Group[1] -
{1,3,4}, {num:1,3,4}
becomes Group[1, 3 and 4] concatenated
-
-
or. Uses the first group as specified by parameters that is non-empty
Example
{or:1,3}
:- Suppose Group is:
{1:'', 2:'a', 3:'b'}
, then the result is:b
, as Group[1] is empty - Suppose Group is:
{1:'z', 2:'a', 3:'b'}
, then the result is:z
, as Group[1] is non-empty
- Suppose Group is:
-
replace. Replacements with a regular expression
Example:
{replace:1,some((?=thing|when)),any$}
Assume Group 1 is:
"some something someone somewhen"
Then the result is:
"some anything someone anywhen"
{
"type": "resolver",
"prefix": "bildercache.de",
"match": "^http://(?:[\\w\\d]+\\.)?bildercache\\.de/anzeige",
"finder": "src=\"(.*?bild/.*?)\" title=\"(.+?)\"",
"builder": "{1}",
"namer": "{2}"
}
Will look for the finder expression and construct a new URL consisting of the first group (i.e. .?bild/.? ) and use the second group to suggest a name.
If neither redirectors nor resolvers are powerful enough for your needs then you may resort to the sandbox type plugins. With them you're allowed to perform minimalistic operations within a Javascript sandbox.
- You're allowed to use normal Javascript.
- You're furthermore provided with the source text of the page the URL originally pointed to.
- You can make your own Request
The sandbox will keep the state within an instance (i.e. per download). API for keeping global state is planned.
You may implement one of the following functions:
- process
- resolve
Additionally you may define finder
and builder
(s.a.) so that defaultResolve
can be properly generated.
Please note that sandboxed plugins are still in development and still pretty limited. Also, correctly encoding your function isn't exactly a piece of cake. I prefer coding the function as plain javascript in some html and using the output of uneval().
The sandbox offers the following non-standard methods/properties:
- Properties
-
prefix (String)
- Plugin prefix -
sendInitialReferer (Boolean)
- See above -
responseText (String)
- The source text as detailed above. -
baseURL (String)
- The original URL.
-
- Functions
-
process (void)
- Your process function or the default one. -
resolve (void)
- Your resolve function or the default one. -
defaultResolve (void)
- The default resolve function -
setURL(url: String, [nameSuggestion: String])
- (re)sets the URL -
finish(void)
- must be called when done. nameSuggestion(1.2.4, DTA-3) is optional.
-
- Utility functions
-
alert(msg)
- The "usual" alert. Use only for fast debugging -
log(msg)
- Logs msg using the standard DownThemAll logging facility (will appear in diagnostic logs). -
Request/XMLHttpRequest (void)
- Aliased constructors for web requests. A Request will behave a lot like XMLHttpRequest, however there are certain differences, most importantly:- overrideMimeType is omitted
- responseXML is omitted
- onreadyStateChange is omitted. Use onload/onerror instead.
-
-
makeRequest(url: String, [load: Function(request), error: Function(request), context: Object])
- Easy access to Request. You may specify load and error callbacks (both are recommended). The callbacks will be called in scope of context or global scope if omitted. responseText will always be set accordingly (before calling the callbacks if any).
This function is called directly on the URL. Scope is the global scope of the Sandbox. Implement this to provide a more sophisticated redirector or to do some URL fixups before resolving.
Functionally equivalent to the default implementation:
makeRequest(baseURL, resolve, resolve);
This function is called on the source text. Scope is the global scope of the Sandbox. Implement this to provide a more sophisticated resolver.
Functionally equivalent to the default implementation:
defaultResolve();
redirector and resolver plugins can be re-written as Sandbox plugins (but shouldn't, for performance reasons)
{
"type": "sandbox",
"prefix": "google.com",
"match": "^http://.*google\\.com/",
"process": "setURL('http://example.com', 'myfile.ext'); finish();"
}
This one is functionally equivalent to a normal resolver.
{
"type": "sandbox",
"prefix": "bayimg.com",
"match": "^http://(?:[\\w\\d]+\\.)?bayimg\\.com/(?!image)",
"process": "makeRequest(baseURL, resolve, resolve);",
"resolve": "defaultResolve();",
"finder": "src=\"(.+?)\".*?id=\"mainImage\"",
"builder": "{1}"
}
Will compute the image url using the same function imagefap.com used to call. (Newlines added)
{
"type": "sandbox",
"prefix": "imagefap.com",
"match": "^http://.*imagefap\\.com/image\\.php",
"resolve": "var lD = function (s) {
var s1 = unescape(s.substr(0, s.length - 1));
var t = \"\";
for (i = 0; i < s1.length; i++) {t += String.fromCharCode(s1.charCodeAt(i) - s.substr(s.length - 1, 1));}
return unescape(t);
};
var m = /lD\\('(.*?)'\\)/.exec(responseText);
if (m && m.length >= 2) {
setURL(lD(m[1]));
}
finish();"
}
Redirectors may also "clean" file names. This is handy as a lot of hosts mess with the original file name.
The cleaners are applied after the default clean, which deletes the first 3 or 5 characters if they are followed by an underliner ('_') or space.
43122_imagelab.jpg -> imagelab.jpg
Simply specify a "cleaners" property containing an array of cleaner objects like so:
"cleaners": [{
"pattern": "[\\w\\d]{3}\\.(\\w+)$",
"replacement": ".$1"
}]
This example defines a single cleaner object which will strip the last 3 characters before the file extension dot.
image1ab.jpg -> image.jpg
AntiContainer will install a DownThemAll! filter with the name "AntiContainer". It is enabled by default.
The matching pattern of this filter will be regenerated on application startup accordingly to the installed filters that do not have noFilter = false
specified.
When you add new plugins the AntiContainer filter is not regenerated instantly. Opening the DownThemAll! manager window or DownThemAll! preferences window should trigger an update, as does restarting the application (e.g. Firefox), however.
So you've written a plugin that other AntiContainer users might find useful as well? Then please don't hesitate to post a pull request or file an issue.