スマホの中の写真 埋もれてない?
スマホがこの世に誕生し、撮られる写真はそれ以前の10倍に。
世界で1年に撮影される写真は瞬時に1兆枚を突破。
1スマホの中に少なくとも1,000枚以上の写真があるそうです。
せっかく撮影しても、整理できずにいませんか?。
「子供と仕事の写真ぐちゃぐちゃ・・」「あの思い出はどこ・・?」
思い出が埋もれたり、写真と一緒に消えてしまうのは悲しい。
とはいえ整理はめんどくさい。よくあるフォトアプリも挫折した。
そんな方々、そして誰より私たち夫婦の悩みを解決するために
日本一簡単操作で作れるフォトアルバムを作ります!
3タップフォトアルバムの試作品
できたものはこちら
プログラミング初心者の
— OKINAKA(おきなかがいこつ) (@okinakamasayos1) December 18, 2021
日本一楽 LINEフォトアルバム挑戦記💪
プロトタイプ作成中
写真送付で
フォトアルバム完成!
まではおおよそオッケー👌
コメント入れたい。。。#protoout#LINEDC#プログラミング初心者 #プログラミング初心者と繋がりたい pic.twitter.com/wOpjn86ndt
①写真ボタンを押す
②写真を選ぶ
③送信
:
なんと3タップでアルバム投稿は完成!
入力せずとも、「投稿者」と「投稿日時」も自動で記入!
いつの、誰のお気に入り写真か、一瞬で振り返ることができます!
「日本一簡単」と謳うからには、私たちが挫折した
「意識高い系フォトアルバム」よりも楽に投稿できなければなりません。
実際に比較して、 「日本一楽に投稿」の基準を掲げました。
:::note warn
3タップで写真投稿 6工程でコメント投稿
:
「6工程でのコメント投稿」はまだ実現できていませんが、
今後絶対制作してみせます。(頑張る💪)
全体の流れ・コードはこちら
// 応答メッセージURL
const REPLY = "https://api.line.me/v2/bot/message/reply";
// アクセストークン
const ACCESS_TOKEN = "********";
// スプレッドシート情報
const SHEET_ID = '********';
const SHEET = SpreadsheetApp.openById(SHEET_ID).getSheetByName('シート1');
// Google Drive ID
const GOOGLE_DRIVE_ID = "1WZOXuCbs8yb574GHQLp5Ov6SJYPKFLTz";
// LINEから送られてきたデータを取得 doPost()
function doPost(e) {
//メッセージ受信
const data = JSON.parse(e.postData.contents).events[0];
//ユーザーID取得
const lineUserId = data.source.userId;
// リプレイトークン取得
const replyToken = data.replyToken;
// 送信されたメッセージの種類を取得
// https://developers.line.biz/ja/docs/messaging-api/message-types/#sticker-messages
const postType = data.message.type;
// 写真の時
if ( "image" === postType ) {
imageSave(replyToken, lineUserId, data);
} else {
sendMessage(replyToken, '画像を送信してください')
}
}
// 送信された画像を保存 imageSave()
function imageSave(replyToken, lineUserId, data) {
// LINEから画像取得 getImg()
const imgData = getImg(data);
// Googleドライブに保存 saveImg()
const imgInfo = saveImg(imgData, lineUserId);
// //「保存完了」とLINEにメッセージを送る
sendMessage(replyToken, imgInfo);
}
// LINEから画像取得 getImg()
function getImg(data) {
const IMG_URL = 'https://api-data.line.me/v2/bot/message/' + data.message.id + '/content';
const HEAD = {
"method":"get",
"headers": {
"Authorization" : "Bearer " + ACCESS_TOKEN
}
}
const imgData = UrlFetchApp.fetch(IMG_URL, HEAD);
return imgData;
}
// Googleドライブに保存 saveImg()
function saveImg(imgBinary, lineUserId){
//GoogleDriveフォルダID
const folder = DriveApp.getFolderById(GOOGLE_DRIVE_ID);
//ランダムな文字列を生成して、画像のファイル名とする
const fileName = Math.random().toString(36).slice(-8);
//Googleドライブのフォルダに画像を生成
const imageFile = folder.createFile(imgBinary.getBlob().setName(fileName));
//「保存しました」としたメッセージを変数に代入
const imgInfo = '保存したよ!https://docs.google.com/spreadsheets/d/1X8sR_aCzZydKSdAInkBZG9TcDeWInoq38TeTKRt9-KA/edit#gid=0';
//画像ファイルURL取得
const imageURL = '****スプシURL****' + imageFile.getId();
//画像ファイルにリンクでアクセスの権限付与
imageFile.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
debugImgLog(imageURL, lineUserId);
return imgInfo;
}
// スプレッドシートに画像を保存 debugImgLog()
function debugImgLog(text, userId) {
if ('' == text) {
return;
}
const date = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss')
const userName = getUserDisplayName(userId)
const userImg = getUserDisplayImg(userId)
SHEET.appendRow([userId, userImg, userName, text, date,'=image("'+text+'")']);
// 日付順に並び替え
const numColumn = SHEET.getLastColumn(); // 最後列の列番号を取得
const numRow = SHEET.getLastRow()-1; // 最後行の行番号を取得
const dataRange = SHEET.getRange(2, 1, numRow, numColumn);
dataRange.sort([{column: 5, ascending: false}]);
}
// ユーザーのプロフィール名取得 getUserDisplayName()
function getUserDisplayName(userId) {
const url = 'https://api.line.me/v2/bot/profile/' + userId;
const userProfile = UrlFetchApp.fetch(url,{
'headers': {
'Authorization' : 'Bearer ' + ACCESS_TOKEN,
},
})
return JSON.parse(userProfile).displayName;
}
// ユーザーのプロフィール画像取得 getUserDisplayImg()
function getUserDisplayImg(userId) {
const url = 'https://api.line.me/v2/bot/profile/' + userId;
const userProfile = UrlFetchApp.fetch(url,{
'headers': {
'Authorization' : 'Bearer ' + ACCESS_TOKEN,
},
})
return JSON.parse(userProfile).pictureUrl;
}
// LINEにメッセージ送信 sendMessage()
function sendMessage(replyToken, replyText) {
const postData = {
"replyToken" : replyToken,
"messages" : [
{
"type" : "text",
"text" : replyText
}
]
};
const headers = {
"Content-Type" : "application/json; charset=UTF-8",
"Authorization" : "Bearer " + ACCESS_TOKEN
};
const options = {
"method" : "POST",
"headers" : headers,
"payload" : JSON.stringify(postData)
};
return UrlFetchApp.fetch(REPLY, options);
参考記事(ありがたい😢) LINEで送った画像をGoogleドライブに保存するメモ
詰まっているところ コメントを入れられない
写真+コメントも「思い出」として残したい。そこで
function doPost(e)
の中身に下記を追加し、
if文
を下記のように変更することで実装を試みました。
いまのところコメントは指定セルに入るのですが、画像が保存されなくなってしまいます。
もし原因・対策分かる方、よければ教えてください。。。
function doPost(e)
の中に追記したコード
const json = JSON.parse(e.postData.contents);
const message = json.events[0].message.text;
const messageParameter = message.split(/\r\n|\n/);
const lastRow = SHEET.getLastRow();
書き変えたif文
と意図 コメントは入るが画像が入らない
// 写真の時はデータ取得
if ( "image" === postType ) {
imageSave(replyToken, lineUserId, data);
//写真でなければG2のセルに入力
} else {
var lastRow = SHEET.getLastRow();
SHEET.getRange('G' + 2).setValue(messageParameter[0]);
}
うまくいっていない全体コードはこちらです **(クリックで表示)**
// 応答メッセージURL
const REPLY = "https://api.line.me/v2/bot/message/reply";
// アクセストークン
const ACCESS_TOKEN = "********";
// スプレッドシート情報
const SHEET_ID = '********';
const SHEET = SpreadsheetApp.openById(SHEET_ID).getSheetByName('シート1');
// Google Drive ID
const GOOGLE_DRIVE_ID = "********";
// LINEから送られてきたデータを取得 doPost()
function doPost(e) {
//メッセージ受信
const data = JSON.parse(e.postData.contents).events[0];
//ユーザーID取得
const lineUserId = data.source.userId;
// リプレイトークン取得
const replyToken = data.replyToken;
// 送信されたメッセージの種類を取得
// https://developers.line.biz/ja/docs/messaging-api/message-types/#sticker-messages
const postType = data.message.type;
//コメント入力のために追加しているか箇所①
const json = JSON.parse(e.postData.contents);
const message = json.events[0].message.text;
const messageParameter = message.split(/\r\n|\n/);
var lastRow = SHEET.getLastRow();
//追加①ここまで
// if文書き変え 写真の時データ取得
if ( "image" === postType ) {
imageSave(replyToken, lineUserId, data);
//そうじゃない時はG2に文字入力
} else {
var lastRow = SHEET.getLastRow();
SHEET.getRange('G' + 2).setValue(messageParameter[0]);
}
//書き変えここまで
}
// 送信された画像を保存 imageSave()
function imageSave(replyToken, lineUserId, data) {
// LINEから画像取得 getImg()
const imgData = getImg(data);
// Googleドライブに保存 saveImg()
const imgInfo = saveImg(imgData, lineUserId);
// //「保存完了」とLINEにメッセージを送る
sendMessage(replyToken, imgInfo);
}
// LINEから画像取得 getImg()
function getImg(data) {
const IMG_URL = 'https://api-data.line.me/v2/bot/message/' + data.message.id + '/content';
const HEAD = {
"method":"get",
"headers": {
"Authorization" : "Bearer " + ACCESS_TOKEN
}
}
const imgData = UrlFetchApp.fetch(IMG_URL, HEAD);
return imgData;
}
// Googleドライブに保存 saveImg()
function saveImg(imgBinary, lineUserId){
//GoogleDriveフォルダID
const folder = DriveApp.getFolderById(GOOGLE_DRIVE_ID);
//ランダムな文字列を生成して、画像のファイル名とする
const fileName = Math.random().toString(36).slice(-8);
//Googleドライブのフォルダに画像を生成
const imageFile = folder.createFile(imgBinary.getBlob().setName(fileName));
//「保存しました」としたメッセージを変数に代入
const imgInfo = '保存したよ!https://docs.google.com/spreadsheets/d/1X8sR_aCzZydKSdAInkBZG9TcDeWInoq38TeTKRt9-KA/edit#gid=0';
//画像ファイルURL取得
const imageURL = 'https://drive.google.com/uc?export=view&id=' + imageFile.getId();
//画像ファイルにリンクでアクセスの権限付与
imageFile.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
debugImgLog(imageURL, lineUserId);
return imgInfo;
}
// スプレッドシートに画像を保存 debugImgLog()
function debugImgLog(text, userId) {
if ('' == text) {
return;
}
const date = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss')
const userName = getUserDisplayName(userId)
const userImg = getUserDisplayImg(userId)
SHEET.appendRow([userId, userImg, userName, text, date,'=image("'+text+'")']);
// 日付順に並び替え
const numColumn = SHEET.getLastColumn(); // 最後列の列番号を取得
const numRow = SHEET.getLastRow()-1; // 最後行の行番号を取得
const dataRange = SHEET.getRange(2, 1, numRow, numColumn);
dataRange.sort([{column: 5, ascending: false}]);
}
// ユーザーのプロフィール名取得 getUserDisplayName()
function getUserDisplayName(userId) {
const url = 'https://api.line.me/v2/bot/profile/' + userId;
const userProfile = UrlFetchApp.fetch(url,{
'headers': {
'Authorization' : 'Bearer ' + ACCESS_TOKEN,
},
})
return JSON.parse(userProfile).displayName;
}
// ユーザーのプロフィール画像取得 getUserDisplayImg()
function getUserDisplayImg(userId) {
const url = 'https://api.line.me/v2/bot/profile/' + userId;
const userProfile = UrlFetchApp.fetch(url,{
'headers': {
'Authorization' : 'Bearer ' + ACCESS_TOKEN,
},
})
return JSON.parse(userProfile).pictureUrl;
}
// LINEにメッセージ送信 sendMessage()
function sendMessage(replyToken, replyText) {
const postData = {
"replyToken" : replyToken,
"messages" : [
{
"type" : "text",
"text" : replyText
}
]
};
const headers = {
"Content-Type" : "application/json; charset=UTF-8",
"Authorization" : "Bearer " + ACCESS_TOKEN
};
const options = {
"method" : "POST",
"headers" : headers,
"payload" : JSON.stringify(postData)
};
return UrlFetchApp.fetch(REPLY, options);
}
工夫した点と目指したいこと
送られた写真をそのままスプレッドシートに張り付けたかったのですが断念。
そこで一旦GoogleDriveに写真を保存し、Drive内写真のURLをシートに入力させ、
=image("写真のURL")
とセル内で表示させることで、画像表示させました。
アルバムっぽく表示させるため、別シートを設定、
LINEから飛んできた情報を一旦原紙シートに記載し、それとは別のシートで、
自動的にアルバムのように表示させることにしました。
とはいえまだ手作りExcel感満載ですので、今後はwebアプリとして表現できるように
実装を進めたいと思っています。
まだまだ雑ですがこのような形に仕上げていきたいです。
https://twitter.com/okinakamasayos1/status/1470994683405168643
思い出が消えない世界を作りたい
将来「写真分類・投稿・アルバム化」も全部「自動」にして
あとは振り返るだけ!そんな「思い出が消えない世界」を作りたいと思っています。
「日本一簡単なLINEフォトアルバム」は、その夢へのはじめの一歩です。
夢を叶えるために、1月中旬には人生初のクラウドファンディングにも挑戦しますので、
これからも応援してくださるととても嬉しいです!!
@shiracamus さん編集リクエストありがとうございました!!#見落としていたのでありがたいです!!
https://note.com/m_okinaka/n/n30c09e837ae0