■ガラケーユーザ(以降ユーザ)を一名、グループトークに参加させるために作成
■概要
グループトークに送られた、image、text、stampをメールとしてユーザに逐次転送。
ユーザから受け取ったメールのテキスト部分をトークルームに書き込み。
■使ったシステム
◆line developers の messaging API → トークルームからユーザに送る
◆LINE notify → ユーザが送信したメールのテキストをトークルームに書き込み
◆GAS(GoogleAppsScript)
■制限その他
◆image ガラケーは大きな画像を受けられないので、サムネイルを転送。(情報少なく苦労した)
◆text 絵文字はサポートしない
◆ユーザがimageを添付しても転送しない。(要望があれば実装)
◆無料でのmessaging APIは利用回数の制限がある。(2021年1月現在10000回/月らしい)
■参考にさせていただいたサイト。他にも様々なサイトを参考にさせて頂きました、有難うございました。
◆Googleドライブに置いた画像のURL取得方法 (オリジナルとサムネイル)
h ttps://qiita.com/noirbreath/items/2b0ca7eeaaef963aa6be
◆Google Apps Scriptで特定のGmail新着メールをLineに通知
h ttps://flat-kids.net/2020/03/28/google-apps-script%E3%81%A7%E7%89%B9%E5%AE%9A%E3%81%AEgmail%E6%96%B0%E7%9D%80%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%92line%E3%81%AB%E9%80%9A%E7%9F%A5/
■セキュリティ・その他
大丈夫っぽいけれど、・・・・
今回は個人的利用、商用ではない
gs、javaは未経験につき無茶苦茶なコーディングかも知れない・・・
■コード
//環境により変更する項目------------------------
//LINEボットのアクセストークン
var ACCESS_TOKEN = 'XXXXXXXXXXXXXX--------XXXXXXXXXXXXXXXXXXXXXXXXXX';
//Googleドライブに作ったフォルダのURLの末尾にある30文字くらいの文字列
var FOLDER_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
//Lineに参加するユーザのメアド
var mailAddressUser = 'hoge@hoge.co.jp';
//このシステムの管理者メアド
var mailAddressAdmin = 'hogehoge@hoge.com';
//LINE notify token
var lineToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
//ユーザからのメールをチェックする間隔。function getMail()をトリガー対象にした設定に合わせる。
var get_interval = 5; //〇分前~現在の新着メールを取得 トリガーをこれに合わせる
//-------------------------------------------
//グローバル変数として定義(今の時代、禁じ手なのかも)
var username = ''
//-------------------------------------------
var from = ' from:' + mailAddressUser;
// getMail()をトリガー対象に設定
function getMail(){
//取得間隔
var now_time= Math.floor(new Date().getTime() / 1000) ;//現在時刻を変換
var time_term = now_time - (60 * get_interval); //変換
//検索条件指定(前回確認した以降の未読を検索、fromに特定の送信者メアドを定義
var strTerms = '(' + from + ' is:unread' + ' after:'+ time_term + ')';
//検索して取得
var myThreads = GmailApp.search(strTerms);
//スレッドからメールを取得し二次元配列に格納
var myMessages = GmailApp.getMessagesForThreads(myThreads);
for(var i in myMessages){
var strDate = Utilities.formatDate( myMessages[i][0].getDate(), 'Asia/Tokyo', 'M/d HH:mm');
var strSubject = myMessages[i][0].getSubject();
var strMessage = myMessages[i][0].getPlainBody().slice(0,500);
//LINEにメッセージを送信
sendLine(strDate,strSubject,strMessage);
//メッセージを既読にする
myMessages[i][0].markRead();
}
}
function sendLine(strDate,strSubject,strMessage){
//Lineに送信するためのトークン
var strToken = lineToken;
var options =
{
"method" : "post",
//"payload" : "message=" + strDate + "\n 件名:" + strSubject + "\n 本文:" + strMessage,
"payload" : "message="+ strSubject + strMessage,
"headers" : {"Authorization" : "Bearer "+ lineToken}
};
UrlFetchApp.fetch("https://notify-api.line.me/api/notify",options);
}
//-------------------------------------------
//返信用エンドポイント
var REPLY_URL = 'https://api.line.me/v2/bot/message/reply';
function sendMsg(url, payload) {
UrlFetchApp.fetch(url, {
'headers': {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer ' + ACCESS_TOKEN,
},
'method': 'post',
'payload': JSON.stringify(payload),
});
}
//lineからイメージを受け取った場合の処理
function getImage(id) {
//画像取得用エンドポイント
var url = 'https://api-data.line.me/v2/bot/message/' + id + '/content';
var data = UrlFetchApp.fetch(url,{
'headers': {
'Authorization' : 'Bearer ' + ACCESS_TOKEN,
},
'method': 'get'
});
var file_name ='line.png';
var img = data.getBlob().getAs('image/png').setName(file_name);
return img;
}
//lineから受け取ったイメージをgoogle driveに格納、そのサムネールを取り出しdrive内に格納、それをメールに添付して送信
function saveImage(blob) {
try{
var folder = DriveApp.getFolderById(FOLDER_ID);
var fileOriginal = folder.createFile(blob);
// 保存した画像に共有権を設定する (リンクを知っている全員が閲覧可、でないと自分でもURL指定の場合、読みこめない)
fileOriginal.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
// 保存した画像のサムネイルを取り込む(ガラケーは大きなファイルを受けられないので)
var fileId = fileOriginal.getId();
var previewURL = 'https://drive.google.com/thumbnail?sz=w240-h240&id='+fileId
//MailApp.sendEmail(mailAddress,previewURL, previewURL);
// サムネイル画像をGoogleドライブに保存する
var fileName = 'thumbnail.png';
// サムネイル画像を取得してGoogleドライブに保存
var fileBlob = UrlFetchApp.fetch(previewURL).getBlob().setName(fileName);
var fileThumbnail = DriveApp.createFile(fileBlob);
//Google Driveからファイル名で、ファイルを取得する
var report = DriveApp.getFilesByName(fileName).next()
// サムネイル画像を添付してメールを送信する
MailApp.sendEmail(mailAddressUser,username, '画像',{attachments: [report]});
// オリジナル画像ファイル削除
fileOriginal.setTrashed(true);
// サムネイル画像ファイル削除
fileThumbnail.setTrashed(true);
return file.getUrl();
}catch(e){
return false;
}
}
//lineからスタンプを受け取った場合の処理
function getSticker(stickerId){
var stickerURL = 'https://stickershop.line-scdn.net/stickershop/v1/sticker/'+stickerId + '/android/sticker.png'
// スタンプ画像をGoogleドライブに保存する
var fileName = 'sticker.png';
var fileBlob = UrlFetchApp.fetch(stickerURL).getBlob().setName(fileName);
var fileSticker = DriveApp.createFile(fileBlob);
var report = DriveApp.getFilesByName(fileName).next()
MailApp.sendEmail(mailAddressUser,username, 'スタンプ',{attachments: [report]});
// スタンプ画像削除
fileSticker.setTrashed(true);
}
// lineIdからlineユーザ名を返す
function getUsername(userId) {
var url = 'https://api.line.me/v2/bot/profile/' + userId;
var response = UrlFetchApp.fetch(url, {
'headers': {
'Authorization': 'Bearer ' + ACCESS_TOKEN
}
});
return JSON.parse(response.getContentText()).displayName;
}
//lineのWEBHOOKを処理する
function doPost(e) {
var event = JSON.parse(e.postData.contents).events[0];
var userId = JSON.parse(e.postData.contents).events[0].source.userId;
//手抜きというか作法無視?C言語時代のグローバル変数。いろんな場所で参照するので・・・
username =getUsername(userId);
if (typeof e === "undefined"){
//eがundefinedの場合動作を終了する
return;
}
switch (event.type) {
case 'follow':
MailApp.sendEmail(mailAddressAdmin, username, 'フォローされました。');
return;
case 'unfollow':
MailApp.sendEmail(mailAddressAdmin,username, 'ブロックされました。');
return;
case 'join':
MailApp.sendEmail(mailAddressAdmin,username, 'Join group :');
return;
case 'leave':
MailApp.sendEmail(mailAddressAdmin,username, 'Leave group :');
return;
case 'message':
switch (event.source.type) {
case 'user':
break;
case 'group':
break;
case 'room':
break;
}
break;
}
if(event.message.type == 'image') {
try {
//画像取得
var img = getImage(event.message.id);
//サムネイル画面を取得するため、Google Driveにいったん格納し、サムネイルを取り出しメールに添付して送信
var url = saveImage(img);
/* sendMsg(REPLY_URL,{'replyToken': event.replyToken,
'messages': [{'type': 'text','text': url ? "保存しました:\n" + url : "ダウンロードエラー",}]})*/
}catch(e) {
Logger.log(e);
}
}
if(event.message.type == 'text') {
try {
var receive_message = JSON.parse(e.postData.contents).events[0].message.text;
MailApp.sendEmail(mailAddressUser,username, receive_message);
}catch(e) {
Logger.log(e);
}
}
if(event.message.type == 'sticker') {
try {
//MailApp.sendEmail(mailAddressUser,username, 'https://stickershop.line-scdn.net/stickershop/v1/sticker/' + event.message.stickerId + '/android/sticker.png');
getSticker(event.message.stickerId);
}catch(e) {
Logger.log(e);
}
}
if(event.message.type == 'video') {
try {
var message = '動画 '
MailApp.sendEmail(mailAddressUser,username,message);
}catch(e) {
Logger.log(e);
}
}
if(event.message.type == 'audio') {
try {
var message = '音楽'
MailApp.sendEmail(mailAddressUser,username,message);
}catch(e) {
Logger.log(e);
}
}
if(event.message.type == 'file') {
try {
var message = 'ファイル '
MailApp.sendEmail(mailAddressUser,username,message);
}catch(e) {
Logger.log(e);
}
}
if(event.message.type == 'location') {
try {
var message = '位置情報 '
MailApp.sendEmail(mailAddressUser,username,message);
}catch(e) {
Logger.log(e);
}
}
return ;
}