這篇介紹把LINE的webhook整合到同一個Flask裡,方便管理。但流量大的時候,還是要分開。
程式LINE webhook framework的Python版,故其它語言就沒有參考價值。下列列出模組化的部份,不列出完整程式。
首先LINE_bot物件變成兩組
#R
line_bot_api = LineBotApi('KEY')
handler = WebhookHandler('SECRET')
#E
line_bot_api_e = LineBotApi('KEY')
handler_e = WebhookHandler('SECRET')
路由分成兩個,裡面就可以做各自的事情。
'''
R
'''
@app.route("/webhook", methods=['POST'])
def callback():
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
'''
E
'''
@app.route("/webhook02", methods=['POST'])
def callback_E():
@handler_e.add(MessageEvent, message=TextMessage)
def handle_message_E(event):
如此Restful介面就變成如下,port號一樣,僅路由不同:
https://url:port/webhook
https://url:port/webhook02
2020年1月14日 星期二
LINE Front-end Framework(LIFF)
LIFF是LINE利用web page來實現LINE原有功能無法實現的一個管道。
下面範例是開啟一個網頁,可以在網頁中抓取LINE使用者的ID及相關資料。
------------------------------------------------------------------------------------------------------------------------------------------------
我用的範例網頁程式是LINE提供,網址如下:
https://github.com/line/line-liff-starter
將這個程式放在你的網站上的一個目錄,記下該目錄的URL,下面步驟要用到。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
進入LIFF頁籤,點ADD新增。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Size是選這個LIFF窗格的佔螢幕範圍,Full是全滿,Compact是半滿。
Endpoint URL存取你的網頁的URL。
BLE feature可以直接略過,它是Bluetooth Low Energy實體物件在用的(要另外買這個東西)。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
結果會秀出LIFF URL,把這個URL貼到要觸發這個LIFF的地方,例如LINE的選單(RichMenu)
----------------------------------------------------------------------------------------------------------------------------------------
把LIFF URL貼到選單(RichMenu)
-------------------------------------------------------------------------------------
觸發按鈕會出現在選單上
--------------------------------------------------------------------------------------------------------------------------------
下面範例是開啟一個網頁,可以在網頁中抓取LINE使用者的ID及相關資料。
------------------------------------------------------------------------------------------------------------------------------------------------
我用的範例網頁程式是LINE提供,網址如下:
https://github.com/line/line-liff-starter
將這個程式放在你的網站上的一個目錄,記下該目錄的URL,下面步驟要用到。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
進入LIFF頁籤,點ADD新增。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Size是選這個LIFF窗格的佔螢幕範圍,Full是全滿,Compact是半滿。
Endpoint URL存取你的網頁的URL。
BLE feature可以直接略過,它是Bluetooth Low Energy實體物件在用的(要另外買這個東西)。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
結果會秀出LIFF URL,把這個URL貼到要觸發這個LIFF的地方,例如LINE的選單(RichMenu)
----------------------------------------------------------------------------------------------------------------------------------------
把LIFF URL貼到選單(RichMenu)
-------------------------------------------------------------------------------------
觸發按鈕會出現在選單上
--------------------------------------------------------------------------------------------------------------------------------
MariaDB的Pool connection
因為發現我們的JAVA程式連MySQL資料庫的建立連線過程浪費很多時間,故想用connection pool的觀念來作,找到mariaDB(MySQL的免費後繼版)有直接提供pool的功能給JAVA,故我就研究如何套用到程式上。
mariaDB原生的pool功能,測試後效能比沒用pool快4倍。要用mariaDB原生的Driver,要用JAVA 8以上的版本,資料庫軟體可直接去mariaDB的網站下載。
程式碼在最下面,程式中最後一個區塊是最佳pool範例程式,改程式很簡單。
資料庫連結的JAR檔可在下列原廠下載
https://mariadb.com/kb/en/library/mariadb-connector-j/
這裡有教Eclipse怎麼載入connector的JAR檔
https://www.jianshu.com/p/489e4f0c1621
import java.sql.*;
import org.mariadb.jdbc.MariaDbPoolDataSource;
public class helloworld {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
long time1, time2, time3;
Class.forName("org.mariadb.jdbc.Driver");
//**********************************
// Original Database connection method
//**********************************
time1 = System.currentTimeMillis();
for(int i = 1; i <=1000;i++) {
try(
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/drink?user=root&password=0000");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM history LIMIT 6,5"))
{
rs.next();
//System.out.println(i + "\t" + rs.getString(2) );
}
}
time2 = System.currentTimeMillis();
time3 = time2-time1;
System.out.println("花了:" + time3 + " ms");
//**********************************
// mariaDB pool with minimal modified
//**********************************
time1 = System.currentTimeMillis();
for(int i = 1; i <=1000;i++) {
String connectionString = "jdbc:mysql://localhost:3306/drink?user=root&password=0000&maxPoolSize=100&pool";
try (Connection connection = DriverManager.getConnection(connectionString)) {
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT * FROM history LIMIT 5,5");
rs.next();
}
}
}
time2 = System.currentTimeMillis();
time3 = time2-time1;
System.out.println("花了:" + time3 + " ms");
//**********************************
// mariaDB pool (best)
//**********************************
//所有參數都在JDBC的連結中,而且增加了"&maxPoolSize=100",設定pool大小是100
time1 = System.currentTimeMillis();
for(int i = 1; i <=1000;i++) {
MariaDbPoolDataSource pool = new MariaDbPoolDataSource("jdbc:mysql://localhost:3306/drink?user=root&password=0000&maxPoolSize=100");
try (Connection connection = pool.getConnection()) {
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT * FROM history");
rs.next();
//System.out.println(i + "\t" + rs.getString(2) );
}
connection.close();
}
}
time2 = System.currentTimeMillis();
time3 = time2-time1;
System.out.println("花了:" + time3 + " ms");
}
}
mariaDB原生的pool功能,測試後效能比沒用pool快4倍。要用mariaDB原生的Driver,要用JAVA 8以上的版本,資料庫軟體可直接去mariaDB的網站下載。
程式碼在最下面,程式中最後一個區塊是最佳pool範例程式,改程式很簡單。
資料庫連結的JAR檔可在下列原廠下載
https://mariadb.com/kb/en/library/mariadb-connector-j/
這裡有教Eclipse怎麼載入connector的JAR檔
https://www.jianshu.com/p/489e4f0c1621
import java.sql.*;
import org.mariadb.jdbc.MariaDbPoolDataSource;
public class helloworld {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
long time1, time2, time3;
Class.forName("org.mariadb.jdbc.Driver");
//**********************************
// Original Database connection method
//**********************************
time1 = System.currentTimeMillis();
for(int i = 1; i <=1000;i++) {
try(
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/drink?user=root&password=0000");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM history LIMIT 6,5"))
{
rs.next();
//System.out.println(i + "\t" + rs.getString(2) );
}
}
time2 = System.currentTimeMillis();
time3 = time2-time1;
System.out.println("花了:" + time3 + " ms");
//**********************************
// mariaDB pool with minimal modified
//**********************************
time1 = System.currentTimeMillis();
for(int i = 1; i <=1000;i++) {
String connectionString = "jdbc:mysql://localhost:3306/drink?user=root&password=0000&maxPoolSize=100&pool";
try (Connection connection = DriverManager.getConnection(connectionString)) {
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT * FROM history LIMIT 5,5");
rs.next();
}
}
}
time2 = System.currentTimeMillis();
time3 = time2-time1;
System.out.println("花了:" + time3 + " ms");
//**********************************
// mariaDB pool (best)
//**********************************
//所有參數都在JDBC的連結中,而且增加了"&maxPoolSize=100",設定pool大小是100
time1 = System.currentTimeMillis();
for(int i = 1; i <=1000;i++) {
MariaDbPoolDataSource pool = new MariaDbPoolDataSource("jdbc:mysql://localhost:3306/drink?user=root&password=0000&maxPoolSize=100");
try (Connection connection = pool.getConnection()) {
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT * FROM history");
rs.next();
//System.out.println(i + "\t" + rs.getString(2) );
}
connection.close();
}
}
time2 = System.currentTimeMillis();
time3 = time2-time1;
System.out.println("花了:" + time3 + " ms");
}
}
LINE機器人傳sticker貼圖
stickers可以讓對話更有趣、更生動。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以下是PHP程式碼,先將所有會用到的sticker列出來,然後判斷LINE傳來的資料型態是否為sticker,然後再隨機挑一個一開始列出來的sticker,回傳給使用者。
程式碼
$_CONFIG['arrStickerNum']['1'] = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,21,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430);
$_CONFIG['arrStickerNum']['2'] = array(18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527);
$_CONFIG['arrStickerNum']['11537'] = array(52002734,52002735,52002736,52002737,52002738,52002739,52002740,52002741,52002742,52002743,52002744,52002745,52002746,52002747,52002748,52002749,52002750,52002751,52002752,52002753,52002754,52002755,52002756,52002757,52002758,52002759,52002760,52002761,52002762,52002763,52002764,52002765,52002766,52002767,52002768,52002769,52002770,52002771,52002772,52002773);
$_CONFIG['arrStickerNum']['11538'] = array(51626494,51626495,51626496,51626497,51626498,51626499,51626500,51626501,51626502,51626503,51626504,51626505,51626506,51626507,51626508,51626509,51626510,51626511,51626512,51626513,51626514,51626515,51626516,51626517,51626518,51626519,51626520,51626521,51626522,51626523,51626524,51626525,51626526,51626527,51626528,51626529,51626530,51626531,51626532,51626533);
$_CONFIG['token'] = '
include ('lineJSONmaker.class.php');
class LineJSONmaker3 extends LineJSONmaker{
public function setSticker($packageId, $stickerId){
{
"type": "sticker",
"packageId": "$packageId",
"stickerId": "$stickerId"
}
EOT;
$this->arrJSON[] = $json;
}
}
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
$objLineJSON = new LineJSONmaker3($_CONFIG['token'], $data['events'][0]['replyToken']);
if($data['events'][0]['message']['type'] == 'sticker')
{
$keysPackage = array_keys($_CONFIG['arrStickerNum']);
$indexPackage = rand(0,count($keysPackage)-1);
$packageId = $keysPackage[$indexPackage];
$indexSticker = rand(0,count($_CONFIG['arrStickerNum'][$packageId])-1);
$stickerId = $_CONFIG['arrStickerNum'][$packageId][$indexSticker];
$objLineJSON->setSticker($packageId,$stickerId);
}
$result = $objLineJSON->send();
public function setSticker($packageId, $stickerId){
$json = <<
{
"type": "sticker",
"packageId": "$packageId",
"stickerId": "$stickerId"
}
EOT;
$this->arrJSON[] = $json;
}
?>
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下列是LINE官方文件所列出的sticker代號表,下面列出我會用到的部份。
Sticker列表
2020年1月13日 星期一
LINE的quickReply
設計LINE機器人時,有些固定的輸入可以使用泡泡選單呈現,在LINE的JSON語法裡它叫quickReply。
下面是quickReply的JSON格式:
{
"replyToken": "",
"messages": [
{
"type": "text",
"text": "測試泡泡選單。",
"quickReply": {
"items": [
{
"type": "action",
"action": {
"type": "message",
"label": "泡泡1",
"text": "泡泡1"
}
},
{
"type": "action",
"action": {
"type": "message",
"label": "泡泡2",
"text": "泡泡2"
}
},
{
"type": "action",
"action": {
"type": "message",
"label": "泡泡3",
"text": "泡泡3"
}
}
]
}
}
]
}
若當初建立LINE的channel時,是選Developer Trial,你就可以用下列語法PUSH訊息到LINE,把換成你的,要從webhook收到的JSON取得,最後加入上面的quickReply的JSON,就可以主動發送了。
curl -v -X POST https://api.line.me/v2/bot/message/push \ -H 'Content-Type:application/json' \ -H 'Authorization: Bearer {}' \ -d '{ "to": "", }'
也可以在webhook收到訊息後,用reply的格式回傳,參考下列文章。
參考本部落格的LINE機器人:
https://oscarhsu70.blogspot.com/2020/01/line.html
參考官方文件:
https://developers.line.biz/en/docs/messaging-api/using-quick-reply/
下面是quickReply的JSON格式:
{
"replyToken": "
"messages": [
{
"type": "text",
"text": "測試泡泡選單。",
"quickReply": {
"items": [
{
"type": "action",
"action": {
"type": "message",
"label": "泡泡1",
"text": "泡泡1"
}
},
{
"type": "action",
"action": {
"type": "message",
"label": "泡泡2",
"text": "泡泡2"
}
},
{
"type": "action",
"action": {
"type": "message",
"label": "泡泡3",
"text": "泡泡3"
}
}
]
}
}
]
}
若當初建立LINE的channel時,是選Developer Trial,你就可以用下列語法PUSH訊息到LINE,把
curl -v -X POST https://api.line.me/v2/bot/message/push \ -H 'Content-Type:application/json' \ -H 'Authorization: Bearer {
也可以在webhook收到訊息後,用reply的格式回傳,參考下列文章。
參考本部落格的LINE機器人:
https://oscarhsu70.blogspot.com/2020/01/line.html
參考官方文件:
https://developers.line.biz/en/docs/messaging-api/using-quick-reply/
LINE官網機器人申請過程
第一次開發LINE機器人,需要LINE develop的帳號,請參考下列連結,建立開發者帳號。
https://developers.line.biz/en/docs/messaging-api/getting-started/
重要提醒! 一定要驗證你的email,LINE機器人才能正常工作。
先建立channel
選Messaging API
輸入你的機器人的設定,來建立你的LINE機器人。包含它的大頭照(App icon),機器人的名字(App name)。
這裡我們選Developer Trial,為了多一個PUSH MESSAGES的功能,可以主動發訊息給別人,需不是只能Reply(回應訊息)。Category及Subcategory選擇你的分類。Email是有其它事的話,可以連絡到你。
完成剛才的建立APP後,再進入你的APP繼續設定。
把下列4個地方設定好:
第一個Channel access token (long-lived),小時數預設0就好,表示這個Token沒有時間限制。
第二個Use webhooks,把它設定成Enabled。如果等下自己的PHP程式出錯,Use webhooks會自動調成Disable,你就要再回來改成Enable。
第三個Webhook URL,把你的Webhook server網址設定進去,如果你是第一次接觸Webhook,可參考Facebook Messenger API使用方法,裡面有對Webhook作解釋。但在設定這一項之前,你可能需要先建好你的Webhook程式網頁,不然它會回應失敗,這在下一段會講。
第四個Auto-reply messages,把它Disable掉,使用者才不會收到預設回應訊息。
建立下列PHP程式網頁,放在你的Server上,我喜歡設定檔名為webhook.php,存取網址要如同你上面設定的一樣。"" 要改成剛才ISSUE出來的Channel access token。記得建一個webhook.txt,放在這個程式檔的旁邊,記錄傳來的Webhook事件,到時候有問題,你可以自己打開來看發生什麼事。
$_CONFIG['token'] = '';
$logName = 'webhook.txt';
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
rewrite($logName, "\n\n");
rewrite($logName, "\n".$_SERVER['REQUEST_URI']);
rewrite($logName, "\n".$raw);
receiveMsg($data['events'][0]);
function receiveMsg($messaging)
{
global $logName;
$result = array();
$result = sendText($messaging['replyToken']
, 'Text received, echo: '.$messaging['message']['text']);
rewrite($logName, "\n".$result[0].' : '.$result[1]);
}
function sendText($receive,$text){
global $logName;
$url = 'https://api.line.me/v2/bot/message/reply';
$data['replyToken'] = $receive;
$data['messages'] = array(array( 'type' => 'text', 'text' => $text) );
$json = json_encode($data);
rewrite($logName, "\n".$json);
//rewrite($logName, "\n".'before http_post_data: '.$json);
$result = http_post_data($url, $json);
return $result;
}
function http_post_data($url, $data_string) {
global $_CONFIG;
//$token = $_CONFIG['token'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json; charset=utf-8' ,
'Authorization: Bearer {'.$_CONFIG['token'].'}' ,
'Content-Length: ' . strlen($data_string))
);
ob_start();
curl_exec($ch);
$return_content = ob_get_contents();
ob_end_clean();
$return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
return array($return_code, $return_content);
}
function rewrite($filename, $data)
{
$filenum=fopen($filename,'a');
fwrite($filenum,$data);
fclose($filenum);
}
從剛才設定畫面的最下面,找到QRcode,用你自己的手機的LINE加入好友,就可以開始測試。
對話結果就如同下面
https://developers.line.biz/en/docs/messaging-api/getting-started/
重要提醒! 一定要驗證你的email,LINE機器人才能正常工作。
先建立channel
選Messaging API
輸入你的機器人的設定,來建立你的LINE機器人。包含它的大頭照(App icon),機器人的名字(App name)。
這裡我們選Developer Trial,為了多一個PUSH MESSAGES的功能,可以主動發訊息給別人,需不是只能Reply(回應訊息)。Category及Subcategory選擇你的分類。Email是有其它事的話,可以連絡到你。
完成剛才的建立APP後,再進入你的APP繼續設定。
把下列4個地方設定好:
第一個Channel access token (long-lived),小時數預設0就好,表示這個Token沒有時間限制。
第二個Use webhooks,把它設定成Enabled。如果等下自己的PHP程式出錯,Use webhooks會自動調成Disable,你就要再回來改成Enable。
第三個Webhook URL,把你的Webhook server網址設定進去,如果你是第一次接觸Webhook,可參考Facebook Messenger API使用方法,裡面有對Webhook作解釋。但在設定這一項之前,你可能需要先建好你的Webhook程式網頁,不然它會回應失敗,這在下一段會講。
第四個Auto-reply messages,把它Disable掉,使用者才不會收到預設回應訊息。
建立下列PHP程式網頁,放在你的Server上,我喜歡設定檔名為webhook.php,存取網址要如同你上面設定的一樣。"
$_CONFIG['token'] = '
$logName = 'webhook.txt';
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
rewrite($logName, "\n\n");
rewrite($logName, "\n".$_SERVER['REQUEST_URI']);
rewrite($logName, "\n".$raw);
receiveMsg($data['events'][0]);
function receiveMsg($messaging)
{
global $logName;
$result = array();
$result = sendText($messaging['replyToken']
, 'Text received, echo: '.$messaging['message']['text']);
rewrite($logName, "\n".$result[0].' : '.$result[1]);
}
function sendText($receive,$text){
global $logName;
$url = 'https://api.line.me/v2/bot/message/reply';
$data['replyToken'] = $receive;
$data['messages'] = array(array( 'type' => 'text', 'text' => $text) );
$json = json_encode($data);
rewrite($logName, "\n".$json);
//rewrite($logName, "\n".'before http_post_data: '.$json);
$result = http_post_data($url, $json);
return $result;
}
function http_post_data($url, $data_string) {
global $_CONFIG;
//$token = $_CONFIG['token'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json; charset=utf-8' ,
'Authorization: Bearer {'.$_CONFIG['token'].'}' ,
'Content-Length: ' . strlen($data_string))
);
ob_start();
curl_exec($ch);
$return_content = ob_get_contents();
ob_end_clean();
$return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
return array($return_code, $return_content);
}
function rewrite($filename, $data)
{
$filenum=fopen($filename,'a');
fwrite($filenum,$data);
fclose($filenum);
}
從剛才設定畫面的最下面,找到QRcode,用你自己的手機的LINE加入好友,就可以開始測試。
對話結果就如同下面
LINE-BOT-SDK套件(Python)介紹
Line提供Python的套件,給Python程式設計者可以使用套件API跟LINE互動,就不需要撰寫太多複雜的程式及JSON傳輸格式。套件是以Flask提供服務,啟動後,就是LINE的Webhook。
下載套件方法:
pip install line-bot-sdk
範例程式碼,可以Echo使用者輸入的字句:
下載套件方法:
pip install line-bot-sdk
範例程式碼,可以Echo使用者輸入的字句:
from flask import Flask, request, abort
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,
)
app = Flask(__name__)
userNo = 1
line_bot_api = LineBotApi('')
handler = WebhookHandler('')
@app.route("/")
def hello():
return "Hello World!"
@app.route("/callback", methods=['POST'])
def callback():
# get X-Line-Signature header value
signature = request.headers['X-Line-Signature']
# get request body as text
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
#handle webhook body
try:
handler.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
if (event.reply_token == '00000000000000000000000000000000'):
return None
global userNo
text_message = TextSendMessage(text='Hello, world',
quick_reply=QuickReply(items=[
QuickReplyButton(action=MessageAction(label="label", text="text"))
]))
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=userNo))
userNo += 1
if __name__ == "__main__":
app.run(
host = '0.0.0.0',
port = 12345,
debug = True,
ssl_context ='adhoc'
)
訂閱:
文章 (Atom)
-
Line提供Python的套件,給Python程式設計者可以使用套件API跟LINE互動,就不需要撰寫太多複雜的程式及JSON傳輸格式。套件是以Flask提供服務,啟動後,就是LINE的Webhook。 下載套件方法: pip install line-bot-sdk...
-
這個Python程式可以線上將TWNIC的台灣IP清單,轉成iptables的指令,貼到/etc/iptables.rules上,就可以限制只能台灣的IP能存取。 限制port時,用如下寫法,port 80使用"TaiwanIP"規則(平常我們是寫ACC...
-
https://blog.xuite.net/yh96301/blog/367515625-Ubuntu+15.1%E5%AE%89%E8%A3%9DVMware+Workstation+Player+12.1 https://blog.csdn.net/yzf0011/ar...


























