Skip to content

Instantly share code, notes, and snippets.

@matthewgream
Created October 14, 2023 11:28
Show Gist options
  • Save matthewgream/0515376848bbea57abc996c14eef21a9 to your computer and use it in GitHub Desktop.
Save matthewgream/0515376848bbea57abc996c14eef21a9 to your computer and use it in GitHub Desktop.
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
function code_filter_for_gcloud (v) {
return !v.includes ('CODE' + ':' + 'GCLOUD');
}
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
/* CODE:GCLOUD
const { Console } = require ('node:console');
console = new Console ({ // eslint-disable-line no-global-assign
stdout: process.stdout, stderr: process.stderr,
inspectOptions: { depth: Infinity, sorted: true }
});
console.log (`Node.js ${process.version}`);
const __log_queueInsert__original = __log_queueInsert;
__log_queueInsert = function (m) { // eslint-disable-line no-func-assign
console.log ('[SYSTEM_LOG]: ' + m.join (' '));
}
const __telegram_background_enqueue__seconds = 30;
const __telegram_background_enqueue__finalize = function () {
if (__telegram_background_enqueue__finalize.__intervalId)
clearInterval (__telegram_background_enqueue__finalize.__intervalId);
__telegram_background_process ();
}
const __telegram_background_enqueue__original = __telegram_background_enqueue;
__telegram_background_enqueue = function (...args) { // eslint-disable-line no-func-assign
console.log (`intercepted __telegram_background_enqueue: interval.of:${__telegram_background_enqueue__seconds}s, process.on:exit`);
__telegram_background_enqueue__finalize.__intervalId = setInterval (__telegram_background_process, __telegram_background_enqueue__seconds * 1000);
process.on ('exit', __telegram_background_enqueue__finalize);
__telegram_background_enqueue = __telegram_background_enqueue__original; // eslint-disable-line no-func-assign
return __telegram_background_enqueue__original (...args);
}
CODE:GCLOUD */
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
/* CODE:GCLOUD
function system_profiling (level) {
if (level) {
const logLevel = Number (level) >= 0 && Number (level) <= 4 ? Number (level) : 3;
require ('@google-cloud/profiler').start ({
projectId: GCLOUD_DEFAULT_CONFIG.project, logLevel,
serviceContext: { service: GCLOUD_DEFAULT_CONFIG.service }
});
console.log (`NODE_PROFILING:${logLevel}`)
}
}
if (process.env ['NODE_PROFILING'])
system_profiling (process.env ['NODE_PROFILING']);
/*
CODE:GCLOUD */
function system_profiling () {
}
/* CODE:GCLOUD
*/
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
function adapter_test () {
}
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
/* CODE:GCLOUD
//
class Range {
constructor (sh, ad, va = undefined) { this.sh = sh; this.ad = `${sh.getName ()}!${ad}`; this.va = va; }
__grid () {
function __ref (ad) {
const _s = (x, a, b) => { for (var i = 0, r = ''; i < x.length; i++) if (x [i] >= a && x [i] <= b) r += x [i]; return r; }
const rc = ad.toUpperCase ().substring (ad.lastIndexOf ('!') + 1).split (':');
const c1 = _s (rc [0], 'A', 'Z'), c2 = rc.length > 1 ? _s (rc [1], 'A', 'Z') : '', r1 = _s (rc [0], '0', '9'), r2 = rc.length > 1 ? _s (rc [1], '0', '9') : '';
return [c1, r1, c2, r2]; }
const [c1, r1, c2, r2] = __ref (this.ad);
return { 'sheetId': this.sh.getId (),
'startRowIndex': r1 ? (Number (r1) - 1) : 0, 'endRowIndex': r2 ? Number (r2) : this.sh.getMaxRows (),
'startColumnIndex': c1 ? (gsheet_abc2col (c1) - 1) : 0, 'endColumnIndex': c2 ? gsheet_abc2col (c2) : this.sh.getMaxColumns (),
}; }
__a1ad (grid) {
return `${this.sh.getName ()}!${gsheet_col2abc (grid.startColumnIndex + 1)}${grid.startRowIndex + 1}:${gsheet_col2abc (grid.endColumnIndex)}${grid.endRowIndex}`; }
clear () { this.sh.sp.__request ('', `/values/${this.ad}:clear`, {}, 'POST'); return this; }
clearContent () { return this.clear (); }
getValue (valueRenderOption = 'UNFORMATTED_VALUE') { return this.getValues (valueRenderOption)?.[0]?.[0]; }
getValues (valueRenderOption = 'UNFORMATTED_VALUE') {
var v = this.va || ((this.va = this.sh.sp.__request ('', `/values/${this.ad}`, { valueRenderOption })) && (this.va = this.va.values)) || Array ();
const g = this.__grid (), c = (g.endColumnIndex - g.startColumnIndex), r = (g.endRowIndex - g.startRowIndex);
if (v.length < r) v = [...v, ...Array (r - v.length).fill (Array (c).fill (''))];
for (var i = 0; i < v.length; i++) if (v [i].length < c) v [i] = [...v [i], ...Array (c - v [i].length).fill ('')];
return v; }
setValue (va, valueInputOption = 'USER_ENTERED') { return this.setValues ([ [ va ] ], valueInputOption); }
setValues (va, valueInputOption = 'USER_ENTERED') {
for (var offset = 0, number = Math.ceil (JSON.stringify (va).length / GSHEET_CFG.PAYLOAD_SIZE_LIMIT),
length = Math.ceil (va.length / number), grid = this.__grid (), values, range; offset < number; offset ++) {
values = va.slice (offset * length, (offset + 1) * length),
range = this.__a1ad ({...grid, startRowIndex: grid.startRowIndex + (offset * length), endRowIndex: grid.startRowIndex + (offset * length) + values.length });
this.sh.sp.__request ('', `/values/${range}`, { valueInputOption }, 'PUT', { range, values });
}
this.va = va; return this; }
__rgbColor (rgbColor) {
const __code = (x, a) => parseInt (x.slice (a, a + 2), 16) / 256, __name = (x) => ({ 'black': '#000000' } [x]);
return ((rgbColor = __name (rgbColor) || rgbColor) [0] === '#') ? { red: __code (rgbColor, 1), green: __code (rgbColor, 3), blue: __code (rgbColor, 5) } : null; }
__numberFormat (pattern) { var type = 'NUMBER';
if (pattern == '0.###############') pattern = 'General'; // type = 'NUMBER';
else if (util_str_hasanychar (pattern, '%')) type = 'PERCENT';
else if (util_str_hasanychar (pattern, 'ymdhMs')) type = 'DATE_TIME';
return { pattern, type }; }
__userEnteredFormatContent (userEnteredFormat) {
const __fields = (x) => Object.entries (x).flatMap (([n, v]) => typeof v == 'object' && Object.keys (v).length > 0 ? Object.keys (v).map (v => n+'.'+v) : n).join (',');
return { 'fields': `userEnteredFormat(${__fields (userEnteredFormat)})`, 'cell': { userEnteredFormat } }; }
__userEnteredFormat (format) {
this.sh.sp.__batchUpdate ({ 'repeatCell': { ...this.__userEnteredFormatContent (format), 'range': this.__grid () } }); return this; }
__batchUpdateOptimizer__numberFormat (requests) {
const __pass = (u, xa, xb, ya, yb, c) => u.reduce ((r, u_) => {
if (r.length > 0 && (r [0] [xa] == u_ [xa] && r [0] [xb] == u_ [xb]) && r [0] [yb] == u_ [ya] && c (r [0].format, u_.format)) r [0] [yb] ++; else r.unshift (u_); return r; }, Array ());
const __comp = (a, b) => (!a && !b) || (a && b && a == b);
return __pass (__pass (requests.sort ((a, b) => b.col - a.col), 'col', 'colend', 'row', 'rowend', __comp), 'row', 'rowend', 'col', 'colend', __comp); }
getNumberFormats () {
const __format = (pattern) => (pattern && pattern == 'General') ? '0.###############' : pattern;
const response = this.sh.sp.__request ('', ``, { 'ranges': this.ad, 'fields': 'sheets.data.rowData.values.userEnteredFormat.numberFormat' }), grid = this.__grid ();
return response ?.sheets ?.[0] ?.data ?.[0] ? Array.from ({ length: grid.endRowIndex - grid.startRowIndex }, (_, row) =>
Array.from ({ length: grid.endColumnIndex - grid.startColumnIndex }, (_, col) =>
__format (response ?.sheets ?.[0] ?.data ?.[0] ?.rowData ?.[row] ?.values ?.[col] ?.userEnteredFormat ?.numberFormat ?.pattern || '')
)) : undefined;
}
setNumberFormats (formats) {
const __cell = (grid, c, cx, r, rx) => { const cell = __DEEPCOPY (grid); cell.startColumnIndex = c + grid.startColumnIndex; cell.endColumnIndex = cx + grid.startColumnIndex;
cell.startRowIndex = r + grid.startRowIndex; cell.endRowIndex = rx + grid.startRowIndex; return cell; }
const grid = this.__grid ();
const requests = formats.filter ((_x1, row) => row < (grid.endRowIndex - grid.startRowIndex)).flatMap ((format_cols, row) =>
format_cols.filter ((_x2, col) => col < (grid.endColumnIndex - grid.startColumnIndex)).map ((format, col) => ({col, colend: col + 1, row, rowend: row + 1, format})));
this.sh.sp.__batchUpdate (this.__batchUpdateOptimizer__numberFormat (requests).map (r =>
({ 'repeatCell': { ...this.__userEnteredFormatContent ({ 'numberFormat': this.__numberFormat (r.format) }),
'range': __cell (grid, r.col, r.colend, r.row, r.rowend) } }))); return this; }
getNumRows () { const grid = this.__grid (); return (grid.endRowIndex + 1) - grid.startRowIndex; }
setFontFamily (fontFamily) { return this.__userEnteredFormat ({ 'textFormat': { fontFamily } }); }
setFontSize (fontSize) { return this.__userEnteredFormat ({ 'textFormat': { fontSize } }); }
setFontColor (fontColor) { return this.__userEnteredFormat ({ 'textFormat': { 'foregroundColorStyle': { 'rgbColor': this.__rgbColor (fontColor) } } }); }
setWrapStrategy (wrapStrategy) { return this.__userEnteredFormat ({ wrapStrategy }); }
_setFilter (filter) { filter ['range'] = this.__grid (); this.sh.sp.__batchUpdate ({ 'setBasicFilter': { filter }}); }
getFilter () { return this.sh.getFilter (); } // XXX only if intersects
}
//
class RangeList {
constructor (sh, ad) { this.sh = sh; this.ad = ad.map (ad => `${this.sh.getName ()}!${ad}`); }
getRanges () { const va = this.sh.sp.__batchGet (this.ad); return this.ad.map ((ad, i) => new Range (this.sh, ad, va [i])); }
}
//
class Sheet {
constructor (sp, md) { this.sp = sp; this.md = md; }
__sync (sheetId) { this.md = this.sp.__update (sheetId); return this; }
__setRows (rs, re, properties, fields) { const sheetId = this.md.properties.sheetId, dimension = 'ROWS', startIndex = (rs - 1), endIndex = (re - 1);
this.sp.__batchUpdate ({ 'updateDimensionProperties': { 'range': { sheetId, dimension, startIndex, endIndex }, properties, fields } });
return this.__sync (sheetId); }
activate () { return this; }
getIndex () { return 1; }
isSheetHidden () { return false; }
showSheet () { return this; }
hideSheet () { return this; }
getParent () { return this.sp; }
getId () { return this.md.properties.sheetId; }
getName () { return this.md.properties.title; }
getMaxRows () { return this.md.properties.gridProperties.rowCount; }
getMaxColumns () { return this.md.properties.gridProperties.columnCount; }
getLastRow () { return this.md.properties.gridProperties.rowCount; } // not correct really
getLastColumn () { return this.md.properties.gridProperties.columnCount; } // not correct really
getFrozenRows () { return this.md.properties.gridProperties.frozenRowCount; }
hideRows (rs, re) { return this.__setRows (rs, re, { 'hiddenByUser': true }, 'hiddenByUser'); }
showRows (rs, re) { return this.__setRows (rs, re, { 'hiddenByUser': false }, 'hiddenByUser'); }
appendRow () { system_error_throw ('appendRow: not implemented'); }
// appendRow (rv) { const sheetId = this.md.properties.sheetId, values = rv.map (stringValue => ({ 'userEnteredValue': { stringValue }})), fields = 'userEnteredValue';
// this.sp.__batchUpdate ({ 'appendCells': { sheetId, 'rows': [{ values }], fields } }); return this.__sync (sheetId); }
deleteRows (rs, rc) { const sheetId = this.md.properties.sheetId, startRowIndex = (rs - 1), endRowIndex = (rs - 1) + rc, shiftDimension = 'ROWS';
this.sp.__batchUpdate ({ 'deleteRange': { 'range' : { sheetId, startRowIndex, endRowIndex }, shiftDimension } }); return this.__sync (sheetId); }
insertRowsBefore (rs, rc) { const sheetId = this.md.properties.sheetId, startIndex = (rs - 1), endIndex = (rs - 1) + rc, dimension = 'ROWS';
this.sp.__batchUpdate ({ 'insertDimension': { 'range': { sheetId, dimension, startIndex, endIndex }, 'inheritFromBefore': false } }); return this.__sync (sheetId); }
insertRowsAfter (rs, rc) { const sheetId = this.md.properties.sheetId, dimension = 'ROWS';
this.sp.__batchUpdate (rs >= this.md.properties.gridProperties.rowCount ? { 'appendDimension': { sheetId, dimension, 'length': rc } } :
{ 'insertDimension': { 'range': { sheetId, dimension, 'startIndex': (rs - 1), 'endIndex': (rs - 1) + rc }, 'inheritFromBefore': true } }); return this.__sync (sheetId); }
getRange (ra, ca, nr, nc) {
if (typeof ra == 'string') return new Range (this, ra);
if (![ra, ca].every (util_str_numIs)) return undefined;
const { rowCount, columnCount } = this.md.properties.gridProperties, xx = (a, n, e) => (n && util_str_numIs (n)) ? a + n : e - 1;
return new Range (this, `${gsheet_col2abc (ca)}${ra}:${gsheet_col2abc (xx (ca, nc, columnCount))}${xx (ra, nr, rowCount)}`); }
getRangeList (ra) { return new RangeList (this, ra); }
getConditionalFormatRules () {
return this.md.conditionalFormats || Array (); }
setConditionalFormatRules (rules) { const sheetId = this.md.properties.sheetId;
const cur_length = (this.md.conditionalFormats || Array ()).length, new_length = rules.length, del_length = Math.max (cur_length - new_length, 0);
rules.forEach (rule => rule?.ranges?.forEach (range => range.sheetId = sheetId));
this.sp.__batchUpdate ([
...Array.from ({ length: del_length }, (_, index) => ({ 'deleteConditionalFormatRule': { sheetId, index: new_length + ((del_length - 1) - index) }})),
...rules.slice (0, cur_length).map ((rule, index) => ({ 'updateConditionalFormatRule': { index, rule }})),
...rules.slice (cur_length).map ((rule, index) => ({ 'addConditionalFormatRule': { index: cur_length + index, rule }}))
]);
this.md.conditionalFormats = rules;
}
_setFilter (filter) { this.sp.__batchUpdate ({ 'setBasicFilter': { filter }}); }
getFilter () { const filter = this.md.basicFilter; if (filter && filter.criteria && filter.filterSpecs) delete filter.criteria; return filter; }
}
//
class Spreadsheet {
constructor (id) { this.id = id; this.__update (); }
__create (sh) { return __CACHABLE (this.__create, sh.properties.sheetId, () => new Sheet (this, sh)); }
__update (sheetId = undefined) { this.md = this.__request (); return sheetId ? this.md.sheets.find (sh => sh.properties.sheetId == sheetId) : undefined; }
__request (xxxx = '', path = '', args = undefined, method = 'GET', data = undefined) {
return util_retry_whileNull (GSHEET_CFG.REQUEST_RETRY_COUNT, GSHEET_CFG.REQUEST_RETRY_DELAY,
() => util_exception_wrapper2 (() => gsheet_request (this.id, path, args, method, data),
(e) => { console.log ([xxxx, this.id, path, args, method]); console.log (e); return undefined; })); }
__batchGet (ranges, valueRenderOption = 'UNFORMATTED_VALUE') { var results = Array ();
for (var offset = 0, length = GSHEET_CFG.BATCH_REQUEST_LIMIT; offset < ranges.length && results; offset += length) { // could be smarter, needs to be url length
const re = this.__request (`${offset}/${offset + length}/${ranges.length}`, `/values:batchGet`, { 'ranges': ranges.slice (offset, offset + length), valueRenderOption });
results = re && re.valueRanges ? [...results, ...re.valueRanges.map (v => v.values)] : undefined;
} return results; }
__batchUpdate (requests) { requests = util_array_always (requests);
const chunks = JSON.stringify (requests).length / GSHEET_CFG.PAYLOAD_SIZE_LIMIT,
length = Math.ceil (Math.min (requests.length / chunks, GSHEET_CFG.BATCH_UPDATE_LIMIT - GSHEET_CFG.BATCH_UPDATE_THRESHOLD));
for (var offset = 0; offset < requests.length; offset += length)
this.__request (`${offset}/${offset + length}/${requests.length}`, `:batchUpdate`, {}, 'POST', { 'requests': requests.slice (offset, offset + length) }); }
getId () { return this.id; }
getName () { return this.md.properties.title; }
getSheets () { return this.md.sheets.map (sh => this.__create (sh)); }
getSheetByName (na) { const sh = this.md.sheets.find (sh => sh.properties && sh.properties.title == na); return sh ? this.__create (sh) : undefined; }
moveActiveSheet (n) { return this; } // eslint-disable-line no-unused-vars
duplicateActiveSheet () { system_error_throw ('duplicateActiveSheet: not supported'); }
}
//
class SpreadsheetApp {
static __create (id) { return __CACHABLE (SpreadsheetApp.__create, id, () => new Spreadsheet (id)); }
static openById (id) { return SpreadsheetApp.__create (id); }
static getActiveSpreadsheet () { return SpreadsheetApp.__create (APPLICATION_CONSOLE); }
} SpreadsheetApp.WrapStrategy = { 'CLIP': 'CLIP' };
CODE:GCLOUD */
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
/* CODE:GCLOUD
class ScriptApp {
static getScriptId () { return APPLICATION_SCRIPT; }
static getOAuthToken () { return gcloud_auth_token_header () ['Authorization'].split (' ') [1]; }
}
[ 'https://mail.google.com/',
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/devstorage.read_write',
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/script.scriptapp',
'https://www.googleapis.com/auth/script.projects.readonly',
'https://www.googleapis.com/auth/script.processes',
'https://www.googleapis.com/auth/script.external_request',
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/script.container.ui',
'https://www.googleapis.com/auth/script.deployments',
'https://www.googleapis.com/auth/script.metrics'
].forEach (scope => CLOUD_DEFAULT_AUTH_SCOPES.includes (scope) || CLOUD_DEFAULT_AUTH_SCOPES.push (scope));
class PropertiesInstance {
constructor (type) { this._type = type; }
getProperty (name) { return PropertiesInstance.store [this._type] [name]; }
getProperties () { return PropertiesInstance.store [this._type]; }
setProperty (name, data) { PropertiesInstance.store [this._type] [name] = data; return this; }
deleteProperty (name) { delete PropertiesInstance.store [this._type] [name]; return this; }
deleteAllProperties () { PropertiesInstance.store [this._type] = {}; return this; }
getKeys () { return Object.keys (PropertiesInstance.store [this._type]); }
} PropertiesInstance.store = { script: {}, document: {}, user: {} };
class PropertiesService {
static getScriptProperties () { return new PropertiesService.type ('script'); }
static getDocumentProperties () { return new PropertiesService.type ('document'); }
static getUserProperties () { return new PropertiesService.type ('user'); }
} PropertiesService.type = PropertiesInstance;
class CacheInstance {
constructor (type) { this._type = type; }
get (name) { return CacheInstance.store [this._type] [name]; }
getAll (names) { return names.map (name => CacheInstance.store [this._type] [name]); }
put (name, data, time) { CacheInstance.store [this._type] [name] = data; return this; } // eslint-disable-line no-unused-vars
putAll (namedatas, time) { Object.entries (namedatas).forEach (([name, data]) => CacheInstance.store [this._type] [name] = data); return this; } // eslint-disable-line no-unused-vars
} CacheInstance.store = { script: {} };
class CacheService {
static getScriptCache () { return new CacheService.type ('script'); }
} CacheService.type = CacheInstance;
class Lock {
hasLock () { return true; }
releaseLock () { }
tryLock () { return true; }
waitLock () { }
}
class LockService {
static getScriptLock () { return new Lock (); }
static getDocumentLock () { return new Lock (); }
static getUserLock () { return new Lock (); }
}
class HtmlService {
}
class ContentService {
}
class GmailApp {
}
class Session {
static getScriptTimeZone () { return 'Etc/UTC'; }
}
CODE:GCLOUD */
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
/* CODE:GCLOUD
function util_hash_sha256 (x) {
return require ('crypto').createHash ('SHA256').update (x).digest ();
}
function util_sign_rsasha256 (s, k) {
return require ('crypto').createSign ('RSA-SHA256').update (s).sign (k);
}
function util_base64_encode (x) {
return Buffer.from (x).toString ('base64');
}
function util_base64_decode (x) {
return Buffer.from (x, 'base64');
}
function util_zip (name, files) {
const ZipFile = require ('adm-zip'), zip = new ZipFile (); files.forEach (file => zip.addFile (file.name, file.data)); return zip.toBuffer ();
}
function util_unzip (data) {
const ZipFile = require ('adm-zip'), zip = new ZipFile (Buffer.from (data));
return zip.getEntries ().map (entry => ({
getName: () => entry.entryName,
getContentType: () => entry.entryName.endsWith ('txt') ? 'text/plain' : ( entry.entryName.endsWith ('csv') ? 'text/csv' : 'application/octet-stream' ),
getDataAsString: () => zip.readAsText (entry)
}));
}
function util_gzip (input) {
return require ('zlib').gzipSync (input);
}
function util_gunzip (input) {
return require ('zlib').gunzipSync (input).toString ();
}
function util_sleep (s) {
const waitTill = Date.now () + (s * 1000); while (waitTill > Date.now ()) { } // eslint-disable-line no-empty
}
/*
CODE:GCLOUD */
function util_hash_sha256 (x) {
return Utilities.computeDigest (Utilities.DigestAlgorithm.SHA_256, x);
}
function util_sign_rsasha256 (s, k) {
return Utilities.computeRsaSha256Signature (s, k);
}
function util_base64_encode (x) {
return Utilities.base64Encode (x);
}
function util_base64_decode (x) {
return Utilities.base64Decode (x);
}
function util_zip (name, files) {
return Utilities.zip (files.map (f => Utilities.newBlob (f.data, f.type, f.name)), name).getBytes ();
}
function util_unzip (data) {
return Utilities.unzip (Utilities.newBlob (util_arraybuffer_to_data (data), 'application/zip'));
}
function util_gzip (input) {
return Utilities.gzip (Utilities.newBlob (input)).getBytes ();
}
function util_gunzip (input) {
return Utilities.ungzip (Utilities.newBlob (input).setContentType ('application/x-gzip')).getDataAsString ();
}
function util_sleep (m) {
return Utilities.sleep (m * 1000);
}
/* CODE:GCLOUD
*/
// -----------------------------------------------------------------------------------------------------------------------------------------
/* CODE:GCLOUD
const __connect_responseDebugHeaders = (r) => r?.headers;
const __connect_responseDebugContent = (r) => r?.clone ()?.text ();
const __connect_responseFetch = (u, o) => {
if (o?.headers ['Content-Type'] == 'data') o.headers ['Content-Type'] = 'application/octet-stream';
if (o?.headers ['Content-Type'] == 'text') o.headers ['Content-Type'] = 'text/plain';
if (o.payload) o.body = o.payload, delete o.payload;
return sync_fetch (u, o);
}
const __connect_responseLength = (r) => r?.length || 0;
const __connect_responseStatus = (r) => r.status;
const __connect_responseCheck = (r) => r.ok || system_error_throw (`__connect_error: ${r.status} ${r.statusText}`);
const __connect_responseDecode = (r, t) => (t = { // eslint-disable-line no-cond-assign
'arraybuffer': (r) => r.arrayBuffer (),
'blob': (r) => r.blob (),
'json': (r) => r.json (),
'xml' : (r) => __xml_parse (r.text ()),
'text': (r) => String (r.text ()),
'data': (r) => new Uint8Array (r.arrayBuffer ())
} [t]) ? t (r) : undefined;
function __xml_parse (text) { // eslint-disable-line no-unused-vars
system_error_throw ('__xml_parse: not implemented');
}
/*
CODE:GCLOUD */
const __connect_responseDebugHeaders = (r) => r?.getAllHeaders ();
const __connect_responseDebugContent = (r) => r?.getContentText ();
const __connect_responseFetch = (u, o) => {
if (o?.headers ['Content-Type'] == 'data') o.headers ['Content-Type'] = 'application/octet-stream';
if (o?.headers ['Content-Type'] == 'text') o.headers ['Content-Type'] = 'text/plain';
return UrlFetchApp.fetch (u, o);
}
const __connect_responseLength = (r) => r?.getContent ()?.length || 0;
const __connect_responseStatus = (r) => r.getResponseCode ();
const __connect_responseCheck = () => { }
const __connect_responseDecode = (r, t) => (t = {
'arraybuffer': (r) => util_data_to_arraybuffer (r.getBlob ().getBytes ()),
'blob': (r) => r.getBlob (),
'json': (r) => JSON.parse (r.getContentText ()),
'xml' : (r) => __xml_parse (r.getContentText ()),
'text': (r) => r.getContentText (),
'data': (r) => r.getContent (),
} [t]) ? t (r) : undefined;
function __xml_parse (text) {
return text.includes ('<') && text.includes ('>') && (text = XmlService.parse (text)) ? text?.getRootElement () : undefined;
}
/* CODE:GCLOUD
*/
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
/* CODE:GLINUX
const __fs_cache_data = {
directory: process.env ['CACHEDIR'] || './cache', file: undefined, dirty: 0, flush: 25, fsize: 512, findex: 100
};
const __fs_cache_load = () => { if (__fs_cache_data.file) return;
__fs_cache_data.file = {};
for (var d, i = __fs_cache_data.findex; (d = util_exception_wrapper2 (() => util_file (__fs_cache_data.directory, '/cache' + (i ++) + '.txt', 'text'))); )
__fs_cache_data.file = Object.assign (__fs_cache_data.file, JSON.parse (d));
debugLog (`cache: ${util_obj_length (__fs_cache_data.file)}`);
process.on ('exit', () => __fs_cache_save ());
}
const __fs_cache_save = () => { if (!__fs_cache_data.file) return;
for (var x = Object.keys (__fs_cache_data.file), i = __fs_cache_data.findex; x.length > 0; ) {
var y = {}; for (var j = 0, z; j < __fs_cache_data.fsize && x.length > 0; j ++) z = x.shift (), y [z] = __fs_cache_data.file [z];
util_exception_wrapper2 (() => util_file (__fs_cache_data.directory, '/cache' + (i ++) + '.txt', 'create', JSON.stringify (y)));
}
}
const __fs_cache_xxx = () => { if (++__fs_cache_data.dirty >= __fs_cache_data.flush) __fs_cache_data.dirty = 0, __fs_cache_save (); }
//const __fs_cache_del = (n) => { __fs_cache_load (); delete __fs_cache_data.file [n]; __fs_cache_xxx (); }
const __fs_cache_set = (n, v) => { __fs_cache_load (); __fs_cache_data.file [n] = v; __fs_cache_xxx (); }
const __fs_cache_get = (n) => { __fs_cache_load (); return __fs_cache_data.file?.[n]; }
//const __fs_cache_all = () => { __fs_cache_load (); return __fs_cache_data.file; }
// -----------------------------------------------------------------------------------------------------------------------------------------
class CacheInstance_File {
get (name) { return __fs_cache_get (name); }
put (name, data, time) { __fs_cache_set (name, data); return this; } // eslint-disable-line no-unused-vars
getAll (names) { return Object.fromEntries (names.map (name => [name, __fs_cache_get (name)])); }
putAll (namedatas, time) { Object.entries (namedatas).forEach (([name, data]) => __fs_cache_set (name, data)); return this; } // eslint-disable-line no-unused-vars
} CacheService.type = CacheInstance_File;
// -----------------------------------------------------------------------------------------------------------------------------------------
class PropertiesInstance_Cloud {
static __data (type) {
if (PropertiesInstance_Cloud.variables.init == false) {
PropertiesInstance_Cloud.variables.init = true;
const data = properties_cloud_request ();
if (data) PropertiesInstance_Cloud.variables.data = data;
}
return PropertiesInstance_Cloud.variables.data [type]; }
static __reset (type) {
PropertiesInstance_Cloud.variables.data [type] = { }; }
constructor (type) { this._type = type; this._data = PropertiesInstance_Cloud.__data (this._type); }
getProperty (name) { return this._data [name]; }
setProperty (name, data) { this._data [name] = data; return this; }
getProperties () { return this._data; }
deleteProperty (name) { delete this._data [name]; return this; }
deleteAllProperties () { PropertiesInstance_Cloud.__reset (this._type); return this; }
getKeys () { return Object.keys (this._data); }
} PropertiesInstance_Cloud.variables = { data: { script: {}, user: {}, document: {} }, init: false };
PropertiesService.type = PropertiesInstance_Cloud;
// -----------------------------------------------------------------------------------------------------------------------------------------
function util_file (folder, filename, attribute, arg1) {
const filesystem = require ('fs');
return util_exception_wrapper2 (() => { const fullname = (folder || '.') + '/' + filename;
if (attribute == 'modified') return filesystem.statSync (fullname) ['mtime'];
if (attribute == 'data' || attribute == 'arraybuffer') return filesystem.readFileSync (fullname).buffer;
else if (attribute == 'text') return String (filesystem.readFileSync (fullname));
else if (attribute == 'delete') return filesystem.rmSync (fullname);
else if (attribute == 'create') return filesystem.writeFileSync (fullname, Buffer.from (arg1));
return undefined;
});
}
// -----------------------------------------------------------------------------------------------------------------------------------------
class SymbolDataStore_FileSystem extends DataStoreBase {
static get cacheable () { return true; }
static load (name, link, opts = {}) { return util_file (__fs_cache_data.directory, name, opts.type || 'text'); }
static save (data, name, link, opts = {}) { return util_file (__fs_cache_data.directory, name, 'create', data); }
} SymbolDataStore.providers.unshift (SymbolDataStore_FileSystem);
// -----------------------------------------------------------------------------------------------------------------------------------------
CODE:GLINUX */
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
const GZip = {
compressToBase64: function (input) { return util_base64_encode (util_gzip (input)); },
decompressFromBase64: function (input) { return util_gunzip (util_base64_decode (input)); },
compressToUTF16: function (input) { return util_base32768_encode (util_gzip (input)); },
decompressFromUTF16: function (input) { return util_gunzip (util_base32768_decode (input)); },
compressToUint8Array : function (input) { return util_gzip (input); },
decompressFromUint8Array : function (input) { return util_gunzip (input); },
}
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
function properties_cloud_request () {
return util_exception_wrapper3 (() => connect_urlResponseJson ('Properties', APPLICATION_URL + util_str_url_args ({ properties: true })));
}
function properties_cloud_respond () {
const properties = Object.fromEntries (['Script', 'Document', 'User'].map (type => [type.toLowerCase (), PropertiesService [`get${type}Properties`] ().getProperties ()]));
return [ JSON.stringify (properties), 'json' ];
}
function properties_webHandler_GET (type, args) {
const __mimetype = (text) => ({ 'text': ContentService.MimeType.TEXT, 'json': ContentService.MimeType.JSON } [text]);
return connect_webHandler_process_GET (args, (parameters) => !util_is_null (parameters ['properties']),
() => { const [ data, type ] = properties_cloud_respond (); return data ? ContentService.createTextOutput (data).setMimeType (__mimetype (type)) : undefined; });
}
function properties_webHandler_setup () {
connect_webHandler_register_GET (properties_webHandler_GET);
}
// -----------------------------------------------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment