puvox-library 1.0.11 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/library_standard.js +268 -51
- package/package.json +1 -1
- package/test.js +8 -0
package/library_standard.js
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
* const helpers = new PuvoxLibrary();
|
11
11
|
* console.log ( helpers.get_last_child_of_array(array) );
|
12
12
|
* console.log ( helpers.get_visitor_ip() );
|
13
|
+
* console.log ( helpers.telegramMessage("hello world", "1234567890", "BOTKEY123:456789") );
|
13
14
|
* ... etc
|
14
15
|
*
|
15
16
|
*/
|
@@ -158,6 +159,150 @@ const puvox_library =
|
|
158
159
|
return this.stringArrayToNumeric(this.stringToArray(arr));
|
159
160
|
},
|
160
161
|
|
162
|
+
|
163
|
+
|
164
|
+
// region: ####### from CCXT ##########
|
165
|
+
keys: Object.keys,
|
166
|
+
values: (x) => ((!isArray (x)) ? Object.values (x) : x),
|
167
|
+
extend: (...args) => Object.assign ({}, ...args), // NB: side-effect free
|
168
|
+
clone:(x) => (isArray (x) ? Array.from (x) : extend (x)),
|
169
|
+
index: (x) => new Set (values (x)),
|
170
|
+
ordered: (x) => x, // a stub to keep assoc keys in order (in JS it does nothing, it's mostly for Python)
|
171
|
+
unique: (x) => Array.from (index (x)),
|
172
|
+
arrayConcat: (a, b) => a.concat (b),
|
173
|
+
inArray (needle, haystack) {
|
174
|
+
return haystack.includes (needle);
|
175
|
+
},
|
176
|
+
toArray (object) {
|
177
|
+
return Object.values (object);
|
178
|
+
},
|
179
|
+
isEmpty (object) {
|
180
|
+
if (!object) {
|
181
|
+
return true;
|
182
|
+
}
|
183
|
+
return (Array.isArray (object) ? object : Object.keys (object)).length < 1;
|
184
|
+
},
|
185
|
+
keysort (x, out = {}) {
|
186
|
+
for (const k of keys (x).sort ()) {
|
187
|
+
out[k] = x[k];
|
188
|
+
}
|
189
|
+
return out;
|
190
|
+
},
|
191
|
+
indexBy (x, k, out = {}) {
|
192
|
+
// description: https://github.com/ccxt/ccxt/blob/master/js/base/functions/generic.js
|
193
|
+
for (const v of values (x)) {
|
194
|
+
if (k in v) {
|
195
|
+
out[v[k]] = v;
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
199
|
+
return out;
|
200
|
+
},
|
201
|
+
groupBy (x, k, out = {}) {
|
202
|
+
// description: https://github.com/ccxt/ccxt/blob/master/js/base/functions/generic.js
|
203
|
+
for (const v of values (x)) {
|
204
|
+
if (k in v) {
|
205
|
+
const p = v[k];
|
206
|
+
out[p] = out[p] || [];
|
207
|
+
out[p].push (v);
|
208
|
+
}
|
209
|
+
}
|
210
|
+
return out;
|
211
|
+
},
|
212
|
+
filterBy (x, k, value = undefined, out = []) {
|
213
|
+
// description: https://github.com/ccxt/ccxt/blob/master/js/base/functions/generic.js
|
214
|
+
for (const v of values (x)) {
|
215
|
+
if (v[k] === value) {
|
216
|
+
out.push (v);
|
217
|
+
}
|
218
|
+
}
|
219
|
+
return out;
|
220
|
+
},
|
221
|
+
sortBy: (array, key, descending = false, direction = descending ? -1 : 1) => array.sort ((a, b) => {
|
222
|
+
if (a[key] < b[key]) {
|
223
|
+
return -direction;
|
224
|
+
} else if (a[key] > b[key]) {
|
225
|
+
return direction;
|
226
|
+
} else {
|
227
|
+
return 0;
|
228
|
+
}
|
229
|
+
}),
|
230
|
+
sortBy2: (array, key1, key2, descending = false, direction = descending ? -1 : 1) => array.sort ((a, b) => {
|
231
|
+
if (a[key1] < b[key1]) {
|
232
|
+
return -direction;
|
233
|
+
} else if (a[key1] > b[key1]) {
|
234
|
+
return direction;
|
235
|
+
} else {
|
236
|
+
if (a[key2] < b[key2]) {
|
237
|
+
return -direction;
|
238
|
+
} else if (a[key2] > b[key2]) {
|
239
|
+
return direction;
|
240
|
+
} else {
|
241
|
+
return 0;
|
242
|
+
}
|
243
|
+
}
|
244
|
+
}),
|
245
|
+
flatten: function flatten (x, out = []) {
|
246
|
+
|
247
|
+
for (const v of x) {
|
248
|
+
if (isArray (v)) {
|
249
|
+
flatten (v, out);
|
250
|
+
} else {
|
251
|
+
out.push (v);
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
return out;
|
256
|
+
},
|
257
|
+
pluck: (x, k) => values (x).filter ((v) => k in v).map ((v) => v[k]),
|
258
|
+
omit (x, ...args) {
|
259
|
+
if (!Array.isArray (x)) {
|
260
|
+
|
261
|
+
const out = clone (x);
|
262
|
+
|
263
|
+
for (const k of args) {
|
264
|
+
if (isArray (k)) { // omit (x, ['a', 'b'])
|
265
|
+
for (const kk of k) {
|
266
|
+
delete out[kk];
|
267
|
+
}
|
268
|
+
} else {
|
269
|
+
delete out[k]; // omit (x, 'a', 'b')
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
return out;
|
274
|
+
}
|
275
|
+
|
276
|
+
return x;
|
277
|
+
},
|
278
|
+
sum (...xs) {
|
279
|
+
const ns = xs.filter (isNumber); // leave only numbers
|
280
|
+
return (ns.length > 0) ? ns.reduce ((a, b) => a + b, 0) : undefined;
|
281
|
+
},
|
282
|
+
deepExtend: function deepExtend (...xs) {
|
283
|
+
let out = undefined;
|
284
|
+
for (const x of xs) {
|
285
|
+
if (isDictionary (x)) {
|
286
|
+
if (!isDictionary (out)) {
|
287
|
+
out = {};
|
288
|
+
}
|
289
|
+
for (const k in x) { // eslint-disable-line guard-for-in
|
290
|
+
out[k] = deepExtend (out[k], x[k]);
|
291
|
+
}
|
292
|
+
} else {
|
293
|
+
out = x;
|
294
|
+
}
|
295
|
+
}
|
296
|
+
return out;
|
297
|
+
},
|
298
|
+
// endregion: ####### from CCXT ##########
|
299
|
+
|
300
|
+
|
301
|
+
|
302
|
+
|
303
|
+
|
304
|
+
|
305
|
+
|
161
306
|
objectCopy(obj){
|
162
307
|
return JSON.parse(JSON.stringify(obj));
|
163
308
|
},
|
@@ -382,8 +527,9 @@ const puvox_library =
|
|
382
527
|
isArray(x) { return ( (!!x) && (x.constructor === Array) ) || (Array.isArray(x)); },
|
383
528
|
|
384
529
|
isSimpleVariableType(obj){ return this.isSimpleVariableTypeName(typeof obj); },
|
385
|
-
isSimpleVariableTypeName(
|
386
|
-
|
530
|
+
isSimpleVariableTypeName(typeName_){ return this.inArray( [ "boolean", "integer", "float", "double", "decimal", "string"], typeName_); },
|
531
|
+
isNumericVariableType(obj){ return this.isNumericVariableTypeName(typeof obj); },
|
532
|
+
isNumericVariableTypeName(typeName_){ return this.inArray( [ "integer", "float", "double", "decimal"], typeName_); },
|
387
533
|
|
388
534
|
stringToBoolean(string){
|
389
535
|
switch(string.toLowerCase().trim()){
|
@@ -460,12 +606,18 @@ const puvox_library =
|
|
460
606
|
trimOnlyFromEnd(content){
|
461
607
|
return content.replace(/\s*$/,"");
|
462
608
|
},
|
609
|
+
startsWith(content, what){
|
610
|
+
return content.startsWith(what);
|
611
|
+
},
|
463
612
|
startsWithArray(content,array){
|
464
613
|
array.forEach(function(val){
|
465
614
|
if (content.startsWith(val)) return true;
|
466
615
|
})
|
467
616
|
return false;
|
468
617
|
},
|
618
|
+
endsWith(content, what){
|
619
|
+
return content.endsWith(what);
|
620
|
+
},
|
469
621
|
endsWithArray(content,array){
|
470
622
|
array.forEach(function(val){
|
471
623
|
if (content.endsWith(val)) return true;
|
@@ -1295,6 +1447,8 @@ const puvox_library =
|
|
1295
1447
|
)
|
1296
1448
|
},
|
1297
1449
|
|
1450
|
+
milliseconds(){ return (new Date().getTime()); },
|
1451
|
+
|
1298
1452
|
fancyTimeFormat(time)
|
1299
1453
|
{
|
1300
1454
|
var time = time.toFixed(0);
|
@@ -2467,36 +2621,68 @@ const puvox_library =
|
|
2467
2621
|
|
2468
2622
|
|
2469
2623
|
// region ### TELEGRAM FUNCTIONS ###
|
2470
|
-
|
2471
|
-
|
2472
|
-
|
2473
|
-
|
2474
|
-
|
2475
|
-
|
2476
|
-
|
2624
|
+
async telegramMessage(text, chat_id, bot_key, extra_opts={}){
|
2625
|
+
const is_repeated_call = 'is_repeated_call' in extra_opts;
|
2626
|
+
const use_cache = 'cache' in extra_opts;
|
2627
|
+
if (! ('parse_mode' in extra_opts)){
|
2628
|
+
extra_opts['parse_mode'] = 'html';
|
2629
|
+
}
|
2630
|
+
if (! ('disable_web_page_preview' in extra_opts)){
|
2631
|
+
extra_opts['disable_web_page_preview'] = true;
|
2632
|
+
}
|
2633
|
+
// whether it's without `-100` prefix
|
2634
|
+
chat_id = chat_id.toString();
|
2635
|
+
if (!this.startsWith(chat_id, '-100')) chat_id = '-100' + chat_id;
|
2636
|
+
text = this.br2nl(text);
|
2637
|
+
text = this.stripTags(text,'<b><strong><i><em><u><ins><s><strike><del><a><code><pre>'); // allowed: https://core.telegram.org/bots/api#html-style
|
2638
|
+
text = text.substring(0, 4095); //max telegram message length 4096
|
2639
|
+
const requestOpts = Object.assign({'chat_id':chat_id, 'text':text}, extra_opts);
|
2640
|
+
delete requestOpts['cache'];
|
2641
|
+
delete requestOpts['is_repeated_call'];
|
2642
|
+
const responseText = await this.getRemoteData('https://api.telegram.org/bot'+ bot_key +'/sendMessage', requestOpts); // pastebin_com/u0J1Cph3 //'sendMessage?'.http_build_query(opts, '');
|
2477
2643
|
try {
|
2478
2644
|
const responseJson = JSON.parse(responseText);
|
2479
2645
|
if (responseJson.ok){
|
2480
|
-
return
|
2481
|
-
}
|
2482
|
-
|
2483
|
-
|
2484
|
-
|
2485
|
-
if(
|
2486
|
-
|
2487
|
-
|
2488
|
-
|
2489
|
-
|
2490
|
-
|
2491
|
-
return response;
|
2646
|
+
return responseJson;
|
2647
|
+
}
|
2648
|
+
// for some reason, if still unsupported format submitted, resubmit the plain format
|
2649
|
+
//i.e. {"ok":false,"error_code":400,"description":"Bad Request: can't parse entities: Unsupported start tag \"br/\" at byte offset 43"}
|
2650
|
+
else {
|
2651
|
+
if( responseJson.description.indexOf ('Bad Request: can\'t parse entities')> -1 ){
|
2652
|
+
if ( ! is_repeated_call ){
|
2653
|
+
const extraOpts2 = this.objectCopy(opts);
|
2654
|
+
text = "[SecondSend with stipped tags] \r\n" + this.stripTags(text) ;
|
2655
|
+
extraOpts2['is_repeated_call'] = true;
|
2656
|
+
return this.telegram_message(text, chat_id, bot_key, extraOpts2);
|
2492
2657
|
}
|
2493
|
-
} else {
|
2494
|
-
return response;
|
2495
2658
|
}
|
2659
|
+
return responseJson;
|
2496
2660
|
}
|
2497
2661
|
} catch (ex) {
|
2498
|
-
return {'ok': false, 'description': responseText };
|
2662
|
+
return {'ok': false, 'description': ex.message + ':::' + responseText };
|
2663
|
+
}
|
2664
|
+
},
|
2665
|
+
|
2666
|
+
telegram_interval_ms: 50, // telegram seems to accept around 30 times per second, so we'd better wait around that milliseconds
|
2667
|
+
telegram_last_sent_time: 0,
|
2668
|
+
|
2669
|
+
async telegramMessageCached(text, chat_id, bot_key, extra_opts={}){
|
2670
|
+
const curMS = this.milliseconds();
|
2671
|
+
const goneMS = curMS - this.telegram_last_sent_time;
|
2672
|
+
if ( goneMS < this.telegram_interval_ms ){
|
2673
|
+
await this.sleep (this.telegram_interval_ms - goneMS);
|
2499
2674
|
}
|
2675
|
+
this.telegram_last_sent_time = curMS;
|
2676
|
+
const cacheId = this.cache.file.idForContent( text +'_'+ chat_id +'_'+ bot_key +'_'+ JSON.stringify(extra_opts) );
|
2677
|
+
if (this.cache.file.addIdIfNotExists('function_telegram_message', cacheId) ){
|
2678
|
+
return this.telegramMessage(text, chat_id, bot_key, extra_opts);
|
2679
|
+
}
|
2680
|
+
else {
|
2681
|
+
return false;
|
2682
|
+
}
|
2683
|
+
//if(is_callable([$this,'notifications_db_entry']))
|
2684
|
+
// $this->notifications_db_entry($key, $array['chat_id'], $this->stringify($res), time(), $ok );
|
2685
|
+
//return $res;
|
2500
2686
|
},
|
2501
2687
|
|
2502
2688
|
openUrlInBrowser(url)
|
@@ -2657,26 +2843,27 @@ const puvox_library =
|
|
2657
2843
|
// } catch (ex) { reject (ex); }
|
2658
2844
|
// });
|
2659
2845
|
},
|
2660
|
-
|
2661
|
-
|
2662
2846
|
// if(setHashInAddress) { window.location.hash = id_or_Name; }
|
2663
2847
|
|
2664
2848
|
|
2665
2849
|
|
2666
2850
|
|
2667
2851
|
// ######## CACHE ITEMS (client-side JS) ########
|
2668
|
-
|
2669
|
-
setAppName (name){ this.
|
2670
|
-
|
2671
|
-
|
2672
|
-
|
2673
|
-
|
2674
|
-
|
2852
|
+
_privateAppName : null, //override with anything you want
|
2853
|
+
setAppName (name){ this._privateAppName = name; },
|
2854
|
+
getAppName(){
|
2855
|
+
if (!this._privateAppName || this._privateAppName === ''){
|
2856
|
+
throw new Error ('Before you start using caching functions, please at first define your appplication\'s name(identifier) at first with .setAppName("whatever_my_app_name"), so it will get its own cache-storage');
|
2857
|
+
}
|
2858
|
+
return this._privateAppName;
|
2859
|
+
},
|
2675
2860
|
|
2861
|
+
cache: {
|
2862
|
+
localStorage : {
|
2676
2863
|
storage: typeof window !== 'undefined' ? window.localStorage : null,
|
2677
2864
|
|
2678
2865
|
get(name, defaultValue, expireSeconds = 0){
|
2679
|
-
let appName =
|
2866
|
+
let appName = puvox_library.getAppName();
|
2680
2867
|
let val = this.storage.getItem(appName + '_' + name);
|
2681
2868
|
let expireVal = this.storage.getItem(appName + '_createtime_' + name);
|
2682
2869
|
if (val === null) {
|
@@ -2696,15 +2883,17 @@ const puvox_library =
|
|
2696
2883
|
},
|
2697
2884
|
set(name, value){
|
2698
2885
|
try{
|
2699
|
-
|
2700
|
-
this.storage.setItem(
|
2886
|
+
const appName = puvox_library.getAppName();
|
2887
|
+
this.storage.setItem(appName + '_' +name, value);
|
2888
|
+
this.storage.setItem(appName + '_createtime_' +name, (new Date()).getTime());
|
2701
2889
|
return true;
|
2702
2890
|
}
|
2703
2891
|
catch(ex){ alert("Cache storage quote exceeded. can't save value. err598"); return false; }
|
2704
2892
|
},
|
2705
|
-
remove(name
|
2706
|
-
|
2707
|
-
this.storage.removeItem(
|
2893
|
+
remove(name){
|
2894
|
+
const appName = puvox_library.getAppName();
|
2895
|
+
this.storage.removeItem(appName + '_' + name);
|
2896
|
+
this.storage.removeItem(appName + '_createtime_' + name);
|
2708
2897
|
},
|
2709
2898
|
getItem(name, subItemName, defaultValue){
|
2710
2899
|
let val = this.get(name, '{}');
|
@@ -2725,30 +2914,27 @@ const puvox_library =
|
|
2725
2914
|
return this.set(name, JSON.stringify(parsed) );
|
2726
2915
|
}
|
2727
2916
|
},
|
2728
|
-
file
|
2917
|
+
file: {
|
2729
2918
|
// ########## CACHE DIRS (server-side JS) ##########
|
2730
|
-
parent(){ return puvox_library; },
|
2731
|
-
AppName(){ return puvox_library.AppName; },
|
2732
|
-
|
2733
2919
|
customCacheDir:null,
|
2734
|
-
|
2920
|
+
dir(){
|
2735
2921
|
if (!this.customCacheDir){
|
2736
|
-
this.customCacheDir =
|
2922
|
+
this.customCacheDir = puvox_library.file.getTempDir() + '/';
|
2737
2923
|
}
|
2738
|
-
let finaldir = this.customCacheDir + '
|
2924
|
+
let finaldir = this.customCacheDir + '_cache_' + puvox_library.getAppName() + '/';
|
2739
2925
|
return finaldir;
|
2740
2926
|
},
|
2741
2927
|
filePath(uniqFileName){
|
2742
|
-
const parent =
|
2928
|
+
const parent = puvox_library;
|
2743
2929
|
uniqFileName = parent.isString(uniqFileName) || parent.isNumeric(uniqFileName) ? uniqFileName : JSON.stringify(uniqFileName);
|
2744
2930
|
uniqFileName = parent.sanitize_key_dashed(parent.getCharsFromStart(uniqFileName, 15)) + "_"+ parent.md5(uniqFileName);
|
2745
|
-
filePath= this.
|
2931
|
+
filePath= this.dir() + uniqFileName + "_tmp"; //"/".
|
2746
2932
|
return filePath;
|
2747
2933
|
},
|
2748
2934
|
//
|
2749
2935
|
get(uniqFileName, defaultContent ='', expire_seconds=8640000, decode = true)
|
2750
2936
|
{
|
2751
|
-
const parent =
|
2937
|
+
const parent = puvox_library;
|
2752
2938
|
let filePath = this.filePath(uniqFileName);
|
2753
2939
|
if ( filePath.length < 3) return "too tiny filename";
|
2754
2940
|
|
@@ -2783,7 +2969,7 @@ const puvox_library =
|
|
2783
2969
|
},
|
2784
2970
|
set(uniqFileName, content)
|
2785
2971
|
{
|
2786
|
-
const parent =
|
2972
|
+
const parent = puvox_library;
|
2787
2973
|
let filePath= this.filePath(uniqFileName);
|
2788
2974
|
let contentFinal = parent.isString(content) ? content : ((parent.isArray(content) || parent.isObject(content)) ? JSON.stringify(content) : content);
|
2789
2975
|
return parent.file.write(filePath, contentFinal);
|
@@ -2809,6 +2995,37 @@ const puvox_library =
|
|
2809
2995
|
// console.log("writeFileAppendJson", e);
|
2810
2996
|
// }
|
2811
2997
|
// },
|
2998
|
+
containerDefaultPrefix: "_cached_ids_",
|
2999
|
+
tempIds:{},
|
3000
|
+
idForContent(slugOrContent){
|
3001
|
+
return puvox_library.md5(puvox_library.isSimpleVariableType(slugOrContent) ? slugOrContent : JSON.stringify(slugOrContent));
|
3002
|
+
},
|
3003
|
+
existsId(containerSlug, id){
|
3004
|
+
return (id in this.getIds(containerSlug));
|
3005
|
+
},
|
3006
|
+
getIds(containerSlug) {
|
3007
|
+
if (! (containerSlug in this.tempIds)) {
|
3008
|
+
const content = puvox_library.file.read(this.dir() + this.containerDefaultPrefix + containerSlug, '{}');
|
3009
|
+
this.tempIds[containerSlug] = JSON.parse(content);
|
3010
|
+
}
|
3011
|
+
return this.tempIds[containerSlug];
|
3012
|
+
},
|
3013
|
+
setIds(containerSlug, idsDict) {
|
3014
|
+
this.tempIds[containerSlug] = idsDict;
|
3015
|
+
return puvox_library.file.write(this.dir() + this.containerDefaultPrefix + containerSlug, JSON.stringify(this.tempIds[containerSlug]));
|
3016
|
+
},
|
3017
|
+
addId(containerSlug, id){
|
3018
|
+
const ids = this.getIds(containerSlug);
|
3019
|
+
ids[id] = 1;
|
3020
|
+
this.setIds(containerSlug, ids);
|
3021
|
+
},
|
3022
|
+
addIdIfNotExists(containerSlug, id){
|
3023
|
+
if (! this.existsId(containerSlug, id)){
|
3024
|
+
this.addId(containerSlug, id);
|
3025
|
+
return true;
|
3026
|
+
}
|
3027
|
+
return false;
|
3028
|
+
},
|
2812
3029
|
}
|
2813
3030
|
},
|
2814
3031
|
|
@@ -2823,7 +3040,7 @@ const puvox_library =
|
|
2823
3040
|
return this._required_instances[name];
|
2824
3041
|
}
|
2825
3042
|
},
|
2826
|
-
file
|
3043
|
+
file: {
|
2827
3044
|
parent() {return puvox_library;},
|
2828
3045
|
fs() {return puvox_library.modules('fs');},
|
2829
3046
|
os() {return puvox_library.modules('os');},
|
package/package.json
CHANGED
package/test.js
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
const h = require('./library_standard.js');
|
2
|
+
function c(...args){console.log(...args);} function cc(o){console.dir(o, {'maxArrayLength': null});} function x(...args){c(...args);process.exit();} function xx(o){cc(o);process.exit();}
|
3
|
+
|
4
|
+
h.setAppName("myApp");
|
5
|
+
async function x(){
|
6
|
+
c(await h.telegramMessageCached('Hello World', 1668904096, '1651207488:AAF0KDLW6tmDUElN7RxVbp5RwQK5u77znhU'));
|
7
|
+
}
|
8
|
+
x();
|