From b514629a33b668d539a3fedc25889a7566bfb6eb Mon Sep 17 00:00:00 2001 From: rodrigorodriguez Date: Sun, 9 Apr 2023 19:20:15 -0300 Subject: [PATCH] new(basic.gblib): GPT-3 automatically dialog generation. --- blank.docx | Bin 0 -> 9044 bytes blank.xlsx | Bin 0 -> 15051 bytes boot.mjs | 1 + .../basic.gblib/services/DialogKeywords.ts | 2 +- packages/basic.gblib/services/GBVMService.ts | 56 ++--- .../services/KeywordsExpressions.ts | 216 ++++++++++++++---- .../basic.gblib/services/SystemKeywords.ts | 183 +++++++++++---- packages/core.gbapp/services/GBMinService.ts | 57 ++--- packages/default.gbui/src/GBUIApp.js | 2 +- packages/kb.gbapp/dialogs/AskDialog.ts | 80 ++++++- packages/kb.gbapp/services/KBService.ts | 63 +++-- .../security.gbapp/services/SecService.ts | 2 +- src/app.ts | 22 +- 13 files changed, 512 insertions(+), 172 deletions(-) create mode 100644 blank.docx create mode 100644 blank.xlsx diff --git a/blank.docx b/blank.docx new file mode 100644 index 0000000000000000000000000000000000000000..88beb99b1b49a67c5f6f2caa131cb9547b50ae61 GIT binary patch literal 9044 zcmaia1ymi&vNrDS?yfro*Wm8%?z(Yz2!vq4HMo=D?(P~OxH|+V5bQzDJvTXd|2u!} zHMREiOjUQ6_4ItBAPo+I0RjU91A-b5t_JcO!9V}kcQmzeVrF{b!0} zOoOjCS$+dN9QoT#Y1)4nN4AhyKL`|y(E*dQErjz@xxyF44tX9L6` zNyCMx0P8zjxRbA>g504-yD3;?5coAebBWE(eF2^gS!anR5-K1LP>RcGcYcX{XF^Wf zOS7NYwhxh)HQ^5x6tEMQ?h8b1LDEKV8sI2UYjCYd;D!*t_EI1R)@sSBnTkg~>|Q>e zZxrCOsTMrYf##*!;u&^LzQ(gBI8s#B0%@g;#BA1N( zC!Qgg+B7@&j$wCndAO}XZY!J4(9kQWyWJkj;exWIC-yUv3DxVp7Eu8S?m-1Y_q0r~N-u0#3Vb%qWOFP_U#)VA*;!SG%E zY!UW3(JI|3)W~%(bHuDl?zh%ZzST#%KovmDV+%X9>1sqB%YZ7W|7?V!>uS43DgR{_K zM7cSKLe`fHVdfWApkt?MA~<I3I$3OXkgWdv?I~AdO_QdUCU3PwHix z>ubJ<{Srp&vmpLS&!awjKK}0tK=6Fk&EC<3`L8^!e!*mZTA5;G=m`z$~uF~Eh( zWhVEeI`~)LV^<7`?IUSRu7`idKh*p>srN?KBq`lX)tK7Hgy8@{8+k|pxkqQ0&piZp zOA)oZbj3z;H(|0UWFBs~6$YdXP*et{CkTXT=fJi*;O0 zN^HM8&pqj1z5Y@ke_H2vyX42q+AjhSLQn26Lr)@)84$U1B?CycE4$x;?2iR84A&`0 zVo-3|u^+WZSKY_fcEpq?(Xb4@Wu{fEcN7}{HHWol9rjxDJ~%O*Jl^qy?JMF(5)g){rxXr=eQ%aoct zfPD5hDYai=Xod778&Uz9o`Rj3uSNHyS&~AX&1s)7s^I%lEc8jKapB`%Ie#uBVV2fE zMM9jkDVVX(UB#zWkbS+C2vndnw~bm$~Bnfo+N2_0f~N`FHB(M~)6h zFo{&ZVoV$*m~;viwA*tsiau?EBCw%2eV3dqV{0kq0+V(&wdboYpvU?W`% zI-EL;0L~^|Il6v_iYgbprT4oO7u*i;{?x1YLF9dgILvR|MJaOHR=dT8K7tutKI9Dz zzOK-x+;gmdkQC%fpV5CTg|CZgN*XP~=au)Qlc_YXr)GoK(IxiHf~02CW>Rl0gL=|m zEt{HLr+;;$S}~Mui0O^+Ij!1uxv344G&9z5fpel-8xqirxkfP1$(iSAv27fqCE1ho z{(K+hUUvoG!I%&e)s?2pP?E>4LdUyUtQin33fMgKuy3$0Itl7m%flRtK+&n>bHlLq zZU1IE8JY~9$?>Cn3fWp-Vn>Z?b4GGU+~W@aB?P01lRk?)hu=Kpza=R0-y!Ja>|tZ- z^pcn}8M01`oM_JhNUyNoGEh3OvbNng~<~6cLwoCrIXR5QQ>M|MdEtIK3!i3Gbq;~xY)aRiJds>gYWyT(I>v8qvtPh zv%ISOVe)uKVVvM0Z?Cxn59CU%R$x$mHKjeP4ykD0% zme|CVM4s5Dse>81X=T#)b~Ay%mxX66j$$SNm_YB*Dmlx$QYW0x_1Rw%(uSGrKI|(kuYE?gqiK!$Ko+#WJ6@u699-tTD|1@Fy zBlFCl{vlePs-Oh1ZN&KD``LU?uuL)}@kgIb8b*c(+YvbEB`hezvqPODSG$oXM0OBaX&iFSy zkgq{du_?UCmM^!fb9dFi}o?h(goDT%^&BLfKl_0ml~nt6f(yqk)n zQas%lOp$4&XZ3(E_|Cvn-<4s5&1K~gOKr57rj_6Uo$p#bx2K@Xxr*V|!{i_462&Ph z80{N++V)HxE8jF16q{q+D%HNL^HZ%bFw|qRcv~7-ypCFj-a#E}X2N38k0x?zTbbTU zrFC$u#nocSGwYy9Xhu1;qbd=o7CPmZC)quh7F^iG;6)(wgQ8o3|I9zCL7|wzxSaNO zzovdmKx{D8lngxVQTYLSe^+t6mYD%}DZ4o)Jh{)FcvVCum}nVpA^APJ85V_8(fY#} zhxFi-f2eEH`S}z|Z+I9y7A0vyowJ_z)a_dXHWT+JvtpVkc*XF8Oo&-do8;|bfkpw| znPsWyt$~R-os`XJvtphWjD>DQeX67NP-fKk99NeLJ)tL}GrV%S1438WL^-EekLq*8m?3RS5OKFpuYB=j}qmCvx$F74AEQK^nwe z5l}{r;p*-v;x#l-u>%0;h;eX=!9(@4r~MJzWeP#@eaq!w$+f^(4OD<)+z;p(+m;j$J>h!HJ1!+cj5+%vjB>PmU8fP@Iw9*_R1JR^@1`yB^(hItD>b;}zEKJNB z1sY>J(xQ!DnSd&CkDW;-vh*79$7GyjLtP3|ImXt_u>Bg}^hd5gq%;Z`JD`6P+PSDj z0MFF=@kNuF8EpsNeXr(e@B{u?h1!ZyE8oIuPdZVng(miqml^X(h3$xZA)%SRJIQ&G z9Ziep^<_i*s|Jy4=j*C7JIYFPkEv<2Zx@%Q!^?CY{1um# zY$#(*8|K=Znt>-}7d_s#OHGTP-YjUbu391#RUGGD;%osnPx^#jjowMC-GH{US)K{c%jXg`knG6uYQHQ z+yk|F&4&|FcjoQfInT}YGoW9XMyOD#@E3f4(gv`N!xoRX(bLAfKV0*hu)ES+F4USKBth}U@5^2uMa)KL%q%} zxtsLc&?KTTXP0hDqah4*13fVZf_w`Z7qQmIOM=4bwCb z3^VG>tIUjvxky*Ap^s_^E0wO#+3XshR+>Fh@yQjtB*Wi@je@fg&tORxQE}{3C=G{t zcTd=Jn}P0eX8JJ%wL19w=2Ft3`5Bb$9V^ZRLtR8z4Rv9#*%@$Z6Z*d8=jJ1;Fh?gg zouyxwV%D~-{DE$4B3#XQIZHZ-B_=hcq@agZ5*RcYH#eX7!G>YF9`a(^?*=2GB{Qrcf^Ij&l}*2IPFlh%Rr z->j+`Po1&0@fY)43qDd~bZL5S`N`&WBTEw(bpFB0UOLM7FLQnAjr|{tvh=0P!oL{f z%+!tL38W01Y(fzyOHo00;5Vhty{1`amkS&6!!ssIb(Cpnzd z_R=H?zVJ8vm~NPj26iXIts^9%re{iS!o=hepHO7M@0O+Ds9< zLT3lZGB)|{CE6n%s`aI6_fKueBh0)yZX*cq=I;llZyYf6_eTw>cnx4~ ztqFyFA5_Y?gG+Yj?d%6iKAJ6}DkO@prOuuRH9xvgCM?4qpSyV#Rtws&>jlovBCP1VAjp3h_|5N~C5 zAW!6FB)+UQ0M1Sb4RbWVX-tqx9bLKCZ}*DuV2r|V#2UKm@T*GZtH5ZR`PM?oK7JRX z(JWAB?7kPX{5neCQSzayIq70zzL*VpbfIstR(Ypwt{W*O($;4lIkyl0cH!Rc;)AvF z?#$vFByDYbKg(0?oHpN!wMe4NbHnu%${lKDm61hqmH4Nz>TdUp+MYw30e4LKXdkFt zRXa-j()O;0Z65A}LZ}lg*ekw;j0gyO>=r<{zRp^8Lu*Ef1_2?f1+yW>s(S81TWWD; zHfKYv6>ehg=cnWgzRb`a<@&*r-ar!;+O4&eb+L|)|f6~|iR(bHlW zZ5QhAy^$*kpCnK~xm>{*oBh9ryxZ(a>FJK*n{=;gMinYq(F(n5=Yodq&b}7qH zWs*UAT0?eoe!lQsL8XXsdBOhGeZDAD02b@D6<+i70Yt*=S83KUD?Ih@V8i7(KsZ*^ z&cRMAv}IR3U)l~d5s=V$9kuEjo6_A>mWcO5T3D9#5oo3*9nI_jnY|p0tl%6 z<@+sQgaa-}JAFbsk%&ae82bU)#TK)&t%V#tPe;bvt8iW{=0X*3ln>yiXM9rjNf2>~ zF6yqclNIRS``jMgC5>nL$KA=xe|vI1U+WxvAXYsc2H;|@Gq*h)jf)cp31oU-Y^-Bj z`&**k93p?bKflqgjfpdfnyyFz3ZFm>efrtmctE!yC z?a&5&yBNX&@_ceHWh^Q9B*)4Wu`q=R!Yo$Rz|WP%TT_^d0&_=Y zx-5~VFq=1TVCMtku}DGrPRVhiXMEQw=mPmAkVOjKIAl21`lyVpA89c#$jqJ;Y2%#D zl__w9tf|=dm6>@`b(3@iZQ)Ut<&8jpP#DTz#}{R*<3l%)sIKKAKFe0wc*{en;&_2t!a->N9=$& zA@dh{i>ac5U%(|MNEXlXFH@pJQdQnjOLoLg1cfpdz^*rxBla#A+~7s`dRw|81enCv z)W%dh`l=m#6B}w)@^ZRN&gb>FWCh>Nm0CMe=tKpF=+F7WXxnzL9+}rA+wFYy6!MYr zVOe*4UbPoVyqgrxW1ETDIe{wkD(o!(mJZcE)zXr5PbAoq8IK@ ze6_NK*u83`qczhtn0oERb8=7nTa4zP7pPShLOYj;+weG{2vaIQ{TJJ(-c!E_#&j5Q4?N%>5&Jk#Bz3%#SyXqaBHvMV>zKfjslEy?! z&%{Hv=0rF9HbA2@!G%ZI?wMxrU6=mLLM5&DQP2zu1mu9?-xeygzZWVqdplZfG~t-f-1WN6=lZexM;I6lE`uNimCeS zoTj9XM_wn2%o0u*`kpP8FYkUkW1rlfCkjins>#hv4a2Pu9MUIoeRZIxfHXpWvds%& zpQ3AzWE(LrU+!{)H{)O!gde$;G&)D^Yw6q`DFVbI7(5Y|mqP**oNXxo=@wEF9r7jU z9?kr<(keLm7o_MIu9OFWF0nV^a?#w;f*x`Tiyd22;w8nod?|KG?AwYNyp+^VOdT!L z%bW{7``7IAmkXr4fw`%ctf8f8K9Qh-@ADnFhfds{rd7v~HNC-J>}>AX6G!t5Y;=MD zo1OprirdN5+1b+0{O23STIFTA3jjjvE^WzDH5P?0>m;ci)f)sRZlVrr9W&bS+@AdS z!v4eLH{MfjK@HN5Q9j-_y9Yl;n>R3(sgP>9QdA2%CaUsJmC|;v&TpnLG)XiZ2rAgg z&74{}oA7pUMdK6TM^Vnbi$>Kb#)etywJ&4L30~360?$c2Wtq1-2K#y#cgnI?5(-sa z^gOc+uu{)6=CQkZjjUdUB`T{HEP-P2>}8Z0PQ!@jw*;1s_U=<7w4NU0)Z@JQ(hr*S zWixZ4Dw;&U&`iG>4cy(O)-NBC>jSVCD^kcO$B);;3f=shNdYOP8(}SHBMbCoT=mHZ zfe;PtjDZ|(;MajYhe1I+&;B%nlRJhyTx#_8qBTEAiwKolN%3kTawgO~dG4up)av_z zDrXG!c(lT11D7&CDly%+l8`VE>P?LC?#VyABMe-+{ff1H^~onEES-@734loefdEG{ zNiYLPN)~(bVrbbr-vZA2)L!TpXRSN!f!jSh%ky8I^@2ia3qL2sGeo1W;^AQGr2F#h z)|&8~6#x{`?+@<=wBs9015l(EAfqXr6=w&&#(hB%Flo+z@amIPA;m~d#A1)#Nbwry z#i0IZtCCUH>0#+CNHw2Kk=2N*qz>t!$D222!cMpyQ4aah;L|mvW~hNZ&6PLoyW0_s z2^`u;WrnrV(jwFQ4AnQx{hRbdkw{s>csbB1J8lY9s)Qfz5Q*w_;^VgJMk9&>0oK-o znjL^h#f4HQg*(2kTCCL)>Eq|;gz^zN{RTiD&&BEw4)Gzs^I^eXo|3qWLRttKMk3HDEI$MN1>N&pO5Uic;Z z{>-dnI}Lc7XJ^ShS1|=?P%sRTU*8}64!pm7fACNG?Q4WT1%HQqUy||{kv@0zzfk%= z#eat}U$Eg{wDgQI{8#)xNb#T2zk`J@LH3KJA%2to1$_Rg;CDRj1ylS*to=XWxJBoBmYs zd)0ke!+uc<{(n^bV@3N@{`W%g&*@VT{yqNRD)pb@zlY{O9XUz#|EwJf(vZ()1p$G7 O{&hS@iZ98_+5Z6Gll~0= literal 0 HcmV?d00001 diff --git a/blank.xlsx b/blank.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..fa249fbcdaf8fbce23c97e8ad1a244239127d78c GIT binary patch literal 15051 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 E7ps_YDgXcg literal 0 HcmV?d00001 diff --git a/boot.mjs b/boot.mjs index 3749aa205..ce93db2e4 100644 --- a/boot.mjs +++ b/boot.mjs @@ -6,6 +6,7 @@ import { exec } from 'child_process'; import pjson from './package.json' assert { type: 'json' }; // Displays version of Node JS being used at runtime and others attributes. + console.log(``); console.log(``); console.log(` █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® `); diff --git a/packages/basic.gblib/services/DialogKeywords.ts b/packages/basic.gblib/services/DialogKeywords.ts index 0dbf1a15e..86c659842 100644 --- a/packages/basic.gblib/services/DialogKeywords.ts +++ b/packages/basic.gblib/services/DialogKeywords.ts @@ -559,7 +559,7 @@ export class DialogKeywords { // } let { min, user, params } = await DialogKeywords.getProcessInfo(pid); const sec = new SecService(); - await sec.setParam(user.userId, name, value); + await sec.setParam(user.userId, name , value); GBLog.info(`BASIC: ${name} = ${value} (botId: ${min.botId})`); return { min, user, params }; } diff --git a/packages/basic.gblib/services/GBVMService.ts b/packages/basic.gblib/services/GBVMService.ts index 20a78a616..76642e5ba 100644 --- a/packages/basic.gblib/services/GBVMService.ts +++ b/packages/basic.gblib/services/GBVMService.ts @@ -137,41 +137,13 @@ export class GBVMService extends GBService { GBLogEx.info(min, `BASIC: Installing .gbdialog node_modules for ${min.botId}...`); const npmPath = urlJoin(process.env.PWD, 'node_modules', '.bin', 'npm'); child_process.execSync(`${npmPath} install`, { cwd: folder }); - - // // Hacks push-rpc to put timeout. - - // const inject1 = ` - // const { AbortController } = require("node-abort-controller"); - // var controller_1 = new AbortController(); - // var signal = controller_1.signal; - // setTimeout(function () { controller_1.abort(); }, 24 * 60 * 60 * 1000);`; - // const inject2 = `signal: signal,`; - // const js = Path.join(process.env.PWD, folder, 'node_modules/@push-rpc/http/dist/client.js'); - - // lineReplace({ - // file: js, - // line: 75, - // text: inject1, - // addNewLine: true, - // callback: ({ file, line, text, replacedText, error }) => { - // lineReplace({ - // file: js, - // line: 82, - // text: inject2, - // addNewLine: true, - // callback: ({ file, line, text, replacedText, error }) => { - // GBLogEx.info(min, `BASIC: Patching node_modules for ${min.botId} done.`); - // } - // }); - // } - // }); } // Hot swap for .vbs files. const fullFilename = urlJoin(folder, filename); if (process.env.DEV_HOTSWAP) { Fs.watchFile(fullFilename, async () => { - await this.translateBASIC(fullFilename, mainName, min); + await this.translateBASIC(fullFilename, min); const parsedCode: string = Fs.readFileSync(jsfile, 'utf8'); min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode; }); @@ -184,17 +156,17 @@ export class GBVMService extends GBService { const jsStat = Fs.statSync(jsfile); const interval = 30000; // If compiled is older 30 seconds, then recompile. if (compiledAt.isFile() && compiledAt['mtimeMs'] > jsStat['mtimeMs'] + interval) { - await this.translateBASIC(fullFilename, mainName, min); + await this.translateBASIC(fullFilename, min); } } else { - await this.translateBASIC(fullFilename, mainName, min); + await this.translateBASIC(fullFilename, min); } const parsedCode: string = Fs.readFileSync(jsfile, 'utf8'); min.sandBoxMap[mainName.toLowerCase().trim()] = parsedCode; return filename; } - public async translateBASIC(filename: any, mainName: string, min: GBMinInstance) { + public async translateBASIC(filename: any, min: GBMinInstance) { // Converts General Bots BASIC into regular VBS let basicCode: string = Fs.readFileSync(filename, 'utf8'); @@ -264,9 +236,11 @@ export class GBVMService extends GBService { let list = this.list; let httpUsername = this.httpUsername; let httpPs = this.httpPs; - let page = null; let today = this.today; let now = this.now; + let page = null; + let files = []; + let col = 1; // Transfers NLP auto variables into global object. @@ -351,18 +325,25 @@ export class GBVMService extends GBService { var lines = code.split('\n'); const keywords = KeywordsExpressions.getKeywords(); let current = 41; - const map = {}; + const map = {}; for (let i = 1; i <= lines.length; i++) { + let line = lines[i - 1]; + + // Remove lines before statments. + + line = line.replace(/^\s*\d+\s*/gi,''); + for (let j = 0; j < keywords.length; j++) { - lines[i - 1] = lines[i - 1].replace(keywords[j][0], keywords[j][1]); + line = line.replace(keywords[j][0], keywords[j][1]); } // Add additional lines returned from replacement. - let add = lines[i - 1].split(/\r\n|\r|\n/).length; + let add = line.split(/\r\n|\r|\n/).length; current = current + (add ? add : 0); map[i] = current; + lines[i - 1] = line; } code = `${lines.join('\n')}\n`; @@ -419,7 +400,8 @@ export class GBVMService extends GBService { }; const dk = new DialogKeywords(); const sys = new SystemKeywords(); - + await dk.setFilter ({pid: pid, value: null }); + sandbox['variables'] = variables; sandbox['id'] = sys.getRandomId(); sandbox['username'] = await dk.userName({ pid }); diff --git a/packages/basic.gblib/services/KeywordsExpressions.ts b/packages/basic.gblib/services/KeywordsExpressions.ts index 3985ba586..b53d1aa80 100644 --- a/packages/basic.gblib/services/KeywordsExpressions.ts +++ b/packages/basic.gblib/services/KeywordsExpressions.ts @@ -32,7 +32,9 @@ 'use strict'; -import { GBVMService } from "./GBVMService.js"; +import { GBAdminService } from '../../admin.gbapp/services/GBAdminService.js'; +import { GBVMService } from './GBVMService.js'; +import Path from 'path'; /** * Image processing services of conversation to be called by BASIC. @@ -46,7 +48,7 @@ export class KeywordsExpressions { if (accum.isConcatting) { accum.soFar[accum.soFar.length - 1] += ',' + curr; } else { - if(curr===""){ + if (curr === '') { curr = null; } accum.soFar.push(curr); @@ -67,15 +69,20 @@ export class KeywordsExpressions { names.forEach(name => { let value = items[i]; i++; - json = `${json} "${name}": ${value} ${names.length == i ? '' : ','}`; + json = `${json} "${name}": ${value === undefined ? null : value} ${names.length == i ? '' : ','}`; }); json = `${json}`; return json; }; + public static isNumber(n) { + return !isNaN(parseFloat(n)) && isFinite(n); + } + /** * Returns the list of BASIC keyword and their JS match. + * Based on https://github.com/uweg/vbscript-to-typescript. */ public static getKeywords() { // Keywords from General Bots BASIC. @@ -91,14 +98,134 @@ export class KeywordsExpressions { return result; }; + keywords[i++] = [ + /^\s*INPUT(.*)/gim, + ($0, $1, $2) => { + + let separator; + if ($1.indexOf(',') > -1){ + separator = ','; + } + else if ($1.indexOf(';') > -1){ + separator = ';'; + } + let parts; + if ( separator && (parts = $1.split(separator)) && parts.length > 1){ + return ` + TALK ${parts[0]} + HEAR ${parts[1]}`; + } + else + { + return ` + HEAR ${$1}`; + } + } + ]; + + keywords[i++] = [ + /^\s*WRITE(.*)/gim, + ($0, $1, $2) => { + return `PRINT${$1}`; + } + ]; + keywords[i++] = [/^\s*REM.*/gim, '']; + keywords[i++] = [/^\s*CLOSE.*/gim, '']; + + // Always autoclose keyword. + + keywords[i++] = [/^\s*CLOSE.*/gim, '']; + keywords[i++] = [/^\s*\'.*/gim, '']; + keywords[i++] = [ + /^\s*PRINT ([\s\S]*)/gim, + ($0, $1, $2) => { + let sessionName; + let kind = null; + let pos; + $1 = $1.trim(); + + if ($1.substr(0, 1) === '#') { + let sessionName = $1.substr(1, $1.indexOf(',') - 1); + $1 = $1.replace(/\; \"\,\"/gi, ''); + $1 = $1.substr($1.indexOf(',') + 1); + + let separator; + if ($1.indexOf(',') > -1){ + separator = ','; + } + else if ($1.indexOf(';') > -1){ + separator = ';'; + } + let items; + if (separator && (items = $1.split(separator)) && items.length > 1) { + return `await sys.save({pid: pid, file: files[${sessionName}], args:[${items.join(',')}]})`; + } else { + return `await sys.set({pid: pid, file: files[${sessionName}], address: col++, name: "${items[0]}", value: ${items[0]}})`; + } + } else { + return `await dk.talk({pid: pid, text: ${$1}})`; + } + } + ]; + + keywords[i++] = [ + /^\s*open([\s\S]*)/gim, + ($0, $1, $2) => { + let sessionName; + let kind = null; + let pos; + + $1 = $1.replace('FOR APPEND', ''); + $1 = $1.replace('FOR OUTPUT', ''); + + + + if ((pos = $1.match(/\s*AS\s*\#/gi))) { + kind = 'AS'; + } else if ((pos = $1.match(/\s*WITH\s*\#/gi))) { + kind = 'WITH'; + } + + if (pos) { + let part = $1.substr($1.lastIndexOf(pos[0])); + sessionName = `${part.substr(part.indexOf('#') + 1)}`; + $1 = $1.substr(0, $1.lastIndexOf(pos[0])); + } + $1 = $1.trim(); + if (!$1.startsWith('"') && !$1.startsWith("'")) { + $1 = `"${$1}"`; + } + const params = this.getParams($1, ['url', 'username', 'password']); + + // Checks if it is opening a file or a webpage. + + if (kind === 'AS' && KeywordsExpressions.isNumber(sessionName)) { + const jParams = JSON.parse(`{${params}}`); + const filename = `${jParams.url.substr(0, jParams.url.lastIndexOf("."))}.xlsx`; + let code = + ` + col = 1 + await sys.save({pid: pid,file: "${filename}", args: [id] }) + await dk.setFilter ({pid: pid, value: "id=" + id }) + files[${sessionName}] = "${filename}" + `; + return code; + } else { + sessionName = `"${sessionName}"`; + kind = `"${kind}"`; + return `page = await wa.openPage({pid: pid, handle: page, sessionKind: ${kind}, sessionName: ${sessionName}, ${params}})`; + } + } + ]; + keywords[i++] = [ /^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*SELECT\s*(.*)/gim, ($0, $1, $2) => { - let tableName = /\s*FROM\s*(\w+)/.exec($2)[1]; + let tableName = /\s*FROM\s*(\w+\$*)/.exec($2)[1]; let sql = `SELECT ${$2}`.replace(tableName, '?'); return `${$1} = await sys.executeSQL({pid: pid, data:${$1}, sql:"${sql}", tableName:"${tableName}"})\n`; } @@ -114,8 +241,6 @@ export class KeywordsExpressions { } ]; - // Based on https://github.com/uweg/vbscript-to-typescript. - keywords[i++] = [/^\s*else(?!{)/gim, '}\nelse {']; keywords[i++] = [/^\s*select case +(.*)/gim, 'switch ($1) {']; @@ -141,30 +266,42 @@ export class KeywordsExpressions { keywords[i++] = [/^\s*loop *$/gim, '}']; keywords[i++] = [ - /^\s*open\s*(.*)/gim, + /^\s*open([\s\S]*)/gim, ($0, $1, $2) => { let sessionName; let kind = null; let pos; - if (pos = $1.match(/\s*AS\s*\#/)) { - kind = '"AS"'; - } else if (pos = $1.match(/\s*WITH\s*\#/)) { - kind = '"WITH"'; + $1 = $1.replace(' FOR APPEND', ''); + + if ((pos = $1.match(/\s*AS\s*\#/))) { + kind = 'AS'; + } else if ((pos = $1.match(/\s*WITH\s*\#/))) { + kind = 'WITH'; } if (pos) { let part = $1.substr($1.lastIndexOf(pos[0])); - sessionName = `"${part.substr(part.indexOf('#') + 1)}"`; + sessionName = `${part.substr(part.indexOf('#') + 1)}`; $1 = $1.substr(0, $1.lastIndexOf(pos[0])); } - + $1 = $1.trim(); if (!$1.startsWith('"') && !$1.startsWith("'")) { $1 = `"${$1}"`; } const params = this.getParams($1, ['url', 'username', 'password']); - return `page = await wa.openPage({pid: pid, handle: page, sessionKind: ${kind}, sessionName: ${sessionName}, ${params}})`; + // Checks if it is opening a file or a webpage. + + if (kind === 'AS' && KeywordsExpressions.isNumber(sessionName)) { + const jParams = JSON.parse(`{${params}}`); + const filename = `${Path.basename(jParams.url, 'txt')}xlsx`; + return `files[${sessionName}] = "${filename}"`; + } else { + sessionName = `"${sessionName}"`; + kind = `"${kind}"`; + return `page = await wa.openPage({pid: pid, handle: page, sessionKind: ${kind}, sessionName: ${sessionName}, ${params}})`; + } } ]; @@ -176,112 +313,112 @@ export class KeywordsExpressions { ]; keywords[i++] = [ - /^\s*hear (\w+) as (\w+( \w+)*.xlsx)/gim, + /^\s*hear (\w+\$*) as (\w+( \w+)*.xlsx)/gim, ($0, $1, $2) => { return `${$1} = await dk.hear({pid: pid, kind:"sheet", arg: "${$2}"})`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*login/gim, + /^\s*hear (\w+\$*) as\s*login/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"login"})`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*email/gim, + /^\s*hear (\w+\$*) as\s*email/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"email"})`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*integer/gim, + /^\s*hear (\w+\$*) as\s*integer/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"integer"})`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*file/gim, + /^\s*hear (\w+\$*) as\s*file/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"file"})`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*boolean/gim, + /^\s*hear (\w+\$*) as\s*boolean/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"boolean"})`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*name/gim, + /^\s*hear (\w+\$*) as\s*name/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"name"})`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*date/gim, + /^\s*hear (\w+\$*) as\s*date/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"date"})`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*hour/gim, + /^\s*hear (\w+\$*) as\s*hour/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"hour"})`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*phone/gim, + /^\s*hear (\w+\$*) as\s*phone/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"phone"})`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*money/gim, + /^\s*hear (\w+\$*) as\s*money/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"money")}`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*qrcode/gim, + /^\s*hear (\w+\$*) as\s*qrcode/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"qrcode")}`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*language/gim, + /^\s*hear (\w+\$*) as\s*language/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"language")}`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*zipcode/gim, + /^\s*hear (\w+\$*) as\s*zipcode/gim, ($0, $1) => { return `${$1} = await dk.hear({pid: pid, kind:"zipcode")}`; } ]; keywords[i++] = [ - /^\s*hear (\w+) as\s*(.*)/gim, + /^\s*hear (\w+\$*) as\s*(.*)/gim, ($0, $1, $2) => { return `${$1} = await dk.hear({pid: pid, kind:"menu", args: [${$2}]})`; } ]; keywords[i++] = [ - /^\s*(hear)\s*(\w+)/gim, + /^\s*(hear)\s*(\w+\$*)/gim, ($0, $1, $2) => { return `${$2} = await dk.hear({pid: pid})`; } @@ -345,21 +482,21 @@ export class KeywordsExpressions { ]; keywords[i++] = [ - /^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*sort\s*(\w+)\s*by(.*)/gim, + /^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*sort\s*(\w+\$*)\s*by(.*)/gim, ($0, $1, $2, $3) => { return `${$1} = await sys.sortBy({pid: pid, array: ${$2}, memberName: "${$3}"})`; } ]; keywords[i++] = [ - /^\s*see\s*text\s*of\s*(\w+)\s*as\s*(\w+)\s*/gim, + /^\s*see\s*text\s*of\s*(\w+\$*)\s*as\s*(\w+\$*)\s*/gim, ($0, $1, $2, $3) => { return `${$2} = await sys.seeText({pid: pid, url: ${$1})`; } ]; keywords[i++] = [ - /^\s*see\s*caption\s*of\s*(\w+)\s*as(.*)/gim, + /^\s*see\s*caption\s*of\s*(\w+\$*)\s*as(.*)/gim, ($0, $1, $2, $3) => { return `${$2} = await sys.seeCaption({pid: pid, url: ${$1})`; } @@ -618,7 +755,6 @@ export class KeywordsExpressions { // Uses auto quote if this is a frase with more then one word. if (/\s/.test($3) && $3.substr(0, 1) !== '"') { - $3 = `"${$3}"`; } return `await dk.talk ({pid: pid, text: ${$3}})`; @@ -772,19 +908,19 @@ export class KeywordsExpressions { ]; keywords[i++] = [ - /^\s*save\s*(\w+)\s*as\s*(.*)/gim, + /^\s*save\s*(\w+\$*)\s*as\s*(.*)/gim, ($0, $1, $2, $3) => { return `await sys.saveFile({pid: pid, file: ${$2}, data: ${$1}})`; } ]; - + keywords[i++] = [ /^\s*(save)(\s*)(.*\.xlsx)(.*)/gim, ($0, $1, $2, $3, $4) => { - $3 = $3.replace (/\'/g, "") - $3 = $3.replace (/\"/g, "") - $4 = $4.substr(2) - return `await sys.save({pid: pid,file: "${$3}" , args: [${$4}]})`; + $3 = $3.replace(/\'/g, ''); + $3 = $3.replace(/\"/g, ''); + $4 = $4.substr(2); + return `await sys.save({pid: pid, file: "${$3}", args: [${$4}]})`; } ]; diff --git a/packages/basic.gblib/services/SystemKeywords.ts b/packages/basic.gblib/services/SystemKeywords.ts index 1e8719d26..bfc60102f 100644 --- a/packages/basic.gblib/services/SystemKeywords.ts +++ b/packages/basic.gblib/services/SystemKeywords.ts @@ -58,6 +58,7 @@ import DynamicsWebApi from 'dynamics-web-api'; import * as MSAL from '@azure/msal-node'; import { GBConversationalService } from '../../core.gbapp/services/GBConversationalService.js'; import { WebAutomationServices } from './WebAutomationServices.js'; +import { KeywordsExpressions } from './KeywordsExpressions.js'; /** * @fileoverview General Bots server core. @@ -471,7 +472,7 @@ export class SystemKeywords { * @example SET page, "elementHTMLSelector", "text" * */ - public async set({ pid, handle, file, address, value }): Promise { + public async set({ pid, handle, file, address, value, name = null }): Promise { const { min, user } = await DialogKeywords.getProcessInfo(pid); // Handles calls for HTML stuff @@ -485,14 +486,6 @@ export class SystemKeywords { // TODO: Add a semaphore between FILTER and SET. - // Processes FILTER option to ensure parallel SET calls. - - const filter = await DialogKeywords.getOption({ pid, name }); - if (filter) { - const row = this.find({ pid, handle: null, args: [filter] }); - address += row['line']; - } - // Handles calls for BASIC persistence on sheet files. GBLog.info(`BASIC: Defining '${address}' in '${file}' to '${value}' (SET). `); @@ -501,16 +494,53 @@ export class SystemKeywords { const botId = min.instance.botId; const path = DialogKeywords.getGBAIPath(botId, 'gbdata'); + let document = await this.internalGetDocument(client, baseUrl, path, file); + let sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get(); + let body = { values: [[]] }; + // Processes FILTER option to ensure parallel SET calls. + + const filter = await DialogKeywords.getOption({ pid, name: 'filter' }); + let titleAddress; + + if (filter) { + // Transforms address number (col index) to letter based. + // Eg.: REM This is A column and index automatically specified by filter. + // SET file.xlsx, 1, 4000 + + if (KeywordsExpressions.isNumber(address)) { + address = `${this.numberToLetters(address)}`; + titleAddress = `${address}1:${address}1`; + } + + // Processes SET FILTER directive to calculate address. + + body.values[0][0] = 'id'; + const addressId = 'A1:A1'; + await client + .api( + `${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${addressId}')` + ) + .patch(body); + + const row = await this.find({ pid, handle: null, args: [file, filter] }); + if (row) { + address += row['line']; // Eg.: "A" + 1 = "A1". + } + } address = address.indexOf(':') !== -1 ? address : address + ':' + address; - let document = await this.internalGetDocument(client, baseUrl, path, file); + if (titleAddress) { + body.values[0][0] = name.trim().replace(/[^a-zA-Z]/gi, ''); + + await client + .api( + `${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${titleAddress}')` + ) + .patch(body); + } - let body = { values: [[]] }; body.values[0][0] = value; - - let sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get(); - await client .api( `${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')` @@ -529,7 +559,10 @@ export class SystemKeywords { }); if (!documents || documents.length === 0) { - throw `File '${file}' specified on GBasic command not found. Check the .gbdata or the .gbdialog associated.`; + throw new Error( + `File '${file}' specified on GBasic command not found. Check the .gbdata or the .gbdialog associated.`, + { cause: 404 } + ); } return documents[0]; @@ -575,36 +608,84 @@ export class SystemKeywords { */ public async save({ pid, file, args }): Promise { const { min, user } = await DialogKeywords.getProcessInfo(pid); - args.shift(); + GBLog.info(`BASIC: Saving '${file}' (SAVE). Args: ${args.join(',')}.`); let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min); const botId = min.instance.botId; const path = DialogKeywords.getGBAIPath(botId, 'gbdata'); - let document = await this.internalGetDocument(client, baseUrl, path, file); - let sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get(); + let sheets; + let document; + try { + document = await this.internalGetDocument(client, baseUrl, path, file); + sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get(); + } catch (e) { + if (e.cause === 404) { + // Creates the file. - await client - .api( - `${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A2:DX2')/insert` - ) - .post({}); + const blank = Path.join(process.env.PWD, 'blank.xlsx'); + const data = Fs.readFileSync(blank); + await client.api(`${baseUrl}/drive/root:/${path}/${file}:/content`).put(data); - if (args.length > 128) { - throw `File '${file}' has a SAVE call with more than 128 arguments. Check the .gbdialog associated.`; + // Tries to open again. + + document = await this.internalGetDocument(client, baseUrl, path, file); + sheets = await client.api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`).get(); + } else { + throw e; + } } + let address; let body = { values: [[]] }; - const address = `A2:${this.numberToLetters(args.length - 1)}2`; + // Processes FILTER option to ensure parallel SET calls. + + const filter = await DialogKeywords.getOption({ pid, name: 'filter' }); + if (filter) { + + // Creates id row. + + body.values[0][0] = 'id'; + const addressId = 'A1:A1'; + await client + .api( + `${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${addressId}')` + ) + .patch(body); + body.values[0][0] = undefined ; + + // FINDs the filtered row to be updated. + + const row = await this.find({ pid, handle: null, args: [file, filter] }); + if (row) { + address = `A${row['line']}:${this.numberToLetters(args.length)}${row['line']}`; + } + } + + // Editing or saving detection. + + if (!address) { + await client + .api( + `${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A2:DX2')/insert` + ) + .post({}); + address = `A2:${this.numberToLetters(args.length - 1)}2`; + } + + // Fills rows object to call sheet API. + for (let index = 0; index < args.length; index++) { let value = args[index]; if (value && (await this.isValidDate({ pid, dt: value }))) { value = `'${value}`; } - body.values[0][index] = value; - } + // If filter is defined, skips id column. + + body.values[0][filter ? index + 1 : index] = value; + } await client .api( `${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')` @@ -675,11 +756,7 @@ export class SystemKeywords { } public async isValidNumber({ pid, number }) { - const { min, user } = await DialogKeywords.getProcessInfo(pid); - if (number === '') { - return false; - } - return !isNaN(number); + return KeywordsExpressions.isNumber(number); } public isValidHour({ pid, value }) { @@ -1179,6 +1256,33 @@ export class SystemKeywords { await client.api(`https://graph.microsoft.com/v1.0/drives/${driveId}/items/${itemId}/invite`).post(body); } + public async internalCreateDocument(min, path, content) { + GBLog.info(`BASIC: CREATE DOCUMENT '${path}...'`); + let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min); + const gbaiName = DialogKeywords.getGBAIPath(min.botId); + const tmpDocx = urlJoin(gbaiName, path); + + // Templates a blank {content} tag inside the blank.docx. + + const blank = Path.join(process.env.PWD, 'blank.docx'); + let buf = Fs.readFileSync(blank); + let zip = new PizZip(buf); + let doc = new Docxtemplater(); + doc.setOptions({ linebreaks: true }); + doc.loadZip(zip); + doc.setData({ content: content }).render(); + buf = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' }); + + // Performs the upload. + + await client.api(`${baseUrl}/drive/root:/${tmpDocx}:/content`).put(buf); + } + + public async createDocument({ pid, path, content }) { + const { min, user, params } = await DialogKeywords.getProcessInfo(pid); + this.internalCreateDocument(min, path, content); + } + /** * Copies a drive file from a place to another . * @@ -1224,8 +1328,9 @@ export class SystemKeywords { parentReference: { driveId: folder.parentReference.driveId, id: folder.id }, name: `${Path.basename(dest)}` }; - - return await client.api(`${baseUrl}/drive/items/${srcFile.id}/copy`).post(destFile); + const file = await client.api(`${baseUrl}/drive/items/${srcFile.id}/copy`).post(destFile); + GBLog.info(`BASIC: FINISHED COPY '${src}' to '${dest}'`); + return file; } catch (error) { if (error.code === 'itemNotFound') { GBLog.info(`BASIC: COPY source file not found: ${srcPath}.`); @@ -1234,7 +1339,6 @@ export class SystemKeywords { } throw error; } - GBLog.info(`BASIC: FINISHED COPY '${src}' to '${dest}'`); } /** @@ -1468,10 +1572,6 @@ export class SystemKeywords { localName = Path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.docx`); Fs.writeFileSync(localName, buf, { encoding: null }); - // Loads the file as binary content. - - let zip = new PizZip(buf); - // Replace image path on all elements of data. const images = []; @@ -1537,6 +1637,9 @@ export class SystemKeywords { } }; + // Loads the file as binary content. + + let zip = new PizZip(buf); let doc = new Docxtemplater(); doc.setOptions({ paragraphLoop: true, linebreaks: true }); doc.loadZip(zip); diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index 6cf635c74..a15100020 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -166,7 +166,6 @@ export class GBMinService { // Calls mountBot event to all bots. let i = 1; - if (instances.length > 1) { this.bar1 = new cliProgress.SingleBar( { @@ -179,19 +178,20 @@ export class GBMinService { this.bar1.start(instances.length, i, { botId: 'Boot' }); } - - await CollectionUtil.asyncForEach(instances, (async instance => { - try { - await this['mountBot'](instance); - } catch (error) { - GBLog.error(`Error mounting bot ${instance.botId}: ${error.message}\n${error.stack}`); - } - finally { - if (this.bar1) { - this.bar1.update(i++, { botId: instance.botId }); + await CollectionUtil.asyncForEach( + instances, + (async instance => { + try { + await this['mountBot'](instance); + } catch (error) { + GBLog.error(`Error mounting bot ${instance.botId}: ${error.message}\n${error.stack}`); + } finally { + if (this.bar1) { + this.bar1.update(i++, { botId: instance.botId }); + } } - } - }).bind(this)); + }).bind(this) + ); if (this.bar1) { this.bar1.stop(); @@ -200,10 +200,10 @@ export class GBMinService { pingSendTimeout: null, keepAliveTimeout: null, listeners: { - unsubscribed(subscriptions: number): void { }, - subscribed(subscriptions: number): void { }, - disconnected(remoteId: string, connections: number): void { }, - connected(remoteId: string, connections: number): void { }, + unsubscribed(subscriptions: number): void {}, + subscribed(subscriptions: number): void {}, + disconnected(remoteId: string, connections: number): void {}, + connected(remoteId: string, connections: number): void {}, messageIn(...params): void { GBLogEx.info(0, '[IN] ' + params); }, @@ -237,8 +237,6 @@ export class GBMinService { GBLogEx.info(0, 'API RPC HTTP Server started.'); - - // // Loads schedules. // GBLog.info(`Preparing SET SCHEDULE dialog calls...`); @@ -286,7 +284,7 @@ export class GBMinService { /** * Unmounts the bot web site (default.gbui) secure domain, if any. */ - public async unloadDomain(instance: IGBInstance) { } + public async unloadDomain(instance: IGBInstance) {} /** * Mount the instance by creating an BOT Framework bot object, @@ -331,7 +329,7 @@ export class GBMinService { const gbai = DialogKeywords.getGBAIPath(min.botId); let dir = `work/${gbai}/cache`; - const botId = gbai.replace(/\.[^/.]+$/, ""); + const botId = gbai.replace(/\.[^/.]+$/, ''); if (!Fs.existsSync(dir)) { mkdirp.sync(dir); @@ -563,8 +561,9 @@ export class GBMinService { min.instance.authenticatorTenant, '/oauth2/authorize' ); - authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${min.instance.marketplaceId - }&redirect_uri=${urlJoin(min.instance.botEndpoint, min.instance.botId, 'token')}`; + authorizationUrl = `${authorizationUrl}?response_type=code&client_id=${ + min.instance.marketplaceId + }&redirect_uri=${urlJoin(min.instance.botEndpoint, min.instance.botId, 'token')}`; GBLog.info(`HandleOAuthRequests: ${authorizationUrl}.`); res.redirect(authorizationUrl); }); @@ -1065,8 +1064,9 @@ export class GBMinService { await this.processEventActivity(min, user, context, step); } } catch (error) { - const msg = `ERROR: ${error.message} ${error.error ? error.error.body : ''} ${error.error ? (error.error.stack ? error.error.stack : '') : '' - }`; + const msg = `ERROR: ${error.message} ${error.error ? error.error.body : ''} ${ + error.error ? (error.error.stack ? error.error.stack : '') : '' + }`; GBLog.error(msg); await min.conversationalService.sendText( @@ -1085,8 +1085,7 @@ export class GBMinService { if (error.code === 401) { GBLog.error('Calling processActivity due to Signing Key could not be retrieved error.'); await adapter['processActivity'](req, res, handler); - } - else { + } else { throw error; } } @@ -1275,7 +1274,9 @@ export class GBMinService { // Files in .gbdialog can be called directly by typing its name normalized into JS . const isVMCall = Object.keys(min.scriptMap).find(key => min.scriptMap[key] === context.activity.text) !== undefined; - if (isVMCall) { + if (/create dialog|creative dialog|create a dialog|criar diálogo|criar diálogo/gi.test(context.activity.text)) { + await step.beginDialog('/dialog'); + } else if (isVMCall) { await GBVMService.callVM(context.activity.text, min, step, user, this.deployer, false); } else if (context.activity.text.charAt(0) === '/') { const text = context.activity.text; diff --git a/packages/default.gbui/src/GBUIApp.js b/packages/default.gbui/src/GBUIApp.js index ade11eebf..a444c7bec 100644 --- a/packages/default.gbui/src/GBUIApp.js +++ b/packages/default.gbui/src/GBUIApp.js @@ -326,7 +326,7 @@ class GBUIApp extends React.Component { ref={chat => { this.chat = chat; }} - locale={'pt-br'} + locale={'en-us'} directLine={this.state.line} webSpeechPonyfillFactory={window.WebChat.createCognitiveServicesSpeechServicesPonyfillFactory({ credentials: { authorizationToken: token, region: 'westus' } diff --git a/packages/kb.gbapp/dialogs/AskDialog.ts b/packages/kb.gbapp/dialogs/AskDialog.ts index 5ed1df231..20ef55adc 100644 --- a/packages/kb.gbapp/dialogs/AskDialog.ts +++ b/packages/kb.gbapp/dialogs/AskDialog.ts @@ -50,6 +50,9 @@ import { GBVMService } from '../../basic.gblib/services/GBVMService.js'; import { GBImporter } from '../../core.gbapp/services/GBImporterService.js'; import { GBDeployer } from '../../core.gbapp/services/GBDeployer.js'; import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js'; +import Fs from 'fs'; +import urlJoin from 'url-join'; +import { SystemKeywords } from '../../basic.gblib/services/SystemKeywords.js'; /** * Dialog arguments. @@ -78,6 +81,7 @@ export class AskDialog extends IGBDialog { min.dialogs.add(new WaterfallDialog('/answerEvent', AskDialog.getAnswerEventDialog(service, min))); min.dialogs.add(new WaterfallDialog('/answer', AskDialog.getAnswerDialog(min, service))); min.dialogs.add(new WaterfallDialog('/ask', AskDialog.getAskDialog(min))); + min.dialogs.add(new WaterfallDialog('/dialog', AskDialog.getLLVMDialog(min, service))); } private static getAskDialog(min: GBMinInstance) { @@ -234,7 +238,7 @@ export class AskDialog extends IGBDialog { } // TODO: https://github.com/GeneralBots/BotServer/issues/9 // else if (user.subjects && user.subjects.length > 0) { - // // ...second time running Search, now with no filter. + // // ..second time running Search, now with no filter. // const resultsB = await service.ask(min.instance, text, searchScore, undefined); @@ -304,6 +308,7 @@ export class AskDialog extends IGBDialog { } const CHATGPT_TIMEOUT = 60 * 1000; GBLog.info(`ChatGPT being used...`); + const response = await GBServer.globals.chatGPT.sendMessage(text, { timeoutMs: CHATGPT_TIMEOUT }); if (!response) { @@ -363,4 +368,77 @@ export class AskDialog extends IGBDialog { } ]; } + + private static getLLVMDialog(min: GBMinInstance, service: KBService) { + return [ + async step => { + if (step.context.activity.channelId !== 'msteams' && process.env.ENABLE_AUTH) { + return await step.beginDialog('/auth'); + } else { + return await step.next(step.options); + } + }, + async step => { + return await min.conversationalService.prompt(min, step, 'Please, describe the dialog scene.'); + }, + async step => { + step.options.dialog = step.result; + return await min.conversationalService.prompt(min, step, 'How would you call this?'); + }, + async step => { + if (GBServer.globals.chatGPT) { + let input = `Write a BASIC program that ${step.options.dialog.toLowerCase()}. And does not explain.`; + + await min.conversationalService.sendText(min, step, 'Thank you. The dialog is being written right now...'); + + const CHATGPT_TIMEOUT = 3 * 60 * 1000; + GBLog.info(`ChatGPT Code: ${input}`); + let response = await GBServer.globals.chatGPT.sendMessage(input, { + timeoutMs: CHATGPT_TIMEOUT + }); + + // Removes instructions, just code. + + response = response.replace(/Copy code/gim, '\n'); + let lines = response.split('\n') + let filteredLines = lines.filter(line => /\s*\d+\s*.*/.test(line)) + response = filteredLines.join('\n'); + + // Gets dialog name and file handling + + let dialogName = step.result.replace('.', ''); + const docx = urlJoin(`${min.botId}.gbdialog`, `${dialogName}.docx`); + const sys = new SystemKeywords(); + const document = await sys.internalCreateDocument(min, docx, response); + await service.addQA(min, dialogName, dialogName); + + let message = `Waiting for publishing...`; + await min.conversationalService.sendText(min, step, message); + + await step.replaceDialog('/publish', { confirm: true }); + + message = `Dialog is ready! Let's run:`; + await min.conversationalService.sendText(min, step, message); + + + let sec = new SecService(); + const member = step.context.activity.from; + const user = await sec.ensureUser( + min.instance.instanceId, + member.id, + member.name, + '', + 'web', + member.name, + null + ); + + await step.endDialog(); + + await GBVMService.callVM(dialogName.toLowerCase(), + min, step, user, this.deployer, false); + } + } + ]; + } } diff --git a/packages/kb.gbapp/services/KBService.ts b/packages/kb.gbapp/services/KBService.ts index 691731249..0219f40e4 100644 --- a/packages/kb.gbapp/services/KBService.ts +++ b/packages/kb.gbapp/services/KBService.ts @@ -529,7 +529,7 @@ export class KBService implements IGBKBService { const isBasic = answer.toLowerCase().startsWith('/basic'); if (/TALK\s*\".*\"/gi.test(answer) || isBasic) { const code = isBasic ? answer.substr(6) : answer; - const path = DialogKeywords.getGBAIPath(min.botId,`gbdialog`); + const path = DialogKeywords.getGBAIPath(min.botId, `gbdialog`); const scriptName = `tmp${GBAdminService.getRndReadableIdentifier()}.docx`; const localName = Path.join('work', path, `${scriptName}`); Fs.writeFileSync(localName, code, { encoding: null }); @@ -604,17 +604,11 @@ export class KBService implements IGBKBService { answer.content.endsWith('.xlsx') ) { const path = DialogKeywords.getGBAIPath(min.botId, `gbkb`); - const doc = urlJoin( - GBServer.globals.publicAddress, - 'kb', - path, - 'assets', - answer.content - ); + const doc = urlJoin(GBServer.globals.publicAddress, 'kb', path, 'assets', answer.content); const url = `http://view.officeapps.live.com/op/view.aspx?src=${doc}`; await this.playUrl(min, min.conversationalService, step, url, channel); } else if (answer.content.endsWith('.pdf')) { - const path = DialogKeywords.getGBAIPath(min.botId,`gbkb`); + const path = DialogKeywords.getGBAIPath(min.botId, `gbkb`); const url = urlJoin('kb', path, 'assets', answer.content); await this.playUrl(min, min.conversationalService, step, url, channel); } else if (answer.format === '.md') { @@ -627,6 +621,37 @@ export class KBService implements IGBKBService { } } + public async addQA(min, questionText, answerText) { + const pkg = await GuaribasPackage.findOne({ + where: { instanceId: min.instance.instanceId } + }); + + const question = { + from: 'autodialog', + to: '', + subject1: '', + subject2: '', + subject3: '', + subject4: '', + content: questionText.replace(/["]+/g, ''), + instanceId: min.instance.instanceId, + skipIndex: false, + packageId: pkg.packageId + }; + const answer = { + instanceId: min.instance.instanceId, + content: answerText, + format: '.txt', + media: null, + packageId: pkg.packageId, + prevId: 0 + }; + const a =await GuaribasAnswer.create(answer); + question['answerId'] = a.answerId; + const q = await GuaribasQuestion.create(question); + + } + public async importKbPackage( min: GBMinInstance, localPath: string, @@ -692,9 +717,12 @@ export class KBService implements IGBKBService { 'cache', `img-docx${GBAdminService.getRndReadableIdentifier()}.png` ); - const url = urlJoin(GBServer.globals.publicAddress, - DialogKeywords.getGBAIPath(instance.botId).replace(/\.[^/.]+$/, "") - , 'cache', Path.basename(localName)); + const url = urlJoin( + GBServer.globals.publicAddress, + DialogKeywords.getGBAIPath(instance.botId).replace(/\.[^/.]+$/, ''), + 'cache', + Path.basename(localName) + ); const buffer = await image.read(); Fs.writeFileSync(localName, buffer, { encoding: null }); return { src: url }; @@ -965,7 +993,7 @@ export class KBService implements IGBKBService { let category = categoryReg[1]; if (category === 'number') { - min['nerEngine'].addRegexEntity('number','pt', '/d+/gi'); + min['nerEngine'].addRegexEntity('number', 'pt', '/d+/gi'); } if (nameReg) { let name = nameReg[1]; @@ -996,13 +1024,8 @@ export class KBService implements IGBKBService { GBLog.info(`[GBDeployer] Start Bot Server Side Rendering... ${localPath}`); const html = await GBSSR.getHTML(min); - let path = DialogKeywords.getGBAIPath(min.botId,`gbui`); - path = Path.join( - process.env.PWD, - 'work', - path, - 'index.html' - ); + let path = DialogKeywords.getGBAIPath(min.botId, `gbui`); + path = Path.join(process.env.PWD, 'work', path, 'index.html'); GBLogEx.info(min, `[GBDeployer] Saving SSR HTML in ${path}.`); Fs.writeFileSync(path, html, 'utf8'); diff --git a/packages/security.gbapp/services/SecService.ts b/packages/security.gbapp/services/SecService.ts index 18e2b3ad3..510b9c580 100644 --- a/packages/security.gbapp/services/SecService.ts +++ b/packages/security.gbapp/services/SecService.ts @@ -279,7 +279,7 @@ export class SecService extends GBService { { obj = {}; } - obj['name'] = value; + obj[name] = value; user.params = JSON.stringify(obj); return await user.save(); } diff --git a/src/app.ts b/src/app.ts index 30bf8d4e0..6fd7e8a1e 100644 --- a/src/app.ts +++ b/src/app.ts @@ -52,11 +52,13 @@ import { GBDeployer } from '../packages/core.gbapp/services/GBDeployer.js'; import { GBImporter } from '../packages/core.gbapp/services/GBImporterService.js'; import { GBMinService } from '../packages/core.gbapp/services/GBMinService.js'; import auth from 'basic-auth'; +import { ChatGPTAPIBrowser } from 'chatgpt'; import child_process from 'child_process'; import * as winston from 'winston-logs-display'; import { RootData } from './RootData.js'; import { GBSSR } from '../packages/core.gbapp/services/GBSSR.js'; import { Mutex } from 'async-mutex'; +import { GBVMService } from '../packages/basic.gblib/services/GBVMService.js'; /** * General Bots open-core entry point. @@ -82,7 +84,7 @@ export class GBServer { GBLog.error(`Running TEST_SHELL ERROR: ${error}...`); } } - + const server = express(); GBServer.globals.server = server; @@ -215,6 +217,22 @@ export class GBServer { GBServer.globals.minService = minService; await minService.buildMin(instances); + if (process.env.OPENAI_EMAIL) { + if (!GBServer.globals.chatGPT) { + GBServer.globals.chatGPT = new ChatGPTAPIBrowser({ + email: process.env.OPENAI_EMAIL, + password: process.env.OPENAI_PASSWORD, + markdown: false + }); + await GBServer.globals.chatGPT.init(); + } + } + + // let s = new GBVMService(); + // await s.translateBASIC('work/gptA.vbs', GBServer.globals.minBoot ); + // await s.translateBASIC('work/gptB.vbs', GBServer.globals.minBoot ); + // await s.translateBASIC('work/gptC.vbs', GBServer.globals.minBoot ); + // process.exit(9); if (process.env.ENABLE_WEBLOG) { // If global log enabled, reorders transports adding web logging. @@ -257,8 +275,6 @@ export class GBServer { })(); }; - // - if (process.env.CERTIFICATE_PFX) { const options1 = { passphrase: process.env.CERTIFICATE_PASSPHRASE,