こんにちは! 効率化オタクのヨス(プロフィールはこちら)です。
毎日の出来事を「日記につけておきたいな」……と思っても、なかなか続かないものです。
そもそも、専用の「日記アプリ」や「メモアプリ」を開くのがめんどくさいんですよね。
日記をつけたいけど、わざわざアプリを開くのが面倒で三日坊主になるっス……。
わたしも長年その手間に悩まされてきました(笑)。
そこで、普段から使い慣れているLINEを使って、全自動でGoogleドキュメントの日記を作成するシステムを構築しました。
LINEの専用Botにテキストや写真を送るだけで、深夜にGoogleドキュメントとカレンダーへ勝手にまとまるという魔法のような仕組みになっています。
LINE自動日記システムとは?
本記事で紹介する「LINE自動日記システム」とは、LINEのトーク画面に文章や画像をポンッと送信するだけで、日記として整理してくれる仕組みです。

でも「自動で整理するシステムなんて、プログラミングの知識がないと作れないのでは……」と不安になりませんか?
ご安心ください!
本記事では、知識ゼロの人でも自分専用の「LINE自動日記システム」を作れる方法を紹介しています。

記事の後半では「魔法のプロンプト」を公開しています。
これをAI(ChatGPTなど)にコピー&ペーストするだけで、AIがすべての設定手順とプログラムを勝手に書き出してくれるのです。
あとはAIの指示に従うだけで、ものの数十分で自動日記ボットが完成しますよ。
LINE自動日記システムを作る3つのメリット
そもそも、なぜわざわざこのシステムを作るのでしょうか?
ここでは、自動日記システムを作る3つのメリットを紹介します。
LINE自動日記システムを作る3つのメリット
LINEに送るだけで記録される
LINE自動日記システムを作るメリットの1つ目は、LINEに送るだけで記録されることです。

日記が続かない最大の原因は「わざわざアプリを起動する」というハードルにあります。
いつも使っているLINEを開く。そして、友人へ返信するような感覚でテキストや画像を送るだけで記録されるのは、想像以上の快適さです。
思いついた瞬間に息を吐くように記録を残せるため、三日坊主とはおさらば!
Googleドキュメントに日記が蓄積される
LINE自動日記システムを作るメリットの2つ目は、Googleドキュメントに日記が蓄積されることです。
ドキュメントにテキストとして蓄積しておくと、最近話題の「Gemini Notebook(旧NotebookLM)」のソースとしてそのまま読み込ませられます。
「去年の今ごろ、何に悩んでいたっけ?」とAIに質問すれば、過去の自分の日記からズバリ回答してくれるような、最強の外部脳ができあがるというわけです。
Googleカレンダーにも記録される
LINE自動日記システムを作るメリットの3つ目は、Googleカレンダーにも記録されることです。

