2016年9月12日 星期一

iPhone 7 開賣通知程式

過去數年,我能成功購買到第一水 iPhone 及 iPad,是因為編寫了簡單的開賣通知程式,在開賣的一刻以電郵通知我。不過,程式寫得不好,容易出現誤鳴。所以今年重新設計,同時以新學到的 Bash 技術實現。代碼如下:
#!/bin/bash

##----------------------------------------------------------------------------------------
##  iPhone 7 Availability Monitor
##----------------------------------------------------------------------------------------
##  Platform: CentOS7 + bash
##  Written by Pacess
##  Copyright 2016 Pacess Studio.  All rights reserved.
##----------------------------------------------------------------------------------------

##  Variables
userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36" 
directory="snapshot"
log="guard.log"

timeOut=5
noOfRetry=3

##----------------------------------------------------------------------------------------
function PHLog  {
   echo "$1"
   echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$log"
}

##----------------------------------------------------------------------------------------
##  Program start
echo "$(date '+%Y-%m-%d %H:%M:%S')"
echo "-----------------------------------------------------------"
echo "--  iPhone 7 Availability Monitor Version 1.00           --"
echo "--  Written by Pacess                                    --"
echo "--  Copyright 2016 Pacess Studio.  All rights reserved.  --"
echo "-----------------------------------------------------------"
echo ""

##  Move to home directory first
cd /root/iphone-7-availability-monitor

##----------------------------------------------------------------------------------------
##  Retrieving website content
echo "Retrieving website content..."
curl -s --retry $noOfRetry -m $timeOut -A "$userAgent" http://www.apple.com/hk/shop/buy-iphone/iphone-7/5.5-inch-display-128gb-jet-black#01,10,20 > "$directory/store.apple.com.html"
errorCode=$?;  test "$errorCode" -ne "0" && { PHLog "curl exit error code: $errorCode";  exit; }

##----------------------------------------------------------------------------------------
##  Load website content
content=$(cat "$directory/store.apple.com.html")
checkSum=$(echo "$content" | md5sum)
echo "Check sum: $checkSum"

