iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 26
0
AI & Data

利用Google App Script 實作Telegram Bot系列 第 26

Day 26-Telegram Bot:Google以圖搜圖

  • 分享至 

  • xImage
  •  

Day 26-Telegram Bot:Google以圖搜圖

再來要講以圖搜圖這個功能,使用的搜尋引擎是Google。

至於要怎麼做呢?

其實就是用這個網址就可以搜到圖片了。

https://www.google.com/searchbyimage?&image_url=<image URL>

你以為我在開玩笑?

沒有!真的就是透過這個網址來搜尋圖片。

關鍵是在於這個image URL到底是什麼,只要取得image URL便可以透過Google來搜尋圖片。

getFile

好,那要怎麼搜尋圖片呢?

讓我們回到官方文件的懷抱,找到getFile的地方。

https://core.telegram.org/bots/api#getfile

我們必須要利用這個getFile來取得這個圖片的資料,才有辦法透過這些資料來搜尋。

https://ithelp.ithome.com.tw/upload/images/20201006/20130283EfVBLSJpY7.png

https://api.telegram.org/file/bot<token>/<file_path>

在這邊可以看到中間有一行紅字,這代表說我們只要透過者個網址就可以得到我們的檔案。

Token想必大家都懂,關鍵是在於後面的file_path,這東西又要怎麼取得呢?

靠這傢伙!

https://api.telegram.org/bot<token>/getFile?file_id=<file_id>

透過這行網址我們就可以取得我們檔案的file_path。

file_id應該就不用多說了吧,就是我們傳送檔案時回傳到後台資料上會有的id。

整理一下取得檔案的流程。

首先我們要取得檔案id。

隨便傳一張照片給機器人,我們去之前儲存訊息的試算表看回傳回來的資料,如果以圖片傳送的方式取不到檔案id的話,可以改成以檔案形式傳送。

{
    message = {
        message_id = 525.0,
        date = 1.601610232E9,
        chat = {
            username = toikusen,
            id = 1.098175067E9,
            type = private,
            first_name = 昱成
        },
        document = {
            file_unique_id = AgADdwEAAorOuFc,
            file_size = 3161800.0,
            mime_type = image / png,
            file_id = BQACAgUAAxkBAAICDV92ofgAAfA1szW18S99QMC9dBbm4AACdwEAAorOuFdl84JQc90LGBsE,
            file_name = file_0.png,
            thumb = {
                file_id = AAMCBQADGQEAAgINX3ah - AAB8DWzNbXxL31AwL10FubgAAJ3AQACis64V2XzglBz3QsYXR7pbXQAAwEAB20AAz4 - AAIbBA,
                file_size = 19326.0,
                width = 320.0,
                height = 225.0,
                file_unique_id = AQADXR7pbXQAAz4 - AAI
            }
        },
        from = {
            first_name = 昱成,
            language_code = zh - hant,
            id = 1.098175067E9,
            is_bot = false,
            username = toikusen
        }
    },
    update_id = 8.94000226E8
}

上面有兩個file_id,我們要的是document物件下方的file_id,而不是thumb底下的。

接著將機器人的token還有file_id都輸入以下網址。

https://api.telegram.org/bot<token>/getFile?file_id=<file_id>

出現如下圖的訊息就代表我們成功取得file_path了,而我們的file_path就是後面的documents/file_5.png。

https://ithelp.ithome.com.tw/upload/images/20201008/20130283iwPTNszPmE.png

接著將我們的機器人token跟剛剛取得的file_path輸入以下網址。

https://api.telegram.org/file/bot<token>/<file_path>

如果資料都正確的話,就會看到檔案正在下載的圖示,到這邊我們就成功取得使用者傳送圖片給機器人的檔案了。

https://ithelp.ithome.com.tw/upload/images/20201006/20130283lTLo8loa0W.png

Google以圖搜圖

接著就是搜尋的部分。

透過下方這個Google搜尋的網址就可以搜到圖片。

https://www.google.com/searchbyimage?&image_url=<image URL>

而這個image URL

就是https://api.telegram.org/file/bot<token>/<file_path>這整串。

也就是說網址會變這樣

https://www.google.com/searchbyimage?&image_url=https://api.telegram.org/file/bot<token>/<file_path>

超級長的一串網址,試著執行就會是這樣的情況。

https://ithelp.ithome.com.tw/upload/images/20201006/20130283UCd7J4FQSf.png

你以為以圖搜圖只有這樣?當然不可能。

Telegram Bot 搭配Google以圖搜圖

現在我們已經搞懂整個取得檔案的過程還有搜尋的方法了,接著我們要把這些動作通通自動化,將他們轉換成程式碼。

我們想要達成的目標是讓使用者上傳一張圖片,接著使用者只要回覆這張圖片並輸入/find就可以透過Google搜尋到圖片了。

也就是說首先我們要判斷輸入的訊息是/find,這個判斷我們寫在sendtext裡面。

判斷訊息

function sendtext(estringa){  
if(estringa.message.text === "/find"){
    var cheak1 = estringa.message.photo;
    if(estringa.message.reply_to_message == null){var cheak2 = null;}
    else{var cheak2 = estringa.message.reply_to_message.photo;}
    if(cheak1 || cheak2){
      var TGfile = getFileFromTG(cheak1 , cheak2  , chatid);
      var mensaje = imageSearch(TGfile , chatid);
    }
    else{
      var payload = {
      "method": "sendMessage",
      "chat_id": chatid, 
      "text": "直接輸入/find是不行的喔!\n"+"要回覆想搜尋的圖片並且輸入/find才行!"}
      start(payload);
    }
    return mensaje;
  }
}

第2行:判斷訊息是否為/find
第3行:如果傳送的訊息是photo則將這個photo設為cheak1
第4-5行:判斷如果回覆訊息不是null,也就是這個訊息是回覆訊息的話,則將這個回覆photo的訊息設為cheak2。
第6-9行:如果說同時符合cheak1cheak2則將cheak1 , cheak2 , chatid這三個數值丟入getFileFromTG方法,並且執行imageSearch方法。
第10-16行:這邊的else則是我的一個小設計,如果說使用者不清楚這個功能的用法,他可能不是用reply_to_message就直接輸入/find想搜尋圖片,這時候會沒有反應,因此我寫了一個提示訊息,如果使用者直接輸入/find而沒有用reply_to_message那就會傳送訊息,告訴他應該要對著圖片用reply_to_message的方式。

接著來寫我們取得檔案與搜尋圖片的方法。

getFile&搜尋圖片

我們另外開一個程式碼專案,search_photo.gs,程式碼裡包含兩個方法getFileFromTGimageSearch

function getFileFromTG(cheak1 , cheak2 , chatid){
  if(cheak1){var array = cheak1;}
  else{var array = cheak2;}
  var text = array[1];
  var photoId = text.file_id;

  var payload = {
    "method": "post",
    "payload": {
      "method": "getFile",
      "file_id": photoId
    }
  }
  var getUrl = UrlFetchApp.fetch("https://api.telegram.org/bot你機器人的token/" , payload);
  var filePath = JSON.parse(getUrl);
  var temp = "https://api.telegram.org/file/bot你機器人的token/" + filePath.result.file_path;
  return temp;
  }

function imageSearch(TGfile , chatid){
var payload = {
        "method": "sendMessage",
        'chat_id': chatid,
        'text': '測試search'
      }
    
    payload.text ="找到啦!\n" + "https://www.google.com/searchbyimage?&image_url=" + TGfile + "";
    
    return payload;

}

第3-5行:這邊有點像回聲機器人的做法,取得我們的照片。
第7-12行:使用getFile方法將圖片存進payload
第14行:連結至我們的機器人。
第15行:將資料轉為JSON格式。
第16行:取得file_path
第27行:傳送找到圖片的訊息,透過網址https://www.google.com/searchbyimage?&image_url=<image URL>,而<image URL>的地方我們用TGfile來寫,這個TGfile其實就是我們在前面用sendtext方法,來將getFileFromTG最後取得file_path的網址存入TGfile

Debug

如果要debug也很簡單,只要稍微改寫一下前面的假裝傳入資料就可以了。
像是reply_to_message後面記得要放photo還有檔案的ID,這樣子也可以直接在內部做調整。

function debug() {

var test2 = {
    "update_id" : 894000208,
    "message" : {
        "entities" : "[Ljava.lang.Object;@ 7e928f86", 
        "message_id" : 480, 
        "date" : 1601532240, 
        "chat" : {
                "username" : "toikusen",
                "type" : "private",
                "id" : 1098175067,
                "first_name" : "昱成"
            }, "text" : "/find", 
            "from":{"username":"toikusen", 
            "id":1098175067, 
            "is_bot":"false", 
            "language_code":"zh-hant",
            "first_name":"昱成"}, 
            "reply_to_message":{"photo":['0',{"file_id":"BQACAgUAAxkBAAIB3191cU92qA092dXJ0kTWlrB3VFGWAAKcAQACis6wV23LopUmXBoLGwQ"}],
                                "message_id":479,
                                "date":"1601532240",
                                "from":{"first_name":"昱成", 
                                        "username":"toikusen", 
                                        "id":1098175067, 
                                        "language_code":"zh-hant",
                                        "is_bot":false}, 
                                        "chat":{"type":"private", 
                                                "first_name":"昱成", 
                                                "id":1098175067, 
                                                "username":"toikusen"}, 
                                                "document":{"thumb":{
"height":"225.0", 
"file_unique_id":"AQADXR7pbXQAAz4-AAI", 
"width" : "320",                                                                      "file_id":"AAMCBQADGQEAAgHfX3VxT3aoDT3Z1cnSRNaWsHdUUZYAApwBAAKKzrBXbcuilSZcGgtdHultdAADAQAHbQADPj4AAhsE",
"file_size":"19326"}, 
"file_name":"03.png", 
"file_size":"3161800.0", 
"mime_type":"image/png", 
"file_unique_id" : "AgADnAEAAorOsFc", 
"file_id" : "BQACAgUAAxkBAAIB3191cU92qA092dXJ0kTWlrB3VFGWAAKcAQACis6wV23LopUmXBoLGwQ"
    }
}
}

}

  var payload = identificar(test);
  start(payload)
}

到這邊完成我們就完成以圖搜圖的功能啦。

實際操作會像下圖這樣。

https://ithelp.ithome.com.tw/upload/images/20201006/20130283SknOE758gL.png

點下連結就會進到Google以圖搜圖的頁面。

https://ithelp.ithome.com.tw/upload/images/20201006/20130283YPIVYHW57g.png

後記:

可能有人會想說為什麼一定要用這個reply_to_message的方式才能搜尋呢?直接輸入/find,告訴機器人想要搜圖,再丟一張圖片給他搜尋這樣不行嗎?

可以,當然可以,但這樣會比較複雜,我最初也是想用這個想法來完成我的功能,但我發現在做的時候有蠻多的問題,必須要多加好幾層的判斷。

例如說開啟功能之後如果沒有關閉這個功能的話,那往後只要傳送圖片,就算你沒有想要搜圖,機器人也會回傳搜圖的訊息,這樣就不是我們想要做的了。

而reply_to_message的好處就在於,我們是在回覆圖片時才會觸發這個功能,也就是說我們這樣做其實是做了一個觸發條件,同時也很直覺的告訴機器人我們就是要找這張圖片,這也就是為什麼選用reply_to_message來實現這個搜圖的功能。

其實在最一開始打算做機器人時就已經決定要做這個以圖搜圖的功能了,所以這算是我認為一定要做出來的東西,不過沒想到我在這邊也是卡了很久,本來還想說要使用sauceNAO或是ascii2d,但顯然沒有這麼簡單,所以後來才決定先用Google搜尋來做,之後有時間再來嘗試利用其他搜尋引擎來找圖吧。

在使用上也可以搭配其他通訊軟體來用,比方說剛好手邊沒有電腦(電腦以圖搜圖比較方便),在Facebook或是Line收到一張圖片,只要用分享的功能傳到Telegram就可以用機器人來搜圖,還算是蠻好用的,網路上也有許多用其他語法寫的搜圖機器人,有興趣的人可以自行延伸啦。

參考資料:

https://github.com/Tsuk1ko/cq-picsearcher-bot
http://slashlook.com/archive2020/20200320.html


上一篇
Day 25-Telegram Bot:Debug
下一篇
Day 27-Telegram Bot:天氣機器人API
系列文
利用Google App Script 實作Telegram Bot30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言