📑

NotionにDeepLとChatGPTを使ってオリジナルの英語単語帳を作る

2024/01/18に公開

NotionにDeepLとChatGPTを使ってオリジナルの英語単語帳を作る

英語の勉強していますか?
自分は今とても英語の勉強をやりたいです。

なので、Notionにわからない単語を書いておくだけで自動で意味と例文と語源をNotionに保存するスクリプトを書きました。

スクリプト

スクリプトはGASで書きました。理由はサーバーを用意することなく無限に動かせるからです。
そして、語源と例文はChatGPTに考えさせました。

1つ1つ解説するのはめんどくさいので、コードをそのまま貼ります。適宜データを変更してください。
また、ChatGPTのAPIとNotionAPI、DeepLのAPIのAPI Keyはそれぞれで取得してください。

下記のスクリプトを1時間ずつ動かして、自動で更新するように実装しています。

以下がコードです。

function run() {
  let createLastTime = getLastCheckedTime();
  getPagesFromNotion(createLastTime);
}

function getPagesFromNotion(lastCheckedTime) {
  const url = `https://api.notion.com/v1/databases/${DATABASE_ID}/query`;

  const options = {
    method: 'post',
    headers: {
      'Authorization': `Bearer ${NOTION_API_KEY}`,
      'Content-Type': 'application/json',
      'Notion-Version': "2021-08-16"
    },
    payload: JSON.stringify({
      filter: {
        property: "Created time",
        created_time: {
          after: lastCheckedTime
        }
      }
    }),
    sorts: [
      {
        property: "Created time",
        direction: "ascending"
      }
    ],
    muteHttpExceptions: true
  };

  try {
    const response = UrlFetchApp.fetch(url, options);
    const data = JSON.parse(response.getContentText());

    if (data.results.length > 0) {
      // console.log(data.results)

      data.results.sort((a, b) => {
        return new Date(a.properties['Created time'].created_time) - new Date(b.properties['Created time'].created_time);
      });

      // data.results.forEach(page => {
      //   console.log(page.properties["単語"].title[0].plain_text);
      // });
      

      data.results.forEach(page => {
        let pageId = page.id;
        let text = page.properties['単語'].title[0].text.content
        let translageText = translateTextWithDeepL(text);

        let created_time = page.properties['Created time'].created_time
        const properties = {
          '意味': { // 例: 'Name' というタイトルのプロパティを更新
            'rich_text': [
              {
                'text': {
                  'content': translageText
                }
              }
            ]
          }
        }

        updateNotionPageProperties(pageId, properties);

        let prompt = '「' + text + '」という単語を使って下記のフォーマットで簡単で短めの英語の例文とその後ろに()でその日本語翻訳を1つだけ作成してください。必ず1つだけにしてください。'
        let example = generateExampleSentence(text, prompt);

        const exampleText = {
          '例文': { // 例: 'Name' というタイトルのプロパティを更新
            'rich_text': [
              {
                'text': {
                  'content': example
                }
              }
            ]
          }
        }
        updateNotionPageProperties(pageId, exampleText);

        let etymology = '「' + text + '」という単語の語源を解説して。解説はできるだけ短く50語以内に解説して;'
        let etymologyText = generateExampleSentence(text, etymology);

        const etymologyInput = {
          '語源': { // 例: 'Name' というタイトルのプロパティを更新
            'rich_text': [
              {
                'text': {
                  'content': etymologyText
                }
              }
            ]
          }
        }
        updateNotionPageProperties(pageId, etymologyInput);

        saveLastCheckedTime(created_time)
      });
    } else {
      console.log("データは存在しませんでした");
    }
  } catch (error) {
    console.error('Error fetching pages from Notion:', error);
  }
}

function translateTextWithDeepL(text) {
  const url = `https://api-free.deepl.com/v2/translate?auth_key=${DEEPL_API_KEY}`;
  const payload = {
    'text': text,
    'target_lang': "JA"
  };

  const options = {
    'method': 'post',
    'payload': payload,
    'muteHttpExceptions': true
  };

  try {
    const response = UrlFetchApp.fetch(url, options);
    const jsonResponse = JSON.parse(response.getContentText());

    if (jsonResponse.translations && jsonResponse.translations.length > 0) {
      console.log(jsonResponse.translations)
      const translatedText = jsonResponse.translations[0].text;
      // console.log(`Translated Text: ${translatedText}`);
      return translatedText;
    }
  } catch (error) {
    console.error('Error during translation with DeepL:', error);
  }
}

function updateNotionPageProperties(pageId, properties) {
  const url = `https://api.notion.com/v1/pages/${pageId}`;

  const options = {
    method: 'patch',
    headers: {
      'Authorization': `Bearer ${NOTION_API_KEY}`,
      'Content-Type': 'application/json',
      'Notion-Version': "2021-08-16"
    },
    payload: JSON.stringify({
      properties: properties
    }),
    muteHttpExceptions: true
  };

  try {
    const response = UrlFetchApp.fetch(url, options);
    const jsonResponse = JSON.parse(response.getContentText());
    // console.log(jsonResponse);
  } catch (error) {
    console.error('Error updating Notion page:', error);
  }
}

function generateExampleSentence(word, prompt) {
  const url = "https://api.openai.com/v1/chat/completions";
  // const prompt = `Create an English sentence using the word "${word}":`;
  // const prompt = '「' + word + '」という単語を使って下記のフォーマットで簡単で短めの英語の例文とその後ろに()でその日本語翻訳を1つだけ作成してください。必ず1つだけにしてください。'
  const apiUrl = 'https://api.openai.com/v1/chat/completions';

  const messages = [
    { 'role': 'system', 'content': prompt },
    { 'role': 'user', 'content': prompt },
  ];

  const headers = {
    'Authorization': 'Bearer ' + OPENAI_API_KEY,
    'Content-type': 'application/json',
    'X-Slack-No-Retry': 1
  };
  //オプションの設定(モデルやトークン上限、プロンプト)
  const options = {
    'muteHttpExceptions': true,
    'headers': headers,
    'method': 'POST',
    'payload': JSON.stringify({
      'model': 'gpt-3.5-turbo',
      'max_tokens': 2000,
      'temperature': 0.9,
      'messages': messages
    })
  };
  //OpenAIのChatGPTにAPIリクエストを送り、結果を変数に格納
  const response = JSON.parse(UrlFetchApp.fetch(apiUrl, options).getContentText());
  //ChatGPTのAPIレスポンスをログ出力
  // console.log(response.choices[0].message.content);
  return response.choices[0].message.content;
}

function getLastCheckedTime() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const lastCheckedTime = sheet.getRange('A1').getValue();
  return lastCheckedTime;
}

function saveLastCheckedTime(time) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  sheet.getRange('A1').setValue(time);
}


Discussion