Notes開発者のためのXPagesデザインレシピ

簡単でCoolなXPagesアプリケーションを作るための情報を発信していきます

Notesクライアント

NotesビューにYoutubeAPIから取得したサムネイルを表示したい(前編)

はじめに

 NotesクライアントのビューにWebページのようなサムネイル画像を表示したいと思ったことはないでしょうか?イメージリソースに画像を登録し、文書にイメージリソース名を指定すれば、Notesビューにもサムネイル画像を表示することは可能です。
 しかし、イメージリソースは設計レベルの要素なので、一般ユーザーが気軽に登録することはできません。今回ノーツコンソーシアム大阪研究会の浜さんがLotusScriptのDXLクラスを拡張し、LotusScriptからイメージリソースの登録と削除を可能にする関数を作られたので、それを活用し、YoutubeAPIからチャンネル動画一覧とサムネイル画像を取得し、Notesビューに表示してみたいと思います。
【完成型】

※実行確認はWindows10 Pro + Notes12.0.2FP1を使用しています。NotesJSONクラスを利用しているためNotes10以降の環境が必要です。

YoutubeAPIから情報を取得するには?

 YoutubeAPIから情報を取得するにはどのようにすれば良いでしょう?わからないことはChatGPTに聞いてみます。ここでの注意はまず、できるであろうメジャーな言語で問いかけを作る点です。
youtube apiを使って、特定チャンネルの動画一覧を取得するJavaScriptを書いて下さい
と聞いてみると下記のような回答が返ってきます。(回答は毎回異なります。)

 上記コードからYoutubeAPIの利用には「API Key」「ChannelID」「問合せURL」が必要なことがわかります。
 まずは確実に動くコードが欲しいので、JavaScriptのソースをHTMLファイルなどに書き込み、実行後は「VBAに変換して下さい」と質問し、VBAに書き換えて貰うとLotusScriptに移植しやすくなります。現在の生成AIの活用では、質問→実装テスト→質問→実装テストの繰り返しが必要です。

【APIKeyの取得】
APIKeyはGoogleアカウントを持っていれば簡単に発行できますので、Google検索などで取得方法を確認し、発行して下さい。

 取得できるAPIKeyには1日のアップロード、ダウンロードの上限があり、10,000ユニットという範囲で動作が可能です。上限を超えると、レスポンスが返らなくなりますが、翌日にはまた10,000ユニットが与えられます。

【ChannelIDの取得】
ChannelIDはGoogleでチャンネル名を検索し、URL部分に「https://www.youtube.com/channel」とあれば「channel」以降の部分がChannelIDです。

 

Advanced REST Clientを使ってURLをたたいてみる

ChatGPTの回答からYoutubeAPIの問合せURLは
「https://www.googleapis.com/youtube/v3/search?key=APIKEY&channelId=CHANNELID&part=snippet,id&order=date」
だとわかりましたが、ChatGPTの回答は正しいとは限りません。問合せが実行できることを確認するためにAdvanced REST Clientを使ってレスポンスが返ってくることを確認します。
※APIKEY、CHANNELIDの部分はご自分で取得した値にそれぞれ変更して下さい。

 

LotusScriptを使ってYoutubeAPIを実行してみる

 LotusScriptを使ってYoutubeAPIを実行してみます。NotesV10以降はNotesHTTPクラスが追加されましたが、バイナリなどが扱えないため、昔ながらの「MSXML2.ServerXMLHTTP.6.0」を使用します。
実行するとYoutubeAPIから取得したレスポンスがメッセージボックスに表示されます。

【ソース】

Sub Click(Source As Button)
	'---------- ---------- ---------- ---------- ---------- 
	'YoutubeAPIから取得したレスポンスをMsgboxに表示
	'
	'---------- ---------- ---------- ---------- ---------- 
	Const APIURL		=  "https://www.googleapis.com/youtube/v3/search?key="
	Const APIKEY		= "(取得したAPIKEY)"			'APIKey
	Const CHANNELID	= "(検索したChannelID)"									'ChannelID
	
	'クラス・変数宣言	
	Dim vXml			As Variant					'XMLオブジェクト
	Dim sUrl			As String					'送信するURL
	Dim vResponse		As Variant					'HTTPRequestからの戻り値
	
	'フィールドの値を取得して、リクエストURIを生成(指定のチャンネルから日付の新しい順に取得、件数を指定しないと5件取得される)
	sUrl = APIURL + APIKEY + "&channelId=" +  CHANNELID + "&part=snippet,id&order=date"
	
	'Getリクエストを実行し、結果を取得
	Set vXml = CreateObject("MSXML2.ServerXMLHTTP.6.0")	
	vXml.Open "GET", sUrl, False
	vXml.send ""
	
	Msgbox vXml.responseText
	
	Msgbox "Done!"
	
End Sub

【レスポンスのデータ構造】

YoutubeAPIから取得したレスポンスをNotesJSONクラスを使って文書に保存する

 YoutubeAPIで取得したレスポンスをNotesJSONクラスを利用して、必要な項目を文書に保存します。フォームを作成し「Title、VideoId、Thumbnail、ChannelTitle、Response」の5つのフィールドを配置します。一度の問合せでYoutubeAPIから取得できる動画の数は5つですので下記のコードで作成される文書数は最大で5文書となります。

【ソース】

Sub Click(Source As Button)
	'---------- ---------- ---------- ---------- ---------- 
	'YoutubeAPIから取得したレスポンスをJSONに分解し、文書として登録
	'
	'---------- ---------- ---------- ---------- ---------- 
	Const APIURL		=  "https://www.googleapis.com/youtube/v3/search?key="
	Const APIKEY		= "(取得したAPIKEY)"			'APIKey
	Const CHANNELID	= "(検索したChannelID)"									'ChannelID
	
	'クラス・変数宣言
	Dim session		As New NotesSession
	Dim db				As NotesDatabase
	Dim doc			As NotesDocument
	Dim jsonNav		As NotesJSONNavigator
	
	Dim vXml			As Variant					'XMLオブジェクト
	Dim sUrl			As String					'送信するURL
	Dim vResponse		As Variant					'HTTPRequestからの戻り値
	Dim iItemCnt		As Integer					'JSONオブジェクト件数
	Dim iCnt			As Integer					'ループカウンタ
	
	'フィールドの値を取得して、リクエストURIを生成(指定のチャンネルから日付の新しい順に取得、件数を指定しないと5件取得される)
	sUrl = APIURL + APIKEY + "&channelId=" +  CHANNELID + "&part=snippet,id&order=date"
	
	'Getリクエストを実行し、結果を取得
	Set vXml = CreateObject("MSXML2.ServerXMLHTTP.6.0")	
	vXml.Open "GET", sUrl, False
	vXml.send ""
	
	'レスポンスをJSONナビゲータに格納、リストの数を取得
	Set jsonNav	= session.CreateJSONNavigator(vXml.responseText)
	iItemCnt		= jsonNav.GetElementByName("items").Value.Size
	
	'文書を作成し、Responseを保存
	For iCnt = 0 To iItemCnt - 1	
		Set db			= session.CurrentDatabase
		Set doc		= db.CreateDocument
		
		doc.Form			= "frmLevel2"
		doc.Title			= jsonNav.GetElementByPointer("/items/" & Cstr(iCnt) & "/snippet/title").Value
		doc.VideoId			= jsonNav.GetElementByPointer("/items/" & Cstr(iCnt) & "/id/videoId").Value
		doc.Thumbnail		= jsonNav.GetElementByPointer("/items/" & Cstr(iCnt) & "/snippet/thumbnails/default/url").Value
		doc.ChannelTitle	= jsonNav.GetElementByPointer("/items/" & Cstr(iCnt) & "/snippet/channelTitle").Value
		doc.Response		= vXml.responseText & Chr(13) & "<" & Cstr(iCnt) & ">"
		
		Call doc.Save(True,True)
	Next
	
	Msgbox "Done!"
End Sub

【フォームイメージ】

YoutubeAPIを繰り返し呼出、文書を作成する

 上記ソースでは、一度のレスポンスに含まれるレコード5件を分解し、5つの文書を登録しました。6件目以降のレコードを取得するには、レスポンスに含まれる「nextPageToken」の値を取得し、URLに追加します。
【2ページ目以降を取得するURL】
「https://www.googleapis.com/youtube/v3/search?key=APIKEY&channelId=CHANNELID&part=snippet,id&order=date&pageToken=NEXTPAGETOKEN

【ソース】

