Merge pull request #26 from ifl0w/feature/generic-json-api-source

Feature/generic json api source
This commit is contained in:
ifl0w 2017-10-07 19:35:33 +02:00 committed by GitHub
commit 3f0252c033
7 changed files with 1132 additions and 461 deletions

View file

@ -0,0 +1,90 @@
let JSONPathParser = function () {
/**
* Access a simple json path expression of an object.
* Returns the accessed value or null if the access was not possible.
*
* @param inputObject the object to access
* @param inputString the json path expression
* @returns {*}
*/
this.access = function(inputObject, inputString) {
if (inputObject === null || inputObject === undefined) {
return null;
}
if (inputString.length === 0) {
return inputObject;
}
let startDot = inputString.indexOf('.');
if (startDot === -1) {
startDot = inputString.length;
}
let keyString = inputString.slice(0, startDot);
let inputStringTail = inputString.slice(startDot+1);
let startParentheses = keyString.indexOf('[');
if (startParentheses === -1) {
let targetObject = this._getTargetObject(inputObject, keyString);
if (targetObject == null) {
return null;
}
return this.access(targetObject, inputStringTail)
} else {
let indexString = keyString.slice(startParentheses+1, keyString.length-1);
keyString = keyString.slice(0, startParentheses);
let targetObject = this._getTargetObject(inputObject, keyString);
if (targetObject == null) {
return null;
}
switch (indexString) {
case "@random":
return this.access(this.randomElement(targetObject), inputStringTail);
// add special keywords here
default:
// expecting integer
return this.access(targetObject[parseInt(indexString)], inputStringTail);
}
}
};
/**
* Check validity of the key string and return the target object or null.
* @param inputObject
* @param keyString
* @returns {*}
* @private
*/
this._getTargetObject = function (inputObject, keyString) {
if (!keyString.empty && keyString !== "$" && !inputObject.hasOwnProperty(keyString)) {
return null;
}
return (keyString === "$") ? inputObject : inputObject[keyString];
};
/**
* Returns the value of a random key of a given object.
*
* @param inputObject
* @returns {*}
*/
this.randomElement = function(inputObject) {
let keys = Object.keys(inputObject);
let randomIndex = Math.floor(Math.random()*keys.length);
return inputObject[keys[randomIndex]];
}
};

View file

@ -15,6 +15,7 @@ const RWG_SETTINGS_SCHEMA = 'org.gnome.shell.extensions.space.iflow.randomwallpa
const RWG_SETTINGS_SCHEMA_DESKTOPPER = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.desktopper';
const RWG_SETTINGS_SCHEMA_UNSPLASH = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.unsplash';
const RWG_SETTINGS_SCHEMA_WALLHEAVEN = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.wallheaven';
const RWG_SETTINGS_SCHEMA_GENERIC_JSON = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.genericJSON';
const LoggerModule = Self.imports.logger;
@ -41,6 +42,7 @@ const RandomWallpaperSettings = new Lang.Class({
desktopperSettings: null,
unsplashSettings: null,
wallheavenSettings: null,
genericJsonSettings: null,
_init: function () {
this._settings = Convenience.getSettings(RWG_SETTINGS_SCHEMA);
@ -67,6 +69,11 @@ const RandomWallpaperSettings = new Lang.Class({
this.wallheavenSettings = this._builder.get_object('wallheaven-settings');
this.bindWallheaven();
// Generic JSON Settings
this._generic_json_settings = Convenience.getSettings(RWG_SETTINGS_SCHEMA_GENERIC_JSON);
this.genericJsonSettings = this._builder.get_object('generic-json-settings');
this.bindGenericJSON();
this._toggleAfSliders();
this.widget = this._builder.get_object('main-widget');
@ -76,7 +83,7 @@ const RandomWallpaperSettings = new Lang.Class({
}.bind(this));
this._builder.get_object('source-combo').connect('changed', (sourceCombo) => {
let container = this._builder.get_object('source-settings-frame');
let container = this._builder.get_object('source-settings-container');
if (this.currentSourceSettingsWidget !== null) {
container.remove(this.currentSourceSettingsWidget);
}
@ -91,13 +98,16 @@ const RandomWallpaperSettings = new Lang.Class({
case 2: // wallheaven
this.currentSourceSettingsWidget = this.wallheavenSettings;
break;
case 3: // generic JSON
this.currentSourceSettingsWidget = this.genericJsonSettings;
break;
default:
this.currentSourceSettingsWidget = this.noSettings;
break;
}
container.add(this.currentSourceSettingsWidget);
container.getParent
});
this._settings.bind('history-length',
@ -124,6 +134,10 @@ const RandomWallpaperSettings = new Lang.Class({
this._builder.get_object('change-lock-screen'),
'active',
Gio.SettingsBindFlags.DEFAULT);
this._settings.bind('disable-hover-preview',
this._builder.get_object('disable-hover-preview'),
'active',
Gio.SettingsBindFlags.DEFAULT);
},
_toggleAfSliders: function () {
@ -161,6 +175,10 @@ const RandomWallpaperSettings = new Lang.Class({
this._builder.get_object('unsplash-image-height'),
'value',
Gio.SettingsBindFlags.DEFAULT);
this._unsplash_settings.bind('featured-only',
this._builder.get_object('unsplash-featured-only'),
'active',
Gio.SettingsBindFlags.DEFAULT);
},
bindWallheaven: function () {
@ -194,6 +212,22 @@ const RandomWallpaperSettings = new Lang.Class({
this._builder.get_object('wallheaven-allow-sketchy'),
'active',
Gio.SettingsBindFlags.DEFAULT);
},
bindGenericJSON: function () {
this._builder.get_object('generic-json-docs-link').set_label("More information here");
this._generic_json_settings.bind('generic-json-request-url',
this._builder.get_object('generic-json-request-url'),
'text',
Gio.SettingsBindFlags.DEFAULT);
this._generic_json_settings.bind('generic-json-response-path',
this._builder.get_object('generic-json-response-path'),
'text',
Gio.SettingsBindFlags.DEFAULT);
this._generic_json_settings.bind('generic-json-url-prefix',
this._builder.get_object('generic-json-url-prefix'),
'text',
Gio.SettingsBindFlags.DEFAULT);
}
});

View file

@ -5,6 +5,7 @@
<value value='0' nick='desktoppr'/>
<value value='1' nick='unsplash'/>
<value value='2' nick='wallheaven'/>
<value value='3' nick='genericJSON'/>
</enum>
<schema path="/org/gnome/shell/extensions/space-iflow-randomwallpaper-sources/"
@ -61,6 +62,12 @@
<description>Weather the gnome lock screen should also be set to the new wallpaper.</description>
</key>
<key type='b' name='disable-hover-preview'>
<default>false</default>
<summary>Disable hover preview</summary>
<description>Disables the preview of the background while hovering the history list</description>
</key>
</schema>
<schema path="/org/gnome/shell/extensions/space-iflow-randomwallpaper-sources/"
@ -94,6 +101,11 @@
<summary>Image Width</summary>
<description>The height of the image.</description>
</key>
<key type='b' name='featured-only'>
<default>false</default>
<summary>Featured images only</summary>
<description>This results in a smaller wallpaper pool but the images are considered to have higher quality.</description>
</key>
</schema>
<schema path="/org/gnome/shell/extensions/space-iflow-randomwallpaper-sources/"
@ -135,4 +147,24 @@
<description>Weather the people category should be searched.</description>
</key>
</schema>
<schema path="/org/gnome/shell/extensions/space-iflow-randomwallpaper-sources/"
id='org.gnome.shell.extensions.space.iflow.randomwallpaper.genericJSON'>
<key type='s' name='generic-json-request-url'>
<default>""</default>
<summary>The request URL</summary>
<description>The URL where the JSON will be requested.</description>
</key>
<key type='s' name='generic-json-response-path'>
<default>""</default>
<summary>JSON Path</summary>
<description>The JSON path that describes the picture URL.</description>
</key>
<key type='s' name='generic-json-url-prefix'>
<default>""</default>
<summary>Image URL prefix</summary>
<description>This prefix is added to the final image URL.</description>
</key>
</schema>
</schemalist>

File diff suppressed because it is too large Load diff

View file

@ -8,11 +8,13 @@ const Json = imports.gi.Json;
const RWG_SETTINGS_SCHEMA_DESKTOPPER = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.desktopper';
const RWG_SETTINGS_SCHEMA_UNSPLASH = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.unsplash';
const RWG_SETTINGS_SCHEMA_WALLHEAVEN = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.wallheaven';
const RWG_SETTINGS_SCHEMA_GENERIC_JSON = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.genericJSON';
const SettingsModule = Self.imports.settings;
const HistoryModule = Self.imports.history;
const LoggerModule = Self.imports.logger;
const JSONPath = Self.imports.jsonpath.jsonpath;
let BaseAdapter = new Lang.Class({
Name: "BaseAdapter",
@ -33,7 +35,11 @@ let BaseAdapter = new Lang.Class({
},
fileName: function (uri) {
let base = new String(uri).substring(uri.lastIndexOf('/') + 1);
let base = decodeURIComponent(uri);
base = base.substring(base.lastIndexOf('/') + 1);
if(base.indexOf('?') >= 0) {
base = base.substr(0, base.indexOf('?'));
}
return base;
},
@ -62,7 +68,6 @@ let DesktopperAdapter = new Lang.Class({
url += '?safe_filter=safe';
}
url = encodeURI(url);
this.logger.debug("Base URL: " + url);
let message = Soup.Message.new('GET', url);
@ -95,6 +100,7 @@ let UnsplashAdapter = new Lang.Class({
'query': '',
'w': 1920,
'h': 1080,
'featured': false
},
_init: function () {
@ -111,7 +117,6 @@ let UnsplashAdapter = new Lang.Class({
let url = 'https://api.unsplash.com/photos/random?' + optionsString;
url += 'client_id=64daf439e9b579dd566620c0b07022706522d87b255d06dd01d5470b7f193b8d';
url = encodeURI(url);
this.logger.debug("Base URL: " + url);
let message = Soup.Message.new('GET', url);
@ -152,12 +157,14 @@ let UnsplashAdapter = new Lang.Class({
this.options.query = this._settings.get('unsplash-keyword', 'string');
this.options.username = this._settings.get('username', 'string');
if (this.options.username[0] === '@') {
if (this.options.username && this.options.username[0] === '@') {
this.options.username = this.options.username.substring(1); // remove @ prefix
}
this.options.w = this._settings.get('image-width', 'int');
this.options.h = this._settings.get('image-height', 'int');
this.options.featured = this._settings.get('featured-only', 'boolean');
}
});
@ -188,7 +195,6 @@ let WallheavenAdapter = new Lang.Class({
let optionsString = this._generateOptionsString();
let url = 'http://alpha.wallhaven.cc/search?' + optionsString;
url = encodeURI(url);
this.logger.debug("Base URL: " + url);
let message = Soup.Message.new('GET', url);
@ -264,3 +270,40 @@ let WallheavenAdapter = new Lang.Class({
this.options.purity = purity.join('');
}
});
let GenericJsonAdapter = new Lang.Class({
Name: "GenericJsonAdapter",
Extends: BaseAdapter,
_settings: null,
_jsonPathParser: null,
_init: function () {
this.parent();
this._jsonPathParser = new JSONPath.JSONPathParser();
this._settings = new SettingsModule.Settings(RWG_SETTINGS_SCHEMA_GENERIC_JSON);
},
requestRandomImage: function (callback) {
let session = new Soup.SessionAsync();
let url = this._settings.get("generic-json-request-url", "string");
url = encodeURI(url);
let message = Soup.Message.new('GET', url);
session.queue_message(message, (session, message) => {
let response = JSON.parse(message.response_body.data);
let JSONPath = this._settings.get("generic-json-response-path", "string");
let imageUrl = this._jsonPathParser.access(response, JSONPath);
imageUrl = this._settings.get("generic-json-url-prefix", "string")+imageUrl;
if (callback) {
let historyEntry = new HistoryModule.HistoryEntry(null, 'Generic JSON Source', imageUrl);
historyEntry.source.sourceUrl = imageUrl;
callback(historyEntry);
}
});
}
});

View file

@ -60,6 +60,7 @@ let WallpaperController = new Lang.Class({
this._desktopperAdapter = new SourceAdapter.DesktopperAdapter();
this._unsplashAdapter = new SourceAdapter.UnsplashAdapter();
this._wallheavenAdapter = new SourceAdapter.WallheavenAdapter();
this._genericJsonAdapter = new SourceAdapter.GenericJsonAdapter();
this.logger = new LoggerModule.Logger('RWG3', 'WallpaperController');
},
@ -98,6 +99,9 @@ let WallpaperController = new Lang.Class({
case 2:
this.imageSourceAdapter = this._wallheavenAdapter;
break;
case 3:
this.imageSourceAdapter = this._genericJsonAdapter;
break;
default:
this.imageSourceAdapter = this._desktopperAdapter;
break;
@ -178,7 +182,8 @@ let WallpaperController = new Lang.Class({
*/
if (settings.is_writable("picture-uri")) {
// Set a new Background-Image (should show up immediately):
if (settings.set_string("picture-uri", path)) {
let rc = settings.set_string("picture-uri", path);
if (rc) {
Gio.Settings.sync(); // Necessary: http://stackoverflow.com/questions/9985140
// call callback if given
@ -240,7 +245,7 @@ let WallpaperController = new Lang.Class({
});
},
_backgroundTimout: function (delay) {
_backgroundTimeout: function (delay) {
if (this.timeout) {
return;
}
@ -260,15 +265,19 @@ let WallpaperController = new Lang.Class({
},
previewWallpaper: function (historyid, delay) {
this.previewId = historyid;
this._resetWallpaper = false;
if (!this._settings.get('disable-hover-preview', 'boolean')) {
this.previewId = historyid;
this._resetWallpaper = false;
this._backgroundTimout(delay);
this._backgroundTimeout(delay);
}
},
resetWallpaper: function () {
this._resetWallpaper = true;
this._backgroundTimout();
if (!this._settings.get('disable-hover-preview', 'boolean')) {
this._resetWallpaper = true;
this._backgroundTimeout();
}
},
getHistoryController: function () {