##  Check if keyword "Relate" found
wording=$(grep -o ">Add to Bag<" "$directory/store.apple.com.html")
wordingSize=${#wording}
echo "Wording size: $wordingSize"
if (($wordingSize < 12)); then
   echo "Content ok!"
else
   PHLog "Apple website content have been changed..."

   ##  Save file
   mv "$directory/store.apple.com.html" "$directory/$(date '+%Y%m%d%H%M%S')_store.apple.com.html"

   ##  Update checksum, prevent sending email every 15 mins, use > will replace existing contents
   echo "$checkSum" > store.apple.com.md5

   ##----------------------------------------------------------------------------------------
   ##  Send email alert
   echo -e "Dear Pacess,\n\niPhone 7 is now available at http://www.apple.com/hk/shop/buy-iphone/iphone-7/5.5-inch-display-128gb-jet-black#01,10,20.\n\nThanks!\n\nSita-bot" | mail -r "robot@pacess.com (Sita-bot)" -s "[Monitor] iPhone 7 is available now..." pacess@pacess.com
fi

2016年9月9日 星期五

iPhone 7 搶機神器・二


昨天寫的《iPhone 7 搶機神器》在開賣的一刻失敗了,一直無法把 iPhone 7 加到購物籃。不過,今次的失敗並不是程式寫得不好;而是我想買的亮黑色 128GB 在網頁開賣的一刻沒有貨...。

一如以往,自 iPhone 4s 起,最先開賣的是 Apple Store 應用程式。當天情況依舊。不過卻是 CSL 客戶能優先選購。在開賣的一刻,使用 CSL 1010 的同事順利進入 Apple Store。那時,我在使用公司的 WiFi;不論網頁還是應用程式都處於閉店狀態,就算重新啟動應用程式,還是閉店。我甚至利用了兩個 VPN 來連接,同樣是閉店。直到同事輕輕鬆鬆買了兩台 iPhone 7 Plus 亮黑色 128GB,我的電腦及手機才緩慢地開店。但亮黑色已經售罄...。


在努力連線,我仍然是閉店的時候,朋友傳來開店畫面。他也是用 CSL 1010。在 Facebook 看到朋友成功購買的貼圖,又是 CSL。似乎 CSL 真的做得好一點。

2016年9月8日 星期四

iPhone 7 搶機神器


明天是第一批 iPhone 7 在網上發售的日子,下午三時候開賣。過去數年到設定了開賣程式,在開賣時以電郵通知我進行手動購買。今次也不例外,編寫了一個全新的通知程式,準確度更高。

雖然有開賣提示幫忙,但是明天當刻有兩個較長的會議,可能無法親自落單。既然如此,唯有編寫機械人程式代勞。程式員就像有分身這個能力一樣。利用早前學到的 CasperJS 技巧,花了三個多小時,不斷反覆測試,終於完成了「iPhone 7 搶機神器」。只要輸入一行指令,拍一下 Enter 鍵,程式便能自動進入 iPhone 7 頁面購買。如果利用 Cronjob 把它執行,便能在開賣時不停地買。到時,最怕是卡數爬升得太快...;還有就是大量人湧入 Apple 網頁時造成的網絡延遲及突發情況,未知程式能否處理得來。

2016年9月2日 星期五

AWS: Relational Database and Migration Workshop


今日出席了 Amazon Web Services 舉辦的「AWS: Relational Database and Migration Workshop」,以下是一點筆記:
  • 使用 Master-Slave 方式時,可以用不同的 Availability Zone
  • AWS 的 DB 沒有 SSH/RDP 服務
  • PostgreSQL 支援 SSL
  • EBS 加密數據庫時在數據庫層面; Hardware Security Module 則是在檔案層面
  • 一個 AWS 帳號不以生產不同的用戶帳號及權限
  • 當 Primary 數據庫出問題後,AWS 需要花 5-30 秒去轉換 Availability Zone
  • 建議最多用 5 個 Replica
  • CloudWatch 可以查看 VPC 的情況
  • 2016年9月1日 星期四

    Windows + Apache + MSSQL + PHP 測試

    平時較常用 Linux + Apache + MySQL + PHP。今日嘗試把當中兩項改為 Microsoft 的產品,變成 Windows + Apache + MSSQL + PHP,看看需要有多大的改動。

    安裝好 Windows Server 後,裝上 Apache 及 PHP 後,編寫了一個簡單的程式,分別以 PDO 及 sqlsrv 方式對 MSSQL 內的表格進行存取。
    <?php
    //----------------------------------------------------------------------------------------
    //  MSSQL Connection and Query Test for Microsoft Windows 2012
    //----------------------------------------------------------------------------------------
    //  Platform: Windows Server 2012 + PHP7 + Apache24 + MSSQL
    //  Written by Pacess HO
    //  Copyright 2016 Pacess Studio.  All rights reserved.
    //----------------------------------------------------------------------------------------
    
    //  Variables
    $hostname = "127.0.0.1";
    $username = "pacess";
    $password = "Sita0310";
    $database = "SitaChan";
    
    $date = date("YmdHis");
    
    //----------------------------------------------------------------------------------------
    //  Connect to database
    $connectionInfo = array("Database"=>$database, "UID"=>$username, "PWD"=>$password);
    $sqlConnection = sqlsrv_connect($hostname, $connectionInfo);
    
    //----------------------------------------------------------------------------------------
    //  SELECT statement
    $statement = "SELECT * FROM dbo.employees";
    $query = sqlsrv_query($sqlConnection, $statement);
    echo("<br>statement=$statement");
    
    while ($row = sqlsrv_fetch_array($query, SQLSRV_FETCH_NUMERIC))  {
        echo("<br>".$row[1]." / ".$row[2]);
    }
    echo("<hr>");
    
    //----------------------------------------------------------------------------------------
    //  PDO: Connect to database
    //----------------------------------------------------------------------------------------
    $dsn = "sqlsrv:Server=".$hostname.";Database=".$database;
    $pdo = new PDO($dsn, $username, $password);
    $pdo->exec("SET NAMES 'utf8'");
    $pdo->exec("SET CHARACTER SET UTF8");
    $pdo->exec("SET CHARACTER_SET_RESULTS=UTF8");
    
    $pdo->exec("USE TestingDB;");
    
    //----------------------------------------------------------------------------------------
    //  SELECT statement
    $statement = "SELECT * FROM dbo.employees";
    $resultArray = $pdo->query($statement);
    echo("<br>statement=$statement");
    
    $nextID = 1;
    foreach ($resultArray as $row)  {
        $nextID++;
        echo("<br>".$row["employee_name"]." / ".$row["employee_password"]);
    }
    echo("<hr>");
    
    //----------------------------------------------------------------------------------------
    //  INSERT statement
    $newPassword = md5("Pass_".$date);
    
    $statement = "INSERT INTO dbo.employees (employee_id, employee_name, employee_password) VALUES (".$nextID.", 'User_".$date."', '".$newPassword."');";
    $affectedRows = $pdo->exec($statement);
    echo("<br>statement=$statement");
    echo("<br>affectedRows=$affectedRows");
    echo("<hr>");
    
    //----------------------------------------------------------------------------------------
    //  UPDATE statement
    $userPassword = md5($date);
    
    $statement = "UPDATE dbo.employees SET employee_password='".$userPassword."' WHERE employee_name='Pacess'";
    $affectedRows = $pdo->exec($statement);
    echo("<br>statement=$statement");
    echo("<br>affectedRows=$affectedRows");
    echo("<hr>");
    
    ?>

    2016年8月30日 星期二

    在 CentOS7 刪除 MySQL


    之前自己寫下的 CentOS 7 安裝教學,其中一部份是關於 MySQL。最近想試用 MariaDB,發現原本 CentOS 7 已跟機附有,而 MariaDB 及 MySQL 只能二擇其一,所以得要刪除 MySQL。方法是:
    yum remove mysql-community-client mysql-community-common mysql-community-server

    2016年8月29日 星期一

    在 macOS 利用 SQLDeveloper 存取 MSSQL 資料


    今日要把一個 Linux + Apache + MySQL + PHP 項目轉移到 Microsoft Server 上。為減少需要作出的改動,就是照使用 Apache + PHP,把 MySQL 改為 MSSQL。同時不安裝 phpMyAdmin,改為使用 SQLDeveloper。

    在安裝好 SQLDeveloper 後,平時只需要電腦地址、連接埠、用戶名稱及密碼的資料,竟然多了 SID 這一項。搞了一段時間也毫無頭緒,還出現了「Status: Failure - Test failed: IO Error: The Network Adapter could not establish the connection」錯誤。最後發現要安裝 SQL Server and Sybase JDBC 驅動程式才行。還好,安裝步驟簡單。重啟 SQLDeveloper 後,在同一個介面多了 SQL Server 頁。只需要輸入好前面提過的資料,便能順利進入。

    2016年8月26日 星期五

    .club 域名


    同事跟我說,現在有 .club 域名,於是我嘗試搜索 robot.club 是否可以申請。在 GoDaddy 得到的結果是「可以申請」。不過,這個域名是「特別版」,索價要 HK$39,949.99。如果拿來做生意,還算可以接受吧。


    同時,我也搜索了「sitachan.club」。首年索價 HK$23,之後要 HK$136。本來也想把它買回來,可是沒想到怎麼用,還是算吧。

    2016年8月25日 星期四

    利用 Bash 程式下載 Packt 免費電子書並上傳 Git 及發出通知

    之前改編的「利用 Bash 程式下載 Packt 免費電子書」完成後,還是想做更多。要是下載後能直接上傳 GitLab、自動輸入備註、再發送電郵通知就完滿了。於是著手動工。 原本的 Bash 程式在 CentOS 下不用改也能順利執行。因此,只需要加入提交到 Git 及發送電郵便能成事:
    #!/bin/bash
    
    ##----------------------------------------------------------------------------------------
    ##  Packt Free eBook Downloader
    ##----------------------------------------------------------------------------------------
    ##  Platform: CentOS7 + bash
    ##  Written by Pacess
    ##  Copyright 2016 Pacess Studio.  All rights reserved.
    ##----------------------------------------------------------------------------------------
    
    ##----------------------------------------------------------------------------------------
    ##  Update History:
    ##----------------------------------------------------------------------------------------
    ##  2016.08.25
    ##  - Added auto commit to GitLab
    ##----------------------------------------------------------------------------------------
    
    ##  Variables
    userID="sita@chan.com"
    password="Sita0310"
    
    timeOut=5
    noOfRetry=3
    sleepTimeBetweenRequest=1
    
    userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36" 
    downloadDirectory="/Users/pacessho/MEGA/eBooks"
    log="packt_igustin.log"
    cookie="cookie.txt"
    
    ##----------------------------------------------------------------------------------------
    function PHLog  {
        echo "$1"
        echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$log"
    }
    
    ##----------------------------------------------------------------------------------------
    ##  Program start
    echo "$(date '+%Y-%m-%d %H:%M:%S')"
    echo "-----------------------------------------------------------"
    echo "--  Packt Free eBook Downloader Version 1.10             --"
    echo "--  Written by Pacess                                    --"
    echo "--  Copyright 2016 Pacess Studio.  All rights reserved.  --"
    echo "-----------------------------------------------------------"
    echo ""
    
    ##  Move to home directory first
    cd /root/PacktDownloader
    
    ##  Remove previous temp file
    rm -f $cookie packt*.html
    
    ##----------------------------------------------------------------------------------------
    ##  Website login
    PHLog "Logging in $userID..."
    curl -s --retry $noOfRetry -m $timeOut -A "$userAgent" -b "$cookie" -c "$cookie" -d "email=$userID" -d "password=$password" -d "op=Login" -d "form_build_id=form-73ba86bbfb2a50719049129632c84810" -d "form_token=2f1d586bf7df196b77d0761709d03199" -d "form_id=packt_user_login_form" https://www.packtpub.com
    errorCode=$?;  test "$errorCode" -ne "0" && { PHLog "curl exit error code: $errorCode";  exit; }
    
    curl -s --retry $noOfRetry -m $timeOut -A "$userAgent" -b "$cookie" -c "$cookie" https://www.packtpub.com/packt/offers/free-learning > packt_daily.html
    errorCode=$?;  test "$errorCode" -ne "0" && { PHLog "curl exit error code: $errorCode";  exit; }
    
    ##----------------------------------------------------------------------------------------
    ##  Extract claim URL
    claim=$(grep -oE "freelearning-claim/[0-9]+/[0-9]+" packt_daily.html)
    PHLog "Claim URL: $claim"
    
    ##  Extract book title, trim and remove invalid characters
    title=$(grep "dotd-title" -A 2 packt_daily.html | tail -1 | sed 's/^[^0-9A-Za-z]*//;s/[\t ]*<\/h2>$//')
    title="$(echo -e "${title}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/[^A-Za-z0-9 ._-]//g')"
    PHLog "eBook Found: $title"
    
    ##  Extract book ID
    bookID=$(echo $claim | sed "s/.*\/\([0-9]*\)\/.*/\1/")
    echo "";
    
    ##  Claim ebook now
    curl -s --retry $noOfRetry -m $timeOut -A "$userAgent" -b "$cookie" -c "$cookie" -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' -H 'Host: www.packtpub.com' -H 'Referer: https://www.packtpub.com/packt/offers/free-learning' "https://www.packtpub.com/$claim"
    errorCode=$?;  test "$errorCode" -ne "0" && { PHLog "curl exit error code: $errorCode";  exit; }
    
    ##----------------------------------------------------------------------------------------
    ##  Download PDF version
    PHLog "Downloading PDF...$title.pdf"
    curl -s -L --retry $noOfRetry -A "$userAgent" -b "$cookie" -c "$cookie" "https://www.packtpub.com/ebook_download/$bookID/pdf" > "$downloadDirectory/$title.pdf"
    errorCode=$?;  test "$errorCode" -ne "0" && { PHLog "curl exit error code: $errorCode";  exit; }
    
    ##  Download EPUB version
    PHLog "Downloading EPUB...$title.epub"
    curl -s -L --retry $noOfRetry -A "$userAgent" -b "$cookie" -c "$cookie" "https://www.packtpub.com/ebook_download/$bookID/epub" > "$downloadDirectory/$title.epub"
    errorCode=$?;  test "$errorCode" -ne "0" && { PHLog "curl exit error code: $errorCode";  exit; }
    
    ##  Download MOBI version
    PHLog "Downloading MOBI...$title.mobi"
    curl -s -L --retry $noOfRetry -A "$userAgent" -b "$cookie" -c "$cookie" "https://www.packtpub.com/ebook_download/$bookID/mobi" > "$downloadDirectory/$title.mobi"
    errorCode=$?;  test "$errorCode" -ne "0" && { PHLog "curl exit error code: $errorCode";  exit; }
    
    ##----------------------------------------------------------------------------------------
    ##  Job done, log out now
    PHLog "Logging out..."
    curl -s --retry $noOfRetry -m $timeOut -A "$userAgent" -b "$cookie" -c "$cookie" https://www.packtpub.com/logout > packt_logout.html
    errorCode=$?;  test "$errorCode" -ne "0" && { PHLog "curl exit error code: $errorCode";  exit; }
    
    ##  Remove temporary file
    rm -f $cookie packt*.html
    echo "" >> "$log"
    
    ##----------------------------------------------------------------------------------------
    ##  Commit to GitLab
    PHLog "Commiting to GitLab..."
    git config --global user.name "Sita Chan"
    git config --global user.email "sita@pacess.com"
    
    git add *
    git commit -m "Added '$title'"
    git push -u origin master
    
    ##----------------------------------------------------------------------------------------
    ##  Send email alert
    echo -e "Dear Pacess,\n\nA Packt ebook '$title' have been downloaded and commit to GitLab.  Thanks!\n\nSita-bot" | mail -r "sita@pacess.com (Sita-bot)" -s "[GitLab] Added Packt ebook '$title'..." pacess@pacess.com

    2016年8月24日 星期三

    用 Mailx 發送電郵

    最近用多了 Bash 指令去做定時執行的工作;有些時候需要發出電郵通知本人關於運作的情況;所以特別搜索一下做法。

    其中一個可以用的是 Mailx。我沒需要附加檔案,整件事很簡單。用 echo 指令打印文字串,經「|」符號把文字串引導到 Mailx 內。Mailx 後方加入「-r "發件人地址"」,如要加入親和系的名稱,則需要用()包著。然後是「-s "主旨"」,空格後加入收件人地址。


    如收件人多於一位時,可用逗號分隔及接著下一地址。如:「pacess@pacess.com,sita@pacess.com,crystal@pacess.com」