AndrewCho365
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Line Bot 教學 ## 簡介 ### 什麼是 Line Bot? Line Bot 是一個運行在 Line 這個即時通訊平台上的應用程式。它透過 Line 提供的 API (應用程式介面) 與使用者進行互動,可以自動回覆訊息、提供資訊、執行特定功能,甚至串接其他服務。 :::info 你知道嗎? Line Bot 就是啟用Messaging API的官方帳號 像有些老師與家長溝通的帳號、商家的帳號(例如麥當勞...) 啟用Messaging API的官方帳號就可以透過程式自動回覆發送訊息 ::: ### Line Bot 的主要功能: * **自動回覆訊息:** 根據使用者輸入的文字、貼圖、圖片等內容,自動發送預先設定的回覆。 * **推播訊息:** 主動向使用者發送通知、提醒或促銷訊息。 * **提供資訊:** 可以查詢天氣、新聞、股價、交通資訊等各種即時資訊。 * **執行特定功能:** 例如預訂餐廳、查詢商品等。 * **串接外部服務:** 可以與其他服務、應用程式或資料庫整合,提供更豐富的功能。 ### 開發 Line Bot 的優點: * **龐大的用戶基礎:** Line 在許多國家和地區擁有廣大的用戶群。 * **多樣化的互動方式:** 支援文字、圖片、影片、聲音、貼圖、位置資訊等多種訊息格式。 * **豐富的 API 功能:** 提供開發者許多工具來打造功能強大的機器人。 * **提升品牌形象:** 可以作為企業與顧客互動的新管道,提供更便捷的服務。 ## Line Bot Python 簡介 Line Bot 是一種在 Line 這個通訊軟體上運行的應用程式。透過 Line Bot,使用者可以與之互動,獲取資訊、執行指令、甚至進行更複雜的操作。而使用 Python 語言開發 Line Bot,則能利用 Python 豐富的函式庫和簡潔的語法,快速打造功能強大的聊天機器人。 **運作原理:** 1. **使用者互動:** 當 Line 的使用者傳送訊息給你的 Line Bot 時,Line 的伺服器會接收到這個訊息。 2. **訊息傳遞:** Line 伺服器會將這個訊息以 HTTPS POST 的方式傳送至你事先設定好的 Webhook URL。這個 URL 指向你的伺服器或雲端服務,上面運行著你的 Python Line Bot 程式。 3. **伺服器處理:** 你的 Python 程式接收到這個 HTTP POST 請求,並解析其中的訊息內容(例如:文字、圖片、貼圖等)。 4. **邏輯處理:** 根據接收到的訊息,你的 Python 程式會執行預先定義好的邏輯。這可能包括查詢資料庫、呼叫外部 API、進行自然語言處理等等。 5. **訊息回傳:** 你的 Python 程式會根據處理結果,建構要回覆給使用者的訊息。這些訊息可以是文字、圖片、影片、按鈕、輪播等不同格式。 6. **訊息傳送:** 你的伺服器會將建構好的回覆訊息以 HTTPS POST 的方式傳送回 Line 的伺服器。 7. **使用者接收:** Line 的伺服器接收到回覆訊息後,會將其傳送給發送訊息的使用者,使用者就能在 Line 的聊天視窗中看到 Bot 的回覆。 **Python 的優勢:** * **易學易用:** Python 語法簡潔清晰,非常適合初學者入門。 * **豐富的函式庫:** Python 社群提供了許多用於網路請求、JSON 處理、資料庫操作等方面的函式庫,能大幅簡化開發流程。 * **Line Bot SDK:** Line 官方提供了 Python SDK,封裝了與 Line Bot API 互動的細節,讓開發者能更方便地處理訊息接收、回覆、以及其他進階功能。 * **廣泛的應用場景:** 使用 Python 開發的 Line Bot 可以應用於各種場景,例如:客服、通知、娛樂、資訊查詢、自動化流程等等。 使用 Python 開發 Line Bot 是一個快速且有效率的方式,讓你能夠輕鬆地在 Line 這個廣受歡迎的平台上打造智能化的互動應用。 ## 程式編寫 為了簡化環境的安裝 我們使用[Firebase Studio](https://studio.firebase.google.com)進行開發 ### 環境安裝 首先使用Google帳號登入[Firebase Studio](https://studio.firebase.google.com) 進入畫面後,在左下角找到**New Workspace** ![螢幕擷取畫面 2025-04-23 134221](https://hackmd.io/_uploads/HkSAC-vJgx.png) 接著會進入範本庫,在下方找到**backend(後端)** 在右邊找到並點擊**Python Flask**圖塊 ![螢幕擷取畫面 2025-04-23 134317](https://hackmd.io/_uploads/HJAlkGDJge.png) 在頁面跳轉後輸入**Line Bot**當作專案名稱,並按下**creat** ![螢幕擷取畫面 2025-04-23 134354](https://hackmd.io/_uploads/HywGJMvJel.png) :::info 其他選項皆使用預設即可,不需要更改 ::: 接著等待工作區建立,並同意服務條款 ![螢幕擷取畫面 2025-04-23 134503](https://hackmd.io/_uploads/By1IBGDkxl.png) 工作區建立完成後會看到VS Code的介面 ![螢幕擷取畫面 2025-04-23 134553](https://hackmd.io/_uploads/By58SfP1le.png) 把其他檔案全部刪光光(不要怕!!!)以及調整一些自己習慣的設定 再來建立名為**bot.py的檔案**以及**localtunnel.txt** ![螢幕擷取畫面 2025-04-23 135713](https://hackmd.io/_uploads/BJu_SGDyge.png) ![螢幕擷取畫面 2025-04-23 135742](https://hackmd.io/_uploads/Sk3dSfDJxx.png) 好啦~可以進到下一步了! ## 機器人製作 ### 機器人申請 進入[LINE Developers](https://developers.line.biz/en/)點選啟動控制台並登入Line帳號 ![image](https://hackmd.io/_uploads/BkcYGMIkll.png) 登入並進入控制台後點擊綠色的**Creat**按鈕輸入**bot**當作provider的名稱 ![image](https://hackmd.io/_uploads/B1H_VfLyex.png) 點擊下方上一步設置的**provider** ![image](https://hackmd.io/_uploads/rk7sNfU1ee.png) 點擊下方的**Create a new channel**大框框 ![image](https://hackmd.io/_uploads/H1y2NzUJxg.png) 在彈窗中選擇**Messaging API** ![image](https://hackmd.io/_uploads/SkHaNG81xg.png) 點擊綠按鈕跳轉到[官方帳號申請頁面](https://entry.line.biz/form/entry/unverified) :::success 跳轉前的頁面可以先留著不要關掉喔!(頁面一) ::: ![image](https://hackmd.io/_uploads/Byu04GIkex.png) 輸入你的機器人名稱及電子郵件等資訊 然後點擊確定 ![image](https://hackmd.io/_uploads/ry9vIfLyll.png) 點擊綠色的**完成**按鈕 ![image](https://hackmd.io/_uploads/SyYxwM8Jxe.png) 點擊綠色的**稍後進行認證**按鈕 ![image](https://hackmd.io/_uploads/H1-fwz8yll.png) 進入管理頁面後 可以把一些同意及教學點掉 再來點選右上角的設定按鈕 ![image](https://hackmd.io/_uploads/SycA_fUylg.png) 在左邊切換到Message API分頁 點擊**啟用Message API**按鈕 ![image](https://hackmd.io/_uploads/BkJgKzL1ge.png) 選擇先前設置的provider ![image](https://hackmd.io/_uploads/rk2btG8yxl.png) 輸入隱私權政策與服務條款 :::info 此部分可以跳過,可以直接點擊確定即可 ::: ![image](https://hackmd.io/_uploads/SkJ7Yf8kxe.png) 再次確認一下資訊,點擊確定 ![image](https://hackmd.io/_uploads/HyE7KzIkex.png) 接著就會看到這個有輸入框的介面 等待程式編寫完後會填上Webhook網址 ![image](https://hackmd.io/_uploads/SyZ8tGIJxg.png) :::success 這個頁面可以先留著不要關掉喔!(頁面二) 讓我們來寫程式吧! ::: ### 函式庫安裝 點選左上角的3條線>>點選**Terminal**>>點選**New Terminal** ![image](https://hackmd.io/_uploads/B1TqxG8kxe.png) 將底下的指令輸入終端機 ```cmd= python -m venv .venv source .venv/bin/activate pip install Flask pip install line-bot-sdk pip install google-genai pip install pillow ``` ![image](https://hackmd.io/_uploads/SJS4xdilgg.png) ### 程式編寫 寫機器人當然要先從echo Bot開始啦! 回到...左邊的檔案櫃打開先前建立的**bot.py**檔案並貼上以下內容⬇️ ```py= from flask import Flask, request, abort # 載入 LINE Message API 相關函式庫 from linebot.v3.webhook import WebhookHandler from linebot.v3.exceptions import InvalidSignatureError from linebot.v3.messaging import ( Configuration, ApiClient, MessagingApi, ReplyMessageRequest, TextMessage as V3TextMessage ) from linebot.v3.webhooks import MessageEvent, TextMessageContent # 請填入你的 Channel Access Token 與 Channel Secret CHANNEL_ACCESS_TOKEN = 'YOUR_CHANNEL_ACCESS_TOKEN' CHANNEL_SECRET = 'YOUR_CHANNEL_SECRET' app = Flask(__name__) # 初始化 LINE Bot API 配置 configuration = Configuration(access_token=CHANNEL_ACCESS_TOKEN) api_client = ApiClient(configuration) line_bot_api = MessagingApi(api_client) handler = WebhookHandler(CHANNEL_SECRET) @app.route("/callback", methods=['POST']) def callback(): signature = request.headers.get('X-Line-Signature') body = request.get_data(as_text=True) app.logger.info("Request body: " + body) try: handler.handle(body, signature) except InvalidSignatureError: app.logger.info("Invalid signature. Please check your channel access token/channel secret.") abort(400) return 'OK' @handler.add(MessageEvent, message=TextMessageContent) def handle_message(event): # 取得使用者傳送的文字訊息 received_text = event.message.text # 回覆的文字訊息,直接 echo 用戶發送的訊息 reply_text = f"你說:{received_text}" # 使用 LINE Bot API 回覆 with ApiClient(configuration) as api_client: line_bot_api = MessagingApi(api_client) line_bot_api.reply_message_with_http_info( ReplyMessageRequest( reply_token=event.reply_token, messages=[V3TextMessage(text=reply_text)] ) ) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=8080) ``` #### 密鑰填寫 接著回到[Line控制台](https://developers.line.biz/console/)(頁面一) 找到你的機器人點進去進到**Basic settings**分頁 往下滑動找到**Channel secret**並複製到程式碼中 ![image](https://hackmd.io/_uploads/HJa29f81lg.png) 回到上方在**Basic settings**的右邊找到**Messaging API**分頁往下滑動找到**Channel access token** 點擊**Issue**並將產生的金鑰複製到程式碼中 ![image](https://hackmd.io/_uploads/BJDdozU1gl.png) ## 內網穿透 因為Line Message API要求使用Webhook以及HTTPS,所以我們在內網環境時需要使用內網穿透解決沒有公網IP的問題,順便解決HTTPS 我們可以使用[localtunnel](https://theboroer.github.io/localtunnel-www/)的服務進行內網穿透 一樣點選左上角的3條線>>點選**Terminal**>>點選**New Terminal** 將以下指令輸入終端機執行 此指令將會安裝內網穿透服務 ```cmd= npm install -g localtunnel ``` ![image](https://hackmd.io/_uploads/S1nDFwjxel.png) 等待安裝完畢後 ![image](https://hackmd.io/_uploads/SkY9KPjxlx.png) 想一個不容易被別人使用的子網域名 例如我是用**westernpenguin** 則開通內網穿透的指令長這樣 記得把指令複製到**localtunnel.txt**下次啟動通道比較方便 ```cmd= lt --port 8080 -s westernpenguin ``` ![image](https://hackmd.io/_uploads/S1sTKDjgxe.png) 接著等待跳出網址 將終端機中顯示網址複製並在後面貼上**/callback** :::info 例如: https://westernpenguin.loca.lt/callback ::: 並貼上到先前建立好官方帳號時可以填入Webhook連結的地方(頁面二) :::info 如果你想架Minecraft 伺服器也可以用這個內網穿透服務喔! ::: ### 測試 打開Line傳送訊息給你的機器人吧! 如果如果如果沒問題應該就會自動回覆你 ![image](https://hackmd.io/_uploads/Hy5SSdogex.png) :::warning 欸?為什麼會先顯示不能個別回覆的訊息 這是因為Line預設一些訊息回覆 等等後面會有移除預設回覆的教學喔! ::: ## AI回覆 因為Line 機器人太廢了,~~除了使用者多就沒優點了~~ 所以只好串接Google 的 Gemini進行人工智慧對話 :::info 為什麼不用Chat GPT的服務呢? 因為Chat GPT提供的免費額度是有限的,而 Google 的免費服務提供在1分鐘內60次的提問 ::: 首先,使用Google個人帳戶登入[Google AI Studio](https://aistudio.google.com/app/apikey)獲得金鑰 點藍色按鈕在彈窗中隨便選一個專案 接著就會跳出金鑰了 ![image](https://hackmd.io/_uploads/H1bwT_oleg.png) ![image](https://hackmd.io/_uploads/r1_Ta_ilee.png) 接著替換全部程式碼⬇️(記得將api_key及機器人金鑰替換成你自己的) ```python= from flask import Flask, request, abort # 載入 LINE Message API 相關函式庫 from linebot.v3.webhook import WebhookHandler from linebot.v3.exceptions import InvalidSignatureError from linebot.v3.messaging import ( Configuration, ApiClient, MessagingApi, ReplyMessageRequest, TextMessage as V3TextMessage ) from linebot.v3.webhooks import MessageEvent, TextMessageContent, ImageMessageContent from google import genai from google.genai import types from PIL import Image import requests from collections import defaultdict import json import os # 新增 os 模組 import tempfile # 新增 tempfile 模組 # 請填入你的 Channel Access Token 與 Channel Secret CHANNEL_ACCESS_TOKEN = 'YOUR_CHANNEL_ACCESS_TOKEN' CHANNEL_SECRET = 'YOUR_CHANNEL_SECRET' # 儲存圖片的目錄 SAVE_IMAGE_PATH = "saved_images" if not os.path.exists(SAVE_IMAGE_PATH): os.makedirs(SAVE_IMAGE_PATH) # 初始化 Google GenAI 客戶端 client = genai.Client(api_key="YOUR_api_key") model_name = "gemini-2.0-flash" # 啟用聯網搜尋工具 tools = [types.Tool(google_search=types.GoogleSearch())] generate_content_config = types.GenerateContentConfig( temperature=0.7, top_p=1, top_k=1, max_output_tokens=1500, tools=tools, response_mime_type="text/plain", system_instruction=( "你是一個智慧型的LINE聊天機器人,請用繁體中文回答問題。" "如果有人問你是誰,請回答你的名字叫'西極企鵝',並加上一些自我介紹。" "盡量適當地用表情符號表達情緒" "因為Line 不支援Markdown" "所以請使用emoji 表示順序等資訊增加可讀性" ) ) # 儲存對話記錄 chat_sessions = defaultdict(list) app = Flask(__name__) # 初始化 LINE Bot API 配置 configuration = Configuration(access_token=CHANNEL_ACCESS_TOKEN) api_client = ApiClient(configuration) line_bot_api = MessagingApi(api_client) handler = WebhookHandler(CHANNEL_SECRET) @app.route("/callback", methods=['POST']) # 修正路由 URL def callback(): signature = request.headers['X-Line-Signature'] body = request.get_data(as_text=True) app.logger.info("Request body: " + body) try: handler.handle(body, signature) except InvalidSignatureError: app.logger.info("Invalid signature. Please check your channel access token/channel secret.") abort(400) return 'OK' @handler.add(MessageEvent, message=TextMessageContent) def handle_message(event): user_id = event.source.user_id if user_id not in chat_sessions: chat_sessions[user_id] = client.chats.create(model=model_name, config=generate_content_config) chat = chat_sessions[user_id] msg = event.message.text print(f"Received message: {msg}") # 使用 Google GenAI 生成回覆 response = chat.send_message(message=msg) reply = response.text with ApiClient(configuration) as api_client: line_bot_api = MessagingApi(api_client) line_bot_api.reply_message_with_http_info( ReplyMessageRequest( reply_token=event.reply_token, messages=[V3TextMessage(text=reply)] ) ) @handler.add(MessageEvent, message=ImageMessageContent) def handle_image_message(event): message_id = event.message.id try: # 使用 requests 從 LINE API 下載圖片內容 content_url = f"https://api-data.line.me/v2/bot/message/{message_id}/content" headers = {"Authorization": f"Bearer {CHANNEL_ACCESS_TOKEN}"} response = requests.get(content_url, headers=headers, stream=True) if response.status_code == 200: # 使用 PIL.Image.open 處理圖片數據 image = Image.open(response.raw) # 傳遞圖片和文字訊息給 Gemini 處理 user_id = event.source.user_id if user_id not in chat_sessions: chat_sessions[user_id] = client.chats.create(model=model_name, config=generate_content_config) chat = chat_sessions[user_id] message_text = "這是一張圖片,請分析並生成相關內容。" response = client.models.generate_content( model="gemini-2.0-flash", contents=[image, message_text], config=generate_content_config ) response = chat.send_message(f"Image processed: {response.text}", config=generate_content_config) # 修正參數傳遞 reply_text = f"{response.text}\n" else: reply_text = f"無法下載圖片,狀態碼: {response.status_code}" except Exception as e: reply_text = f"處理圖片時發生錯誤: {e}" line_bot_api.reply_message_with_http_info( ReplyMessageRequest( reply_token=event.reply_token, messages=[V3TextMessage(text=reply_text)] ) ) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=8080) ``` ### 測試 打開Line傳送訊息給你的機器人吧! 如果如果如果沒問題應該就會自動回覆你一些由生成的文字 ![image](https://hackmd.io/_uploads/rJewKdilex.png) :::warning 對!那個可惡的訊息又出現了 下一段就來教怎麼移除預設回覆 ::: ## 移除預設回覆 [LINE 官方帳號管理頁面](https://manager.line.biz/)是一個管理官方帳號的控制台 進入並挑選你的機器人 在左邊找到**自動回應訊息** ![image](https://hackmd.io/_uploads/SyA95_olxg.png) 在右邊找到訊息後點那3個點選擇刪除 ![image](https://hackmd.io/_uploads/ryS1juoggl.png) 接著應該就不會出現那個討厭的回覆了 :::info 相反的,你也可以透過它建立一些自動回覆 ::: ## 結尾 謝謝大家聆聽我的Line Bot教學課程 因為課程時間較短,內容沒有很詳細 這份講義會慢慢補齊,如果有問題也可以在群組詢問我 謝謝

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully