/** (id,元素的tag,父元素,创建时顺便添加的class:可以多个) 获取一个指定id的元素如果没用就在服元素创建这个元素 */ function getByID(id, tag, father) { let t = document.getElementById(id); if (!t) { t = document.createElement(tag); t.id = id; for (let i = 3; i < arguments.length; i++) { if (arguments[i]) { t.classList.add(arguments[i]); } } father.appendChild(t); } return t; } function getByClass(className, tag, father) { let t = father.getElementsByClassName(className)[0]; if (!t) { t = document.createElement(tag); t.classList.add(className); for (let i = 3; i < arguments.length; i++) { if (arguments[i]) { t.classList.add(arguments[i]); } } father.appendChild(t); } return t; } function test(test) { porserArguments(test.arguments); } var throttling = { "maxNumUserMessagesInConversation": 0, "numUserMessagesInConversation": 0 }; //解析type2的item function porserType2Item(item){ let chatDiv = document.getElementById('chat'); if(item.result){ let result = item.result; if(result.value=='Success'){ }else if (result.value == 'Throttled') { addError(result.message); addError('24消息请求数达到了限制!'); }else{ addError(result.message); addError('发生未知错误!'); } } if (item.throttling) { throttling = item.throttling; } if (item.messages) { let nextFather = getByID(item.requestId, 'div', chatDiv, 'bing'); porserMessages(item.messages, nextFather); } } /** * 解析arguments * 解析聊天消息,将消息添加到页面 * **/ function porserArguments(argumentss) { for (let i = 0; i < argumentss.length; i++) { porserType2Item(argumentss[i]); } } /* 解析messages */ function porserMessages(messages, father) { for (let i = 0; i < messages.length; i++) { let message = messages[i]; if(message.author=='user'){ continue;//不解析用户的消息 } //解析adaptiveCards 也就是聊天消息部分 下面类型的都是带有adaptiveCards的 if (!message.messageType && message.adaptiveCards) {//如果是正常的聊天 let adaptiveCardsFatherDIV = getByID(message.messageId, 'div', father, 'adaptiveCardsFatherDIV'); porserAdaptiveCards(message.adaptiveCards, adaptiveCardsFatherDIV); //解析sourceAttributions 也就是引用链接部分 if (message.sourceAttributions) { if (message.sourceAttributions.length > 0) { let sourceAttributionsDIV = getByID(message.messageId + 'sourceAttributions', 'div', father, 'sourceAttributions'); porserSourceAttributions(message.sourceAttributions, sourceAttributionsDIV); } } //解析suggestedResponses 建议发送的消息,聊天建议 if (message.suggestedResponses) { porserSuggestedResponses(message.suggestedResponses); } } else if (message.messageType == 'InternalSearchQuery') { //如果是收索消息 let div = getByID(message.messageId, 'div', father, 'InternalSearchQuery'); porserLineTextBlocks(message.text, div); } else if (message.messageType == 'InternalLoaderMessage') { //如果是加载消息 let div = getByID(message.messageId, 'div', father, 'InternalLoaderMessage'); porserLineTextBlocks(message.text, div); } else if (message.messageType == 'GenerateContentQuery') {//如果是生成内容查询 let div = getByID(message.messageId, 'div', father, 'GenerateContentQuery'); generateContentQuery(message, div); }else if (message.messageType == 'RenderCardRequest'){//渲染卡片请求,目前不知道有什么用 renderCardRequest(message, father); }else if(message.messageType == 'Disengaged'){ let div = getByID(message.messageId, 'div', chat, 'error'); div.innerHTML = ` ${message.hiddenText}
聊天中断!试试开始新主题? `; }else if(message.contentOrigin == 'TurnLimiter'){ addError(message.text); addError('聊天被限制了,试试开始新主题?'); } else { console.log('发现一个另类message', JSON.stringify(message)); } } } /* 解析渲染卡片请求,暂时不知道如何解析这个请求,就先判断里面有没有内容吧!没有就不显示。 */ function renderCardRequest(message,father){ if(father[message.messageId+'renderCardRequest']){//防止解析多次 return; } father[message.messageId+'renderCardRequest'] = true; let url = 'https://www.bing.com/search?' let theUrls = new URLSearchParams(); theUrls.append("showselans",1); theUrls.append("q",message.text); theUrls.append("iframeid",message.messageId); let src = url+theUrls.toString(); fetch(src).then(async (ret)=>{ let html = await ret.text(); // b_poleContent pc设备 || b_ans b_imgans 移动设备 if(html.indexOf('class="b_poleContent"')>=0 || html.indexOf('class="b_ans')>=0){ let div = getByID(message.messageId, 'div', father, 'RenderCardRequest'); div.innerHTML = ``; } }); } /* 解析generateContentQuery生成内容查询,目前是只有图片 */ function generateContentQuery(message, father) { if(message.contentType=="IMAGE"){ if(father.runed){//防止生成多次 return; } father.runed = true; generateContentQueryImg(message, father); }else{ console.log('发现一个另类generateContentQuery', JSON.stringify(message)); } } /** * 解析图片生成目前是只有图片 */ function generateContentQueryImg(message, father){ getMagicUrl().then(async magicUrl => { if (!magicUrl) { addError("魔法链接不正确!无法加载图片"); return; } if (!expUrl.test(magicUrl)) { addError("魔法链接不正确!无法加载图片") return; } let theUrls = new URLSearchParams(); theUrls.append('re', '1'); theUrls.append('showselective', '1'); theUrls.append('sude', '1'); theUrls.append('kseed', '7500'); theUrls.append('SFX', '2'); theUrls.append('q', message.text); theUrls.append('iframeid', message.requestId); let theUrl = URLTrue(magicUrl,"images/create?") + theUrls.toString(); try{ father.innerHTML = `正在生成${message.text}的图片.`; let html = (await (await fetch(theUrl)).text()); //如果有错误就输出错误 let urr = new RegExp('class="gil_err_mt">([^<>]*)').exec(html); if(urr && urr[1]){ father.innerHTML = `