Googleドキュメントだけでなく、カレンダーにも予定として登録されることで、万が一ドキュメントが消えてしまったときのバックアップとして機能します。
さらに、時系列で視覚的に並ぶカレンダーなら、「いつ・どこで・何をしたか」を直感的に探せますよね。
LINEで送るだけで勝手にカレンダーに登録されるなんて、魔法みたいッスね!
そうなんです! 過去の振り返りが圧倒的にラクになりますよ!
なお、同じ日にLINEで送った複数の文章や画像は、その日の深夜24:00にまとめて「同じ日の内容」として記録されます。
Googleカレンダーを日記として活用する方法も参考になります。
LINE自動日記システムで工夫したこと
ここからは、長く使い続けるためにシステムをどう工夫したかを紹介します。
LINE自動日記システムで工夫したこと
年ごとに新しいファイルを自動生成する
LINE自動日記システムで工夫したことの1つ目は、年ごとに新しいファイルを自動生成するようにしたことです。
Googleドキュメントへ蓄積されていくと聞くと、数年経てばファイルが重くなってしまうのではと心配になりませんか?
そこはご安心ください。
毎日バッチ処理が動く際、データの日付から「西暦」を自動で判定します。
そして「2026年 日記帳」のように、年が変わるタイミングで新しいファイルを自動で作るように設定しました。
ドライブ内のフォルダ構成を綺麗に保つ
LINE自動日記システムで工夫したことの2つ目は、ドライブ内のフォルダ構成を綺麗に保つようにしたことです。
Googleドライブ内の構成はこんな感じになります。
- ドキュメント保存用フォルダ(自分で1回だけ作る)
- 2026年 日記帳(自動生成)
- 2027年 日記帳(2027年1月1日に自動生成)
- 画像保存用の親フォルダ(自分で1回だけ作る)
- 2026年日記用画像(自動生成)
- 20260830_123456.jpg
- 20260831_123456.jpg
- 20260901_123456.jpg
- 2027年日記用画像(2027年1月1日に自動生成)
- 2026年日記用画像(自動生成)
ドキュメントと画像を分けて保存し、年が変わるごとに専用の入れ物が自動で作られます。
何年日記を書き続けてもデータがごちゃごちゃになりません。
スプレッドシートを一時保存として使う
LINE自動日記システムで工夫したことの3つ目は、スプレッドシートを一時保存として使うようにしたことです。
LINEからメッセージを送った瞬間、直接ドキュメントやカレンダーに書き込んでいるわけではありません。
一度スプレッドシートにデータを「バッファ」としてためておく仕組みにしています。
深夜24時になったタイミングで、その日のデータを一気に書き出し、書き終わったらシートを「空」に戻します。
この「ワンクッション」を置くことで、カレンダーの予定が重複するようなエラーを防ぎ、きれいに1日分をまとめられるというわけです。
LINE自動日記システムを構築する手順
ここからは、実際にシステムを構築する手順を紹介します。
大まかな流れは以下の3ステップです。よくわからない人(ほとんどだと思う)はこちらのプロンプトを使って、AIと相談しながらやってください。
【ステップ1】LINE側の準備
LINE自動日記システムを構築する手順の1つ目は、LINE側の準備です。
- LINE Developers(開発者向けサイト)で自分専用のBotを作成する
- プログラムと連携するための「アクセストークン」を発行する
LINEボットのアイコンは次のイラストを自由に使ってください(AIが生成)。

