wiki:Development/PlugIns/JavaScript

Version 3 (modified by timothy, 13 years ago) (diff)

Added an example plugin.

TracNav(Development)? This is part of the Development Documentation Project, please help document Colloquy if you know anything that would be relevant here for other users to know about.

JavaScript PlugIns for Colloquy

To develop JavaScript PlugIns, you will need:

  • A plain text editor (TextEdit is fine in plain-text mode).
  • The latest list of function names Colloquy looks for (available in the Colloquy SDK JavaScript template below).
  • Reasonably good knowledge of JavaScript, Colloquy classes and utilizing the Cocoa frameworks.
  • A good understanding of how to call Objective-C methods from JavaScript, detailed in Using Objective-C From JavaScript.

There is a template script available in the JavaScript SDK section containing stubs and commentary for all available functions a JavaScript PlugIn for Colloquy can implement.

For those not familiar with the language, we recomend: W3Schools' JavaScript Tutorial.

(for more information come to our chat room)


Example Plugin: Grab URL Titles

The following example will take a URL mentioned in the chat and get it's title by fetching the HTML. Save this script in Colloquy's PlugIns folder as "Grab Title.js" and /reload plugins in Colloquy. Note: this script requires build [3436] or later.

var ignoreExtensions = { 'mp3': 1, 'jpg': 1, 'jpeg': 1, 'bmp': 1, 'gif': 1, 'png': 1,
	'jp2': 1, 'tif': 1, 'tiff': 1, 'zip': 1, 'dmg': 1, 'sit': 1, 'sitx': 1, 'pdf': 1,
	'mov': 1, 'avi': 1, 'wmv': 1, 'mpg': 1, 'swf': 1, 'rar': 1, 'aiff': 1, 'aif': 1, 'm4p': 1 };

var titleCache = {};
var enabled = true;

function processUserCommand(command, arguments, connection, view) {
	if( command == 'grabtitle' ) {
		if( arguments == 'enable' || arguments == 'on' || arguments == 'yes' ) {
			view.addEventMessageToDisplay('Grab Title enabled.', 'grabTitleEnabled', null );
			enabled = true;
		} else if( arguments == 'disable' || arguments == 'off' || arguments == 'no' ) {
			view.addEventMessageToDisplay('Grab Title disabled.', 'grabTitleDisabled', null );
			enabled = false;
		} else if( arguments == 'reset' || arguments == 'clear' || arguments == 'forget' ) {
			view.addEventMessageToDisplay('Grab Title cache cleared.', 'grabTitleReset', null );
			titleCache = {};
		}

		return true;
	}

	return false;
}

function processIncomingMessage(message, view) {
	if( ! enabled ) return;

	var html = message.bodyAsHTML();
	var final = html;
	var linkRegex = /<a href="([^"]+)">([^<]+)<\/a>/gim;
	var result;
	while( ( result = linkRegex.exec( html ) ) ) {
		var url = result[1];
		if( ! /https?:\/\//.test(url) )
			continue;
		if( url != result[2] && url != 'http://' + result[2] )
			continue;

		var extensionRegex = /\.(\w+)$/;
		var extensionResult = extensionRegex.exec( url );
		if( extensionResult && ignoreExtensions[extensionResult[1].toLowerCase()] )
			continue;

		var title = titleCache[url];

		if( title === undefined ) {
			try {
				var req = new XMLHttpRequest();
				req.open( 'GET', url, false );
				req.send();

				if( req.status == 200 ) {
					var titleRegex = /<title>([^<]*)<\/title>/gmi;
					var titleResult = titleRegex.exec( req.responseText );
					if( titleResult ) {
						title = titleResult[1];
						titleCache[url] = title;
					} else titleCache[url] = null;
				} else titleCache[url] = null;
			} catch( err ) {
				titleCache[url] = null;
			}
		}

		if( title ) final = final.replace( result[0], '<a href="' + url + '" title="' + url + '">' + title + '</a>' );
	}

	message.setBodyAsHTML( final );
}