通知ファイアウォール by Gemini

## 目次
>1. [通知洪水に歯止めをかけたい](https://qiita.com/kawashimakoki22084/items/479e7f1a778e48db79ea#通知が多い)
>2. [geminiに通知を見張らせる](https://qiita.com/kawashimakoki22084/items/479e7f1a778e48db79ea#geminiにタイムラインを見張らせろ)
>3. [フローチャート](https://qiita.com/kawashimakoki22084/items/479e7f1a778e48db79ea#フローチャート)
>4. [定常通知分析&タスク追加を実演](https://qiita.com/kawashimakoki22084/items/479e7f1a778e48db79ea#実演動画)
>5. [あなたの手元にも通知警備員を！](https://qiita.com/kawashimakoki22084/items/479e7f1a778e48db79ea#公開taskerプロジェクト)



## 通知が多い！

多すぎる。通知が！

LINEに関しては、常に公式アカウントからの通知が100件超える始末だ。

![スクリーンショット 2025-01-02 19.55.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3844414/7525ef91-fdbc-1aa1-d2a9-54a6016d289c.png)


オトモダチからのLINEメッセージの打率は1割を切っているとみていい。

いらない情報はカットされるべきだろう。

なにせそうでもしないと、**1日にスマホを2600回触るハメになる**からだ。(Hansen,Anders)

## Geminiにタイムラインを見張らせろ！

そうだ。**自分の代わりにスマホのTL(タイムライン)を見張らせて、**

**大事そうなメッセージだけ俺に教えてくれればいい**じゃん！

と、いうわけでシステムを組んでみた。

# フローチャート

```mermaid
graph TD;
    **元通知**-->hhtpリクエスト-->スプレッドシート;
    スプレッドシート-->gemini_API;
    gemini_API-->スプレッドシート;
    スプレッドシート-->Gメールに結果を送信-->taskerで読み取り;
    taskerで読み取り-->**処理後通知**
```

```mermaid
graph TD;
    **希塩酸を滴下**-->**白色沈殿が生成**
    **白色沈殿が生成**-->**濾液にH2S**
    **白色沈殿が生成**-->**沈殿に熱湯を加える**
    **沈殿に熱湯を加える**-->**全て溶解**
    **濾液にH2S**-->**黒色沈殿が生成**
    **黒色沈殿が生成**-->**濾液(処理済)にNH3**
    **黒色沈殿が生成**-->**Cu**
    **全て溶解**-->**Kr2Cr2O4を加えると黄色沈殿**
    **Kr2Cr2O4を加えると黄色沈殿**-->**Pb**
    **濾液(処理済)にNH3,H2S,{(2NH4)CO3}**-->**白色沈殿**
    **H2SO4**-->**白色沈殿**
    **白色沈殿**-->**Ba**
```
```mermaid
graph TD;
    A["希塩酸を滴下"] --> B["白色沈殿が生成"]
    B --> C["濾液にH₂S"]
    B --> D["沈殿に熱湯を加える"]
    D --> E["全て溶解"]
    C --> F["黒色沈殿が生成"]
    F --> G["濾液(処理済)にNH₃"]
    G["濾液(処理済)にNH₃"] --> O["H2S,(NH4)2CO3"]
    O["H2S,(NH4)2CO3"] --> K
    F --> H["Cu"]
    E --> I["K₂Cr₂O₄を加えると黄色沈殿"]
    I --> J["Pb"]
    G --> K["白色沈殿"]
    L["H₂SO₄"] --> K
    K --> M["Ba"]
    H --> P["Pb,Cu,Ba を検出"]
    J --> P["Pb,Cu,Ba を検出"]
    M --> P["Pb,Cu,Ba を検出"]
```


```mermaid
graph TD;
    **培地製作**-->**菌の塗布**
    **PBSA粉末製作**-->**培地製作**
    **試料選定**-->**試料取得**
    **試料取得**-->**希釈処理**
    **希釈処理**-->**菌の塗布**
    **菌の塗布**-->**四週間の培養**
    **四週間の培養**-->**菌の単離**
　　**菌の単離**-->**普通寒天培地で分解**
  　**四週間の培養**-->**PBSAから抽出した液で培養**
   **普通寒天培地で分解**-->**無機寒天培地で分解**
    
```

**別の機会で作った図⇩**
![スクリーンショット 2025-01-02 17.59.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3844414/a4203902-1889-08ca-ae52-597cdd4f28f1.png)

**詳解**
![スクリーンショット 2025-01-02 18.08.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3844414/d8b7bf07-f5a2-4cb5-ebd0-f45a42ce7967.png)

## 実演動画

:::note info
**定期実行の実演**
・「みかんを買ってきて！」というお使いLINEを検知し鳴るスマホ
・予定に言及するメッセージへ対応し、todoリストを自動で追加するプログラムも実行中。
　**例：「明日宿題教えて！」=＞「明日宿題教える」とtodoタスクを追加。**
:::

**重要内容の自動抽出**
<iframe width="560" height="315" src="https://www.youtube.com/embed/xGjLFI-ndvk?si=NgS5tQOhxD9dEu1V" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

**タスクの自動追加**
<iframe width="560" height="315" src="https://www.youtube.com/embed/Qrsurghjd-4?si=slTpQ3c3zvY6ZSLG" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## 公開taskerプロジェクト


:::note warn
**使用方法**
１　「resheetmodule」の「Auth」を選択しスプレッドシートIDを自分のものに変更する
２　ホームの「通知が表示された Gmail, me」を使用できる状態にする

:::

taskerの方のプログラムファイルのダウンロードリンクです。

https://drive.google.com/file/d/1O1EN70VcbCdrXq1UxW0-pCiUxPoGT-e0/view?usp=sharing

# 公開GASコード

:::note info
**実装方法**
1 [テンプレート](https://docs.google.com/spreadsheets/d/1MFqvYQFxQ4nrkHOI79UghsPPlhKfAkOVaWDN31yRT0s/edit?usp=sharing)をダウンロード。
2 開いて「拡張機能」からgoogle app scriptを起動。
3 以下のプログラムをコピペして載せる。
4 「トリガー」から定期実行させるようにする。
5 この記事の下の「listIDプログラム」の指示に従い設定する。
:::

```java:sort.gs
function endless_sort() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  var rows = sheet.getLastRow()-1;
  var range = sheet.getRange(2,1,rows,4);
  range.sort({column:1,ascending:false});
}
```

```java:get_gemini.gs


const GEMINI_API = 'APIキーを入力';

function redirect_GeminiPro() {

  Utilities.sleep(5000);

  //通知文を取得
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName('notion data');
  var cell = sheet.getRange('B2');
  var notiontxt = cell.getValue();
  Logger.log("通知文：" + notiontxt);

  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName('prompt data');
  var cell = sheet.getRange(2,4,15);
  var prompttxt = cell.getValues();
  Logger.log("指示文：" + prompttxt);

 
  //geminiと通信
  const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${GEMINI_API}`
        , payload = {
            'contents': [
              {
                'parts': [{
                  'text': prompttxt + ";" + notiontxt
                }]
              }
            ]
          }
        , options = {
            'method': 'post',
            'contentType': 'application/json',
            'payload': JSON.stringify(payload)
          };

  const res = UrlFetchApp.fetch(url, options)
        , resJson = JSON.parse(res.getContentText());

  // responseがちゃんと返ってきていることを確認
  if (resJson && resJson.candidates && resJson.candidates.length > 0) {
    /** 以下の位置を取得
    {
      "candidates": [
      {
        "content": {
        "parts": [
        {
          "text": 
    */
    console.log(resJson.candidates[0].content.parts[0].text);
    const response = resJson.candidates[0].content.parts[0].text
  } else {
    // HARM_CATEGORYによって、無回答の場合も多々あり
    console.log('回答が返されませんでした。');
  }
  
  if(resJson.candidates[0].content.parts[0].text.match('はい')){
    //メールを送信する
    //送信先のメールアドレス
    const recipient = "メアド";
    //メールの件名
    const subject = "notionF_servise";
    //メールの本文
    const body = "notiontxt"
  
    //メールを送信する
    GmailApp.sendEmail(recipient, subject, body);
    console.log ("メールは正常に送られました")
  }else {
    // HARM_CATEGORYによって、無回答の場合も多々あり
    console.log('メールは送られませんでした。');
  }
  
};


```
```java:add_shedule.gs
function add_schedule() {

  Utilities.sleep(10000);

  //通知文を取得
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName('notion data');
  var cell = sheet.getRange('B2');
  var notiontxt = cell.getValue();
  Logger.log("通知文：" + notiontxt);

  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName('prompt data');
  var cell = sheet.getRange(2,2,15);
  var prompttxt = cell.getValues();
  Logger.log("指示文：" + prompttxt);

 
  //geminiと通信
  const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${GEMINI_API}`
        , payload = {
            'contents': [
              {
                'parts': [{
                  'text': prompttxt + ";" + notiontxt
                }]
              }
            ]
          }
        , options = {
            'method': 'post',
            'contentType': 'application/json',
            'payload': JSON.stringify(payload)
          };

  const res = UrlFetchApp.fetch(url, options)
        , resJson = JSON.parse(res.getContentText());

  // responseがちゃんと返ってきていることを確認
  if (resJson && resJson.candidates && resJson.candidates.length > 0) {
    /** 以下の位置を取得
    {
      "candidates": [
      {
        "content": {
        "parts": [
        {
          "text": 
    */
    console.log(resJson.candidates[0].content.parts[0].text);
    var tax = resJson.candidates[0].content.parts[0].text
   
    var taskListId = "";  // タスクリストID

  var task = {
    title: tax // タスクのタイトルを設定
  };

  
  // Google Tasks APIを使ってタスクをタスクリストに追加
  var result = Tasks.Tasks.insert(task, taskListId);
  Logger.log("タスクが追加されました: " + result.title);

  /*　要素が多すぎるので凍結
  //アクセス可能なカレンダーのIDを指定して、Googleカレンダーを取得する
  let myCalendar = CalendarApp.getCalendarById('メアドを入力');
  //Googleカレンダーに登録する日付を設定する
  let startDate = new Date(getFullYear(), month, day);
  myCalendar.createAllDayEvent(name,startDate);
  */
 

  } else {
    // HARM_CATEGORYによって、無回答の場合も多々あり
    console.log('回答が返されませんでした。');

}
}
```

:::note warn
**todoリストIDの取得用プログラム_使用方法**
1　google_cloudコンソールで「taskerAPI」を有効化
2　以下のプログラムをGAS上で実行
3　add_shedule.gsにリストIDを代入

:::

```java:get_listID.gs
function getList() {
  var taskLists = Tasks.Tasklists.list();
  Logger.log(taskLists.items[0].title);
  Logger.log(taskLists.items[0].id);
}
```

## geminiAPIキーの所得方法

以下のサイトでゲットする。やり方は検索しても出てくる。

https://console.cloud.google.com/


## 参考サイト

https://auto-worker.com/blog/?p=8679#

https://aistudio.google.com/u/1/apikey

https://console.cloud.google.com/apis/dashboard?authuser=1&project=gen-lang-client-0907417392&pageState=(%22duration%22:(%22groupValue%22:%22PT1H%22,%22customValue%22:null))

https://p4p.co.jp/geminizer/gemini-api-gas/#index_id0

https://tasker.joaoapps.com/userguide/en/help/ah_http_request.html


## 終わり！
終