Sub Click(Source As Button)
	'---------- ---------- ---------- ---------- ---------- 
	'YoutubeAPIから取得したレスポンスをJSONに分解し、文書として登録
	'
	'---------- ---------- ---------- ---------- ---------- 
	Const APIURL		=  "https://www.googleapis.com/youtube/v3/search?key="
	Const APIKEY		= "(取得したAPIKEY)"			'APIKey
	Const CHANNELID	= "(検索したChannelID)"									'ChannelID
	
	'クラス・変数宣言
	Dim session		As New NotesSession
	Dim db				As NotesDatabase
	Dim doc			As NotesDocument
	Dim jsonNav		As NotesJSONNavigator
	
	Dim vXml			As Variant					'XMLオブジェクト
	Dim sBaseUrl		As String					'ベースURL	
	Dim sUrl			As String					'送信するURL
	Dim vResponse		As Variant					'HTTPRequestからの戻り値
	Dim iItemCnt		As Integer					'JSONオブジェクト件数
	Dim iCnt			As Integer					'ループカウンタ
	Dim sNextPageToken	As String			'次のページを取得するためのトークン
	Dim iTotalCnt		As Integer
	
	'Getリクエストを実行し、結果を取得
	Set vXml = CreateObject("MSXML2.ServerXMLHTTP.6.0")	
	
    ' 初回リクエストのURLを作成
	sBaseUrl	= APIURL +  APIKEY + "&channelId=" +  CHANNELID + "&part=snippet,id&order=date"
	sUrl		= sBaseUrl
	iTotalCnt 	= 0
	'nextPageTokenがnullになるまでループ
	Do	
		vXml.Open "GET", sUrl, False
		vXml.send ""		
		
		'リクエスト越えチェック
		If vXml.Status = 403 Then
			Msgbox "リクエスト越え",16,"Error"
			Exit Sub
		End If
		
		'レスポンスをJSONナビゲータに格納、リストの数を取得
		Set jsonNav	= session.CreateJSONNavigator(vXml.responseText)
		iItemCnt		= jsonNav.GetElementByName("items").Value.Size
		sNextPageToken	= jsonNav.GetElementByPointer("/nextPageToken").value
		
		'文書を作成し、Responseを保存(一度のResponseを分解)
		For iCnt = 0 To iItemCnt - 1	
			Set db			= session.CurrentDatabase
			Set doc		= db.CreateDocument
			
			doc.Form			= "frmLevel2"
			doc.Title			= jsonNav.GetElementByPointer("/items/" & Cstr(iCnt) & "/snippet/title").Value
			doc.VideoId			= jsonNav.GetElementByPointer("/items/" & Cstr(iCnt) & "/id/videoId").Value
			doc.Thumbnail		= jsonNav.GetElementByPointer("/items/" & Cstr(iCnt) & "/snippet/thumbnails/default/url").Value
			doc.ChannelTitle	= jsonNav.GetElementByPointer("/items/" & Cstr(iCnt) & "/snippet/channelTitle").Value
			doc.Response		= vXml.responseText & Chr(13) & "<" & Cstr(iCnt) & ">"
			
			Call doc.Save(True,True)
		Next
		
		'nextPageTokenを引数に渡し、次のURLを生成
		sUrl = sBaseUrl & "&pageToken=" & sNextPageToken
		
		iTotalCnt	= iTotalCnt + 1
		If iTotalCnt > 3 Then
			Exit Sub
		End If
		
	Loop While(sNextPageToken <> "")
	
	Msgbox "Done!"
	
End Sub

YoutubeAPIの問題(仕様)

これでYoutubeAPIから取得したレコードをNotes文書として登録することができるようになりました。しかしYoutubeAPIには問題があります。それは「同じレコードを複数回返す」と言うことです。これはYoutubeが使っているバックエンドDBの特性かと思います。レスポンスを優先し、同じレコードが返ってくるため、VideoIdなど一意に特定出来る項目を使って、既に登録済みの場合、文書を登録しないように制御する必要があります。LotusScriptを記述できる方であればここまでの解説で十分実装可能かと思いますので、宿題とさせていただきます。

次回予告

次回はいよいよ、サムネイル画像の取得とDXLを使ったイメージリソースの登録、登録したイメージリソースのビューへの表示を行います。
【参考リンク】
ノーツコンソーシアム大阪研究会 浜さんブログ
出直し!! ドミノ塾 (denaoshidomino.com)