AntiSpam Scripting API

Last modified by Vincent Massol on 2026/08/13 13:58

Reference

Most methods of the $services.antispam Script Service are annotated @Programming and check for programming rights before doing anything, so a page calling them must have a content author who holds that right; AntiSpam for developers describes where the Service sits in the extension.

Searching and cleaning:

MethodReturnsProgramming right
getMatchingDocuments(solrQuery, nb, offset)The matching references, each pairing a document with its last author. AntiSpam pages are always excluded.Yes
getLastAuthorReferences(matchingReferences)The set of last authors of the passed matching references, with the guest user removed.Yes
getDocumentsForAuthor(authorReference, nb, offset)The documents created or last modified by that account.Yes
cleanDocument(documentReference, authorReferences, skipActivityStream)Nothing. Deletes the revisions of the document made by those authors, and the document itself when no revision is left.Yes

Accounts:

MethodReturnsProgramming right
getInactiveAuthors(elapsedDays, cleanAuthorsWithAvatars, count)At most count accounts matching every inactivity condition.Yes
cleanAuthors(authorReferences, skipEventStreamRecording)The Job deleting those accounts, so that a page can display its progress.Yes
getCurrentCleanAuthorJobStatus()The status of the running or last deletion job, or null when none ran.No
getKnownUserReferences()Every protected account, expanding the known groups into their members.No
isProtectedUser(authorReference, documentReference)Whether that account is protected, for that page. Pass null as the document to ask about the wiki only.No

Checking and events:

MethodReturnsProgramming right
isSpam(checkerHint, content, parameters)The result of running the named checker over a string, with the matched keywords when it is spam.No
isSpam(checkerHint, document, parameters)The same over a document, serialised to XML first.No
createEventQuery()A new empty event query to build on.No
searchEvents(query)The events matching the query.Yes
deleteEvent(eventId) and deleteEvent(event)A future on the deleted event.Yes

The hint of the checker shipped with the extension is simple. The parameters map is what the checker reads besides the content: the simple checker takes ip, authorReference and documentReference, and logs the match to AntiSpam.Logs when the last two are present.

Testing a page against the keyword list:

{{velocity}}
#set ($result = $services.antispam.isSpam('simple', $doc, {}))
#if ($result.spam)
  Matched: $result.matchedContent.keySet()
#else
  No keyword matched.
#end
{{/velocity}}

Listing the page creations of one account, newest first:

{{velocity}}
#set ($query = $services.antispam.createEventQuery())
#set ($query = $query.eq('application', 'xwiki').eq('type', 'create'))
#set ($query = $query.eq('user', 'xwiki:XWiki.SomeUser'))
#set ($query = $query.addSort('date', 'DESC').setLimit(50))
#foreach ($event in $services.antispam.searchEvents($query))
* $event.date - $event.document
#end
{{/velocity}}

Deleting the accounts that never contributed, as a job, is what the "Clean Inactive Users" screen does:

{{velocity}}
#set ($inactive = $services.antispam.getInactiveAuthors(30, true, 50))
#set ($job = $services.antispam.cleanAuthors($inactive, true))
Started: $job.status.state
{{/velocity}}

Passing true as the last argument of cleanAuthors and cleanDocument wraps the work in the extension's own fold events, which is what keeps a mass deletion out of the event stream and out of everyone's notifications.

FAQ

What happens without programming rights?

The annotated methods throw an AntiSpamException before touching anything, rather than returning an empty result.

Which checkers can I pass as a hint?

simple, the keyword and address checker shipped with the extension. A SpamChecker Component registered under another hint is selectable by that hint.

Can I read the keyword list from a script?

Not through this service. Read the AntiSpam.Keywords page, whose format is described in AntiSpam Configuration.

Related

Get Connected