JS Access - danopia/deviantart-difi GitHub Wiki

GET requests

Sending GET requests is possible with multiple methods and is pretty easy to do so with Userscripts.

DiFi.pushPrivateGet and pushPublicGet

The DiFi object is used natively by the DeviantArt website to communicate with DiFi. In your userscript, you can also use the DiFi calls in order to send GET requests. This is probably the easiest method of choice, if your userscript runs on the DeviantArt pages themselves.

The DiFi.pushPublicGet() method should be used on public methods (i.e. don't need login) and DiFi.pushPrivateGet() method should be used on private calls (i.e. specific to the logged-in user account).

To use the DiFi object, you need to "push" your request to the request queue buffer; once the request is pushed, you can perform it using the .send() method.

The requests made using DiFi object are asynchronos, meaning they run in the background and you need to assign each a callback which will be ran once the request is finished executing.

Example

// This is the example callback
var cb = function(success, data) {
	if (!success) {
		// . . . handle errors
		alert("The DiFi call that we made was not successful.");
	}
	else {
		// Get the call contents
		var content = data.response.content;

		console.log(content.result.hits);
	}
}

// Create a new DiFi call and push it to the queue
DiFi.pushPrivateGet("MessageCenter", "get_views", [ folderid, "oq:devwatch:"+offset+":48:f:tg=deviations" ], cb );

// Now send our request
DiFi.send();

GM_xmlhttpRequest

This built-in feature of userscript should be the matter of choice if you need cross-site requests (i.e. you want to access pages with a different domain). As this is a security-issue, allowing websites to contact each other when you open them, is usually forbidden.

GM_xmlhttpRequest however, is able to do cross-site requests. On the downside, not all browser extensions may fully support it. Currently, Greasemonkey, Tampermonkey and Violentmonkey are supporting this feature.

You need the @grant GM_xmlhttpRequest tag in your userscript to use this feature.

This is also an asynchronous call as you can see that we give it a callback function for onload. This means the script won't wait for the call to finish but will do it in background. Things you want to do afterwards should be called in the callback.

Example

GM_xmlhttpRequest({
	method: 'GET',
	url: "http://www.deviantart.com/global/difi/?c[]=\"MessageCenter\",\"get_views\",[\""+folderid+"\",\"oq:devwatch:"+offset+":48:f:tg=deviations\"]&t=json",
	onload: function(xhr) {
		var data = JSON.parse("(" + xhr.responseText + ")");
		console.log(data);
		console.log(data.DiFi.response.calls[0].response.content[0].result.hits);
	},
	onerror: function(data){
		console.log(data);
	}
});

jQuery

jQuery does not require an additional library that needs to be loaded, as DeviantArt already uses this library pre-loaded within the website.

If you would like to use jQuery outside the DeviantArt, you may load it externally using @request or using @grant unsafeWindow, which allows accessing a site's own global variables.

This is also an asynchronous call but without cross-site access that GM_* calls allow. So you can use it within the website safely.

Example

var $=unsafeWindow.jQuery;
var url="http://www.deviantart.com/global/difi/?c[]=\"MessageCenter\",\"get_views\",[\""+folderid+"\",\"oq:devwatch:"+offset+":48:f:tg=deviations\"]&t=json";
$.get(url,function(xhr) {
	var data = JSON.parse("(" + xhr.responseText + ")");
	console.log(data);
	console.log(data.DiFi.response.calls[0].response.content[0].result.hits);
});

XHR

The vanilla javascript call would be using XMLHttpRequest. It doesn't require an external library and it's a synchronous call, so your script will wait until it's finished. You can avoid this by calling it using setTimeout(request, 0);. It also doesn't support cross-site requests.

Example

var url="http://www.deviantart.com/global/difi/?c[]=\"MessageCenter\",\"get_views\",[\""+userid+"\",\"oq:devwatch:"+offset+":48:f:tg=deviations\"]&t=json";
xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false );
xmlHttp.send( null );
var data = JSON.parse("(" + xmlHttp.responseText + ")");
console.log(data.DiFi.response.calls[0].response.content[0].result.hits);

POST

In principle all those calls above also can also be done with POST requests. In fact, POST requests are preferred by DeviantArt for a couple of reasons:

  • They could hold more request data
  • They are not cacheable
  • They denote the event of performing an action

However, as stated in Protocol deviantart makes sure that POST requests – which usually are doing things like watching, favouriting, giving Llamas or deleting an account – are done only initialized from their own page. This problem can be circumvented using Userscripts to inject auto-executing code.

Injecting

For example the following function takes another function, injects it, calls it afterwards and removed it from the page again (taken from the AMALL userscript):

var contentEval = function(source) {
    if ('function' == typeof source) {
    source = '(' + source + ')();'
    }
    var script = document.createElement('script');
    script.setAttribute("type", "application/javascript");
    script.textContent = source;
    document.body.appendChild(script);
    document.body.removeChild(script);
}

A different option is again to use @grant unsafeWindow to get access to the built-in deviantart-functions.

Whatever we do, at the end, we need to access to the DiFi object.

DiFi object

We can do a lot of useful stuff using the DiFi object. You'll mostly only need two methods: pushPost and Send.

With pushPost you can send one post-url into the queue buffer. This works multiple times and it will be worked on in the order you pushed it in. To start processing your requests, you need to call the Send method.

More information is available on the DiFi object article.

Example (from dAHub Contest Widget)

var DiFi = unsafeWindow.DiFi;
DiFi.pushPost("Comments","preview_v2",["zwiicon","1","1","426223868"],function(success, data){
    var imgrex=/<a (?:[^>]*?)><img (?:[^>]*?)><\/a>/gi;
    var iconlist=data.response.content.match(imgrex);
    $("<div id='dahub_icon_temp'>").attr("data",JSON.stringify(iconlist)).appendTo($("body"));
    $("#dAhub_CM_Tab.selected").click();
});
DiFi.send();

Many more examples can be found by studying the deviant3.js file.

Remarks

All of the above examples assume that you have the following set:

var folderid = <YOUR_INBOX_ID>, offset = 0;
⚠️ **GitHub.com Fallback** ⚠️