code

/*
* Author : James Chou ( wiiai.com )  簡潔但穩定有力的版本 預覽圖片網址 顯示圖片網址 預覽影片網址 顯示影片網址  還有 flex 和 button
*/
var myWant;
var mySearch;
var uMessage;
var userID;
var userName;
var userPicUrl;
var now;
var xyz;
var oriMessagre;
var userWords;
var isChatGPT
var isToline
var vp;
var aiOutput;
var imageThumbnailUrl = ”;
var imageUrl = ”;
var videoThumbnailUrl = ”;
var videoUrl = ”;
var flex1={
  “type”: “bubble”,
  “hero”: {
    “type”: “image”,
    “url”: “https://developers-resource.landpress.line.me/fx/img/01_1_cafe.png”,
    “size”: “full”,
    “aspectRatio”: “20:13”,
    “aspectMode”: “cover”,
    “action”: {
      “type”: “uri”,
      “uri”: “https://line.me/”
    }
  },
  “body”: {
    “type”: “box”,
    “layout”: “vertical”,
    “contents”: [
      {
        “type”: “text”,
        “text”: “最新課程”,
        “weight”: “bold”,
        “size”: “xl”
      },
      {
        “type”: “box”,
        “layout”: “baseline”,
        “margin”: “md”,
        “contents”: [
          {
            “type”: “icon”,
            “size”: “sm”,
            “url”: “https://developers-resource.landpress.line.me/fx/img/review_gold_star_28.png”
          },
          {
            “type”: “icon”,
            “size”: “sm”,
            “url”: “https://developers-resource.landpress.line.me/fx/img/review_gold_star_28.png”
          },
          {
            “type”: “icon”,
            “size”: “sm”,
            “url”: “https://developers-resource.landpress.line.me/fx/img/review_gold_star_28.png”
          },
          {
            “type”: “icon”,
            “size”: “sm”,
            “url”: “https://developers-resource.landpress.line.me/fx/img/review_gold_star_28.png”
          },
          {
            “type”: “icon”,
            “size”: “sm”,
            “url”: “https://developers-resource.landpress.line.me/fx/img/review_gold_star_28.png”
          },
          {
            “type”: “text”,
            “text”: “5.0”,
            “size”: “sm”,
            “color”: “#999999”,
            “margin”: “md”,
            “flex”: 0
          }
        ]
      },
      {
        “type”: “box”,
        “layout”: “vertical”,
        “margin”: “lg”,
        “spacing”: “sm”,
        “contents”: [
          {
            “type”: “box”,
            “layout”: “baseline”,
            “spacing”: “sm”,
            “contents”: [
              {
                “type”: “text”,
                “text”: “課程種類”,
                “color”: “#aaaaaa”,
                “size”: “sm”,
                “flex”: 1
              },
              {
                “type”: “text”,
                “text”: “LineBot相關”,
                “wrap”: true,
                “color”: “#666666”,
                “size”: “sm”,
                “flex”: 5
              }
            ]
          },
          {
            “type”: “box”,
            “layout”: “baseline”,
            “spacing”: “sm”,
            “contents”: [
              {
                “type”: “text”,
                “text”: “主辦”,
                “color”: “#aaaaaa”,
                “size”: “sm”,
                “flex”: 1
              },
              {
                “type”: “text”,
                “text”: “愛迪生開發事業有限公司”,
                “wrap”: true,
                “color”: “#666666”,
                “size”: “sm”,
                “flex”: 5
              }
            ]
          }
        ]
      }
    ]
  },
  “footer”: {
    “type”: “box”,
    “layout”: “vertical”,
    “spacing”: “sm”,
    “contents”: [
      {
        “type”: “button”,
        “style”: “link”,
        “height”: “sm”,
        “action”: {
          “type”: “message”,
          “label”: “課程簡介”,
          “text”: “課程簡介”
        }
      },
      {
        “type”: “button”,
        “style”: “link”,
        “height”: “sm”,
        “action”: {
          “type”: “message”,
          “label”: “課程內容”,
          “text”: “課程內容”
        }
      },
      {
        “type”: “button”,
        “style”: “link”,
        “height”: “sm”,
        “action”: {
          “type”: “message”,
          “label”: “上課時間地點”,
          “text”: “上課時間地點”
        }
      },
      {
        “type”: “button”,
        “style”: “link”,
        “height”: “sm”,
        “action”: {
          “type”: “message”,
          “label”: “交通”,
          “text”: “交通”
        }
      },
      {
        “type”: “button”,
        “style”: “link”,
        “height”: “sm”,
        “action”: {
          “type”: “message”,
          “label”: “如何報名”,
          “text”: “如何報名”
        }
      },
      {
        “type”: “button”,
        “style”: “link”,
        “height”: “sm”,
        “action”: {
          “type”: “message”,
          “label”: “如何繳費”,
          “text”: “如何繳費”
        }
      },
      {
        “type”: “button”,
        “style”: “link”,
        “height”: “sm”,
        “action”: {
          “type”: “message”,
          “label”: “講師”,
          “text”: “講師”
        }
      },
      {
        “type”: “button”,
        “style”: “link”,
        “height”: “sm”,
        “action”: {
          “type”: “message”,
          “label”: “曾上課學員”,
          “text”: “曾上課學員”
        }
      }
    ],
    “flex”: 0
  }
};
var flex2 = {
  “type”: “bubble”,
  “hero”: {
    “type”: “image”,
    “url”: “https://developers-resource.landpress.line.me/fx/img/01_1_cafe.png”,
    “size”: “full”,
    “aspectRatio”: “20:13”,
    “aspectMode”: “cover”,
    “action”: {
      “type”: “uri”,
      “uri”: “https://line.me/”
    }
  },
  “body”: {
    “type”: “box”,
    “layout”: “vertical”,
    “contents”: [
      {
        “type”: “text”,
        “text”: “Brown Cafe”,
        “weight”: “bold”,
        “size”: “xl”
      },
      {
        “type”: “box”,
        “layout”: “baseline”,
        “margin”: “md”,
        “contents”: [
          {
            “type”: “icon”,
            “size”: “sm”,
            “url”: “https://developers-resource.landpress.line.me/fx/img/review_gold_star_28.png”
          },
          {
            “type”: “icon”,
            “size”: “sm”,
            “url”: “https://developers-resource.landpress.line.me/fx/img/review_gold_star_28.png”
          },
          {
            “type”: “icon”,
            “size”: “sm”,
            “url”: “https://developers-resource.landpress.line.me/fx/img/review_gold_star_28.png”
          },
          {
            “type”: “icon”,
            “size”: “sm”,
            “url”: “https://developers-resource.landpress.line.me/fx/img/review_gold_star_28.png”
          },
          {
            “type”: “icon”,
            “size”: “sm”,
            “url”: “https://developers-resource.landpress.line.me/fx/img/review_gray_star_28.png”
          },
          {
            “type”: “text”,
            “text”: “4.0”,
            “size”: “sm”,
            “color”: “#999999”,
            “margin”: “md”,
            “flex”: 0
          }
        ]
      },
      {
        “type”: “box”,
        “layout”: “vertical”,
        “margin”: “lg”,
        “spacing”: “sm”,
        “contents”: [
          {
            “type”: “box”,
            “layout”: “baseline”,
            “spacing”: “sm”,
            “contents”: [
              {
                “type”: “text”,
                “text”: “Place”,
                “color”: “#aaaaaa”,
                “size”: “sm”,
                “flex”: 1
              },
              {
                “type”: “text”,
                “text”: “Flex Tower, 7-7-4 Midori-ku, Tokyo”,
                “wrap”: true,
                “color”: “#666666”,
                “size”: “sm”,
                “flex”: 5
              }
            ]
          },
          {
            “type”: “box”,
            “layout”: “baseline”,
            “spacing”: “sm”,
            “contents”: [
              {
                “type”: “text”,
                “text”: “Time”,
                “color”: “#aaaaaa”,
                “size”: “sm”,
                “flex”: 1
              },
              {
                “type”: “text”,
                “text”: “10:00 – 23:00”,
                “wrap”: true,
                “color”: “#666666”,
                “size”: “sm”,
                “flex”: 5
              }
            ]
          }
        ]
      }
    ]
  },
  “footer”: {
    “type”: “box”,
    “layout”: “vertical”,
    “spacing”: “sm”,
    “contents”: [
      {
        “type”: “button”,
        “style”: “link”,
        “height”: “sm”,
        “action”: {
          “type”: “uri”,
          “label”: “CALL”,
          “uri”: “https://line.me/”
        }
      },
      {
        “type”: “button”,
        “style”: “link”,
        “height”: “sm”,
        “action”: {
          “type”: “uri”,
          “label”: “WEBSITE”,
          “uri”: “https://line.me/”
        }
      },
      {
        “type”: “box”,
        “layout”: “vertical”,
        “contents”: [],
        “margin”: “sm”
      }
    ],
    “flex”: 0
  }
};
//以下是環境變數,就是左方齒輪設定要先填才能代入
const env = {
  OPENAI_TOKEN: PropertiesService.getScriptProperties().getProperty(‘OPENAI_TOKEN’),
  CHANNEL_ACCESS_TOKEN: PropertiesService.getScriptProperties().getProperty(‘CHANNEL_ACCESS_TOKEN’),
  SHEET_URL:PropertiesService.getScriptProperties().getProperty(‘SHEET_URL’),
  AI_SET:PropertiesService.getScriptProperties().getProperty(“AI_SET”),
  AI_MODEL:PropertiesService.getScriptProperties().getProperty(“AI_MODEL”),
  AI_AFTER:PropertiesService.getScriptProperties().getProperty(“AI_AFTER”),
  AI_CH:PropertiesService.getScriptProperties().getProperty(“AI_CH”),
  CHATBOTNEED:PropertiesService.getScriptProperties().getProperty(“CHATBOTNEED”),
  AI_NAME:PropertiesService.getScriptProperties().getProperty(“AI_NAME”)};
  var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“工作表1”); // 根據您的情況調整工作表名稱
  var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“客戶基本資料”); // 根據您的情況調整工作表名稱
  var sheet3 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“關鍵字”);
  var sheet4 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“AI設定”);
  var xcv = env.AI_CH;
// 下面這主程式你就想像成,是使用者輸入時,Line回傳的資料,主要有訊息類別、誰傳的、傳了什麼字、還有一個叫replyToken的參數,這是用來回傳時,要比對的,不然電腦不曉得要回傳到哪.
function doPost(e) {
  // LINE Messenging API Token
  // 以 JSON 格式解析 User 端傳來的 e 資料
  var msg = JSON.parse(e.postData.contents);
  // for debugging
  Logger.log(msg);
  console.log(msg);
  // 從接收到的訊息中取出 replyToken 和發送的訊息文字
  var replyToken = msg.events[0].replyToken;
  var myType = msg.events[0].message.type;
  var userMessage;
  if (myType !== “text”) {userMessage=”貼圖”;}
  else { userMessage = msg.events[0].message.text;}
 // 以上的 if 是先判斷傳的是貼圖或文字,只要是文字,機器人才能據以回答,否則一律視為貼圖處理.(因為使用者有可能傳照片、聲音、影片等目前機器人還不能認出的物件)
  const user_id = msg.events[0].source.userId;
  var event_type = msg.events[0].source.type;
  try {
    var groupid = msg.events[0].source.groupId;
  }
  catch{
    console.log(“wrong”);
  }
  switch (event_type) {
    case “user”:
      var nameurl = “https://api.line.me/v2/bot/profile/” + user_id;
      break;
    case “group”:
      var nameurl = “https://api.line.me/v2/bot/group/” + groupid + “/member/” + user_id;
      break;
  }
  try {
    //  呼叫 LINE User Info API,以 user ID 取得該帳號的使用者名稱
    var response = UrlFetchApp.fetch(nameurl, {
      “method”: “GET”,
      “headers”: {
        “Authorization”: “Bearer ” + env.CHANNEL_ACCESS_TOKEN,
        “Content-Type”: “application/json”
      },
    });
    var namedata = JSON.parse(response);
    var reserve_name = namedata.displayName ;
    var reserve_userId = namedata.userId;
    var reserve_pictureUrl = namedata.pictureUrl;
    var reserve_userMessage = userMessage;
    oriMessagre=userMessage;
    //以上我們最主要的就是取出 replyToken 、 userMessage、user_id、還有頭像的圖片網址
  }
  catch{
    reserve_name = “not avaliable”;
  }
  if (typeof replyToken === ‘undefined’) {
    return;
  };
  isChatGPT = sheet4.getRange(“B1”).getValue();
  isToline = sheet4.getRange(“B2”).getValue();
  if (isToline != “yes”) {isChatGPT = “no”;sheet4.getRange(“B1”).setValue(“No”);} //確保 Line既然只記錄不輸出,自然不用ChatGPT了,省錢.
  userID = user_id;
  userName = reserve_name ;
  userPicUrl = reserve_pictureUrl;
  userWords = reserve_userMessage;
  now = Utilities.formatDate(new Date(), “GMT+8”, “yyyy-MM-dd HH:mm:ss”);   //只要是記錄,時間一定要加進來
  var current_list_row = sheet1.getLastRow();
        sheet1.getRange(current_list_row + 1, 1).setValue(reserve_userId);
        sheet1.getRange(current_list_row + 1, 2).setValue(reserve_name);
        sheet1.getRange(current_list_row + 1, 3).setValue(reserve_userMessage);
        sheet1.getRange(current_list_row + 1, 4).setValue(now);
  checkUserExist();
  mySearch = userMessage.toLowerCase().trim();
  userMessage = userMessage.toLowerCase().trim();
  //以下區段是最先執行權
  if (userMessage.length < 2 && userMessage != “嗨”) {mySearch = “文字太長或太短”;  }
  if (userMessage.length > 300 ) {mySearch = “文字太長或太短”;  }
  //if (userMessage.trim().includes(“緊急呼叫”) && userMessage.trim().length > 5){
  //  var managerID=”輸入管理員的UserID ” ; message=userName+oriMessagre; sendPushMessage(managerID, message);return;}
  if (userMessage.trim()==”最新課程”){replyFlex(replyToken, flex1);return;}
  if (userMessage.trim()==”多媒體”){replyFlex(replyToken, flex2);return;}
  //最先執行權結束
  searchAndFormatResults(userMessage);   //這是先用傳統的資料檢索,如果檢索的到,就不用啟動機器人,檢索不到,才啟動機器人
  if (!myWant){
    uMessage = “”;
  }else{
    uMessage = myWant;
  }
if (uMessage!=””) {myWant=env.AI_NAME+”:\n”+myWant;}
  else {
     if (isChatGPT.toLowerCase().trim()== “yes” ) {
     let resp = GPTturbo(userMessage);
     resp = resp.toString();
     //checkAndReplaceString(resp); //如果採用語意分析法,這行要恢復,用來確保ai的回答不會錯,若錯了會發訊息給管理員
     //searchAgain(resp);  //如果要採用 searchAgain 這個就要恢復,但角色設定也要同時修改
     myWant = resp; // 如果採用語意分析法,這行要MARK掉
     myWant = myWant.replace(/[。.]$/, ”);
     myWant = myWant.trim().replace(/[。]/g, ‘ ‘);
     myWant = myWant.trim().replace(‘(‘, ‘( ‘);
     myWant = myWant.trim().replace(‘[‘, ‘[ ‘);
     myWant = myWant.trim().replace(‘)’, ‘) ‘);
     myWant = myWant.trim().replace(‘].’, ‘] ‘);
     myWant = myWant.trim().replace(‘。’, ‘ ‘);
     }
       }
  //回傳訊息給line 並傳送給使用者
  //replyToLine(replyToken, myWant);
  //replyToLine(replyToken, myWant);  不能這樣子連傳兩則,因為傳完 replyToken 就失效了.
  handleReply(replyToken,myWant);
}
function handleReply(replyToken,myWant) {
  // 檢查圖片網址是否有效
  if (imageThumbnailUrl.includes(‘http’) && imageUrl.includes(‘http’)) {
    replyTextAndImage(replyToken, myWant, imageUrl, imageThumbnailUrl);return;
      }
  // 如果有影片網址也可以進行檢查
  if (videoThumbnailUrl.includes(‘http’) && videoUrl.includes(‘http’)) {
    replyTextAndVideo(replyToken, myWant, videoUrl, videoThumbnailUrl);return;
  }
  replyToLine(replyToken, myWant);
}
function replyToLine(replyToken, myWant) {if (isToline.trim().toLowerCase()== “yes”) {
   var payload = {
    ‘replyToken’: replyToken,
    ‘messages’: [
      {
        ‘type’: ‘text’,
        ‘text’: myWant
      },
    ]
  };
  var options = {
    ‘method’: ‘post’,
    ‘headers’: {
      ‘Content-Type’: ‘application/json’,
      ‘Authorization’: ‘Bearer ‘ + env.CHANNEL_ACCESS_TOKEN
    },
    ‘payload’: JSON.stringify(payload)
  };
  UrlFetchApp.fetch(‘https://api.line.me/v2/bot/message/reply’, options);
}
}
function replyImage(replyToken,myWant) {
  //var imageUrl = ‘https://wiilands.com/wp-content/uploads/2024/04/512512.jpg’; // 圖片的 URL
  //var imageThumbnailUrl = ‘https://wiilands.com/wp-content/uploads/2024/04/512512.jpg’; // 縮圖的 URL
  var payload = {
    ‘replyToken’: replyToken,
    ‘messages’: [
      {
        ‘type’: ‘text’,
        ‘text’: myWant
      },
      {
        ‘type’: ‘image’,
        ‘originalContentUrl’: imageUrl,
        ‘previewImageUrl’: imageThumbnailUrl
      }
    ]
  };
  var options = {
    ‘method’: ‘post’,
    ‘headers’: {
      ‘Content-Type’: ‘application/json’,
      ‘Authorization’: ‘Bearer ‘ + env.CHANNEL_ACCESS_TOKEN
    },
    ‘payload’: JSON.stringify(payload)
  };
  UrlFetchApp.fetch(‘https://api.line.me/v2/bot/message/reply’, options);
}
function replyVideo(replyToken) {
  //var videoUrl = ‘https://example.com/path/to/your/video.mp4’; // 影片的 URL
  //var videoThumbnailUrl = ‘https://example.com/path/to/your/thumbnail.jpg’; // 影片縮圖的 URL
  var payload = {
    ‘replyToken’: replyToken,
    ‘messages’: [
      {
        ‘type’: ‘video’,
        ‘originalContentUrl’: videoUrl,
        ‘previewImageUrl’: videoThumbnailUrl
      }
    ]
  };
  var options = {
    ‘method’: ‘post’,
    ‘headers’: {
      ‘Content-Type’: ‘application/json’,
      ‘Authorization’: ‘Bearer ‘ + env.CHANNEL_ACCESS_TOKEN
    },
    ‘payload’: JSON.stringify(payload)
  };
  UrlFetchApp.fetch(‘https://api.line.me/v2/bot/message/reply’, options);
}
function replyTextAndImage(replyToken, myWant, imageUrl, imageThumbnailUrl) {
    var payload = {
    ‘replyToken’: replyToken,
    ‘messages’: [
      {
        ‘type’: ‘text’,
        ‘text’: myWant
      },
      {
        ‘type’: ‘image’,
        ‘originalContentUrl’: imageUrl,
        ‘previewImageUrl’: imageThumbnailUrl
      }
    ]
  };
    var options = {
    ‘method’: ‘post’,
    ‘headers’: {
      ‘Content-Type’: ‘application/json’,
      ‘Authorization’: ‘Bearer ‘ + env.CHANNEL_ACCESS_TOKEN
    },
    ‘payload’: JSON.stringify(payload)
  };
  UrlFetchApp.fetch(‘https://api.line.me/v2/bot/message/reply’, options);
}
function replyTextAndVideo(replyToken, myWant, videoUrl, videoThumbnailUrl) {
    var payload = {
    ‘replyToken’: replyToken,
    ‘messages’: [
      {
        ‘type’: ‘text’,
        ‘text’: myWant
      },
      {
        ‘type’: ‘image’,
        ‘originalContentUrl’: videoUrl,
        ‘previewImageUrl’: videoThumbnailUrl
      }
    ]
  };
    var options = {
    ‘method’: ‘post’,
    ‘headers’: {
      ‘Content-Type’: ‘application/json’,
      ‘Authorization’: ‘Bearer ‘ + env.CHANNEL_ACCESS_TOKEN
    },
    ‘payload’: JSON.stringify(payload)
  };
  UrlFetchApp.fetch(‘https://api.line.me/v2/bot/message/reply’, options);
}
function replyFlex(replyToken, flexContents) {
  var payload = {
    ‘replyToken’: replyToken,
    ‘messages’: [
      {
        ‘type’: ‘flex’,
        ‘altText’: ‘多媒體訊息’,
        ‘contents’: flexContents
      }
    ]
  };
  var options = {
    ‘method’: ‘post’,
    ‘headers’: {
      ‘Content-Type’: ‘application/json’,
      ‘Authorization’: ‘Bearer ‘ + env.CHANNEL_ACCESS_TOKEN
    },
    ‘payload’: JSON.stringify(payload)
  };
  UrlFetchApp.fetch(‘https://api.line.me/v2/bot/message/reply’, options);
}
function GPTturbo(prompt, temperature = 0.4, model = env.AI_MODEL) {
 //下方的 xyz ,實現了機器人可以記住以往客戶所問的話,最多可以1000字,也實現了機器人對每一位客戶問話的回答風格,但若是採用語意分析法就不能用了
 xyz = env.AI_SET;
 const MAX_TOKENS = 800;
 const TEMPERATURE = 0.4;
 const url = “https://api.openai.com/v1/chat/completions”;
 const payload = {
    model: model,
    messages: [
      { role: “system”, content: xyz },
      { role: “user”, content: prompt },
    ],
    temperature: TEMPERATURE,
    max_tokens: MAX_TOKENS,
  };
  const options = {
    contentType: “application/json”,
    headers: { Authorization: “Bearer ” + env.OPENAI_TOKEN },
    payload: JSON.stringify(payload),
  };
  const res = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());
  var asd= res.choices[0].message.content.trim().replace(‘。’,’ \n’);
  return res.choices[0].message.content.trim().replace(‘。’,’ \n’);
}
function checkUserExist() {
  // 檢查客戶基本資料表中UserID是否存在
  var basicDataRange = sheet2.getRange(2, 1, sheet2.getLastRow(), 1);
  var basicDataValues = basicDataRange.getValues();
  var userExists = false;
  for (var i = 0; i < basicDataValues.length; i++) {
    if (basicDataValues[i][0] == userID) {
      userExists = true;
      userRow = i + 2; // 因為範圍是從第二行開始的
      break;
    }
  }
  // 如果用戶不存在於客戶基本資料表中,則新增
  if (!userExists) {
    sheet2.appendRow([userID, userName,userPicUrl,now]);
    userRow = sheet2.getLastRow(); // 獲取新添加的行數
  } }
function searchAndFormatResults(searchTerm) {
  //searchTerm = “地點”;
  // 檢查搜索詞的有效性
  if ((searchTerm.length < 2 && !/[a-zA-Z]/.test(searchTerm)) || searchTerm.length === 0) {
    return “搜索詞至少需要兩個字符(對於中文),或者是英文字符。”;
  }
  var range = sheet3.getDataRange();
  var values = range.getValues();
  var textResult = “”;
  var matches = [];
  // 遍歷每一行
  for (var i = 0; i < values.length; i++) {
    // 檢查第一列是否包含搜索詞
    if (values[i][0].toString().toLowerCase().trim().includes(searchTerm.toLowerCase().trim())) {
      matches.push(values[i]);
    }
  }
  // 根據匹配的行數處理輸出
if (matches.length === 1) {
  // 只有一行匹配,輸出所有欄位
  var row = matches[0];
  for (var j = 0; j < row.length; j++) {
    if (j === 0) {
      var name = row[j].toString().split(‘#’)[0].trim(); // 取出#之前的內容
      textResult += appendIfNotEmpty(name);
    } else {
      textResult += appendIfNotEmpty(row[j]);
    }
    // 使用正則表達式匹配URL
    var urlPattern = /https?:\/\/\S+/;
    var match = row[j].match(urlPattern);
    if (match) {
      if (row[j].includes(‘預覽圖片網址’)) {
        imageThumbnailUrl = match[0];
      }
      if (row[j].includes(‘顯示圖片網址’)) {
        imageUrl = match[0];
      }
      if (row[j].includes(‘預覽影片網址’)) {
        videoThumbnailUrl = match[0];
      }
      if (row[j].includes(‘顯示影片網址’)) {
        videoUrl = match[0];
      }
    }
  }
  //Logger.log(imageThumbnailUrl+imageUrl);
  textResult = textResult.replace(/undefined/g, “”).replace(/\n\n/g, “\n”);
}
  else if (matches.length > 1) {
    // 多行匹配,只輸出第1欄和包含 http 的欄位
    for (var i = 0; i < matches.length; i++) {
      var name = matches[i][0].toString().split(‘#’)[0].trim(); // 取出#之前的內容
      textResult += appendIfNotEmpty(name) + “\n”;
      for (var j = 1; j < matches[i].length; j++) {
        if (matches[i][j].toString().includes(“http”)) {
          textResult += appendIfNotEmpty(matches[i][j]) + “\n”;
        }
      }
      textResult += “\n”;
    }
    textResult = “有2個以上結果,請再輸入以下任一個來精確查詢。\n” + textResult.replace(/undefined/g, “”).replace(/\n\n/g, “\n”);
  }
  // 檢查是否有匹配結果
  if (textResult === “”) {
    Logger.log(textResult.trim());
  } else {
    // 日誌輸出匹配結果,或根據需要處理匹配結果
    Logger.log(“結果:” + textResult.trim());
    myWant = textResult.trim();
    // 返回純文本格式的匹配結果
  }
}
function searchAgain(searchTerm) {
  //searchTerm = “上課地點”;
  // 檢查搜索詞的有效性
  if ((searchTerm.length < 2 && !/[a-zA-Z]/.test(searchTerm)) || searchTerm.length === 0) {
    return “搜索詞至少需要兩個字符(對於中文),或者是英文字符。”;
  }
  var range = sheet3.getDataRange();
  var values = range.getValues();
  var textResult = “”;
  var matches = [];
  // 遍歷每一行
  for (var i = 0; i < values.length; i++) {
    // 檢查第一列是否包含搜索詞
    if (values[i][0].toString().toLowerCase().trim().includes(searchTerm.toLowerCase().trim())) {
      matches.push(values[i]);
    }
  }
  // 根據匹配的行數處理輸出
  if (matches.length === 1) {
    // 只有一行匹配,輸出所有欄位
    var row = matches[0];
    for (var j = 0; j < row.length; j++) {
      if (j === 0) {
        var name = row[j].toString().split(‘#’)[0].trim(); // 取出#之前的內容
        textResult += appendIfNotEmpty(name);
      } else {
        textResult += appendIfNotEmpty(row[j]);
      }
      // 使用正則表達式匹配URL
    var urlPattern = /https?:\/\/\S+/;
    var match = row[j].match(urlPattern);
    if (match) {
      if (row[j].includes(‘預覽圖片網址’)) {
        imageThumbnailUrl = match[0];
      }
      if (row[j].includes(‘顯示圖片網址’)) {
        imageUrl = match[0];
      }
      if (row[j].includes(‘預覽影片網址’)) {
        videoThumbnailUrl = match[0];
      }
      if (row[j].includes(‘顯示影片網址’)) {
        videoUrl = match[0];
      }
    }
    }
    textResult = textResult.replace(/undefined/g, “”).replace(/\n\n/g, “\n”);
  }
  else if (matches.length > 1) {
    // 多行匹配,只輸出第1欄和包含 http 的欄位
    for (var i = 0; i < matches.length; i++) {
      var name = matches[i][0].toString().split(‘#’)[0].trim(); // 取出#之前的內容
      textResult += appendIfNotEmpty(name) + “\n”;
      for (var j = 1; j < matches[i].length; j++) {
        if (matches[i][j].toString().includes(“http”)) {
          textResult += appendIfNotEmpty(matches[i][j]) + “\n”;
        }
      }
      textResult += “\n”;
    }
    textResult = “有2個以上結果,請再輸入以下任一個來精確查詢。\n” + textResult.replace(/undefined/g, “”).replace(/\n\n/g, “\n”);
  }
  // 檢查是否有匹配結果
  if (textResult === “”) {
    Logger.log(textResult.trim());
    //myWant= “這問題我會請小編迅速回答您!”
  } else {
    // 日誌輸出匹配結果,或根據需要處理匹配結果
    Logger.log(“結果:” + textResult.trim());
    myWant = textResult.trim();
    // 返回純文本格式的匹配結果
  }
}
function datetimeToUnix(timestampStr) {
  // 將日期字符串轉換Date對象
  var date = new Date(timestampStr);
  // 獲取UNIX時間戳(Date對象的getTime()方法返回毫秒,所以除以1000轉換為秒)
  var unixTimestamp = date.getTime() / 1000;
  return unixTimestamp;
}
function appendIfNotEmpty(value) {
  // 檢查值是否為 undefined 或空字符串(包括空白字符)
  if (value !== undefined && value !== null && value.trim() !== ”) {
    return value + “\n”;
  }
  return “”;
}
function getCurrentYear() {
  var currentDate = new Date();  // 創建一個 Date 對象,它將被初始化為當前日期和時間
  var currentYear = currentDate.getFullYear();  // 使用 getFullYear() 方法獲取當前年份
  return currentYear;
}
// 發送 Push Message 的函數
function sendPushMessage(userId, message) {
  const url = ‘https://api.line.me/v2/bot/message/push’;
  const payload = {
    to: userId,
    messages: [
      {
        type: ‘text’,
        text: message
      }
    ]
  };
  const options = {
    method: ‘post’,
    contentType: ‘application/json’,
    headers: {
      ‘Authorization’: ‘Bearer ‘ + env.CHANNEL_ACCESS_TOKEN
    },
    payload: JSON.stringify(payload)
  };
  const response = UrlFetchApp.fetch(url, options);
  Logger.log(response.getContentText());
}
// 測試發送 Push Message
function testSendPushMessage() {
  const userId = ‘請填入您的UserID’; // 替換成接收者的 User ID
  const message = ‘Hello from Google Apps Script!’;
  sendPushMessage(userId, message);
}
function checkAndReplaceString(inputString) {
  //以下這要按您自己的自行修改
  const categories = [“課程內容”, “課程講師”, “公司簡介”, “時間地點”, “上課費用”,”如何報名”, “如何繳費”, “交通”, “其他”];
  for (let i = 0; i < categories.length; i++) {
    if (inputString.includes(categories[i])) {
      aiOutput= categories[i];
    }
    else {aiOutput= “AI設定可能錯誤,不符合任何關鍵字”;userId = ‘請填入您的UserID’;sendPushMessage(userId, aiOutput);}
  }
}
function createSheetsAndPopulateData() {
  //千萬注意,這只執行一次,否則會把你的設定又重置
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  // 創建新工作表
  var sheets = [“客戶基本資料”, “關鍵字”, “AI設定”];
  sheets.forEach(function(sheetName) {
    if (!ss.getSheetByName(sheetName)) {
      ss.insertSheet(sheetName);
    }
  });
  // 在 “客戶基本資料” 表格上加入資料
  var customerSheet = ss.getSheetByName(“客戶基本資料”);
  var customerHeaders = [“UserID”, “DisplayName”, “PicURL”, “Time”];
  customerSheet.getRange(1, 1, 1, customerHeaders.length).setValues([customerHeaders]);
  // 在 “關鍵字” 表格上加入資料
  var keywordSheet = ss.getSheetByName(“關鍵字”);
  var keywordData = [
    [“貼圖”, “若有任何問題,請直接點按手機版 Line 上的功能表”],
    [“文字太長或太短”, “若有任何問題,請直接點按手機版 Line 上的功能表”]
  ];
  keywordSheet.getRange(1, 1, keywordData.length, keywordData[0].length).setValues(keywordData);
  // 在 “AI設定” 表格上加入資料
  var aiSettingSheet = ss.getSheetByName(“AI設定”);
  var aiSettingData = [
    [“isChatGPT”, “no”],
    [“isToLine”, “yes”]
  ];
  aiSettingSheet.getRange(1, 1, aiSettingData.length, aiSettingData[0].length).setValues(aiSettingData);
  // 設置指令碼屬性
  var scriptProperties = PropertiesService.getScriptProperties();
  var properties = {
    ‘AI_AFTER’: ‘謝謝您’,
    ‘AI_MODEL’: ‘gpt-4o’,
    ‘AI_NAME’: ‘小愛機器人’,
    ‘AI_SET’: ‘預設’,
    ‘AI_CH’: ‘不用理會’,
    ‘CHANNEL_ACCESS_TOKEN’: ‘填入你自己的’,
    ‘OPENAI_TOKEN’: ‘這是選項,若要用,請填入你自己的’,
    ‘CHATBOTNEED’: ‘不拘’,
    ‘SHEET_URL’: ‘填入你自己的’
  };
  scriptProperties.setProperties(properties);
    }

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

購物車