forked from mkillewald/Guru
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGuru.rx
933 lines (802 loc) · 35.1 KB
/
Guru.rx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
/**************************************************************************\
$VER: C-Net Guru, v0.1 (Aug-25-2019) by k1ds3ns4t10n of -X-caliber BBS
\**************************************************************************/
options results;signal on SYNTAX;signal on ERROR;signal on IOERR
a=sourceline(2);parse var a . " " title ", " ver " (" vdate ") by " author " " .
tr=transmit;se=sendstring;gc=getchar;gu=getuser;gs=getscratch;mg=maygetchar
bbsidentify bbs;cv=left(word(result,3),4);cnet4=(datatype(cv,"n")=1&cv>"4.25")
bbsidentify name;g.bbsName=strip(result, 'B');esc="1b5b"x;cty="19"x;ctq="11"x
rs="rexxsupport.library";if ~show("l",rs) then if ~addlib(rs,0,-30) then exit
parse source . . fp .; df=left(fp,max(lastpos('/',fp),lastpos(':',fp)))
parse arg mode
if mode~="JL" then changewhere title
/**************************************************************************/
/* */
/* C-Net Guru -X-caliber BBS */
/* a future PHENOM PRODUCTIONS release bbs.aholix.net:6800 */
/* by k1ds3ns4t10n (Mike Killewald) */
/* */
/* Changelog: */
/* v0.1 Aug-25-2019 first version */
/* */
/* INSTALATION INSTRUCTIONS: */
/* 1) Download http_get from Aminet and install in C: */
/* https://aminet.net/package/comm/tcp/http_get */
/* */
/* 2) Obtain a Wolphram|Alpha Short Answer API AppId */
/* http://products.wolframalpha.com/short-answers-api/documentation/ */
/* */
/* 3) Copy and paste your AppId into g.appID where indicated below */
/* this comment block */
/* */
/* 4) Install Guru.rx at Pfiles:Guru/Guru.rx */
/* */
/* 5) Add the two lines below to your CNET:bbsmenu file in the */
/* Available Everywhere section: */
/* */
/* CGURU `0-31| Q#0 pfiles:guru/guru.rx} */
/* GURU~CGURU; */
/* */
/* ^ NOTE: "Q" here is a ctrl-Q */
/* */
/* 6) Add the following line to SYSTEXT:noises */
/* */
/* guru 0 Q#0 pfiles:guru/guru.rx JL}<'0 seek's wisdom from the Guru> */
/* */
/* ^ NOTE: "Q" here is a ctrl-Q */
/* */
/* 7) Do a reload text on your bbs, and you should be all set! */
/* either */
/* type RT at any bbs prompt */
/* or */
/* hit right-Amiga-T from the CNet/5 Control Panel */
/* */
/**************************************************************************/
/* SysOp Configurable Options *********************************************/
g.appId="yourappidhere" /* <--enter your Wolfram|Alpha API AppId here */
/* these paths will be auto created as needed, both paths must
end with a trailing slash */
g.tempPath = "RAM:GURU/" /* temp dir for response files */
g.tempJLPath = "RAM:GURU/JL/" /* temp dir for JL scripts */
/* these swtiches control Guru's output (0=off, 1=on) */
g.cnfPreview = 0 /* In Conference, show preview with Yes/No prompt before
sending results to the room */
g.cnfAutoCan = 1 /* In Conference auto cancel any invalid responses or
timed out messages */
g.autoRetry = 1 /* Auto-retry API request if it times out or returns
a blank result. User may cancel the request by pressing
the ESC key */
g.guruBox = 0 /* Display flashing yellow box around Guru results */
g.debug = 0 /* show errors if using guru as SysOp (account #1 only),
this is for troubleshooting only and should not be left
on during normal operations. */
/* ok to change these as needed for your system */
g.timeout = 30 /* API http request timeout in seconds */
g.guruUser = "Guru" /* the handle of the Guru account that will give results
in Conference. To disable this, set g.guruUser="" */
g.confName = "Conference" /* the name of your Conference (as seen on WHo) */
/* ok to change these messages, feel free to add ANSI or MCI codes */
s.computing = "Computing"
s.replyHazy = "Reply hazy, try again later."
s.resTimedOut= "Response timed out, please try again later."
s.cancelled = "Computational analysis interrupted by my user,.."
s.shareToRoom= "Share with the room?"
s.escToCancel= "(ESC to cancel)"
/* Color format: esc"<intensity>;<background>;<foreground>"
intensity 0=off, 1=on
background colors foreground colors
black=40 black=30
red=41 red=31
green=42 green=32
yellow=43 yellow=33
blue=44 blue=34
magenta=45 magenta=35
cyan=46 cyan=36
white=47 white=37
*/
/* ok to change the color data inside the quotes as needed */
c.cp1 = esc"1;37m" /* command prompt color 1 */
c.cp2 = esc"0;37m" /* command prompt color 2 */
c.cphl = esc"1;32m" /* command prompt highlight color */
c.usr = esc"0;36m" /* user text entry color */
c.res = esc"1;33m" /* results display color */
c.foot = esc"1;30m" /* footer color */
c.err = esc"1;31m" /* Guru Meditation color */
c.jlnu = esc"0;35m" /* the color of the JL noise seen by the user */
/* End of SysOp Configurable Options **************************************/
/**************************************************************************/
c.blink=esc"5m"
c.reset=esc"0m"
if ~exists(g.tempPath) then address command 'makedir 'strip(g.tempPath,"T","/")
if ~exists(g.tempJLPath) then address command 'makedir 'strip(g.tempJLPath,"T","/")
/* these are expected responses from the Wolfram|Alpha API, do not change */
s.didNotCompute = "Wolfram|Alpha did not understand your input"
s.noShortAnswer = "No short answer available"
s.invalidAppId = "Error 1: Invalid appid"
/* as needed per Wolfram|Alpha terms of use */
s.footerString = "powered by Wolfram|Alpha"
/* gather some user info */
gu 40; g.uid = space(result ,0) /* account id */
gu 23; g.userPort=result /* userport */
gu 27; g.maxCol=result-1 /* term width */
if g.appId=="" | g.appId=="yourappidhere" then signal badAppId
else if ~exists("c:http_get") then signal badHttp
g.debug=g.debug&g.uid==1
do forever
cmdPrompt = c.cp1"("c.cphl"?"c.cp1","c.cphl"T"c.cp1","c.cphl"Q"c.cp1") Guru> "c.usr
prompt 65 NORMAL cmdPrompt
query = strip(result,"B")
if query=="###PANIC" | query=="" | upper(query)=="Q" | upper(query)=="QU" |,
upper(query)=="QUI" | upper(query)=="QUIT" then signal EXIT
else if upper(query)=="GURU" & mode~="JL" then signal gurus
else if upper(query)=="<YOUR QUERY>" | upper(query)=="YOUR QUERY" then signal id10t
else if query=="?" | upper(query)=="H" then call guruHelp
else if upper(query)=="T" then call termsOfUse
else leave
call check
end
/* replace back tick ` with tick ' */
query = replace(query, "`", "'")
/* replace " with "" */
query = replace(query, '"', '""')
/* Delete the last results file in case it wasn't deleted last time */
filename= "response"g.uid
call deleteFile(filename)
/* URL encode the query input string */
tquery = query
call getUrlEncodeTable
do i=0 to urlEncode.max
tquery= replace(tquery, urlEncode.in.i, urlEncode.out.i)
end
tquery= space(tquery, 1, "+")
/* build uri */
uri="http://api.wolframalpha.com/v1/result?appid="g.appId"&timeout="g.timeout"&i="tquery
/* fetch result from API */
guruResponse = fetchWebRequest(uri, filename)
/* Delete the results file */
call deleteFile(filename)
/* replace characters C-Net cannot display properly */
call getCharSwapTables
do i=0 to charSwapMax
guruResponse= replace(guruResponse, charSwapIn.i, charSwapOut.i)
end
guru:
validResponse = guruResponse~=s.resTimedOut & guruResponse~=s.replyHazy &,
guruResponse~=s.didNotCompute & guruResponse~=s.noShortAnswer &,
guruResponse~=s.cancelled
if guruResponse==s.invalidAppId then signal badAppId
else if guruResponse==s.didNotCompute & g.guruUser~="" then guruResponse = replace(guruResponse, "Wolfram|Alpha", g.guruUser)
else if guruResponse=="" then guruResponse=s.replyHazy
/* display result directly to user if in normal operation,
or if in JL mode with cnfPreview enabled */
if mode~="JL" | (mode=="JL" & g.cnfPreview) then do
if mode~="JL" then tr
call guruMessage(guruResponse, g.guruBox)
if validResponse then call displayFooter(s.footerString, "right")
end
if mode=="JL" then do
if g.cnfAutoCan & ~validResponse then do
/* cnfAutoCan is enabled and response is invalid. if cnfPreview is off
then show the invalid response direclty to user, then exit */
if ~g.cnfPreview then call guruMessage(guruResponse, g.guruBox)
signal EXIT
end
else if g.cnfPreview then do
if validResponse then do
/* cnfPreview is enabled and response is valid, so show yes/no prompt */
/* get length of footerString + jlPrompt + Yes */
combinedLength = length(s.shareToRoom) + length(" (yes/No): ") + length(s.footerString) + 3
if g.maxCol > combinedLength then se esc"1A"
end
jlPrompt = c.cp1||s.shareToRoom" ("c.cphl"y"c.cp2"es"c.cp1"/"c.cphl"N"c.cp2"o"c.cp1"): "c.usr
prompt 1 NOYES jlPrompt
answer=result
if answer=="No" then signal EXIT
end
/* if we made it this far, send result out to Conference */
call spitToConference(query, guruResponse, g.maxCol-3) /* -3 for safety */
end
EXIT:
if mode=="JL" then se c.jlnu /* reset JL noise color before exiting */
exit
/* Procedures *************************************************************/
deleteFile: procedure expose tr c. g.
parse arg filename
filePath= g.tempPath||filename
delcommand = "run >nil: delete "filePath" force"
if exists(filePath) then do
do delLoop = 1 to 5
address command delcommand
if ~exists(filePath) then leave delLoop
call delay(10)
end
if g.debug & exists(filePath) then tr c.err"GURU: file "filePath" was not deleted"
end
return
/* fetches web request
@param uri the url to retrieve
@param fileName the filename where to store results
returns the result as a string
*/
fetchWebRequest: procedure expose se tr mg esc ver c. g. s.
parse arg uri, filename
filePath= g.tempPath||filename
userAgent= "http_get/1.0 (AmigaOS 3.1; Amiga; 68040; ks:40.68; wb:40.42) CNet/5 Guru/"strip(ver,'L','v')" bbs.aholix.net:6800"
/* run through outer loop at least once, repeat the loop if g.autoRetry is
enabled and body=="" */
do until ~g.autoRetry | body ~= ""
/* init body */
body=""
/* make API request */
httpcmd='run http_get -u "'userAgent'" 'uri' >'filePath
address command httpcmd
call time('r')
/* show status message */
se c.res||s.computing
dotCount=0
/* inner loop checks if the results file is ready and exits if the
file is ready or the timeout period has been reached */
bufferflush
do until time('e') > g.timeout + 1
mg
if result=="NOCHAR" then nop
else if C2D(result)==27 then do
/* ESC key will exit */
body = s.cancelled
leave /* cause loop to exit */
end
else call check
call delay(25) /* 1/2 second */
/* check if results file is ready yet */
if exists(filePath) then do
if open(GRF, filePath, R) then do
body = readln(GRF)
if body == "" then body = s.replyHazy
call close(GRF)
leave /* cause loop to exit */
end
else if g.debug then tr c.err"GURU: could not open "filePath
end
else if g.debug then tr c.err"GURU: "filePath" does not exist"
/* update status message */
if dotCount==0 then se " "s.escToCancel
else se "."
dotCount = dotCount + 1
end
bufferflush
/* clear status message */
CR = "0d"x
computeLen = length(s.computing) + length(s.escToCancel) + dotCount + 1
se CR||copies(' ', computeLen)||CR||c.jlnu
end
/* check if request timed out */
if body=="" then body = s.reqTimedOut
return body
/* word wraps an input string at a given width and will not split any words
@param text the input string to word wrap
@param width the width to wrap at
results will be placed into an array called resultsArr structured as:
resultArr.0 = line count
resultArr.1 = line 1 string
resultArr.2 = line 2 string
.
.
.
resultArr.n = line n string
*/
wordWrap: procedure expose resultArr.
parse arg text, width
/* clear any previous data in the results array */
drop resultArr.
/* line count is held at position 0, init it to line 1 */
resultArr.0 = 1
if length(text) <= width then do
resultArr.1 = text
return
end
line = resultArr.0
resultArr.1 = ""
do while text ~= ""
parse var text word text
/* check if current line + next word < width */
if length(resultArr.line) + length(word) + 1 <= width then do
/* add word to current line */
if resultArr.line=="" then resultArr.line = word
else resultArr.line = resultArr.line" "word
end
else do
/* start new line with with next word */
line = line + 1
resultArr.line = word
end
end
/* store final line count at position 0 of the array */
resultArr.0 = line
return
/* word wraps an input string at a given width and will split words that
are longer than width. This function is based on code provided by
aNACHRONiST, thanks again my man!!
@param text the input string to word wrap
@param width the width to wrap at
@param mode a mode flag (set to JL for JL/Conference)
results will be placed into an array called resultsArr structured as:
resultArr.0 = line count
resultArr.1 = line 1 string
resultArr.2 = line 2 string
.
.
.
resultArr.n = line n string
*/
wordWrapByChar: procedure expose resultArr.
parse arg text, width, responseMode
/* clear previous data in results array */
drop resultArr.
/* init results array */
line = 1
resultArr.0 = line
resultArr.1 = text
textLen = length(text)
if textLen <= width then return
do while textLen > width
/* get position of last space within width chars */
/* If responseMode is JLU or JLG, we will be sending the guru response
in segments of 3 lines each to meet the requirements of the user
input buffer inside Conference.
If responseMode is JLU, the first line of each segment will show
"Guru #/#: " which is 10-12 chars, so we must compensate for that
here as we word wrap the response. */
if responseMode=="JLU" & (line == 1 | (line-1)//3==0) then lineWidth = width - 12
else lineWidth = width
spacePos = lastpos(" ", text, lineWidth)
if spacePos~=0 then do
/* space found, cut text at space position -1 */
cutPos = spacePos-1
resumePos = textLen-spacePos
end
else do
/* space not found, cut text at width */
cutPos = lineWidth
resumePos = textLen-lineWidth
end
resultArr.line = left(text, cutPos)
text = right(text, resumePos)
textLen = length(text)
/* place remaining text into next line */
line = line + 1
resultArr.line = text
/* update line count */
resultArr.0 = line
end
return
/* spits query and response to Conference in safe bite size pieces.
MAD props to aNACHRONiST for the Conference integration!!
@param query the users query string
@param response the response fronm Wolfram|Alpha simple API
@param width the number of chars to break response at
*/
spitToConference: procedure expose tr gu gs cnet4 c. g. resultArr.
parse arg query, response, width
/* init response port to the user port */
responsePort = g.userPort
guruPort = -1
/* find account id for guruUser */
if g.guruUser~="" then do
findaccount g.guruUser; guruUid=result
/* if guruUser account found, check if account is logged in */
if guruUid~=0 then do
/* read in some guruUser account info */
loadscratch guruUid /* lock guru account */
gs 27; guruWidth=result-4 /* -4 for safety */
savescratch 0-guruUid /* remove lock */
/* get highest loaded port */
guHp=word("2225094 2227884", cnet4+1)
gu guHp; hiPort=result
/* check all ports to see if guruUser is logged in */
do i=0 to hiPort
getportid i; portUid=result
if portUid==guruUid then do
/* guruUser is logged in and we found its port, now lets
check if guruUser is in Conference */
guruPort = i
getwhere i; guruWhere = result
if guruWhere==g.confName then do
/* guruUser found, logged in and in Conference */
responsePort = i
/* TODO: add check if user and guru are in same room, if not move Guru to users room */
end
leave i
end
end
end
end
/* replace occurances of " with "" to avoid conflict in generated scripts */
response = replace(response, '"', '""')
if responsePort==g.userPort & g.userPort~=guruPort then responseMode="JLU" /* response to User port */
else do
responseMode="JLG" /* response to Guru port */ /* not really used */
width = guruWidth
end
call wordWrapByChar(response, width, responseMode)
lineCount=resultArr.0
/* get number of segments, each segment holds 3 lines of word wrapped text */
if lineCount > 3 then do
segment = lineCount % 3
if lineCount // 3 ~= 0 then segment = segment + 1
end
else segment = 1
/* generate lead JL script */
if open(JLF,g.tempJLPath||g.userPort'JLF.0',W) then do
call writeln(JLF,'/*Guru JL Lead Script*/')
call writeln(JLF,'address CNETREXX'g.userPort)
call writeln(JLF,'addkeys "Hey Guru, 'query'`"')
call writeln(JLF,'spawn "'g.tempJLPath||g.userPort'JLF.1"')
call writeln(JLF,'exit')
call close(JLF)
end
else do
if g.debug then tr c.err"GURU: Failed to open lead JL script for writing"
return
end
/* generate JL segment scripts */
do segmentLoop=1 to segment
if open(JLF,g.tempJLPath||g.userPort'JLF.'segmentLoop,W) then do
call writeln(JLF,'/*Guru JL Segment Script*/')
call writeln(JLF,'address CNETREXX'responsePort)
/* grab 3 lines of resultArr (1 segment) and write to script */
data=""
do lineLoop=(segmentLoop*3)-2 to segmentLoop*3
if lineLoop > lineCount then leave lineLoop
data=data" "resultArr.lineLoop
end
if segment==1 & responseMode=="JLU" then call writeln(JLF,'addkeys "Guru: 'strip(data,"B")'`"')
else if segment>1 & responseMode=="JLU" then call writeln(JLF,'addkeys "Guru 'segmentLoop'/'segment': 'strip(data,"B")'`"')
else call writeln(JLF,'addkeys "'strip(data,"B")'`"')
if segment > segmentLoop then call writeln(JLF,'spawn "'g.tempJLPath||g.userPort'JLF.'segmentLoop+1'"')
else call writeln(JLF,'address command "run >nil: delete 'g.tempJLPath||g.userPort'JLF.#?"') /* this message will self-destruct! */
call writeln(JLF,'exit')
call close(JLF)
end
else do
if g.debug then tr c.err"GURU: failed to open segment "segmentLoop" script for writing"
return
end
end
/* run the lead JL script and immediately exit. The lead script will spawn
the next segment, which spawns the next segment and so on */
address command 'run >nil: RX 'g.tempJLPath||g.userPort'JLF.0'
return
/* replace - replace srch text with repl text in text
->replace("astrologer","log","nom")
astronomer
Source: Using Arexx on the Amiga, page 313
*/
replace: procedure
parse arg text, srch, repl
if index(text, srch)==0 then return text
slen = length(srch)
tlen = length(text)
do until tlen = 0
tlen = lastpos(srch, text, tlen)
if tlen ~= 0 then do
text = insert(repl, delstr(text,tlen,slen), tlen - 1)
tlen = tlen - 1
end
end
return text
guruHelp:
if g.maxCol<69 then cutPos=39
else cutPos=g.maxCol
tr c.res||title||c.usr" "ver" by "author||esc"1m (bbs.aholix.net:6800)"
tr
tr c.cp1"Usage:"
tr c.usr"At any system prompt, type: "c.cp1"guru "c.cp2"<your query>"
tr c.usr"or in Conference, type "c.cp1"=guru"c.cp2"[ENTER]"c.usr" and enter your query at the "c.cp1"Guru>"c.usr" prompt"
tr
tr c.cp1||trim(left("Ask questions: Look up common acronyms:", cutPos))
tr c.usr||trim(left(" What time is it in Detroit, Michigan? DTW LAX DFW LAG", cutPos))
tr trim(left(" How big is the universe? ROFL LMAO LOL", cutPos))
tr c.cp1||trim(left("Perform unit conversions: Look up notable people:", cutPos))
tr c.usr||trim(left(" 500 miles in kilometers Jay Miner", cutPos))
tr trim(left(" pints in a quart Dennis Ritchie", cutPos))
tr trim(left(" ounces in a cup Guido Van Rossum", cutPos))
tr c.cp1||trim(left("Perform calculations: Get word definitions:", cutPos))
tr c.usr||trim(left(" square root of 42 subcutaneous", cutPos))
tr trim(left(" 3.7 million divided by 634 Thesmophoriazusae", cutPos))
tr
tr c.cphl"?"c.cp2"=help"c.cp1", "c.cphl"T"c.cp2"erms of Use"c.cp1", "c.cphl"Q"c.cp2"uit"
tr
return
termsOfUse:
tr
tr c.cp1"Terms of Use"
tr
tou=esc||c.res"C-Net Guru"c.usr" is powered by "esc"1;31mWolfram"
tou=tou||esc"0;31m|"esc"1;31mAlpha "c.usr"which is also accessible "
tou=tou||"by visiting http://www.wolframalpha.com. Results and information "
tou=tou||"from this site are not a certified or definitive source of "
tou=tou||"information that can be relied on for legal, financial, medical, "
tou=tou||"life-safety or any other critical purposes. Please read the full "
tou=tou||"terms of use at "c.cp2"http://products.wolframalpha.com/api/termsofuse.html"
tr tou
tr
return
gurus:
cls
c.res = esc"0;31m"
gr = "A very short list of notable Gurus are: Jack Tramiel, Nolan "
gr = gr"Bushnell, Jay Miner, Robert J. Mical, David Needle, Dave Haynie, "
gr = gr"Dennis Ritchie, Bjarne Stroustrup, James Gosling, Guido Van "
gr = gr"Rossom, Brendan Eich, John Backus, Niklaus Wirth, Alan Kay, "
gr = gr"Mike Cowlishaw, Anders Hejlsberg, Bradford Cox, Tom Love, Charles "
gr = gr"Babbage, Alan Turing, Steve Wozniak, Robert Russell, Robert "
gr = gr"Yannes, Al Charpentier, ZeroPaige, Dotoran, PHENOM, Araknet, "
gr = gr"Smooth, aNACHRONiST, iMPURE, Fuel, ACiD, Blocktronics, Fairlight, "
gr = gr"Censor Design, Noice, Void, Booze Design, The Black Lotus, Prosonix, "
gr = gr"Sanity, Kefrens, Scoopex, Tristar, Red Sector Incorporated, "
gr = gr"Crionics, Offence, The Kommodore Krew, Cinemaware, Psygnosis, The "
gr = gr"Bitmap Brothers, Sensible Software, Bullfrog, DMA Design, Team17, "
gr = gr"Delphine, Newtek, and many, many more..."
guruResponse = gr
s.footerString="-k1ds3ns4t10n, 2019"
g.guruBox = 1
signal guru
return
guruMessage: procedure expose tr c. g. resultArr.
parse arg response, drawBox
if drawBox then do
tr c.res||c.blink"Û"copies('ß', g.maxCol-2)"Û"
call wordWrap(response, g.maxCol-4)
do i=1 to resultArr.0
tr c.blink"Û "c.reset||c.res|| center(resultArr.i, g.maxCol-4)||c.blink" Û"
end
tr c.res||c.blink"Û"copies('Ü', g.maxCol-2)"Û"c.reset
end
else do
call wordWrap(response, g.maxCol)
do i=1 to resultArr.0
tr c.res||resultArr.i
end
end
return
guruError: procedure expose tr c. g.
parse arg errMsg1, errMsg2
cls
tr c.err
tr c.blink"Û"copies('ß', g.maxCol-2)"Û"
call wordWrap(errMsg1, g.maxCol-4)
do i=1 to resultArr.0
tr c.blink"Û "c.reset||c.err|| center(resultArr.i, g.maxCol-4)||c.blink" Û"
end
call wordWrap(errMsg2, g.maxCol-4)
do i=1 to resultArr.0
tr c.blink"Û "c.reset||c.err|| center(resultArr.i, g.maxCol-4)||c.blink" Û"
end
tr c.blink"Û"copies('Ü', g.maxCol-2)"Û"c.reset
return
displayFooter: procedure expose tr c. g.
parse arg string, mode
select
when mode=="right" then tr c.foot||right(string, g.maxCol, ' ')
when mode=="center" then tr c.foot||center(string, g.maxCol)
otherwise tr c.foot||string
end
return
id10t:
c.err = esc"0;31m"
if mode=="JL" then errMsg1 = "Try: =guru[enter] what is the definition of literally?"
else errMsg1 = "Try: guru what is the definition of literally?"
errMSg2 = "Guru Meditation #00000000:0001D10T"
call guruError(errMsg1, errMsg2)
exit
badAppId:
c.err = esc"0;31m"
errMsg1 = "AppId is invalid! Please read the instructions inside Guru.rx"
errMSg2 = "Guru Meditation #00000000:84D4PP1D"
call guruError(errMsg1, errMsg2)
exit
badHttp:
c.err = esc"0;31m"
errMsg1 = "Could not find http_get! Please re-read the install instructions."
errMsg2 = "Guru Meditation #00000000:084DH77F"
call guruError(errMsg1, errMsg2)
exit
/* https://tools.ietf.org/html/rfc3986 */
/* RFC3986 defines the following classes of characters: */
/* Unreserved: a-z, A-Z, 0-9 and - _ . ~ */
/* Rreserved: gen-delims / sub-delims */
/* gen-delims: : / ? # [ ] @ */
/* sub-delims: ! $ & ' ( ) * + , ; = */
/* */
/* https://tools.ietf.org/html/rfc2396 */
/* RFC2396 (obsolete) defines the following groupings of characters */
/* that must be escaped to be included within a URI: */
/* */
/* Control: <US-ASCII coded characters 00-1F and 7F hexadecimal> */
/* Space: <US-ASCII coded character 20 hexadecimal> */
/* Delims: < > # % " */
/* Unwise: { } | \ ^ [ ] ` */
/* */
urlEncode: procedure
parse arg inputString
encodedString = inputString
call getUrlEncodeTable
do i=0 to urlEncode.max
encodedString = replace(encodedString, urlEncode.in.i, urlEncode.out.i)
end
encodedString=space(encodedString, 1, "+")
return encodedString
getUrlEncodeTable:
/* Delim characters */
urlEncode.in.0="%"; urlEncode.out.0="%25"
urlEncode.in.1='"'; urlEncode.out.1="%22"
urlEncode.in.3="<"; urlEncode.out.3="%3C"
urlEncode.in.4=">"; urlEncode.out.4="%3E"
/* Reserved characters */
urlEncode.in.5="!"; urlEncode.out.5="%21"
urlEncode.in.6="#"; urlEncode.out.6="%23"
urlEncode.in.7="$"; urlEncode.out.7="%24"
urlEncode.in.8="&"; urlEncode.out.8="%26"
urlEncode.in.9="'"; urlEncode.out.9="%27"
urlEncode.in.10="("; urlEncode.out.10="%28"
urlEncode.in.11=")"; urlEncode.out.11="%29"
urlEncode.in.12="*"; urlEncode.out.12="%2A"
urlEncode.in.13="+"; urlEncode.out.13="%2B"
urlEncode.in.14=","; urlEncode.out.14="%2C"
urlEncode.in.15="/"; urlEncode.out.15="%2F"
urlEncode.in.16=":"; urlEncode.out.16="%3A"
urlEncode.in.17=";"; urlEncode.out.17="%3B"
urlEncode.in.18="="; urlEncode.out.18="%3D"
urlEncode.in.19="?"; urlEncode.out.19="%3F"
urlEncode.in.20="@"; urlEncode.out.20="%40"
urlEncode.in.21="["; urlEncode.out.21="%5B"
urlEncode.in.22="]"; urlEncode.out.22="%5D"
/* Unwise characters */
urlEncode.in.23="\"; urlEncode.out.23="%5C"
urlEncode.in.24="^"; urlEncode.out.24="%5E"
urlEncode.in.25="`"; urlEncode.out.25="%60"
urlEncode.in.26="{"; urlEncode.out.26="%7B"
urlEncode.in.27="|"; urlEncode.out.27="%7C"
urlEncode.in.28="}"; urlEncode.out.28="%7D"
/* ASCII control characters */
urlEncode.in.29="00"x; urlEncode.out.29="%00" /* NUL null character */
urlEncode.in.30="01"x; urlEncode.out.30="%01" /* SOH start of header */
urlEncode.in.31="02"x; urlEncode.out.31="%02" /* STX start of text */
urlEncode.in.32="03"x; urlEncode.out.32="%03" /* ETX end of text */
urlEncode.in.33="04"x; urlEncode.out.33="%04" /* EOT end of transmission */
urlEncode.in.34="05"x; urlEncode.out.34="%05" /* ENQ enquiry */
urlEncode.in.35="06"x; urlEncode.out.35="%06" /* ACK acknowledge */
urlEncode.in.36="07"x; urlEncode.out.36="%07" /* BEL bell (ring) */
urlEncode.in.37="08"x; urlEncode.out.37="%08" /* BS backspace */
urlEncode.in.38="09"x; urlEncode.out.38="%09" /* HT horizontal tab */
urlEncode.in.39="0a"x; urlEncode.out.39="%0A" /* LF line feed */
urlEncode.in.40="0b"x; urlEncode.out.40="%0B" /* VT vertical tab */
urlEncode.in.41="0c"x; urlEncode.out.41="%0C" /* FF form feed */
urlEncode.in.42="0d"x; urlEncode.out.42="%0D" /* CR carriage return */
urlEncode.in.43="0e"x; urlEncode.out.43="%0E" /* SO shift out */
urlEncode.in.44="0f"x; urlEncode.out.44="%0F" /* SI shift in */
urlEncode.in.45="10"x; urlEncode.out.45="%10" /* DLE data link escape */
urlEncode.in.46="11"x; urlEncode.out.46="%11" /* DC1 device control 1 */
urlEncode.in.47="12"x; urlEncode.out.47="%12" /* DC2 device control 2 */
urlEncode.in.48="13"x; urlEncode.out.48="%13" /* DC3 device control 3 */
urlEncode.in.49="14"x; urlEncode.out.49="%14" /* DC4 device control 4 */
urlEncode.in.50="15"x; urlEncode.out.50="%15" /* NAK negative acknowledge */
urlEncode.in.51="16"x; urlEncode.out.51="%16" /* SYN synchronize */
urlEncode.in.52="17"x; urlEncode.out.52="%17" /* ETB end transmission block */
urlEncode.in.53="18"x; urlEncode.out.53="%18" /* CAN cancel */
urlEncode.in.54="19"x; urlEncode.out.54="%19" /* EM end of medium */
urlEncode.in.55="1a"x; urlEncode.out.55="%1A" /* SUB substitute */
urlEncode.in.56="1b"x; urlEncode.out.56="%1B" /* ESC escape */
urlEncode.in.57="1c"x; urlEncode.out.57="%1C" /* FS file separator */
urlEncode.in.58="1d"x; urlEncode.out.58="%1D" /* GS group separator */
urlEncode.in.59="1e"x; urlEncode.out.59="%1E" /* RS record separator */
urlEncode.in.60="1f"x; urlEncode.out.60="%1F" /* US unit separator */
urlEncode.in.61="7f"x; urlEncode.out.61="%7F" /* Delete */
urlEncode.max=61
return
/* this is far from a complete list, but just covered the basics */
getCharSwapTables:
/* emdash */
/* input table */ /* output table */
charSwapIn.0="â";charSwapOut.0="-"
/* Umlaut */
/* input table */ /* output table */
charSwapIn.1="ä";charSwapOut.1="ae"
charSwapIn.2="Ã";charSwapOut.2="AE"
charSwapIn.3="ë";charSwapOut.3="e"
charSwapIn.4="Ã";charSwapOut.4="E"
charSwapIn.5="ï";charSwapOut.5="i"
charSwapIn.6="Ã";charSwapOut.6="I"
charSwapIn.7="ö";charSwapOut.7="o"
charSwapIn.8="Ã";charSwapOut.8="O"
charSwapIn.9="ü";charSwapOut.9="u"
charSwapIn.10="Ã";charSwapOut.10="U"
charSwapIn.11="ÿ";charSwapOut.11="y"
charSwapIn.12="Ÿ";charSwapOut.12="Y"
/* Tilde */
/* input table */ /* output table */
charSwapIn.13="ã";charSwapOut.13="a"
charSwapIn.14="Ã";charSwapOut.14="A"
charSwapIn.15="ñ";charSwapOut.15="n"
charSwapIn.16="Ã";charSwapOut.16="N"
charSwapIn.17="õ";charSwapOut.17="o"
charSwapIn.18="Ã";charSwapOut.18="O"
/* Circumflex */
/* input table */ /* output table */
charSwapIn.19="â";charSwapOut.19="a"
charSwapIn.20="Ã";charSwapOut.20="A"
charSwapIn.21="ê";charSwapOut.21="e"
charSwapIn.22="Ã";charSwapOut.22="E"
charSwapIn.23="î";charSwapOut.23="i"
charSwapIn.24="Ã";charSwapOut.24="I"
charSwapIn.25="ô";charSwapOut.25="o"
charSwapIn.26="Ã";charSwapOut.26="O"
charSwapIn.27="û";charSwapOut.27="u"
charSwapIn.28="Ã";charSwapOut.28="U"
/* Acute */
/* input table */ /* output table */
charSwapIn.29="á";charSwapOut.29="a"
charSwapIn.30="Ã";charSwapOut.30="A"
charSwapIn.31="é";charSwapOut.31="e"
charSwapIn.32="Ã";charSwapOut.32="E"
charSwapIn.33="Ã";charSwapOut.33="i"
charSwapIn.34="Ã";charSwapOut.34="I"
charSwapIn.35="ó";charSwapOut.35="o"
charSwapIn.36="Ã";charSwapOut.36="O"
charSwapIn.37="ú";charSwapOut.37="u"
charSwapIn.38="Ã";charSwapOut.38="U"
charSwapIn.39="ý";charSwapOut.39="y"
charSwapIn.40="Ã";charSwapOut.40="Y"
/* Grave */
/* input table */ /* output table */
charSwapIn.41="Ã ";charSwapOut.41="a"
charSwapIn.42="Ã";charSwapOut.42="A"
charSwapIn.43="è";charSwapOut.43="e"
charSwapIn.44="Ã";charSwapOut.44="E"
charSwapIn.45="ì";charSwapOut.45="i"
charSwapIn.46="Ã";charSwapOut.46="I"
charSwapIn.47="ò";charSwapOut.47="o"
charSwapIn.48="Ã";charSwapOut.48="O"
charSwapIn.49="ù";charSwapOut.49="u"
charSwapIn.50="Ã";charSwapOut.50="U"
/* Others */
charSwapIn.51="Ã¥";charSwapOut.51="a"
charSwapIn.52="Ã
";charSwapOut.52="A"
charSwapIn.53="ø";charSwapOut.53="o"
charSwapIn.54="Ã";charSwapOut.54="O"
charSwapIn.55="â";charSwapOut.55="-"
charSwapIn.56="â";charSwapOut.56="-"
charSwapIn.57="â¦";charSwapOut.57="..."
charSwapIn.58="Ã" ;charSwapOut.58="AE"
/* one off special case "ta biblia" in query="bible" */
charSwapIn.59="Ïá½° βιβλία, "; charSwapOut.59=""
charSwapMax=59
return
/**************************************************************************/
CHECK:
if ARG() & ARG(1)~="###PANIC" then return ARG(1)
getcarrier
if result="TRUE" then do
if ARG() then return ARG(1)
else return
end
logentry "Lost Carrier!!"
bufferflush
signal EXIT
SYNTAX:;ERROR:;IOERR:
e1="n1 Error: " rc " (" errortext(rc) ")"
e2=" Line: " left(sigl,4) "File:"
c="`"fp", "ver"'";
e2=e2" "c
tr e1
tr e2
e=strip(translate(sourceline(sigl),"\{",""))
do while e~=""
e3="Source: "left(e,37)
tr e3
e=substr(e,38)
end
bufferflush
exit
/**************************************************************************\
\******************************* -X-caliber telnet://bbs.aholix.net:6800 **/