${urr[1]}

` urr = new RegExp('class="gil_err_sbt">(([^<>]*<(a|div)[^<>]*>[^<>]*[^<>]*)*)').exec(html); if(urr && urr[1]){ father.innerHTML = father.innerHTML+`

${urr[1]}

`; } return; } //如果没错误就匹配链接获取图片 urr = new RegExp('"/(images/create/async/results/(\\S*))"').exec(html); if(!urr || !urr[1]){ console.log(html); addError("请求图片返回不正确的页面,无法加载图片。"); return; } let ur = urr[1]; ur = ur.replaceAll('&','&'); let imgPageHtmlUrl = URLTrue(magicUrl,ur); let count = 0; let run = async ()=>{ father.innerHTML = `正在生成${message.text}的图片.${count}`; if(count>20){ father.innerHTML = "请求图片超时!"; return; } count++; let imgPageHtml; try{ imgPageHtml = (await (await fetch(imgPageHtmlUrl)).text()); }catch(e){ console.error(e); } if(!imgPageHtml){ setTimeout(run,3000); return; } father.innerHTML = ''; let theUrls = new URLSearchParams(); theUrls.append('createmessage',message.text); let a = document.createElement("a"); father.appendChild(a); //用正则找全部图片 let allSrc = imgPageHtml.matchAll(/]*src="([^"]*)"[^<>]*>/g); let src = undefined; let ok = false; while(!(src=allSrc.next()).done){ ok =true; theUrls.append('imgs',src.value[1].split('?')[0]); let img = document.createElement("img"); img.src = src.value[1]; a.appendChild(img); } if(ok){ a.target = '_blank'; a.href = '../GeneratePicture/img.html?'+theUrls.toString(); }else{ father.innerHTML = "服务器未正常返回图片!"; } } setTimeout(run,3000); }catch(e){ console.error(e); addError("请求图片失败:"+e); } }); } /* 解析adaptiveCards 聊天消息部分 */ function porserAdaptiveCards(adaptiveCards, father) { for (let i = 0; i < adaptiveCards.length; i++) { let adaptiveCard = adaptiveCards[i]; if (adaptiveCard.type == 'AdaptiveCard') { porserbody(adaptiveCard.body, father); } else { console.log('发现一个不是AdaptiveCard的adaptiveCard', JSON.stringify(adaptiveCard)); } } } /** 解析body adaptiveCards[].body这个部分 */ function porserbody(bodys, father) { for (let i = 0; i < bodys.length; i++) { let body = bodys[i]; if (body.type == 'TextBlock') { porserTextBlock(body, father); }else { console.log('发现一个不是TextBlock的body', JSON.stringify(body)); } } } /** 补全代码块,如果文本中有~~~开头却没有~~~结束则在最后补一个~~~,防止内容生成时闪烁 */ function completeCodeBlock(makerdown){ let to = function(regA,regB,add,makerdown){ let falst = true; let arrs = makerdown.split('\n'); for(let i=0;i<=arrs.length;i++){ if(falst){ if(regA.test(arrs[i])){ falst = false; } }else{ if(regB.test(arrs[i])){ falst = true; } } } if(!falst){ makerdown = makerdown+add; } return makerdown; } let out = to( new RegExp('^~~~.*$'), new RegExp('^~~~( *)$'), '\n~~~', to( new RegExp('^```.*$'), new RegExp('^```( *)$'), '\n```', makerdown ) ); // console.log(out); return out; } renderMathInElementOptions ={ delimiters: [ {left: "$$", right: "$$", display: true}, {left: '$', right: '$', display: false}, {left: "\\(", right: "\\)", display: false}, {left: "\\begin{equation}", right: "\\end{equation}", display: true}, {left: "\\begin{align}", right: "\\end{align}", display: true}, {left: "\\begin{alignat}", right: "\\end{alignat}", display: true}, {left: "\\begin{gather}", right: "\\end{gather}", display: true}, {left: "\\begin{CD}", right: "\\end{CD}", display: true}, {left: "\\[", right: "\\]", display: true} ], throwOnError: false } /* 解析TextBlock body.type==TextBlock */ function porserTextBlock(body, father) { if (!body.size) { let div = getByClass('textBlock', 'div', father, 'markdown-body'); div.innerHTML = marked.marked(completeCodeBlock(body.text)); renderMathInElement(div,renderMathInElementOptions); let aaas = div.getElementsByTagName('a'); //将超链接在新页面打开 for(let i=0;i${inline}

`; } /*** 解析sourceAttributions 聊天消息引用链接部分 */ function porserSourceAttributions(sourceAttributions, father) { let html = ''; for (let i = 0; i < sourceAttributions.length; i++) { let sourceAttribution = sourceAttributions[i]; html = html + `${sourceAttribution.providerDisplayName}`; } father.innerHTML = html; } /*** 解析suggestedResponses 建议发送的消息,聊天建议 */ function porserSuggestedResponses(suggestedResponses) { var searchSuggestions = document.getElementById('SearchSuggestions'); searchSuggestions.innerHTML = ''; for (let i = 0; i < suggestedResponses.length; i++) { let a = document.createElement('a'); a.innerHTML = suggestedResponses[i].text; searchSuggestions.appendChild(a); } searchSuggestionsAddOnclick(); }