【ステップ2】Google側の準備
LINE自動日記システムを構築する手順の2つ目は、Google側の準備です。
- Googleドライブに「ドキュメント用(日記の本文を収める場所)」「画像用(日記の画像を収める場所)」の2つのフォルダを作成する
- データの一時保存用となるGoogleスプレッドシートを作成する
- 2で作成したGoogleスプレッドシートのGAS(Google Apps Script)に、AIが書いたプログラムを貼り付ける
- 1で作成した2つのフォルダのID、2で作成したGoogleスプレッドシートのID、ステップ1で取得したLINEのチャネルアクセストークン、自分のLINEユーザーIDをGASの中に入れる
なお、GASはこちらになります。
【ステップ3】システム連携とテスト
LINE自動日記システムを構築する手順の3つ目は、システム連携とテストです。
- GASのプログラムを「Webアプリ」として公開(デプロイ)する
- GASで「毎日深夜0時〜1時」のトリガーを設定する
- 公開したURLをLINE側に登録し、両者を連携させる
- 自分のLINEからテスト送信し、正常に記録されるか確認する
システムを構築するための「AI入力用プロンプト」
それでは、この魔法のシステムを構築するための「AIへの指示文(プロンプト)」と「ベースとなるプログラム」を公開します。
ChatGPTやClaudeなどのAIにそのまま貼り付けて、自分専用のシステムを作ってもらいましょう。
AIへの指示文(プロンプト)
AIへの指示文がこちらになります。
あなたは優秀なフルスタックエンジニアであり、プログラミング初心者に優しいメンターです。
これから、私が個人的に利用するための「LINE自動日記システム」の構築をサポートしてください。
一度にすべての手順を出すと初心者の私は混乱してしまうため、必ずステップ・バイ・ステップで、1つの手順が完了して私が報告したら、次の手順を案内するという対話形式で進めてください。
以下の【完成版コード】をベースにして、以下のステップ順に私をナビゲートしてください。
* ステップ1:下準備
* LINE Developersでの「Messaging API」チャネルの作成方法。
* Googleスプレッドシートの作成と、2つのGoogleドライブフォルダ(画像用・ドキュメント用)の作成、それぞれの「ID」を取得する方法。
* ステップ2:GASへのコード貼り付けとIDの設定
* スプレッドシートからGASを開き、以下の【完成版コード】を貼り付ける方法。
* ステップ1で取得したID類をコード上部の該当箇所に設定する方法。
* ステップ3:デプロイとLINEとの連携
* GASをWebアプリとして「デプロイ」する手順(「アクセスできるユーザー」を「全員」にする注意喚起を含む)。
* 取得したWebアプリのURLを、LINE DevelopersのWebhook URLに設定する方法。
* ステップ4:手動テスト(権限の許可)とタイマー設定
* GAS上で `exportDiaryAtMidnight` 関数を手動実行し、初回のみ表示される「承認が必要です」の画面で権限を許可する方法。
* 許可後、GASの「トリガー(時計マーク)」を設定し、毎日深夜に自動実行させる方法。
それでは、ステップ1の案内から始めてください。よろしくお願いします。
上のテキストをコピーして、AIの入力欄に貼り付けてください(まだ送信しないでください)。
ベースとなるGASのコード
続けて以下のコードをコピーし、先ほど貼り付けた指示文のすぐ下に貼り付けて、AIに送信してください。
// ==========================================
// 初期設定:取得したIDをセット
// ==========================================
const SPREADSHEET_ID = "【ここにスプレッドシートのIDを入れる】";
// 画像を保存するフォルダのID(ステップ2で作ったフォルダ)
const IMAGE_FOLDER_ID = "【ここに画像保存用フォルダのIDを入れる】";
// 日記帳ドキュメントを保存するフォルダのID(ステップ2で作ったフォルダ)
const DOC_FOLDER_ID = "【ここにドキュメント保存用フォルダのIDを入れる】";
const LINE_ACCESS_TOKEN = "【ここにLINEのチャネルアクセストークンを入れる】";
// ※自分のLINEユーザーID(セキュリティ強化)
const MY_USER_ID = "【ここに自分のLINEユーザーIDを入れる】";
// ==========================================
// 1. LINEからデータを受け取るプログラム
// ==========================================
function doPost(e) {
const json = JSON.parse(e.postData.contents);
const events = json.events;
if (!events || events.length === 0) {
return ContentService.createTextOutput("OK");
}
const event = events[0];
const userId = event.source.userId;
// セキュリティチェック
if (MY_USER_ID !== "" && userId !== MY_USER_ID) {
return ContentService.createTextOutput("OK");
}
const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getActiveSheet();
const timestamp = new Date();
if (event.type === 'message') {
if (event.message.type === 'text') {
const text = event.message.text;
sheet.appendRow([timestamp, text, "", "", userId]);
} else if (event.message.type === 'image') {
const messageId = event.message.id;
const imageUrl = saveImageToDrive(messageId, timestamp);
sheet.appendRow([timestamp, "", "画像", imageUrl, userId]);
}
}
return ContentService.createTextOutput("OK");
}
function saveImageToDrive(messageId, dateObj) {
const url = 'https://api-data.line.me/v2/bot/message/' + messageId + '/content';
const options = {
"method": "get",
"headers": {
"Authorization": "Bearer " + LINE_ACCESS_TOKEN
}
};
const response = UrlFetchApp.fetch(url, options);
const imageBlob = response.getBlob();
const year = dateObj.getFullYear();
const folderName = year + "年日記用画像";
const parentFolder = DriveApp.getFolderById(IMAGE_FOLDER_ID);
let targetFolder;
const folders = parentFolder.getFoldersByName(folderName);
if (folders.hasNext()) {
targetFolder = folders.next();
} else {
targetFolder = parentFolder.createFolder(folderName);
targetFolder.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
}
const fileName = Utilities.formatDate(dateObj, "JST", "yyyyMMdd_HHmmss") + ".jpg";
imageBlob.setName(fileName);
const file = targetFolder.createFile(imageBlob);
return file.getUrl();
}
// ==========================================
// 2. 毎日夜24時に実行されるまとめプログラム
// ==========================================
function exportDiaryAtMidnight() {
const CALENDAR_NAME = "Diary";
const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getActiveSheet();
const lastRow = sheet.getLastRow();
if (lastRow < 1) {
Logger.log("書き出すデータがありません。");
return;
}
const data = sheet.getRange(1, 1, lastRow, 5).getValues();
const calendars = CalendarApp.getCalendarsByName(CALENDAR_NAME);
const calendar = calendars.length > 0 ? calendars[0] : CalendarApp.createCalendar(CALENDAR_NAME);
// ドキュメント保存用フォルダを取得
const folder = DriveApp.getFolderById(DOC_FOLDER_ID);
const dailyData = {};
data.forEach(function(row) {
const timestamp = new Date(row[0]);
if (isNaN(timestamp.getTime())) return;
const year = timestamp.getFullYear();
const month = timestamp.getMonth() + 1;
const date = timestamp.getDate();
const dateKey = year + "-" + month + "-" + date;
if (!dailyData[dateKey]) {
dailyData[dateKey] = {
dateObj: new Date(year, month - 1, date),
texts: [],
images: []
};
}
const text = row[1];
const isImage = row[2];
const url = row[3];
if (isImage === "画像" && url !== "") {
dailyData[dateKey].images.push(url);
} else if (text !== "") {
dailyData[dateKey].texts.push(text);
}
});
const openedDocs = {};
for (const dateKey in dailyData) {
const dayData = dailyData[dateKey];
const targetDate = dayData.dateObj;
const year = targetDate.getFullYear();
const month = targetDate.getMonth() + 1;
const day = targetDate.getDate();
// 1. Googleドキュメントへの出力
const fileName = year + "年 日記帳";
if (!openedDocs[year]) {
let files = folder.getFilesByName(fileName);
let doc = null;
let found = false;
// ゴミ箱に入っていないファイルを確実に探す
while (files.hasNext()) {
let file = files.next();
if (!file.isTrashed()) {
doc = DocumentApp.openById(file.getId());
found = true;
break;
}
}
// 見つからなければ新規作成
if (!found) {
doc = DocumentApp.create(fileName);
let docFile = DriveApp.getFileById(doc.getId());
docFile.moveTo(folder);
doc.getBody().appendParagraph("# " + fileName).setHeading(DocumentApp.ParagraphHeading.HEADING1);
}
openedDocs[year] = doc;
}
const doc = openedDocs[year];
const body = doc.getBody();
const weekdays = ['日', '月', '火', '水', '木', '金', '土'];
const weekday = weekdays[targetDate.getDay()];
const dateHeading = year + "年" + month + "月" + day + "日(" + weekday + ")";
body.appendParagraph(dateHeading).setHeading(DocumentApp.ParagraphHeading.HEADING2);
dayData.texts.forEach(function(text) {
body.appendParagraph(text);
});
dayData.images.forEach(function(imageUrl) {
try {
const fileIdMatch = imageUrl.match(/id=([a-zA-Z0-9_-]+)/) || imageUrl.match(/d\/([a-zA-Z0-9_-]+)/);
if (fileIdMatch && fileIdMatch[1]) {
const imageFile = DriveApp.getFileById(fileIdMatch[1]);
const blob = imageFile.getBlob();
const img = body.appendImage(blob);
const width = img.getWidth();
const height = img.getHeight();
if (width > 600) {
const ratio = 600 / width;
img.setWidth(600);
img.setHeight(height * ratio);
}
}
} catch (e) {
Logger.log("画像挿入エラー: " + e.message);
}
});
body.appendParagraph(""); // 空白行を追加
// 2. Googleカレンダーへの出力
const eventTitle = "Diary_" + dateKey;
const events = calendar.getEventsForDay(targetDate);
let targetEvent = null;
events.forEach(function(e) {
if (e.getTitle() === eventTitle) targetEvent = e;
});
let descriptionText = dayData.texts.join("\n\n");
if (dayData.images.length > 0) {
descriptionText += "\n\n【画像リンク】\n";
dayData.images.forEach(function(url, i) {
descriptionText += "画像" + (i+1) + ": " + url + "\n";
});
}
if (targetEvent) {
const currentDesc = targetEvent.getDescription() || "";
targetEvent.setDescription(currentDesc + "\n\n" + descriptionText);
} else {
calendar.createAllDayEvent(eventTitle, targetDate, { description: descriptionText });
}
}
for (let year in openedDocs) {
openedDocs[year].saveAndClose();
}
sheet.clearContents();
Logger.log("出力完了。シートのデータをクリアしました。");
}
これをAIに投げるだけで、設定手順をステップバイステップで案内してくれます。
あとはAIの指示に従って作業を進めるだけ。わからなかったら質問するだけで、ものの数十分でシステムが完成です。
なお、GASの知識がある方は、AIを使わずこのままご自身のスプレッドシートのGASに貼り付けてお使いください。
その場合は、コード上部にあるID部分(【ここに〇〇を入れる】の箇所)をご自身のものに書き換え、GASの画面で「毎日深夜0時〜1時」のトリガーを設定するだけで動きますよ。
まとめ
面倒な日記の習慣も、自動化の力を借りれば嘘のようにラクになります。
ぜひこの仕組みを手に入れて、日々のちょっとした出来事を記録する楽しさを味わってみてください!









