diff --git a/files/yfquotes@thegli/desklet.js b/files/yfquotes@thegli/desklet.js index 7fbfa6c..c5ab881 100644 --- a/files/yfquotes@thegli/desklet.js +++ b/files/yfquotes@thegli/desklet.js @@ -48,7 +48,7 @@ const AUTH_COOKIE = "A1"; const CONSENT_COOKIE = "GUCS"; const ABSENT = "N/A"; -const ERROR_RESPONSE_BEGIN="{\"quoteResponse\":{\"result\":[],\"error\":\""; +const ERROR_RESPONSE_BEGIN = "{\"quoteResponse\":{\"result\":[],\"error\":\""; const ERROR_RESPONSE_END = "\"}}"; const LOG_PREFIX = UUID + " - "; @@ -86,17 +86,17 @@ function logError(msg) { global.logError(LOG_PREFIX + msg); } -let YahooFinanceQuoteUtils = function () {}; +let YahooFinanceQuoteUtils = function() { }; YahooFinanceQuoteUtils.prototype = { - - existsProperty : function(object, property) { + + existsProperty: function(object, property) { return object.hasOwnProperty(property) && typeof object[property] !== "undefined" && object[property] !== null; }, - determineQuoteName : function (quote, useLongName) { + determineQuoteName: function(quote, useLongName) { if (useLongName && this.existsProperty(quote, "longName")) { return quote.longName; } else if (this.existsProperty(quote, "shortName")) { @@ -104,8 +104,8 @@ YahooFinanceQuoteUtils.prototype = { } return ABSENT; }, - - isOkStatus : function (soupMessage) { + + isOkStatus: function(soupMessage) { if (soupMessage) { if (IS_SOUP_2) { return soupMessage.status_code === Soup.KnownStatusCode.OK; @@ -115,11 +115,11 @@ YahooFinanceQuoteUtils.prototype = { } return false; }, - - getMessageStatusInfo : function (soupMessage) { + + getMessageStatusInfo: function(soupMessage) { if (soupMessage) { if (IS_SOUP_2) { - return soupMessage.status_code + " " + soupMessage.reason_phrase; + return soupMessage.status_code + " " + soupMessage.reason_phrase; } else { return soupMessage.get_status() + " " + soupMessage.get_reason_phrase(); } @@ -128,29 +128,29 @@ YahooFinanceQuoteUtils.prototype = { } }; -let YahooFinanceQuoteReader = function () {}; +let YahooFinanceQuoteReader = function() { }; YahooFinanceQuoteReader.prototype = { - constructor : YahooFinanceQuoteReader, + constructor: YahooFinanceQuoteReader, quoteUtils: new YahooFinanceQuoteUtils(), - - getCookie : function (customUserAgent, callback) { + + getCookie: function(customUserAgent, callback) { const _that = this; const message = Soup.Message.new("GET", YF_COOKIE_URL); - + if (IS_SOUP_2) { message.request_headers.append(ACCEPT_HEADER, ACCEPT_VALUE_COOKIE); message.request_headers.append(ACCEPT_ENCODING_HEADER, ACCEPT_ENCODING_VALUE); if (customUserAgent != null) { message.request_headers.append(USER_AGENT_HEADER, customUserAgent); } - - _httpSession.queue_message(message, function (session, message) { + + _httpSession.queue_message(message, function(session, message) { // logInfo("Soup2 Cookie response: " + _that.quoteUtils.getMessageStatusInfo(message)); if (_that.quoteUtils.isOkStatus(message)) { try { callback.call(_that, message, message.response_body.data); - } catch(e) { + } catch (e) { logError(e); } } else { @@ -164,14 +164,14 @@ YahooFinanceQuoteReader.prototype = { if (customUserAgent != null) { message.get_request_headers().append(USER_AGENT_HEADER, customUserAgent); } - - _httpSession.send_and_read_async(message, Soup.MessagePriority.NORMAL, null, function (session, result) { + + _httpSession.send_and_read_async(message, Soup.MessagePriority.NORMAL, null, function(session, result) { // logInfo("Soup3 Cookie response: " + _that.quoteUtils.getMessageStatusInfo(message)); if (_that.quoteUtils.isOkStatus(message)) { try { const bytes = session.send_and_read_finish(result); callback.call(_that, message, ByteArray.toString(bytes.get_data())); - } catch(e) { + } catch (e) { logError(e); } } else { @@ -181,25 +181,25 @@ YahooFinanceQuoteReader.prototype = { }); } }, - - postConsent : function (customUserAgent, formData, callback) { + + postConsent: function(customUserAgent, formData, callback) { const _that = this; const message = Soup.Message.new("POST", YF_CONSENT_URL); - + if (IS_SOUP_2) { message.request_headers.append(ACCEPT_HEADER, ACCEPT_VALUE_COOKIE); message.request_headers.append(ACCEPT_ENCODING_HEADER, ACCEPT_ENCODING_VALUE); - if (customUserAgent != null) { + if (customUserAgent != null) { message.request_headers.append(USER_AGENT_HEADER, customUserAgent); } message.set_request(FORM_URLENCODED_VALUE, Soup.MemoryUse.COPY, formData); - - _httpSession.queue_message(message, function (session, message) { + + _httpSession.queue_message(message, function(session, message) { // logInfo("Soup2 Consent response: " + _that.quoteUtils.getMessageStatusInfo(message)); if (_that.quoteUtils.isOkStatus(message)) { try { callback.call(_that, message); - } catch(e) { + } catch (e) { logError(e); } } else { @@ -214,13 +214,13 @@ YahooFinanceQuoteReader.prototype = { message.get_request_headers().append(USER_AGENT_HEADER, customUserAgent); } message.set_request_body_from_bytes(FORM_URLENCODED_VALUE, GLib.Bytes.new(formData)); - - _httpSession.send_and_read_async(message, Soup.MessagePriority.NORMAL, null, function (session, result) { + + _httpSession.send_and_read_async(message, Soup.MessagePriority.NORMAL, null, function(session, result) { // logInfo("Soup3 Consent response: " + _that.quoteUtils.getMessageStatusInfo(message)); if (_that.quoteUtils.isOkStatus(message)) { try { callback.call(_that, message); - } catch(e) { + } catch (e) { logError(e); } } else { @@ -230,24 +230,24 @@ YahooFinanceQuoteReader.prototype = { }); } }, - - getCrumb : function (customUserAgent, callback) { + + getCrumb: function(customUserAgent, callback) { const _that = this; const message = Soup.Message.new("GET", YF_CRUMB_URL); - + if (IS_SOUP_2) { message.request_headers.append(ACCEPT_HEADER, ACCEPT_VALUE_CRUMB); message.request_headers.append(ACCEPT_ENCODING_HEADER, ACCEPT_ENCODING_VALUE); if (customUserAgent != null) { message.request_headers.append(USER_AGENT_HEADER, customUserAgent); } - - _httpSession.queue_message(message, function (session, message) { + + _httpSession.queue_message(message, function(session, message) { // logInfo("Soup2 Crumb response: " + _that.quoteUtils.getMessageStatusInfo(message)); if (_that.quoteUtils.isOkStatus(message)) { try { callback.call(_that, message, message.response_body); - } catch(e) { + } catch (e) { logError(e); } } else { @@ -261,14 +261,14 @@ YahooFinanceQuoteReader.prototype = { if (customUserAgent != null) { message.get_request_headers().append(USER_AGENT_HEADER, customUserAgent); } - - _httpSession.send_and_read_async(message, Soup.MessagePriority.NORMAL, null, function (session, result) { + + _httpSession.send_and_read_async(message, Soup.MessagePriority.NORMAL, null, function(session, result) { // logInfo("Soup3 Crumb response: " + _that.quoteUtils.getMessageStatusInfo(message)); if (_that.quoteUtils.isOkStatus(message)) { try { const bytes = session.send_and_read_finish(result); callback.call(_that, message, ByteArray.toString(bytes.get_data())); - } catch(e) { + } catch (e) { logError(e); } } else { @@ -278,23 +278,23 @@ YahooFinanceQuoteReader.prototype = { }); } }, - - getFinanceData : function (quoteSymbols, customUserAgent, callback) { + + getFinanceData: function(quoteSymbols, customUserAgent, callback) { const _that = this; const requestUrl = this.createYahooQueryUrl(quoteSymbols); const message = Soup.Message.new("GET", requestUrl); - + if (IS_SOUP_2) { if (customUserAgent != null) { message.request_headers.append(USER_AGENT_HEADER, customUserAgent); } - - _httpSession.queue_message(message, function (session, message) { + + _httpSession.queue_message(message, function(session, message) { // logInfo("Soup2 Quotes response: " + _that.quoteUtils.getMessageStatusInfo(message)); if (_that.quoteUtils.isOkStatus(message)) { try { callback.call(_that, message.response_body.data.toString()); - } catch(e) { + } catch (e) { logError(e); } } else { @@ -306,14 +306,14 @@ YahooFinanceQuoteReader.prototype = { if (customUserAgent != null) { message.get_request_headers().append(USER_AGENT_HEADER, customUserAgent); } - - _httpSession.send_and_read_async(message, Soup.MessagePriority.NORMAL, null, function (session, result) { + + _httpSession.send_and_read_async(message, Soup.MessagePriority.NORMAL, null, function(session, result) { // logInfo("Soup3 Quotes response: " + _that.quoteUtils.getMessageStatusInfo(message)); if (_that.quoteUtils.isOkStatus(message)) { try { const bytes = session.send_and_read_finish(result); callback.call(_that, ByteArray.toString(bytes.get_data())); - } catch(e) { + } catch (e) { logError(e); } } else { @@ -323,47 +323,47 @@ YahooFinanceQuoteReader.prototype = { }); } }, - - createYahooQueryUrl : function (quoteSymbols) { + + createYahooQueryUrl: function(quoteSymbols) { return "https://query1.finance.yahoo.com/v7/finance/quote?symbols=" + quoteSymbols.join(",") + "&crumb=" + _crumb; }, - - buildErrorResponse : function (errorMsg) { + + buildErrorResponse: function(errorMsg) { return ERROR_RESPONSE_BEGIN + errorMsg + ERROR_RESPONSE_END; } }; -let QuotesTable = function () { +let QuotesTable = function() { this.el = new St.Table({ - homogeneous : false + homogeneous: false }); }; QuotesTable.prototype = { - constructor : QuotesTable, + constructor: QuotesTable, quoteUtils: new YahooFinanceQuoteUtils(), - currencyCodeToSymbolMap : { - USD : "$", - EUR : "\u20AC", - JPY : "\u00A5", - GBP : "\u00A3", - INR : "\u20A8", - UAH : "\u20B4", - RUB : "\u20BD" - }, - quoteChangeSymbolMap : { - UP : "\u25B2", - DOWN : "\u25BC", - EQUALS : "\u25B6" - }, - - render : function (quotes, settings) { + currencyCodeToSymbolMap: { + USD: "$", + EUR: "\u20AC", + JPY: "\u00A5", + GBP: "\u00A3", + INR: "\u20A8", + UAH: "\u20B4", + RUB: "\u20BD" + }, + quoteChangeSymbolMap: { + UP: "\u25B2", + DOWN: "\u25BC", + EQUALS: "\u25B6" + }, + + render: function(quotes, settings) { for (let rowIndex = 0, l = quotes.length; rowIndex < l; rowIndex++) { this.renderTableRow(quotes[rowIndex], rowIndex, settings); } }, - renderTableRow : function (quote, rowIndex, settings) { + renderTableRow: function(quote, rowIndex, settings) { let cellContents = []; if (settings.changeIcon) { @@ -374,8 +374,9 @@ QuotesTable.prototype = { cellContents.push(this.createQuoteLabel(this.quoteUtils.determineQuoteName(quote, settings.useLongName), quote.symbol, settings.linkQuote, settings.quoteNameMaxLength)); } - if (settings.quoteSymbol) {cellContents.push(this.createQuoteLabel(quote.symbol, - quote.symbol, settings.linkSymbol, settings.quoteSymbolMaxLength)); + if (settings.quoteSymbol) { + cellContents.push(this.createQuoteLabel(quote.symbol, + quote.symbol, settings.linkSymbol, settings.quoteSymbolMaxLength)); } if (settings.marketPrice) { cellContents.push(this.createMarketPriceLabel(quote, settings.currencySymbol, settings.decimalPlaces, @@ -396,18 +397,18 @@ QuotesTable.prototype = { for (let columnIndex = 0; columnIndex < cellContents.length; ++columnIndex) { this.el.add(cellContents[columnIndex], { - row : rowIndex, - col : columnIndex + row: rowIndex, + col: columnIndex }); } }, - createQuoteLabel : function (labelText, quoteSymbol, addLink, labelMaxLength) { - const label = new St.Label({ - text : labelText, - style_class : "quotes-label", - reactive : addLink ? true : false, - style : "width:" + (labelMaxLength/2 + 2) + "em;" + createQuoteLabel: function(labelText, quoteSymbol, addLink, labelMaxLength) { + const label = new St.Label({ + text: labelText, + style_class: "quotes-label", + reactive: addLink ? true : false, + style: "width:" + (labelMaxLength / 2 + 2) + "em;" }); if (addLink) { @@ -422,20 +423,20 @@ QuotesTable.prototype = { } }, - createMarketPriceLabel : function (quote, withCurrencySymbol, decimalPlaces, strictRounding) { + createMarketPriceLabel: function(quote, withCurrencySymbol, decimalPlaces, strictRounding) { let currencySymbol = ""; if (withCurrencySymbol && this.quoteUtils.existsProperty(quote, "currency")) { currencySymbol = this.currencyCodeToSymbolMap[quote.currency] || quote.currency; } return new St.Label({ - text : currencySymbol + (this.quoteUtils.existsProperty(quote, "regularMarketPrice") + text: currencySymbol + (this.quoteUtils.existsProperty(quote, "regularMarketPrice") ? this.roundAmount(quote.regularMarketPrice, decimalPlaces, strictRounding) : ABSENT), - style_class : "quotes-number" + style_class: "quotes-number" }); }, - createAbsoluteChangeLabel : function (quote, withCurrencySymbol, decimalPlaces, strictRounding) { + createAbsoluteChangeLabel: function(quote, withCurrencySymbol, decimalPlaces, strictRounding) { let absoluteChangeText = ""; if (this.quoteUtils.existsProperty(quote, "regularMarketChange")) { let absoluteChange = this.roundAmount(quote.regularMarketChange, decimalPlaces, strictRounding); @@ -448,12 +449,12 @@ QuotesTable.prototype = { } return new St.Label({ - text : absoluteChangeText, - style_class : "quotes-number" + text: absoluteChangeText, + style_class: "quotes-number" }); }, - createPercentChangeIcon : function (quote, uptrendChangeColor, downtrendChangeColor, unchangedTrendColor) { + createPercentChangeIcon: function(quote, uptrendChangeColor, downtrendChangeColor, unchangedTrendColor) { const percentChange = this.quoteUtils.existsProperty(quote, "regularMarketChangePercent") ? parseFloat(quote.regularMarketChangePercent) : 0.00; @@ -469,12 +470,12 @@ QuotesTable.prototype = { } return new St.Label({ - text : iconText, - style : "color: " + iconColor + ";" + text: iconText, + style: "color: " + iconColor + ";" }); }, - createPercentChangeLabel : function (quote, useTrendColors, uptrendChangeColor, downtrendChangeColor, unchangedTrendColor, strictRounding) { + createPercentChangeLabel: function(quote, useTrendColors, uptrendChangeColor, downtrendChangeColor, unchangedTrendColor, strictRounding) { let labelColor = ""; if (useTrendColors && this.quoteUtils.existsProperty(quote, "regularMarketChangePercent")) { const percentageChange = parseFloat(quote.regularMarketChangePercent); @@ -488,16 +489,16 @@ QuotesTable.prototype = { } return new St.Label({ - text : this.quoteUtils.existsProperty(quote, "regularMarketChangePercent") + text: this.quoteUtils.existsProperty(quote, "regularMarketChangePercent") ? (this.roundAmount(quote.regularMarketChangePercent, 2, strictRounding) + "%") : ABSENT, - style_class : "quotes-number", - style : labelColor ? "color: " + labelColor + ";" : "" + style_class: "quotes-number", + style: labelColor ? "color: " + labelColor + ";" : "" }); }, - roundAmount : function (amount, maxDecimals, strictRounding) { - if (maxDecimals > -1) { + roundAmount: function(amount, maxDecimals, strictRounding) { + if (maxDecimals > -1) { if (strictRounding) { return amount.toFixed(maxDecimals); } @@ -509,38 +510,38 @@ QuotesTable.prototype = { return amount; }, - isToday : function (date) { + isToday: function(date) { const today = new Date(); return date.getFullYear() === today.getFullYear() && date.getMonth() === today.getMonth() && date.getDate() === today.getDate(); }, - formatTime : function (unixTimestamp) { + formatTime: function(unixTimestamp) { const ts = new Date(unixTimestamp * 1000); let tsFormat = ""; if (this.isToday(ts)) { tsFormat = ts.toLocaleTimeString(undefined, { - hour : "numeric", - minute : "numeric" + hour: "numeric", + minute: "numeric" }); } else { tsFormat = ts.toLocaleDateString(undefined, { - month : "numeric", - day : "numeric" + month: "numeric", + day: "numeric" }); } return tsFormat; }, - createTradeTimeLabel : function (quote) { + createTradeTimeLabel: function(quote) { return new St.Label({ - text : this.quoteUtils.existsProperty(quote, "regularMarketTime") + text: this.quoteUtils.existsProperty(quote, "regularMarketTime") ? this.formatTime(quote.regularMarketTime) : ABSENT, - style_class : "quotes-number" + style_class: "quotes-number" }); } }; @@ -551,8 +552,8 @@ function StockQuoteDesklet(metadata, id) { } StockQuoteDesklet.prototype = { - __proto__ : Desklet.Desklet.prototype, - init : function (metadata, id) { + __proto__: Desklet.Desklet.prototype, + init: function(metadata, id) { this.metadata = metadata; this.id = id; this.quoteReader = new YahooFinanceQuoteReader(); @@ -561,7 +562,7 @@ StockQuoteDesklet.prototype = { this.onUpdate(); }, - loadSettings : function () { + loadSettings: function() { this.settings = new Settings.DeskletSettings(this, this.metadata.uuid, this.id); this.settings.bindProperty(Settings.BindingDirection.IN, "height", "height", this.onDisplayChanged, null); @@ -621,77 +622,77 @@ StockQuoteDesklet.prototype = { this.onSettingsChanged, null); }, - getQuoteDisplaySettings : function (quotes) { + getQuoteDisplaySettings: function(quotes) { return { - "changeIcon" : this.showChangeIcon, - "quoteName" : this.showQuoteName, - "useLongName" : this.useLongQuoteName, - "linkQuote" : this.linkQuoteName, - "quoteSymbol" : this.showQuoteSymbol, - "linkSymbol" : this.linkQuoteSymbol, - "marketPrice" : this.showMarketPrice, - "currencySymbol" : this.showCurrencyCode, + "changeIcon": this.showChangeIcon, + "quoteName": this.showQuoteName, + "useLongName": this.useLongQuoteName, + "linkQuote": this.linkQuoteName, + "quoteSymbol": this.showQuoteSymbol, + "linkSymbol": this.linkQuoteSymbol, + "marketPrice": this.showMarketPrice, + "currencySymbol": this.showCurrencyCode, "absoluteChange": this.showAbsoluteChange, - "percentChange" : this.showPercentChange, - "colorPercentChange" : this.colorPercentChange, - "tradeTime" : this.showTradeTime, - "decimalPlaces" : this.roundNumbers ? this.decimalPlaces : -1, - "strictRounding" : this.roundNumbers && this.strictRounding, - "uptrendChangeColor" : this.uptrendChangeColor, - "downtrendChangeColor" : this.downtrendChangeColor, - "unchangedTrendColor" : this.unchangedTrendColor, - "quoteSymbolMaxLength" : Math.max.apply(Math, quotes.map((quote) => quote.symbol.length)), - "quoteNameMaxLength" : Math.max.apply(Math, quotes.map((quote) => this.quoteUtils.determineQuoteName(quote, this.useLongQuoteName).length)) + "percentChange": this.showPercentChange, + "colorPercentChange": this.colorPercentChange, + "tradeTime": this.showTradeTime, + "decimalPlaces": this.roundNumbers ? this.decimalPlaces : -1, + "strictRounding": this.roundNumbers && this.strictRounding, + "uptrendChangeColor": this.uptrendChangeColor, + "downtrendChangeColor": this.downtrendChangeColor, + "unchangedTrendColor": this.unchangedTrendColor, + "quoteSymbolMaxLength": Math.max.apply(Math, quotes.map((quote) => quote.symbol.length)), + "quoteNameMaxLength": Math.max.apply(Math, quotes.map((quote) => this.quoteUtils.determineQuoteName(quote, this.useLongQuoteName).length)) }; }, - formatCurrentTimestamp : function () { + formatCurrentTimestamp: function() { const now = new Date(); return now.toLocaleTimeString(undefined, { - hour : "numeric", - minute : "numeric", - second : "numeric" + hour: "numeric", + minute: "numeric", + second: "numeric" }); }, - createLastUpdateLabel : function () { + createLastUpdateLabel: function() { return new St.Label({ - text : _("Updated at ") + this.formatCurrentTimestamp(), - style_class : "quotes-last-update" + text: _("Updated at ") + this.formatCurrentTimestamp(), + style_class: "quotes-last-update" }); }, - createErrorLabel : function (errorMsg) { + createErrorLabel: function(errorMsg) { return new St.Label({ - text : _("Error: ") + errorMsg, - style_class : "error-label" + text: _("Error: ") + errorMsg, + style_class: "error-label" }); }, - onDisplayChanged : function () { + onDisplayChanged: function() { this.mainBox.set_size(this.width, this.height); this.setTransparency(); }, - setTransparency:function() { + setTransparency: function() { this.mainBox.style = "background-color: rgba(0, 0, 0, " + this.transparency + ")"; }, - onSettingsChanged : function () { + onSettingsChanged: function() { this.unrender(); this.removeUpdateTimer(); this.onUpdate(); }, - on_desklet_removed : function () { + on_desklet_removed: function() { this.unrender(); this.removeUpdateTimer(); }, - - onUpdate : function () { + + onUpdate: function() { const quoteSymbols = this.quoteSymbolsText.split("\n"); const customUserAgent = this.sendCustomUserAgent ? this.customUserAgent : null; - + try { if (_crumb) { this.renderFinanceData(quoteSymbols, customUserAgent); @@ -702,24 +703,25 @@ StockQuoteDesklet.prototype = { this.onError(quoteSymbols, err); } }, - - existsCookie: function (name) { + + existsCookie: function(name) { for (let cookie of _cookieJar.all_cookies()) { let cookieName = IS_SOUP_2 ? cookie.name : cookie.get_name(); if (cookieName === name) { return true; } } - + return false; }, - - fetchCookieAndRender : function (quoteSymbols, customUserAgent) { + + fetchCookieAndRender: function(quoteSymbols, customUserAgent) { const _that = this; + this.quoteReader.getCookie(customUserAgent, function(authResponseMessage, responseBody) { if (_that.existsCookie(AUTH_COOKIE)) { _that.fetchCrumbAndRender(quoteSymbols, customUserAgent); - } else if (_that.existsCookie(CONSENT_COOKIE)) { + } else if (_that.existsCookie(CONSENT_COOKIE)) { _that.processConsentAndRender(authResponseMessage, responseBody, quoteSymbols, customUserAgent); } else { logWarning("Failed to retrieve auth cookie!"); @@ -727,12 +729,12 @@ StockQuoteDesklet.prototype = { } }); }, - - processConsentAndRender : function (authResponseMessage, consentPage, quoteSymbols, customUserAgent) { + + processConsentAndRender: function(authResponseMessage, consentPage, quoteSymbols, customUserAgent) { const _that = this; const formElementRegex = /(