├── .env.sample
├── test_data
└── dog.png
├── requirements.txt
├── docker-compose.yml
├── Dockerfile
├── .gitignore
├── .dockerignore
├── templates
├── notify_index.html
└── notify_confirm.html
├── fly.toml.sample
├── MIT-LICENSE
├── README.md
└── app.py
/.env.sample:
--------------------------------------------------------------------------------
1 | LINE_CLIENT_ID=
2 | LINE_CLIENT_SECRET=
3 | LINE_REDIRECT_URI=
4 |
--------------------------------------------------------------------------------
/test_data/dog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/louis70109/flask-line-notify/HEAD/test_data/dog.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask==2.0.3
2 | requests==2.23.0
3 | lotify
4 | gunicorn
5 | Jinja2==3.1.1
6 | MarkupSafe==2.1.1
7 | Werkzeug==2.0.3
8 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | test_url_for:
5 | image: flask-line-notify
6 | build: .
7 | ports:
8 | - 8000:8000
9 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.7
2 | LABEL Name=flask-line-notify Version=0.0.1
3 | WORKDIR /app
4 | COPY ["requirements.txt", "/app/"]
5 | RUN python3 -m pip install -r requirements.txt
6 | ADD . /app
7 | ENV FLASK_APP=app.py
8 | EXPOSE 8000
9 | # CMD ["gunicorn", "api:app", "--log-file=-"]
10 | CMD ["flask", "run", "--host", "0.0.0.0", "--port", "8000"]
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Distribution / packaging
2 | .Python
3 | *.pyc
4 | env/
5 | build/
6 | develop-eggs/
7 | dist/
8 | downloads/
9 | eggs/
10 | .eggs/
11 | lib/
12 | lib64/
13 | parts/
14 | sdist/
15 | var/
16 | *.egg-info/
17 | .installed.cfg
18 | *.egg
19 | node_modules/
20 | # Serverless directories
21 | .serverless
22 | .vscode/
23 | .package-lock.json
24 | .env
25 | __pycache__
26 | .idea
27 | venv
28 | fly.toml
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.gitignore
6 | **/.project
7 | **/.settings
8 | **/.toolstarget
9 | **/.vs
10 | **/.vscode
11 | **/*.*proj.user
12 | **/*.dbmdl
13 | **/*.jfm
14 | **/azds.yaml
15 | **/bin
16 | **/charts
17 | **/docker-compose*
18 | **/Dockerfile*
19 | **/node_modules
20 | **/npm-debug.log
21 | **/obj
22 | **/secrets.dev.yaml
23 | **/values.dev.yaml
24 | README.md
--------------------------------------------------------------------------------
/templates/notify_index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 | LINE Notify
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/fly.toml.sample:
--------------------------------------------------------------------------------
1 | # fly.toml app configuration file generated for flask-line-notify on 2024-04-04T01:11:08+08:00
2 | #
3 | # See https://fly.io/docs/reference/configuration/ for information about how to use this file.
4 | #
5 |
6 | app = 'flask-line-notify'
7 | primary_region = 'nrt'
8 |
9 | [build]
10 |
11 | [env]
12 | LINE_CLIENT_ID = ''
13 | LINE_CLIENT_SECRET = ''
14 | LINE_REDIRECT_URI = 'https://DOMAIN/callback'
15 |
16 | [http_service]
17 | internal_port = 8000
18 | force_https = true
19 | auto_stop_machines = true
20 | auto_start_machines = true
21 | min_machines_running = 0
22 | processes = ['app']
23 |
24 | [[vm]]
25 | memory = '256mb'
26 | cpu_kind = 'shared'
27 | cpus = 1
28 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2019 nijia lin
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Flask-LINE-notify
2 | [](https://opensource.org/licenses/MIT)
3 | [](https://badge.fury.io/py/lotify)
4 |
5 | 前一陣子看到保哥寫了一篇 [LINE Notify 的文章](https://blog.miniasp.com/post/2020/02/17/Go-Through-LINE-Notify-Without-Any-Code),詳細的介紹整個操作流程,這個專案則是去實作整個流程的範例,
6 |
7 | 同時也是 [Lotify](https://github.com/louis70109/lotify) 的範例程式,歡迎大家取用試玩。
8 |
9 | # LINE Notify 註冊
10 |
11 | 可以參考我之前[鐵人賽的文章](https://nijialin.com/2019/09/20/Day5-%E5%81%9A%E4%B8%80%E5%80%8B%E8%88%87-LINE-Notify-%E9%80%A3%E5%8B%95%E7%9A%84%E6%9C%8D%E5%8B%99/)。
12 |
13 | 設定的 Callback Url 為 `http://YOUR_DOMAIN/callback`,本地端測試網址就為 `http://localhost:5000/callback`
14 |
15 | # GCP 一鍵佈署
16 |
17 | [](https://deploy.cloud.run)
18 |
19 | 按下上面部署按鈕之後需要設定 LINE Notify 所需三個`環境變數`
20 |
21 | 
22 |
23 |
24 | # 本地端測試
25 |
26 | ```sh
27 | cp .env.sample .env
28 | python api.py
29 | ```
30 |
31 | 或是
32 |
33 | ```dockerfile
34 | cp .env.sample .env
35 | docker-compose up
36 | ```
37 |
38 | > 兩個方法擇一
39 |
40 | # 步驟
41 |
42 | ### [LINE Notify](https://notify-bot.line.me/zh_TW/) 基本設定
43 | 
44 |
45 | ---
46 |
47 | ### 初始頁面
48 |
49 | 開啟瀏覽器後輸入 `http://localhost:5000` 後就會看到一個輸入按鈕
50 |
51 | 
52 |
53 | ---
54 |
55 | ### 綁定通知 - 選擇`1對1聊天接收`
56 | 
57 |
58 | ---
59 |
60 | ### 連動完成
61 | 這時候 LINE Notify 就會推播一個綁定成功的通知
62 |
63 | 
64 |
65 | ---
66 |
67 | ### 網頁範例
68 | 同時瀏覽器會被導到`/notify/check` 並帶上 code & state 的資訊
69 | 
70 |
71 | ---
72 |
73 | ### 實測內容
74 | 
75 | ---
76 |
77 | # 路由
78 |
79 | - GET /
80 | - 使用者點選綁定的畫面
81 | - GET /callback
82 | - LINE Notify 的設定以及認證完後的 callback 路由
83 | - 幫忙發送推播的路由(因為有[ CORS 問題](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/CORS)所以需要一個 api 來幫忙轉發)
84 | - POST /notify/send
85 | - POST /notify/send_sticker
86 | - POST /notify/send_url
87 | - POST /notify/send_path
88 | - POST /notify/revoke
89 |
90 | # 授權
91 |
92 | [MIT](https://github.com/louis70109/flask-line-notify/blob/master/MIT-LICENSE)
93 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | import uuid
2 | from flask import Flask, render_template, request, jsonify
3 | import os
4 |
5 | from lotify.client import Client
6 |
7 | app = Flask(__name__)
8 |
9 | CLIENT_ID = os.getenv("LINE_CLIENT_ID")
10 | SECRET = os.getenv("LINE_CLIENT_SECRET")
11 | URI = os.getenv("LINE_REDIRECT_URI")
12 | lotify = Client(client_id=CLIENT_ID, client_secret=SECRET, redirect_uri=URI)
13 |
14 |
15 | @app.route("/")
16 | def home():
17 | link = lotify.get_auth_link(state=uuid.uuid4())
18 | return render_template("notify_index.html", auth_url=link)
19 |
20 |
21 | @app.route("/callback")
22 | def confirm():
23 | token = lotify.get_access_token(code=request.args.get("code"))
24 | return render_template("notify_confirm.html", token=token)
25 |
26 |
27 | @app.route("/notify/send", methods=["POST"])
28 | def send():
29 | payload = request.get_json()
30 | response = lotify.send_message(
31 | access_token=payload.get("token"), message=payload.get("message")
32 | )
33 | return jsonify(result=response.get("message")), response.get("status")
34 |
35 |
36 | @app.route("/notify/send/sticker", methods=["POST"])
37 | def send_sticker():
38 | payload = request.get_json()
39 | response = lotify.send_message_with_sticker(
40 | access_token=payload.get("token"),
41 | message=payload.get("message"),
42 | sticker_id=630,
43 | sticker_package_id=4,
44 | )
45 | return jsonify(result=response.get("message")), response.get("status")
46 |
47 |
48 | @app.route("/notify/send/url", methods=["POST"])
49 | def send_url():
50 | payload = request.get_json()
51 | response = lotify.send_message_with_image_url(
52 | access_token=payload.get("token"),
53 | message=payload.get("message"),
54 | image_fullsize=payload.get("url"),
55 | image_thumbnail=payload.get("url"),
56 | )
57 | return jsonify(result=response.get("message")), response.get("status")
58 |
59 |
60 | @app.route("/notify/send/path", methods=["POST"])
61 | def send_file():
62 | payload = request.get_json()
63 | response = lotify.send_message_with_image_file(
64 | access_token=payload.get("token"),
65 | message=payload.get("message"),
66 | file=open("./test_data/dog.png", "rb"),
67 | )
68 | return jsonify(result=response.get("message")), response.get("status")
69 |
70 |
71 | @app.route("/notify/revoke", methods=["POST"])
72 | def revoke():
73 | payload = request.get_json()
74 | response = lotify.revoke(access_token=payload.get("token"))
75 | return jsonify(result=response.get("message")), response.get("status")
76 |
77 |
78 | if __name__ == "__main__":
79 | port = os.environ.get("PORT", 8000)
80 | app.run(host="0.0.0.0", port=port, debug=True)
81 |
--------------------------------------------------------------------------------
/templates/notify_confirm.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 驗證來源以及發送範例
8 |
9 |
10 | Token: {{token}}
11 | 送純文字 or 貼圖
12 | 請輸入文字:
13 |
14 |
15 |
16 |
17 | 發送圖片網址 (建議有 SSL)
18 | 請輸入文字:
19 |
20 | 請輸入網址:
21 |
22 |
23 |
24 | 發送靜態圖片範例
25 | 請輸入文字:
26 |
27 |
28 |
29 | 註銷 token
30 |
31 |
32 |
33 |
94 |
95 |
--------------------------------------------------------------------------------