Skip to content

lineNotify

Published: at 下午05:36

LineNotify

npm init

持續按enter

{
"name": "linenotify",
"version": "1.0.0",
"description": "lineNotify",
"main": "index.js",
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
},
"author": "[email protected]",
"license": "ISC"
}

接著安裝需要的套件

npm install express nodemon request

在package.json 中的script 加入 nodemon執行語法

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "s": "nodemon index.js"
}

執行nodemon語法的話 不用每次改動程式碼都要重新啟動nodeServer

npm run s

即可使用

前往notiy開通服務

右上角帳號資料 點開的選單 選 登錄服務

將資料填齊

其中將 callbackurl 填寫 (不要漏掉最後的斜線)

http://localhost:3000/

等下登錄服務的時候會用到

跟著流程成到下一步後

回到服務一覽表 就可以看到 剛剛 註冊的服務

點進去 會看到ClientId 及ClientSecert(要點擊旁邊按鈕才看到的內容)

回到程式碼部分

開啟到剛剛npm init 後的目錄

新增三個檔案 index.js , index.html , auth.html

先將index.js 的server寫好

const express = require("express");
const app = express();

app.get("/", function (req, res) {
  res.sent("helloWorld");
});

app.listen(3000, function () {
  console.log("Example app listening on port 3000!");
});

存檔

在cmd 打入指令

npm run s

打開chrome 連線到 http://localhost:3000/ 看到 helloWorld 代表成功將server 寫好並開啟了

現在準備要使用得畫面

用編輯器 (visual code or 記事本) 開啟檔案 index.html 寫入

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>

  <body>
    <form method="post" action="/registerLineNotify">
      <div>
        <label> 要註冊的臨時碼</label>
        <input type="text" name="token" value="{token}" readonly />
      </div>
      <div>
        <label> 要註冊的Client ID</label>
        <input type="text" name="clientId" />
      </div>
      <div>
        <label> 要註冊的Client Secret</label>
        <input type="text" name="clientSecret" />
      </div>

      <input type="submit" value="註冊" />
    </form>
  </body>
</html>

回到 index.js 撰寫 相關觸發的程式碼

將畫面(index.html) 對到 http://localhost:3000 的 get 方法

//準備 用變數取代html 中需要取代變數的function ,準備好後要利用callBackMethod 將畫面傳去前端

const fs = require("fs");

function render(filename, params, callback) {
  fs.readFile(filename, "utf8", function (err, data) {
    if (err) return cabllack(err);
    for (var key in params) {
      data = data.replace("{" + key + "}", params[key]);
    }
    callback(null, data); // 用 callback 傳回結果
  });
}

app.get("/", function (req, res) {
  console.log("req", req.query.code);
  render(
    "index.html",
    {
      token: req.query.code,
    },
    function (err, data) {
      res.send(data); // 準備 傳去前端 的callBackMethod
    }
  );
});

為了要讓express 看得懂 http傳回來的body 要再加入(放在所有function 和route 的上面 避免順序問題影響)

const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: false }));

撰寫 寫註冊lineNotify服務的route

app.get("/register/:clientId", function (req, res) {
  render(
    "auth.html",
    {
      clientId: req.params.clientId,
    },
    function (err, data) {
      res.send(data);
    }
  );
});

撰寫發送訊息的網頁

修改index.js

app.post("/pushLineNotifyMessage", function (req, res) {
  console.log(req.body.message);

  pushMessage(req.body.message, req.cookies.accessToken, function (data) {
    render(
      "pushLineNotify.html",
      {
        accessToken: req.cookies.accessToken,
      },
      function (err, data) {
        res.send(data); // 這邊要寫一個 function 才能接收到資料
      }
    );
  });
});
app.get("/pushLineNotify", function (req, res) {
  if (req.cookies.accessToken) {
    render(
      "pushLineNotify.html",
      {
        accessToken: req.cookies.accessToken,
      },
      function (err, data) {
        res.send(data); // 這邊要寫一個 function 才能接收到資料
      }
    );
  } else {
    res.send("token不存在請去註冊");
  }
});

新增一個 pushLineNotify.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>

  <body>
    <form method="post" action="/pushLineNotifyMessage">
      <div>
        <label>發送的token</label>
        <input type="text" name="accessToken" value="{accessToken}" readonly />
      </div>
      <div>
        <label> 要送出的訊息</label>
        <input type="text" name="message" />
      </div>

      <input type="submit" value="送出" />
    </form>
  </body>
</html>

撰寫 註冊完後 要取得 傳輸token 的postMethod

const request = require("request");

function registerLineNotify(token, clientId, clientSecret, callback) {
  const clientServerOptions = {
    method: "POST",
    uri: "https://notify-bot.line.me/oauth/token",
    form: {
      grant_type: "authorization_code",
      code: token,
      redirect_uri: "http://localhost:3000/",
      client_id: clientId,
      client_secret: clientSecret,
    },
  };

  request(clientServerOptions, function (error, response, body) {
    console.log(body);
    let accessToken = JSON.parse(body).access_token;
    console.log("accessToken:", accessToken);
    if (body.status == 200) {
      callback(accessToken);
    } else {
      callback("註冊失敗,請重新註冊");
    }
    return;
  });
}

app.post("/registerLineNotify", function (req, res) {
  registerLineNotify(
    req.body.token,
    req.body.clientId,
    req.body.clientSecret,
    function (data) {
      if (data !== "註冊失敗,請重新註冊") {
        res.cookie("accessToken", data, { maxAge: 24 * 60 * 60 * 1000 });
      } else {
        res.clearCookie("accessToken");
      }
      res.send(data);
    }
  );
});

撰寫 cookie 操作的method 把註冊完成的accessToken 存在cookie中

npm install cookie-parser
app.use(cookieParser());

最後寫完的index.js 會如下

const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const fs = require("fs");
const request = require("request");
const cookieParser = require("cookie-parser");

app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false }));

function render(filename, params, callback) {
  fs.readFile(filename, "utf8", function (err, data) {
    if (err) return cabllack(err);
    for (var key in params) {
      data = data.replace("{" + key + "}", params[key]);
    }
    callback(null, data); // 用 callback 傳回結果
  });
}

function registerLineNotify(token, clientId, clientSecret, callback) {
  const clientServerOptions = {
    method: "POST",
    uri: "https://notify-bot.line.me/oauth/token",
    form: {
      grant_type: "authorization_code",
      code: token,
      redirect_uri: "http://localhost:3000/",
      client_id: clientId,
      client_secret: clientSecret,
    },
  };

  request(clientServerOptions, function (error, response, body) {
    console.log(body);
    let accessToken = JSON.parse(body).access_token;
    console.log("accessToken:", accessToken);

    if (JSON.parse(body).status == 200) {
      callback(accessToken);
    } else {
      callback("註冊失敗,請重新註冊");
    }
    return;
  });
}

app.post("/registerLineNotify", function (req, res) {
  console.log(req.body.token);
  console.log(req.body.clientId);
  console.log(req.body.clientSecret);

  registerLineNotify(
    req.body.token,
    req.body.clientId,
    req.body.clientSecret,
    function (data) {
      console.log("accessToken:", data);
      if (data !== "註冊失敗,請重新註冊") {
        res.cookie("accessToken", data, { maxAge: 24 * 60 * 60 * 1000 });
      } else {
        res.clearCookie("accessToken");
      }

      res.send(data); // 這邊要寫一個 function 才能接收到資料
    }
  );
});

function pushMessage(message, token, callback) {
  const clientServerOptions = {
    method: "POST",
    uri: "https://notify-api.line.me/api/notify",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    auth: {
      bearer: token,
    },
    form: {
      message: message,
    },
  };
  request(clientServerOptions, function (error, response, body) {
    console.log(error, response, body);
    callback(body);
    return;
  });
}

app.get("/register/:clientId", function (req, res) {
  render(
    "auth.html",
    {
      clientId: req.params.clientId,
    },
    function (err, data) {
      res.send(data);
    }
  );
});

app.post("/pushLineNotifyMessage", function (req, res) {
  console.log(req.body.message);

  pushMessage(req.body.message, req.cookies.accessToken, function (data) {
    render(
      "pushLineNotify.html",
      {
        accessToken: req.cookies.accessToken,
      },
      function (err, data) {
        res.send(data); // 這邊要寫一個 function 才能接收到資料
      }
    );
  });
});
app.get("/pushLineNotify", function (req, res) {
  if (req.cookies.accessToken) {
    render(
      "pushLineNotify.html",
      {
        accessToken: req.cookies.accessToken,
      },
      function (err, data) {
        res.send(data); // 這邊要寫一個 function 才能接收到資料
      }
    );
  } else {
    res.send("token不存在請去註冊");
  }
});

app.get("/", function (req, res) {
  console.log("req", req.query.code);
  render(
    "index.html",
    {
      token: req.query.code,
    },
    function (err, data) {
      res.send(data); // 這邊要寫一個 function 才能接收到資料
    }
  );
});

app.listen(3000, function () {
  console.log("Example app listening on port 3000!");
});

用編輯器 (visual code or 記事本) 開啟檔案 auth.html 寫入

<!doctype html>
<html lang="tw">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script>
      function oAuth() {
          var URL = 'https://notify-bot.line.me/oauth/authorize?';
          URL += 'response_type=code';
          URL += '&client_id={clientId}';
          URL += '&redirect_uri=http://localhost:3000/';
          URL += '&scope=notify';
          URL += '&state=NO_STATE';
          window.location.href = URL;
    </script>
  </head>
  <body>
    <button onclick="oAuth();">連結到 LineNotify 按鈕</button>
  </body>
</html>

存檔

現在要去登入 自己的 lineNotify 服務

用chrome 開啟剛剛寫好的auth.html

會看到 連結到 LineNotify 按鈕 點下去後 回連結到 lineNotify 的官網 會問你 要連結到哪個群組

lineNotify 僅可以連結到 lineNotify 的 聊天室 或是群組

選完會出現剛剛做的畫面

再將clientId及clientSecert 填入 輸入方塊 後 按註冊

若成功會收到一組 亂數產生的token

以後就可以利用這個來傳送訊息到你的 lineNotify了

github