1. Line通知能帶給我什麼便利?
身為一個資工系的學生/畢業生,相信你一定也很常會自己撰寫script來自動化處理生活上的事物,像是監控家中NAS的loading或是定期備份自己的資料,處理完成後往往都會透過各種管道送出最後的處理結果,讓您能輕鬆掌握各個排程工作的結果。如果您擁有自己的服務,也常會想要即時得知有新的用戶註冊了。
以往最常使用的便是透過email或是簡訊通知,使用email總感覺即時性不太夠,而且總是需要Google個老半天去找到寄信的範例,而簡訊通知,則是得花自己的錢,而且還得想辦法去找到可以處理各電信業者的機器人程式。
上述兩種方式使用起來都不太方便,加上這兩年Line已經滲透你我的生活,也提供各種平台上的Client(最近連Chrome Extension都推出了!),常言道:簡訊/email通知隨他響,Line訊息則不可不看,此服務就是為了這個目的而誕生,提供最簡單的方式讓您可以自動發送通知到自己的Line上,更棒的是我們提供五種常用語言(Python, PHP, Ruby, Node.js, Golang)的範例程式,讓您只需要簡單修改後即可整合進去您現有的專案!
2. 聽起來不錯,那使用上有什麼需要注意的地方嗎?
本服務的使用限制如下:
- 本服務使用Line官方提供的Bot API,目前該API處於Beta階段,若該API進入正式版本改採收費制度,本服務可能將會再次被迫中止,還請見諒 (fingers crossed)
- 單一則訊息長度為250個字(中英混合)
- 限制單一IP每秒鐘只能夠送一次request
- *** 請注意此token跟DDNS的token不同!(請點選本頁上方"我的token"取得,token最後結尾是一串數字) ***
- 傳送圖片最大上限為2 MB
3. 這正是我需要的!我該怎麼使用呢?
您只需要三個步驟即可註冊使用Line訊息通知!
- 在您手機/電腦的Line上搜尋Line ID: @wch4173n (目前BOT API Trial Account 的限制導致無法直接搜尋ID,請透過QR code掃描方式加入)並且將它加為好友。您可以在Line中直接掃描下方QR Code加入好友
- 點擊上方我的專屬Line通知token標籤頁,複製您的專屬token: OOO-12344321(注意此token跟DDNS的token不同,請點選本頁上方"我的token"取得,token最後結尾是一串數字!)
- 在手機/電腦的Line發送訊息給CsieIoBot,請送出 /add [您的token],例如 /add OOO-12344321,收到CsieIoBot的確認通知即完成註冊!
4. 所以到底該怎麼要CsieIoBot發Line給我啊啊啊啊?
當您完成註冊後,您只需要送出一個http request即可,純送純文字Line訊息範例如下:
curl -G "https://csie.io/lineme?token=abcd-12344321" --data-urlencode 'msg=哇哈哈~測試一下喔!!'
若您需要傳送圖片,請使用POST的方式傳送檔案,簡單範例如下(允許純傳圖片不不帶msg):
curl -F 'token=abcd-12344321' -F 'msg=測試時看個正妹提個神' -F 'file=@Downloads/beauty.jpg' https://csie.io/lineme

5. 我該怎麼讀懂CsieIoBot的return code?
- OK:- 處理成功
- badauth: 認證錯誤
- toolongmsg: 訊息長度超過限制
- noreg: 您尚未註冊使用Line通知服務
6. 我還是有些問題不太清楚,我該怎麼辦?
請聯絡 lab@csie.io,將會有專人提供解答。
7. 為什麼截圖都是Android的畫面?
因為我沒有錢買iphone Orz
** 致謝 **
感謝icross.cc提供Ruby的範例程式碼,同時也感謝Terces提供Node.js呼叫CsieIoBot範例 (訊息+圖片)的範例程式!!
宿網用量提醒服務
快速的宿舍網路總是讓人一用上癮,但是每天8.3GB的流量限制實在是讓人時時擔心,尤其是一旦超流就得被斷線,更是讓人生氣又無奈,所以本服務使用Line通知功能,每三分鐘檢查一次您的宿網使用流量,並在使用流量到達50%、70%、90%以及100%時,自動發出Line通知至您的裝置,讓您可以預先做出處置(例如:遠端回去關機或是打電話給室友拔線等等),省去被斷線的痛苦經驗!
1. 使用方式
您只需要發送簡單的訊息至CsieIoBot即可註冊您的宿網IP,立刻享有流量提醒的服務!- 請先確定您已經註冊Line通知服務,如果還沒的話,請先送出 /add [您的token],例如 /add OOO-12344321
- 註冊宿網IP: /dormadd 140.123.123.123 (請記得換成您的IP)
- 如果以後想要移除宿網IP: /dormdel 140.123.123.123 (請記得換成您的IP)
2. 我想要跑在自己機器上可以嗎?
我們一向欣賞喜歡自己動手做的使用者,所以我們也提供了獨立執行的版本,您可以直接在系上機器運行,安裝及使用方式請參考這個github頁面
3. 有圖有真相

Chrome一鍵快速發送
在桌機/筆電用Chrome瀏覽網頁時,常常會想把現在看的頁面網址或特定文字複製一份到手機上,現在您可以輕輕鬆鬆點擊書籤列的書籤,一秒傳送這些資訊到你的手機上!
1. 使用方式
首先,按照下列步驟新增一個書籤至書籤列:- 在Chrome的書籤列按右鍵,點選"新增網頁"後,填寫相關資訊
- "名稱"任取,在"網址"填上下列字串 (切記將ccurocks-12344321換成您的Line token)
javascript:var msg=prompt("Send to CsieIoBot?", window.location.href);if(msg!=null){var xhttp=new XMLHttpRequest();xhttp.open("GET", 'https://csie.io/lineme?token=ccurocks-12344321&msg='+encodeURIComponent(msg), true);xhttp.send();}
- 如果你的書籤列很滿,點選最上方的"書籤" -> "書籤管理員",在最下方會出現您剛剛新增的書籤,直接把他拖曳到書籤列上即可!
- 最後在任意的tab點選書籤,預設會填入該頁面的網址,但也可輸入任何文字,按下確定後,立刻發送至您的Line!
** 致謝 **
感謝L3F學長提供這個方便的bookmarklet!
Server Loading過重Line通知範例
本範例簡單展示如何將本服務結合進您的monitor script,當系統附載過高時,會自動送出Line訊息(並且包含一張loading圖)通知您!
#!/bin/bash
threshold=4.00 # 設定Loading上限
load=`cat /proc/loadavg | awk '{print $1}'`
overLoad=`echo $load'>'$threshold | bc -l`
if [ $overLoad == "1" ]
then
curl -F 'token=ccurocks-12344321' -F 'msg=不太妙啊~Server的Loading超過設定上限了,快點看一下Loading圖,然後ssh進去檢查一下吧!' -F 'file=@loading.png' https://csie.io/lineme
fi
Sample Output:

Dynamic DNS IP變更通知範例
您也可以結合本服務提供的Dynamic DNS服務,如果您的IP變更了即可收到Line通知!
#!/bin/bash
oldip=`host kerker.csie.io | grep "has address" | awk '{print $4}'`
curip=`curl http://checkip.amazonaws.com`
if [ $oldip != $curip ]
then
# 更新DNS Record
result=`echo url="https://csie.io/update?hn=您的hostname&token=您的token&ip=$curip" | curl -k -K -`
if [ $result == "OK" ]
then
# 送出Line通知
curl -G "https://csie.io/lineme?token=ccurocks-12344321" --data-urlencode "msg=偵測到IP改變,新的IP為:$curip"
else
curl -G "https://csie.io/lineme?token=ccurocks-12344321" --data-urlencode "msg=注意注意!偵測到IP改變,但是DDNS更新失敗!"
fi
fi
Sample Output:

Rsync備份通知範例
您也可以結合您的rsync備份script以及Line通知服務,可以即時得知備份是否成功!
#!/bin/bash
rsync -r -z -c /home/神秘的D槽 root@1.2.3.4:/home/神秘神秘
if [ "$?" -eq "0" ]
then
echo "Done"
curl -G "https://csie.io/lineme?token=ccurocks-12344321" --data-urlencode "msg=rsync備份完成!所有的寶貴檔案都遠端備份完成了!"
else
echo "Error while running rsync"
curl -G "https://csie.io/lineme?token=ccurocks-12344321" --data-urlencode "msg=rsync注意注意!rsync備份發生錯誤,請記得檢查!"
fi
Sample Output:

Python呼叫CsieIoBot範例 (純文字)
# coding=utf-8
import requests
msg = u"Python也可以輕鬆送Line通知!"
req_url = "https://csie.io/lineme?token=%s&msg=%s" % (LINE_TOKEN, msg)
r = requests.get(req_url)
if r.text == "OK":
print "Line通知成功送出!"
else:
print "Line通知無法送出 Orz srO"
Python呼叫CsieIoBot範例 (訊息+圖片)
# coding=utf-8
import requests
# msg可留空,純粹丟圖
param = {'token': 'ccurocks-12344321','msg': "Traffic is Money! 目前流量如下圖"}
files = {'file': open('mrtg.png','rb')}
req_url = 'https://csie.io/lineme'
r = requests.post(req_url, files=files, data=param)
if r.text == "OK":
print "Line通知成功送出!"
else:
print "Line通知無法送出 Orz srO"
PHP呼叫CsieIoBot範例
<?php
$msg = "PHP老而彌堅,呼叫CsieIoBot是ok的!";
$req_url = "https://csie.io/lineme?token=ccurocks-12344321&msg=" . $msg;
$result = file_get_contents($req_url);
if ($result == "OK")
echo "Line通知成功送出!";
else
echo "Line通知無法送出 Orz srO";
?>
PHP呼叫CsieIoBot範例 (訊息+圖片)
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_VERBOSE, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, "https://csie.io/lineme");
curl_setopt($ch, CURLOPT_POST, true);
$post = array(
"file" => "@/home/ccu/snoopy.jpg",
"token" => "ccurocks-12344321",
"msg" => "PHP老而彌堅,呼叫CsieIoBot是ok的!"
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec($ch);
if ($result == "OK")
echo "Line通知成功送出!";
else
echo "Line通知無法送出 Orz srO";
?>
Ruby呼叫CsieIoBot範例
require 'rest-client'
require 'open-uri'
token = 'ccurocks-12344321'
msg = URI::encode("許蓋功")
req_url = "https://csie.io/lineme?token=#{token}&msg=#{msg}"
response = RestClient.get req_url
if response.to_str == "OK"
puts "Line 通知成功送出!"
else
puts "Line 通知無法送出 Orz srO"
puts "response.code = #{response.code} , response.to_str = #{response.to_str}"
end
Ruby呼叫CsieIoBot範例 (訊息+圖片)
require 'rest-client'
require 'open-uri'
response = RestClient.post('https://csie.io/lineme',
'file' => File.new('snoopy.jpg'),
'token' => 'ccurocks-12344321',
'msg' => URI::encode("許蓋功")
)
if response.to_str == "OK"
puts "Line 通知成功送出!"
else
puts "Line 通知無法送出 Orz srO"
puts "response.code = #{response.code} , response.to_str = #{response.to_str}"
Node.js呼叫CsieIoBot範例
var https = require('https');
var options = {
host: 'csie.io',
port: 443,
path: '/lineme?token=ccurocks-12344321&msg=這年頭用Node.js才夠潮啊!!'
};
https.get(options, function(resp){
resp.on('data', function(chunk){
if(chunk == "OK")
console.log("Line notification sent!");
else
console.log("Unable to send Line notification!");
});
}).on("error", function(e){
console.log("Got error: " + e.message);
});
Node.js呼叫CsieIoBot範例 (訊息+圖片)
var request = require('request');
var fs = require( 'fs');
var formData = {
msg: 'node.js rocks',
token: 'ccucs-12345678',
file: fs.createReadStream( __dirname + "/domo_kun.jpg")
};
request.post({
url: 'https://csie.io/lineme',
formData: formData},
function (err, res, body) {
if( err)
return console.error( 'upload fail :X(', err ,')');
// noticed: it might get 'badauth' as response
console.log('upload success! response :', body);
}
);
Golang呼叫CsieIoBot範例
package main
import (
"fmt"
"net/http"
"io/ioutil"
_ "crypto/sha512"
"os"
)
func main() {
response, err := http.Get("https://csie.io/lineme?token=ccurocks-12344321&msg=用Go送更是潮到出水!")
if err != nil {
fmt.Printf("%s", err)
os.Exit(1)
} else {
defer response.Body.Close()
contents, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Printf("%s", err)
os.Exit(1)
}
if string(contents) == "OK" {
fmt.Printf("Line notification sent!\n")
} else {
fmt.Printf("Unable to send Line notification\n")
}
}
}
Golang呼叫CsieIoBot範例 (訊息+圖片)
package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"net/url"
"os"
_ "crypto/sha512"
)
func main() {
client := &http.Client{}
request_url := "https://csie.io/lineme"
form := url.Values{
"token": {"ccurocks-12344321"},
"msg": {"用Go送更是潮到出水!"},
}
body := &bytes.Buffer{}
file_name := "snoopy.jpg"
body_writer := multipart.NewWriter(body)
for field_name, field_value := range form {
body_writer.WriteField(field_name, field_value[0])
}
file_writer, err := body_writer.CreateFormFile("file", file_name)
if err != nil {
panic(err)
}
f, err := os.Open(file_name)
if err != nil {
panic(err)
}
_, err = io.Copy(file_writer, f)
if err != nil {
panic(err)
}
f.Close()
body_writer.Close()
content_type := body_writer.FormDataContentType()
req, err := http.NewRequest("POST", request_url, body)
req.Header.Set("Content-Type", content_type)
rsp, err := client.Do(req)
if err != nil {
panic(err)
}
body_byte, err := ioutil.ReadAll(rsp.Body)
if err != nil {
panic(err)
}
rsp.Body.Close()
fmt.Println(string(body_byte))
}