new(all): Auto import for logo, colors and website content.
This commit is contained in:
		
							parent
							
								
									7fe50d95c4
								
							
						
					
					
						commit
						e91c3a4e06
					
				
					 7 changed files with 176 additions and 65 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -28,3 +28,5 @@ yarn-error.log
 | 
				
			||||||
package-lock.json
 | 
					package-lock.json
 | 
				
			||||||
yarn-lock.json
 | 
					yarn-lock.json
 | 
				
			||||||
packages/saas.gbapp.zip
 | 
					packages/saas.gbapp.zip
 | 
				
			||||||
 | 
					logo.svg
 | 
				
			||||||
 | 
					screenshot.png
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,9 +59,11 @@ import { GBHubSpotPackage } from '../../hubspot.gblib/index.js';
 | 
				
			||||||
import open from 'open';
 | 
					import open from 'open';
 | 
				
			||||||
import ngrok from 'ngrok';
 | 
					import ngrok from 'ngrok';
 | 
				
			||||||
import Path from 'path';
 | 
					import Path from 'path';
 | 
				
			||||||
import { file } from 'googleapis/build/src/apis/file/index.js';
 | 
					 | 
				
			||||||
import { GBUtil } from '../../../src/util.js';
 | 
					import { GBUtil } from '../../../src/util.js';
 | 
				
			||||||
import { GBLogEx } from './GBLogEx.js';
 | 
					import { GBLogEx } from './GBLogEx.js';
 | 
				
			||||||
 | 
					import { GBDeployer } from './GBDeployer.js';
 | 
				
			||||||
 | 
					import { SystemKeywords } from '../../basic.gblib/services/SystemKeywords.js';
 | 
				
			||||||
 | 
					import { DialogKeywords } from '../../basic.gblib/services/DialogKeywords.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * GBCoreService contains main logic for handling storage services related
 | 
					 * GBCoreService contains main logic for handling storage services related
 | 
				
			||||||
| 
						 | 
					@ -665,6 +667,50 @@ ENDPOINT_UPDATE=true
 | 
				
			||||||
    await installationDeployer.openStorageFirewall(group, serverName);
 | 
					    await installationDeployer.openStorageFirewall(group, serverName);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public async setConfig(min, name: string, value: any): Promise<any> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Handles calls for BASIC persistence on sheet files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GBLog.info( `Defining Config.xlsx variable ${name}= '${value}'...`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let { baseUrl, client } = await GBDeployer.internalGetDriveClient(min);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const maxLines = 512;
 | 
				
			||||||
 | 
					    const file = "Config.xlsx";
 | 
				
			||||||
 | 
					      const path = DialogKeywords.getGBAIPath(min.botId, `gbot`);;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let document = await (new SystemKeywords()).internalGetDocument(client, baseUrl, path, file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Creates workbook session that will be discarded.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let sheets = await client
 | 
				
			||||||
 | 
					      .api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets`)
 | 
				
			||||||
 | 
					      .get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let results = await client
 | 
				
			||||||
 | 
					      .api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='A1:A${maxLines}')`)
 | 
				
			||||||
 | 
					      .get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const rows = results.text;
 | 
				
			||||||
 | 
					    let address = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Fills the row variable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (let i = 1; i <= rows.length; i++) {
 | 
				
			||||||
 | 
					      let result = rows[i - 1][0];
 | 
				
			||||||
 | 
					      if (result && result.toLowerCase() === name.toLowerCase()) {
 | 
				
			||||||
 | 
					        address = `B${i}:B${i}`;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let body = { values: [[]] };
 | 
				
			||||||
 | 
					    body.values[0][0] = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await client
 | 
				
			||||||
 | 
					      .api(`${baseUrl}/drive/items/${document.id}/workbook/worksheets('${sheets.value[0].name}')/range(address='${address}')`)
 | 
				
			||||||
 | 
					      .patch(body);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -687,7 +687,13 @@ export class GBMinService {
 | 
				
			||||||
          paramLogoImageAlt: this.core.getParam(instance, 'Logo Image Alt', null),
 | 
					          paramLogoImageAlt: this.core.getParam(instance, 'Logo Image Alt', null),
 | 
				
			||||||
          paramLogoImageWidth: this.core.getParam(instance, 'Logo Image Width', null),
 | 
					          paramLogoImageWidth: this.core.getParam(instance, 'Logo Image Width', null),
 | 
				
			||||||
          paramLogoImageHeight: this.core.getParam(instance, 'Logo Image Height', null),
 | 
					          paramLogoImageHeight: this.core.getParam(instance, 'Logo Image Height', null),
 | 
				
			||||||
          paramLogoImageType: this.core.getParam(instance, 'Logo Image Type', null)
 | 
					          paramLogoImageType: this.core.getParam(instance, 'Logo Image Type', null),
 | 
				
			||||||
 | 
					          logo: this.core.getParam(instance, 'Logo', null),
 | 
				
			||||||
 | 
					          color1: this.core.getParam(instance, 'Color1', null),
 | 
				
			||||||
 | 
					          color2: this.core.getParam(instance, 'Color2', null),
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ import GBBulletPlayer from './players/GBBulletPlayer.js';
 | 
				
			||||||
import SidebarMenu from './components/SidebarMenu.js';
 | 
					import SidebarMenu from './components/SidebarMenu.js';
 | 
				
			||||||
import SEO from './components/SEO.js';
 | 
					import SEO from './components/SEO.js';
 | 
				
			||||||
import GBCss from './components/GBCss.js';
 | 
					import GBCss from './components/GBCss.js';
 | 
				
			||||||
import { DirectLine} from 'botframework-directlinejs';
 | 
					import { DirectLine } from 'botframework-directlinejs';
 | 
				
			||||||
import { ConnectionStatus } from 'botframework-directlinejs';
 | 
					import { ConnectionStatus } from 'botframework-directlinejs';
 | 
				
			||||||
import ReactWebChat from 'botframework-webchat';
 | 
					import ReactWebChat from 'botframework-webchat';
 | 
				
			||||||
import { UserAgentApplication } from 'msal';
 | 
					import { UserAgentApplication } from 'msal';
 | 
				
			||||||
| 
						 | 
					@ -257,16 +257,16 @@ class GBUIApp extends React.Component {
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        case 'multiurl':
 | 
					        case 'multiurl':
 | 
				
			||||||
            playerComponent = (
 | 
					          playerComponent = (
 | 
				
			||||||
              <GBMultiUrlPlayer
 | 
					            <GBMultiUrlPlayer
 | 
				
			||||||
                app={this}
 | 
					              app={this}
 | 
				
			||||||
                ref={player => {
 | 
					              ref={player => {
 | 
				
			||||||
                  this.player = player;
 | 
					                this.player = player;
 | 
				
			||||||
                }}
 | 
					              }}
 | 
				
			||||||
              />
 | 
					            />
 | 
				
			||||||
            );
 | 
					          );
 | 
				
			||||||
            break;
 | 
					          break;
 | 
				
			||||||
          case 'image':
 | 
					        case 'image':
 | 
				
			||||||
          playerComponent = (
 | 
					          playerComponent = (
 | 
				
			||||||
            <GBImagePlayer
 | 
					            <GBImagePlayer
 | 
				
			||||||
              app={this}
 | 
					              app={this}
 | 
				
			||||||
| 
						 | 
					@ -305,18 +305,17 @@ class GBUIApp extends React.Component {
 | 
				
			||||||
    let chat = <div />;
 | 
					    let chat = <div />;
 | 
				
			||||||
    let gbCss = <div />;
 | 
					    let gbCss = <div />;
 | 
				
			||||||
    let seo = <div />;
 | 
					    let seo = <div />;
 | 
				
			||||||
 | 
					    let sideBar = <div />;
 | 
				
			||||||
    let sideBar = (
 | 
					 | 
				
			||||||
      <div className="sidebar">
 | 
					 | 
				
			||||||
        <SidebarMenu chat={this.chat} instance={this.state.instanceClient} />
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (this.state.line) {
 | 
					    if (this.state.line) {
 | 
				
			||||||
      if (this.state.instanceClient) {
 | 
					      if (this.state.instanceClient) {
 | 
				
			||||||
 | 
					        let color1 = this.state.instanceClient.color1;
 | 
				
			||||||
        gbCss = <GBCss instance={this.state.instanceClient} />;
 | 
					        gbCss = <GBCss instance={this.state.instanceClient} />;
 | 
				
			||||||
        seo = <SEO instance={this.state.instanceClient} />;
 | 
					        seo = <SEO instance={this.state.instanceClient} />;
 | 
				
			||||||
        const token = this.state.instanceClient.speechToken;
 | 
					        const token = this.state.instanceClient.speechToken;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        document.body.style.setProperty('background-color', this.state.instanceClient.color2, 'important');
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        chat = (
 | 
					        chat = (
 | 
				
			||||||
          <ReactWebChat
 | 
					          <ReactWebChat
 | 
				
			||||||
            ref={chat => {
 | 
					            ref={chat => {
 | 
				
			||||||
| 
						 | 
					@ -329,15 +328,25 @@ class GBUIApp extends React.Component {
 | 
				
			||||||
            })}
 | 
					            })}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sideBar = (
 | 
				
			||||||
 | 
					          <div
 | 
				
			||||||
 | 
					            className="sidebar"
 | 
				
			||||||
 | 
					            ref={node => {
 | 
				
			||||||
 | 
					              if (node) {
 | 
				
			||||||
 | 
					                node.style.setProperty('background-color', this.state.instanceClient.color1, 'important');
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <SidebarMenu chat={this.chat} instance={this.state.instanceClient} />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!this.state.instanceClient) {
 | 
					 | 
				
			||||||
      sideBar = '';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <StaticContent>
 | 
					      <StaticContent>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {seo}
 | 
					        {seo}
 | 
				
			||||||
        <div>
 | 
					        <div>
 | 
				
			||||||
          {gbCss}
 | 
					          {gbCss}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ class SideBarMenu extends React.Component {
 | 
				
			||||||
        <div className="tittleSideBarMenu">
 | 
					        <div className="tittleSideBarMenu">
 | 
				
			||||||
          <img
 | 
					          <img
 | 
				
			||||||
            className="pragmatismoLogo"
 | 
					            className="pragmatismoLogo"
 | 
				
			||||||
            src={"/themes/" + this.props.instance.theme + "/images/logo.png"}
 | 
					            src={this.props.instance.botId + "/cache/" + this.props.instance.logo}
 | 
				
			||||||
            alt="General Bots Logo" />
 | 
					            alt="General Bots Logo" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -254,29 +254,28 @@ export class ChatServices {
 | 
				
			||||||
  public static async answerByGPT(
 | 
					  public static async answerByGPT(
 | 
				
			||||||
    min: GBMinInstance,
 | 
					    min: GBMinInstance,
 | 
				
			||||||
    user,
 | 
					    user,
 | 
				
			||||||
    pid,
 | 
					    question: string, mode=null
 | 
				
			||||||
    question: string,
 | 
					 | 
				
			||||||
    searchScore: number,
 | 
					 | 
				
			||||||
    subjects: GuaribasSubject[]
 | 
					 | 
				
			||||||
  ) {
 | 
					  ) {
 | 
				
			||||||
    if (!process.env.OPENAI_API_KEY) {
 | 
					    if (!process.env.OPENAI_API_KEY) {
 | 
				
			||||||
      return { answer: undefined, questionId: 0 };
 | 
					      return { answer: undefined, questionId: 0 };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const LLMMode = min.core.getParam(min.instance, 'Answer Mode', 'direct');
 | 
					    const LLMMode = mode??min.core.getParam(min.instance, 'Answer Mode', 'direct');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const docsContext = min['vectorStore'];
 | 
					    const docsContext = min['vectorStore'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!this.memoryMap[user.userSystemId]) {
 | 
					    const memory = new BufferWindowMemory({
 | 
				
			||||||
      this.memoryMap[user.userSystemId] = new BufferWindowMemory({
 | 
					      returnMessages: true,
 | 
				
			||||||
        returnMessages: true,
 | 
					      memoryKey: 'chat_history',
 | 
				
			||||||
        memoryKey: 'chat_history',
 | 
					      inputKey: 'input',
 | 
				
			||||||
        inputKey: 'input',
 | 
					      k: 2
 | 
				
			||||||
        k: 2
 | 
					    });
 | 
				
			||||||
      });
 | 
					
 | 
				
			||||||
 | 
					    if (user && !this.memoryMap[user.userSystemId]) {
 | 
				
			||||||
 | 
					      this.memoryMap[user.userSystemId] = memory;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const memory = this.memoryMap[user.userSystemId];
 | 
					  
 | 
				
			||||||
    const systemPrompt = this.userSystemPrompt[user.userSystemId];
 | 
					    const systemPrompt = user?this.userSystemPrompt[user.userSystemId]:'';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const model = new ChatOpenAI({
 | 
					    const model = new ChatOpenAI({
 | 
				
			||||||
      openAIApiKey: process.env.OPENAI_API_KEY,
 | 
					      openAIApiKey: process.env.OPENAI_API_KEY,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,6 @@ import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
 | 
				
			||||||
import { Document } from 'langchain/document';
 | 
					import { Document } from 'langchain/document';
 | 
				
			||||||
import getColors from 'get-image-colors';
 | 
					import getColors from 'get-image-colors';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  GBDialogStep,
 | 
					  GBDialogStep,
 | 
				
			||||||
  GBLog,
 | 
					  GBLog,
 | 
				
			||||||
| 
						 | 
					@ -377,7 +376,7 @@ export class KBService implements IGBKBService {
 | 
				
			||||||
        returnedScore: ${returnedScore} < required (searchScore): ${searchScore}`
 | 
					        returnedScore: ${returnedScore} < required (searchScore): ${searchScore}`
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return await ChatServices.answerByGPT(min, user, pid, query, searchScore, subjects);
 | 
					    return await ChatServices.answerByGPT(min, user, query);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public async getSubjectItems(instanceId: number, parentId: number): Promise<GuaribasSubject[]> {
 | 
					  public async getSubjectItems(instanceId: number, parentId: number): Promise<GuaribasSubject[]> {
 | 
				
			||||||
| 
						 | 
					@ -853,13 +852,13 @@ export class KBService implements IGBKBService {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async saveHtmlPage(min, url: string, page: Page): Promise<string | null> {
 | 
					  async saveHtmlPage(min, url: string, page: Page): Promise<string | null> {
 | 
				
			||||||
 | 
					    page.setCacheEnabled(false);
 | 
				
			||||||
    const response = await page.goto(url);
 | 
					    const response = await page.goto(url);
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (response.headers && response.status() === 200) {
 | 
					    if (response.headers && (response.status() === 200 || response.status() === 304)) {
 | 
				
			||||||
      const contentType = response.headers()['content-type'];
 | 
					      const contentType = response.headers()['content-type'];
 | 
				
			||||||
      if (contentType && contentType.includes('text/html')) {
 | 
					      if (contentType && contentType.includes('text/html')) {
 | 
				
			||||||
        const buffer = await response.buffer();
 | 
					        const buffer = await page.content();
 | 
				
			||||||
        const urlObj = new URL(url);
 | 
					        const urlObj = new URL(url);
 | 
				
			||||||
        const urlPath = urlObj.pathname.endsWith('/') ? urlObj.pathname.slice(0, -1) : urlObj.pathname; // Remove trailing slash if present
 | 
					        const urlPath = urlObj.pathname.endsWith('/') ? urlObj.pathname.slice(0, -1) : urlObj.pathname; // Remove trailing slash if present
 | 
				
			||||||
        let filename = urlPath.split('/').pop() || 'index'; // Get the filename from the URL path or set it to 'index.html' as default
 | 
					        let filename = urlPath.split('/').pop() || 'index'; // Get the filename from the URL path or set it to 'index.html' as default
 | 
				
			||||||
| 
						 | 
					@ -882,12 +881,12 @@ export class KBService implements IGBKBService {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      if (
 | 
					      if (
 | 
				
			||||||
        depth > maxDepth ||
 | 
					        depth > maxDepth ||
 | 
				
			||||||
        (visited.has(url) ||
 | 
					        visited.has(url) ||
 | 
				
			||||||
          url.endsWith('.jpg') ||
 | 
					        url.endsWith('.jpg') ||
 | 
				
			||||||
          url.endsWith('.pdf') ||
 | 
					        url.endsWith('.pdf') ||
 | 
				
			||||||
          url.endsWith('.jpg') ||
 | 
					        url.endsWith('.jpg') ||
 | 
				
			||||||
          url.endsWith('.png') ||
 | 
					        url.endsWith('.png') ||
 | 
				
			||||||
          url.endsWith('.mp4'))
 | 
					        url.endsWith('.mp4')
 | 
				
			||||||
      ) {
 | 
					      ) {
 | 
				
			||||||
        return [];
 | 
					        return [];
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -904,6 +903,7 @@ export class KBService implements IGBKBService {
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      const currentDomain = new URL(page.url()).hostname;
 | 
					      const currentDomain = new URL(page.url()).hostname;
 | 
				
			||||||
      let links = await page.evaluate(currentDomain => {
 | 
					      let links = await page.evaluate(currentDomain => {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        const anchors = Array.from(document.querySelectorAll('a')).filter(p => {
 | 
					        const anchors = Array.from(document.querySelectorAll('a')).filter(p => {
 | 
				
			||||||
          try {
 | 
					          try {
 | 
				
			||||||
            return currentDomain == new URL(p.href).hostname;
 | 
					            return currentDomain == new URL(p.href).hostname;
 | 
				
			||||||
| 
						 | 
					@ -938,7 +938,7 @@ export class KBService implements IGBKBService {
 | 
				
			||||||
      const childLinks = [];
 | 
					      const childLinks = [];
 | 
				
			||||||
      for (const link of filteredLinks) {
 | 
					      for (const link of filteredLinks) {
 | 
				
			||||||
        const links = await this.crawl(min, link, visited, depth + 1, maxDepth, page);
 | 
					        const links = await this.crawl(min, link, visited, depth + 1, maxDepth, page);
 | 
				
			||||||
        if (links){
 | 
					        if (links) {
 | 
				
			||||||
          childLinks.push(...links);
 | 
					          childLinks.push(...links);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -946,9 +946,41 @@ export class KBService implements IGBKBService {
 | 
				
			||||||
      return [filename, ...childLinks]; // Include the filename of the cached file
 | 
					      return [filename, ...childLinks]; // Include the filename of the cached file
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
      await GBLogEx.info(min, error);
 | 
					      await GBLogEx.info(min, error);
 | 
				
			||||||
 | 
					      return []; // Include the filename of the cached file
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async getLogoByPage(page) {
 | 
				
			||||||
 | 
					    const checkPossibilities = async (page, possibilities) => {
 | 
				
			||||||
 | 
					      for (const possibility of possibilities) {
 | 
				
			||||||
 | 
					        const { tag, attributes } = possibility;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (const attribute of attributes) {
 | 
				
			||||||
 | 
					          const selector = `${tag}[${attribute}*="logo"]`;
 | 
				
			||||||
 | 
					          const elements = await page.$$(selector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          for (const element of elements) {
 | 
				
			||||||
 | 
					            const src = await page.evaluate(el => el.getAttribute('src'), element);
 | 
				
			||||||
 | 
					            if (src) {
 | 
				
			||||||
 | 
					              return src;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return null;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Array of possibilities to check for the logo
 | 
				
			||||||
 | 
					    const possibilities = [
 | 
				
			||||||
 | 
					      { tag: 'img', attributes: ['src', 'alt', 'class'] }, // Check for img elements with specific attributes
 | 
				
			||||||
 | 
					      { tag: 'svg', attributes: ['class', 'aria-label'] } // Check for svg elements with specific attributes
 | 
				
			||||||
 | 
					      // Add more possibilities as needed
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return await checkPossibilities(page, possibilities);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Import all .docx files in reading comprehension folder.
 | 
					   * Import all .docx files in reading comprehension folder.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
| 
						 | 
					@ -960,32 +992,50 @@ export class KBService implements IGBKBService {
 | 
				
			||||||
  ): Promise<any> {
 | 
					  ): Promise<any> {
 | 
				
			||||||
    let files = [];
 | 
					    let files = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Fs.rmSync(min['vectorStorePath'], { recursive: true, force: true });
 | 
				
			||||||
 | 
					    let path = DialogKeywords.getGBAIPath(min.botId, `gbot`);
 | 
				
			||||||
 | 
					    const directoryPath = Path.join(process.env.PWD, 'work', path, 'Website');
 | 
				
			||||||
 | 
					    Fs.rmSync(directoryPath, { recursive: true, force: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const website = min.core.getParam<string>(min.instance, 'Website', null);
 | 
					    const website = min.core.getParam<string>(min.instance, 'Website', null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (website) {
 | 
					    if (website) {
 | 
				
			||||||
      const browser = await puppeteer.launch({ headless: false });
 | 
					      const browser = await puppeteer.launch({ headless: false });
 | 
				
			||||||
      const page = await browser.newPage();
 | 
					      const page = await browser.newPage();
 | 
				
			||||||
      const response = await page.goto(website);
 | 
					      await page.setRequestInterception(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await page.screenshot({ path: 'screenshot.png' });
 | 
					      page.on('request', req => {
 | 
				
			||||||
 | 
					        if (req.resourceType() === 'image' || req.resourceType() === 'stylesheet') {
 | 
				
			||||||
 | 
					          req.abort();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          req.continue();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      await page.goto(website);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const logo = await this.getLogoByPage(page);
 | 
				
			||||||
 | 
					      let path = DialogKeywords.getGBAIPath(min.botId);
 | 
				
			||||||
 | 
					      const logoPath = Path.join(process.env.PWD, 'work', path, 'cache');
 | 
				
			||||||
 | 
					      const baseUrl = page.url().split('/').slice(0, 3).join('/');
 | 
				
			||||||
 | 
					      const logoBinary = await page.goto(urlJoin(baseUrl, logo));
 | 
				
			||||||
 | 
					      const buffer = await logoBinary.buffer();
 | 
				
			||||||
 | 
					      const logoFilename = Path.basename(logo);
 | 
				
			||||||
 | 
					      Fs.writeFileSync(Path.join(logoPath, logoFilename), buffer);
 | 
				
			||||||
 | 
					      await min.core['setConfig'](min, 'Logo', logoFilename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Extract dominant colors from the screenshot
 | 
					      // Extract dominant colors from the screenshot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      await page.screenshot({ path: 'screenshot.png' });
 | 
				
			||||||
      const colors = await getColors('screenshot.png');
 | 
					      const colors = await getColors('screenshot.png');
 | 
				
			||||||
 | 
					      await min.core['setConfig'](min, 'Color1', colors[0].hex());
 | 
				
			||||||
 | 
					      await min.core['setConfig'](min, 'Color2', colors[1].hex());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Assuming you want the two most dominant colors
 | 
					      const maxDepth = 2; // Maximum depth of recursion
 | 
				
			||||||
      const mainColor1 = colors[0].hex();
 | 
					 | 
				
			||||||
      const mainColor2 = colors[1].hex();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      console.log('Main Color 1:', mainColor1);
 | 
					 | 
				
			||||||
      console.log('Main Color 2:', mainColor2);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      const maxDepth = 1; // Maximum depth of recursion
 | 
					 | 
				
			||||||
      const visited = new Set<string>();
 | 
					      const visited = new Set<string>();
 | 
				
			||||||
      files = files.concat(await this.crawl(min, website, visited, 0, maxDepth, page));
 | 
					      files = files.concat(await this.crawl(min, website, visited, 0, maxDepth, page));
 | 
				
			||||||
      
 | 
					
 | 
				
			||||||
      await browser.close();
 | 
					      await browser.close();
 | 
				
			||||||
      
 | 
					
 | 
				
			||||||
      files.shift();
 | 
					      files.shift();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await CollectionUtil.asyncForEach(files, async file => {
 | 
					      await CollectionUtil.asyncForEach(files, async file => {
 | 
				
			||||||
| 
						 | 
					@ -997,7 +1047,6 @@ export class KBService implements IGBKBService {
 | 
				
			||||||
        await vectorStore.addDocuments(flattenedDocuments);
 | 
					        await vectorStore.addDocuments(flattenedDocuments);
 | 
				
			||||||
        await vectorStore.save(min['vectorStorePath']);
 | 
					        await vectorStore.save(min['vectorStorePath']);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    files = await walkPromise(urlJoin(localPath, 'docs'));
 | 
					    files = await walkPromise(urlJoin(localPath, 'docs'));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue