2017年1月2日 星期一

[聖地巡禮] 長騎美眉 第五話 (ろんぐらいだぁす!)

下午6:37


第五話朝聖有兩部分

第一部分是亞美入手新的公路車,騎回つきみ野

第二部分是亞美自己騎去江之島,然後回程半路爆胎
換完內胎後跑去飯田牧場吃冰淇淋

2016年11月20日 星期日

[聖地巡禮] 長騎美眉 第三話 (ろんぐらいだぁす!)

凌晨3:44


這次跑的是第三話的路線

分別是「大垂水峠」和「ヤビツ峠」,所以分兩次跑 XD

Part 1 : 「大垂水峠」
這是官方給的路線圖:

動畫裡出現的場景只有「長尾山」那一段
如果只是單獨來朝聖的話
是可以從長尾出發就好 XD


( 前半段是路途出現的風景,後半才有動畫出現的場景 )

2016年10月31日 星期一

[聖地巡禮] 長騎美眉 第二話 (ろんぐらいだぁす!)

清晨7:12

2016年10月20日 星期四

[Golang] 使用govendor管理packages

晚上10:02
使用govendor管理golang packages

前言:
因為工作使用Go當backend, 想當然一開始要把環境建構起來,
當時的專案裡,有一份環境建構的文件,
照著文件做,結果環境卻build failed !?

因為都是用 go get github.com/xxxx/packages 下載,
因為某些套件的更新,導致一些原本可以用的method變得不相容,
所以需要一個package管理的套件。

從Go的github wiki有列出幾個管理套件,
有試過govender以及glide,感覺govender比較適合我。

從Go 1.6以後就有支援vendor的功能,1.5可以藉由GO15VENDOREXPERIMENT=1的環境變數來實現vendor功能。

廢話有點多,來點實際的範例吧!

範例:
1. 從 https://github.com/kilfu0701/go-vendor-example 下載
git clone https://github.com/kilfu0701/go-vendor-example.git
cd go-vendor-example
export GOPATH=`pwd`
export PATH=$GOPATH/bin:$PATH

2. 安裝govender
go get -u github.com/kardianos/govendor
rm -rf src/github.com src/golang.org                # after install govender, remove "src/github.com" & "src/golang.org"

3. 安裝example需要的packages
cd src/app
govendor sync

4. 回到example主目錄 執行測試
cd $GOPATH
go run src/main.go

打開瀏覽器 http://localhost:8081/

參考資料(refs):
govender github
Goalng套件管理wiki

2014年10月29日 星期三

[NodeJS] domain-parser

晚上7:58
NodeJS - domain-parser
前言:
剛好想要這個功能,但是沒有現成的
有找到php版本,不過判斷的情況不是很完美
只好自己寫一個 XD

套件名稱:
domain-parser
https://www.npmjs.org/package/domain-parser

Version: 0.0.5 (2014/10/29)

Source Code on Github
https://github.com/kilfu0701/node-domain-parser


安裝方式 (Install)
npm install domain-parser

用法 (Usage)
var dp = require('domain-parser');

var result = dp('www.google.com.tw').domainName;
console.log(result);
// google.com.tw

result = dp('direct.jp-bank.japanpost.jp').domainName;
console.log(result);
// japanpost.jp

2014年6月10日 星期二

[Chome] 非chrome web store的套件被強制停用

凌晨2:51

2014年1月3日 星期五

[Python] sqlalchemy 輸出json格式

清晨6:57
sqlalchemy 輸出json格式

前言:
剛好有人發問,寫了一個範例,

做個記錄一下,也許以後自己會用到 XD

範例:
http://pastie.org/8595769
# -*- coding: utf-8 -*-
import hashlib
import sqlalchemy
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Table
from sqlalchemy.schema import MetaData
from sqlalchemy.orm import relationship
from sqlalchemy.orm import Bundle
from sqlalchemy.orm import lazyload
from sqlalchemy.orm.session import Session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = sqlalchemy.create_engine('mysql+mysqldb://user:passwd@host/your_db?charset=utf8')
connection = engine.connect()
session = Session(bind=connection)

my_declarative_base = lambda cls: declarative_base(cls=cls)

@my_declarative_base
class Base(object):
    @property
    def columns(self):
        return [ c.name for c in self.__table__.columns ]

    @property
    def columnitems(self):
        return dict([ (c, getattr(self, c)) for c in self.columns ])

    def __repr__(self):
        return u'{}({})'.format(self.__class__.__name__, self.columnitems)

    def to_json(self):
        return self.columnitems

    def rec_json(self, key_str):
        result = self.columnitems
        result[key_str] = getattr(self, key_str).columnitems

        return result
        
class User(Base):
    __tablename__ = 'user'
    __table_args__ = {
        'mysql_engine': 'InnoDB',
        'mysql_charset': 'utf8'
    }

    id = Column(Integer, primary_key=True)
    name = Column(String(64))
    username = Column(String(64))
    password = Column(String(256))
    address_id = Column(Integer, ForeignKey('user_address.id'))
    address = relationship("Address", lazy="joined")

    def __init__(self, name, username, password):
        self.name = name
        self.username = username
        self.password = hashlib.sha1(password).hexdigest()

    def __repr__(self):
       return u"[User('%s','%s', '%s')]" % \
           (self.name, self.username, self.password)


class Address(Base):
    __tablename__ = 'user_address'
    __table_args__ = {
        'mysql_engine': 'InnoDB',
        'mysql_charset': 'utf8'
    }

    id = Column(Integer, primary_key=True)
    address = Column(String(256), nullable=False)

    def __init__(self, address):
        self.address = address

    def __repr__(self):
        return u"[Address('%s')]" % self.address
        
        

# insert test data...
"""
Base.metadata.create_all(engine)

user_1 = User("user1", "username1", "password_1")
user_2 = User("user2", "username2", "password_2")
address_1 = Address(u'臺灣凱達格蘭大道')
user_1.address = address_1
user_2.address = address_1
session.add(user_1)
session.add(user_2)
session.commit()
"""

for r in session.query(User).options(lazyload('address')):
    print r.rec_json('address')


"""
Output Result:

{'username': 'username1', 'address_id': 17L, 'name': 'user1', 'address': {'id': 17L, 'address': u'\u81fa\u7063\u51f1\u9054\u683c\u862d\u5927\u9053'},
 'password': '3833b3a1c69cf71a31d86cb5bb4d3866789b4d1e', 'id': 33L}
{'username': 'username2', 'address_id': 17L, 'name': 'user2', 'address': {'id': 17L, 'address': u'\u81fa\u7063\u51f1\u9054\u683c\u862d\u5927\u9053'},
 'password': '148dfdc3c539d35004cb808ca84e17ff962af744', 'id': 34L}

"""

參考資料(Refs):
1. http://chimerhapsody.blogspot.tw/2013/09/python-sqlalchemy-orm-part-3-end.html
2. http://docs.sqlalchemy.org/en/rel_0_9/orm/relationships.html
3. http://blogs.gnome.org/danni/2013/03/07/generating-json-from-sqlalchemy-objects/


2014年1月1日 星期三

[Solr] 安裝Solr 4.6 in Debian

凌晨4:14
安裝Solr 4.6

前言:
距離上次寫的安裝設定很遙遠,而且那時候用的還是比較舊的版本,

就趁這次重新安裝的時候,順便寫一篇給自己以後來用 XD

安裝步驟:

這邊我是都把所有東西放到 /opt/ 底下,

依個人需求自行調整。

1. 下載 solr 4.6
cd /opt/

wget http://ftp.tc.edu.tw/pub/Apache/lucene/solr/4.6.0/solr-4.6.0.tgz
tar zxvf solr-4.6.0.tgz

2. 下載 java sdk (http://www.oracle.com/technetwork/java/javase/downloads/index.html)
tar zxvf jdk-7u45-linux-i586.gz

3. 複製solr-4.6/example到/opt/solr/
cp -pr /opt/solr-4.6.0/example/ /opt/solr/

4. 啟動solr
方法1:
cd /opt/solr/
java -Dsolr.solr.home=multicore -jar start.jar

方法2:
wget https://gist.github.com/Polzme/7367523/raw/9ccf8b040b70eca214497dc6ee2b23e9abb0b8ef/solr -O /etc/init.d/solr
chmod +x /etc/init.d/solr
# 依個人需求,修改java的路徑
vim /etc/init.d/solr

#DAEMON=/usr/bin/java
DAEMON=/opt/jdk1.7.0_45/bin/java
service solr start

5. 檢查是否已經啟動?
http://localhost:8983/solr/

6. 設定開機的時候 啟動solr
update-rc.d solr defaults

7. 設定iptables

只允許localhost access 8983的port
iptables -A INPUT -p tcp -s localhost --dport 8983 -j ACCEPT
iptables -A INPUT -p tcp --dport 8983 -j DROP



參考資料(Refs):
1. http://apache.osuosl.org/lucene/solr/ref-guide/apache-solr-ref-guide-4.6.pdf
2. http://wiki.apache.org/solr/SolrTomcat
3. https://coderwall.com/p/0s3flw
4. https://cwiki.apache.org/confluence/display/solr/Running+Solr+on+Tomcat
5. https://gist.github.com/Polzme/7367523/



2013年12月30日 星期一

[Django] Export CSV file ( 匯出CSV檔案 )

凌晨1:20
Export data to a CSV file with Django

前言:
單純因為會用到,所以就剛好寫到這個功能

想說,以後可能在別的公司or自己的server會用到,就順便整理一份範例。

Example Code:
https://gist.github.com/kilfu0701/7332112
# in some views.py, to serve a csv file in Django.
# -*- coding: utf-8 -*-
import csv

from django.http import HttpResponse

def donwload_csv(request):
    # change export csv formatting by request parameter. ( url?encode=utf-8 )
    encode = request.GET.get('encode', 'big5')
 
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="light_member.csv"'
 
    writer = csv.writer(response, delimiter=',', quotechar='"')
    header = [u'活動名稱', u'姓名', u'Email', u'會員身分', u'答案', u'活動登入日期', u'註冊日期', u'Device']
    writer.writerow([x.encode(encode) for x in header])
    # force export column by text format.
    # http://stackoverflow.com/questions/165042/stop-excel-from-automatically-converting-certain-text-values-to-dates
    deli = u'="{0}"'
 
    ## result['data'], some data from databases.
    #result = {}
    #result['data'] = list(aModel.objects.filter(**ftr).values(*fds))
    for i in result['data']:
        role = u'New' if i['new'] == 1 else u'Exist'
 
        raw_row = [i['plan'], i['name'], i['email'], role, i['option'], str(i['timestamp']), str(i['joined_at']), i['os']]
        row = [deli.format(x).encode(encode) for x in raw_row ]
        writer.writerow(row)
 
    return response


其他參考資料:
1. CSV匯出的時候,會遇到excel格式自動判斷錯誤的問題,後來在下面這篇看到解法:
http://stackoverflow.com/questions/165042/stop-excel-from-automatically-converting-certain-text-values-to-dates

2. 官方文件
https://docs.djangoproject.com/en/dev/howto/outputting-csv/

2013年1月16日 星期三

[Python] 在Debain 6上安裝python 2.7 + vritualenv

晚上7:43
剛好看到有人在gist上放了 安裝python2.7的shell script

其實安裝起來還蠻方便的..(笑)

Shell script code:
https://gist.github.com/1069219

安裝完畢後,執行python就可以看到版本是2.7.2



不過有人會想問,那要用回舊的版本勒?

其實可以修改 ~/.profile 這檔案,檔案內容大致上如下:
if [ "$BASH" ]; then
  if [ -f ~/.bashrc ]; then
    . ~/.bashrc
  fi
fi

mesg n
#if [ -d "$HOME/env/bin" ] ; then
#    PATH="$HOME/env/bin:$PATH"
#fi

PATH="$HOME/env/bin:$PATH"註解掉後,就會套用舊的環境設定。

PS: 恩...原本python2.6裝的django是1.4版的,剛好順便升級到py27 + django-1.5 好了 (茶)

2012年12月19日 星期三

[Chrome] Nico Download Manager (nicoDLM)

上午8:06
Chrome Extension - nico Download Manager
前言:
嗯..因為作者本身常常逛nico,

chrome好像沒有類似nicofox這套件能下載動畫 & comment

所以就....(ry


套件名稱:
nico Download Manager ( ニコ動 ダウンロード管理員 )

Version: 0.1.7 (2013/11/20)

Version: 0.1.6 (2013/2/11)
Version: 0.1.5 (2013/1/8)
Version: 0.1.4 (2012/12/26)
Version: 0.1.3 (2012/12/21)
Version: 0.1.2 (2012/12/20)
Version: 0.1.1 (2012/12/19)


下載點(download):
http://fs.tkafu.cc/nico_DLManager-0.1.7.crx (latest)

目前因為chrome把非app store的套件都會停用,目前還在解決中
暫時性的解決方式:
  • http://fs.tkafu.cc/nicoDLM_src.zip下載並解壓縮
  • 從chrome的工具 > 擴充功能 (或是在網址輸入 chrome://extensions ),打開"開發人員模式" > "載入未封裝擴充功能",選擇剛剛解壓縮的資料夾



0.1.7修正:
  • 修復 右鍵選單有時候會消失的BUG。
  • 修復 社群的影片會無法下載。(影片ID全為數字的情況。)

安裝方式:
1. 右鍵另存.crx檔案。
2. 開啟"工具" -> "擴充功能" 的頁面,再把.crx拖曳到chrome安裝即可。


source code at Github
https://github.com/kilfu0701/nicoDLM


使用介紹:
1. 下載.crx之後,安裝到chrome 會多出一個extension icon在右上角


2. 點選icon 會出現一個頁面,裡頭有下載清單、一般設定、語言環境、關於本套件的表格。


3. 設定調整完畢儲存後,開啟nico的影片頁面,下方會出現一個綠色的框。點選此連結,即可下載動畫以及評論。


3. 因為原宿版本要結束了,之後就要改成GINZA版本了!
不過,還是可以用0.1.6的右鍵選單下載動畫


4. 回到套件的下載清單裡,會看到剛剛新增進去的影片,
(影片名稱、敘述、下載進度、屬性等等)


5. 影片品質,可以從進度下方看到一個"HI"或是"LOW"的小圖示,
HI表示高品質、LOW則是低品質(也就是所謂的經濟模式..)

旁邊的"資料夾"小圖示,則是可以開啟檔案所在的目錄
(若檔案不存在時,不會開啟資料夾)


誰適合使用此套件:
經常逛nico、看nico影片的人


誰不適合使用此套件:
嗯?? Nico是甚麼?好吃嗎?(誤很大)


備註:
1. 請正確設定 下載資料夾 的位置,若有啟用UAC的功能,可能會導致檔案無法寫入!

2. 目前只設定最多兩個影片同時下載。

3. 目前尚未加入下載暫停/取消的功能,若想取消正在下載的檔案,可以將套件重啟。

4. 如果下載影片,發生403 forbidden時,建議把該影片的網址 重新再新分頁開啟後,在重新下載。

5. 檔案格式命名,目前沒有多餘的設定可改,暫時只提供%ID%和%TITLE%。

6. 目前只提供Windows的平台,但是沒有各種環境測試過,不確定有沒有相容問題。

7. 原宿版要結束了,GINZA版本 依舊可以用右鍵選單進行下載。



嗯...有發現BUG或是其他功能,可以回報給我。

2012年11月8日 星期四

[Python] [ニコニコ] Nico影片的下載 & 影片網址解析

凌晨3:08
無聊用python寫一個小東西,主要是解析nico的url,找出影片的實際位置,
加入下載影片的功能 @ 2013/1/7

使用方法
目前可以用兩種方法取得URL,

第一種是給整個url的..用 Nico.req('http://www.nicovideo.jp/watch/sm19186604')
第二種是只給影片的ID Nico.reqSM('sm19154040')

新增Nico.DLVideo( 'http://xxx' ),主要是下載影片 XD


程式碼
# -*- coding: utf-8 -*-
import os, sys
import urllib, urllib2, cookielib
from datetime import *
import time

"""
    Get nico video's link.
    Save cookie in a file, for repeating request API server.
"""
class Nico:
    def __init__(self, settings={}, cookieFile='nico_cookies.lwp'):
        self.cj = cookielib.LWPCookieJar()   # cookie
        self.sm = 0                          # video ID
        self.ck_file = cookieFile            # cookie file
        self.header =  {'User-agent' : 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'} # header
        if settings:
            self.login_data = settings       # account / pw
        else:
            self.login_data = {
                'mail' : 'your_account',
                'password' : 'your_password',
            }

        self.flapi_info = {}
        self.post_url = 'https://secure.nicovideo.jp/secure/login?site=niconico'  # login page url
        self.api_url = 'http://flapi.nicovideo.jp/api/getflv?v={0}'               # api url
        self.thumb_url = 'http://ext.nicovideo.jp/api/getthumbinfo/{0}'           # thumb url
        self.page_url = ''                                                        # video page url
        self.video_url = ''                                                       # video real link
        self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj))
        self.domain = '.autocookie.tt.vv'                                         # define a doamin
        self.cookie_expires = 60*60*24*30  # save cookie in a month

        urllib2.install_opener(self.opener)

        ## if cookie file exist, load it
        if os.path.isfile(self.ck_file):
            self.cj.load(self.ck_file)
            if self.validate()==False:  ## after load cookie file, validate it.
                self.get_cookie()       ## invalid, get a new cookie.
        else:
            ## try to get a new cookie
            self.get_cookie()

    """
        if cookie files exists, validate cookies first!

        @return  : bool
    """
    def validate(self):
        try:
            _user = self.get_value('user', self.domain)
            if len(_user)==1 and _user[0]==self.login_data['mail']:
                return True
            else:
                ## custom cookie value not found / account not match, maybe changed.
                return False

        except Exception, e:
            print e
            return False          

    """
        Dump cookie's data.
    """
    def pr_cookie(self):
        for index, cookie in enumerate(self.cj):
            print index, '  :  ', cookie
            print '%s --> %s' % (cookie.name, cookie.value)

        for d in self.cj._cookies:
            print d

    """
        Get a cookie from nico.
    """
    def get_cookie(self):
        self.cj.clear()
        post = urllib.urlencode(self.login_data)
        req = urllib2.Request(self.post_url, post, self.header)
        resp = urllib2.urlopen(req)
        if resp.headers['x-niconico-authflag']=='1':
            print '== get cookie from NICO success =='
            self.add_custom_cookie("user", self.login_data['mail'])   # add a custom cookie
            self.cj.save(self.ck_file)

        elif resp.headers['x-niconico-authflag']=='0':
            print '== Error: Failed getting cookie. Check ID/PW is correct =='
            self.cj.save(self.ck_file)
            sys.exit()
        else:
            print '== Error: cookie format error. =='
            sys.exit()

    """
        get value from cookies.

        @name   : index
        @domain : if domain not set, it will find all cookies without domain

        @return : a list
    """
    def get_value(self, name, domain=''):
        ret = []
        a = 0
        if domain=='':
            for c in self.cj:
                if c.name == name:
                    ret.append(c.value)
        else:
            if len(self.cj._cookies[domain]).__class__ == a.__class__:
                if self.cj._cookies[domain]["/"][name].name == name:
                    ret.append(self.cj._cookies[domain]["/"][name].value)
            else:
                pass

        return ret

    """
        add a custom datas into cookie, for validate user account

        @name  : 
        @value : 
    """
    def add_custom_cookie(self, name, value):
        _expires = int(time.time()) + self.cookie_expires

        self.cj.set_cookie(
            cookielib.Cookie(
                version=0,
                name=name,
                value=value,
                port=None,
                port_specified=False,
                domain=self.domain,
                domain_specified=True,
                domain_initial_dot=False,
                path="/",
                path_specified=True,
                secure=False,
                expires=_expires,
                discard=False,
                comment=None,
                comment_url=None,
                rest={}
            )
        )

    """
        Start request / find the nico video original link.

        @param : post data
        @url   : the nico video's URL
    """
    def req(self, url='', param={}):
        try:
            self.sm = url.rsplit('/', 1)[1]   # get ID
            return self.reqSM(self.sm, param)

        except Exception, e:
            print '== Error: cannot parse video ID in link =='
            sys.exit()

    """
        If already have video ID, than get video link by ID.

        @param : post data
        @sm    : video ID
        @retry : if failed, retry again.
    """
    def reqSM(self, sm='0', param={}, retry=True):
        try:
            self.sm = sm
            self.page_url = "http://www.nicovideo.jp/watch/{0}".format(self.sm)
            
            url = self.api_url.format(self.sm)
            post = urllib.urlencode(param)
            resp = self.opener.open(url, post)
            data = resp.read()
            for i in data.split('&'):
                x = i.split('=')
                self.flapi_info[x[0]] = x[1]

            if 'url' in self.flapi_info:
                self.video_url = self.flapi_info['url']
            else:
                if retry:
                    self.get_cookie()                                   # get a newer cookie
                    self.video_url = self.reqSM(self.sm, param, False)  # req once again
                else:
                    self.video_url = ''

            self.video_url = urllib2.unquote(self.video_url.encode("utf8"))
            return self.video_url

        except Exception, e:
            print '== Error: cannot reverse the video url =='

    """
        Download video. 
            Before doing download, make sure "req()" or "reqSM()" first! 
    """
    def DLVideo(self, url=''):
        if url=='':
            print "Video URL is empty!"
            return False
        
        if self.page_url=='':
            print "Video page link not set. Please run req()/reqSM() first."
            return False
        
        try:
            from BeautifulSoup import BeautifulSoup as Soup
        except:
            print "'BeautifulSoup' libary not found."
            return False
        
        # get thumb info
        resp = self.opener.open(self.thumb_url.format(self.sm))
        data = resp.read()
        soup = Soup(data)
        file_ext = soup.find('movie_type').text
        
        
        # open original page first
        self.opener.open(self.page_url)

        file_name = "{0}.{1}".format(self.sm, file_ext)
        u = urllib2.urlopen(url)
        f = open(file_name, 'wb')
        meta = u.info()
        file_size = int(meta.getheaders("Content-Length")[0])
        print("Downloading: {0} Bytes: {1}".format(url, file_size))

        file_size_dl = 0
        block_sz = 1024
        while True:
            buffer = u.read(block_sz)
            if not buffer:
                break

            file_size_dl += len(buffer)
            f.write(buffer)
            p = float(file_size_dl) / file_size
            status = r"{0}  [{1:.2%}]".format(file_size_dl, p)
            status = status + chr(8)*(len(status))
            sys.stdout.write(status)

        f.close()
        print "Complete!  -->  {0}".format(file_name)
        return True
        
"""
    usage:  
        python nicoDLM.py sm123456 sm345678    .....
"""
if __name__ == "__main__":
    cookie_path = 'nico_cookies.lwp'  # cookie's location
    myset = {
        'mail' : '',
        'password': ''
    }
    
    #nico = Nico(cookieFile=cookie_path, settings=myset)
    #print nico.req('http://www.nicovideo.jp/watch/sm19186604')
    #print nico.reqSM('sm19154040')
    #nico.DLVideo( nico.reqSM('sm18684948') )
    
    num = len(sys.argv)
    if num==1:
        print "no input for download"
    else:
        nico = Nico(cookieFile=cookie_path, settings=myset)
        for i in xrange(1, num):
            nico.DLVideo( nico.reqSM(sys.argv[i]) )
    
    


結論
恩,應該先寫到這邊,

有新的功能在慢慢加近去。XD

2012年8月29日 星期三

[Shell Script] 備份檔案

凌晨12:40
備份用

耶,就隨意寫一個shell script搭配crontab

備份自己server上的一些東西...(茶)


程式碼部分
#/bin/bash
# ./backup.sh -p /var/www/sc/ -t /tmp

function usage ()
{
    echo -e "** param error. **"
    echo -e "usage:"
    echo -e "\tbackup --path /var/www/kilfu --to /var/www/"
    echo -e "\tbackup -p /var/www/kilfu -t /var/www/\n"
    echo -e "param:"
    echo -e "\t-p | --path\t\tfolder's path."
    echo -e "\t-t | --to\t\tthe path where compress into."
    exit
}

function check_folder_exist ()
{
    if [ -d "$1" ]; then
        return 1
    else
        echo -e "[$2] folder not found!"
        exit
    fi
}

if [ $# -le 0 ]; then
    usage
fi

while [ "$1" != "" ]; do
    case $1 in
        -p | --path )           shift
                                _path=$1
                                ;;
        -t | --to )             shift
                                _to=$1
                                ;;
        -h | --help )           usage
                                exit
                                ;;
        * )                     usage
                                exit 1
    esac
    shift
done

if [ $_path == "" ]; then
    $_path
fi


check_folder_exist $_path "path"
check_folder_exist $_to "to"

TODAY=`date +%Y%m%d`
IFS="/"
export IFS;
for word in $_path; do
    if [ "$word" != "" ]; then
        fname="$word"
    fi
done

cd "$_to"
echo -e "Start compressing..."
echo -e "  compress folder:\t$_path"
echo -e "  destination:\t\t$_to"

tar zcvfP "${fname}_${TODAY}.tar" "$_path"


使用方法
1:
/bin/bash backup.sh -p /var/www/sc/ -t /tmp
2: crontab
#分 時 日 月 週
# backup sc
30 3 * * * /bin/bash /var/www/sc/backup.sh --path /var/www/sc --to /home/backup/


恩,就這樣。

2012年6月21日 星期四

[Django] 建立一個google map

凌晨3:02
參考資料(references):
https://docs.djangoproject.com/en/dev/ref/contrib/gis/install/
http://jefurii.cafejosti.net/blog/2011/05/05/basic-google-maps-django/

安裝設定

先安裝geos吧,這邊是用source code自行編譯:

下載/解壓縮: (解壓縮有錯誤訊息,可能沒裝bzip2.. apt-get install bzip2)
wget http://download.osgeo.org/geos/geos-3.3.0.tar.bz2
tar xjf geos-3.3.0.tar.bz2

編譯+安裝: (編譯需要一段時間,大概5~10分鐘吧)
cd geos-3.3.0
./configure
make
sudo make install

安裝完成後,請打ldconfig,把剛剛安裝好的lib讀取進來
sudo ldconfig

django部分

先在你的app/views.py加入
from django.conf import settings
from django.shortcuts import render_to_response
from django.contrib.gis.maps.google.gmap import GoogleMap
from django.contrib.gis.maps.google.overlays import GMarker, GEvent

def google_map(request):
    points = [
        {'lat':'35.42',     'lng': '139.42', 'href':'http://en.wikipedia.org/wiki/Tokyo'},
        {'lat':'51.30',     'lng':   '0.73', 'href':'http://en.wikipedia.org/wiki/London'},
        {'lat':'40.43',     'lng': '-74.0',  'href':'http://en.wikipedia.org/wiki/New_York_City'},
        {'lat':'34.03',     'lng':'-118.15', 'href':'http://en.wikipedia.org/wiki/Los_Angeles'},
        {'lat':'36.774402', 'lng':'-119.755405', 'href':'http://en.wikipedia.org/wiki/Fresno'},]
    markers = []
    for point in points:
        marker = GMarker('POINT(%s %s)' % (point['lng'], point['lat']))
        event = GEvent('click', 'function() { location.href = "%s"}' % point['href'])
        marker.add_event(event)
        markers.append(marker)
    google = GoogleMap(center=(0,0), zoom=1, markers=markers,
                       key=settings.GOOGLE_MAPS_API_PASSWORD)
    return render_to_response('google_map.html',
                              {'google': google,})

然後建立一個template檔案為 google.map.html
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
{{ google.xhtml }}
<head>
  {{ google.style }}
  {{ google.scripts }}
</head>
<body onload="{{ google.js_module }}.map_load()" onunload="GUnload()">
  <div id="{{ google.dom_id }}" style="width:600px; height:400px;"></div>
</body>
</html>

然後到settings.py加入:
INSTALLED_APPS = (
    ...
    'django.contrib.gis',
    ...
)

GEOS_LIBRARY_PATH = '/usr/local/lib/libgeos_c.so'
GOOGLE_MAPS_API_PASSWORD = 'asdasdasdasdasd'

這邊需要google map api v2的key,由於申請方式和以前不同,

需要用到信用卡刷帳單....(雖然都是0元...需求過大的話,才須額外付費)
https://code.google.com/apis/console/

以上寫完,別忘了去設定urls.py

再去看看網址有沒有地圖出來囉。

2012年4月4日 星期三

[Debian] PPTP VPN 防火牆設定 for DNF (日版Arad)

晚上10:14


關於VPN的初始設定和架設,可以看我之前的[Debian] VPN架設 這篇文章。


恩,原本的iptables設定 基本上都可以達到VPN的功用...

但是,我在測試日版ARAD的組隊的時候,總是不夠順暢,

我也知道這遊戲組隊用到的port是UDP 5063,

中間一直用codomo的防火牆來觀察連線的狀態,

經過兩天的測試,才發現需要在iptables多一些prerouting的規則,

不然,A電腦和B電腦都用VPN組隊時,UDP的封包沒辦法轉送給對方,

導致可以組隊,但是會不夠順暢...(偶而會出現電腦的小圖示)

像是下面的圖:

┌----> VPN Server <-----┐
| |
| port:5063 | port:5063
| udp(out) | udp(out)
A B


會變成兩邊的遊戲端,都會向對方傳送組隊的封包,

VPN Server卻沒有轉送給對方,造成UDP封包送不到對方的遊戲端...(昏)
(PS: UDP的運作原理就不用多說了,請參考Google囉)



後來,我把iptables的設定改成以下:
# clean all setting
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# DNF port pre-routing
iptables -t nat -A PREROUTING -p udp --dport 5063 -i eth0 -j DNAT -s 0/0 --to 192.168.10.234
iptables -t nat -A PREROUTING -p udp --dport 5063 -i eth0 -j DNAT -s 0/0 --to 192.168.10.235
iptables -t nat -A PREROUTING -p udp --dport 5063 -i eth0 -j DNAT -s 192.168.10.234 --to 0.0.0.0-255.255.255.255
iptables -t nat -A PREROUTING -p udp --dport 5063 -i eth0 -j DNAT -s 192.168.10.235 --to 0.0.0.0-255.255.255.255

iptables -I FORWARD -p tcp --syn -i ppp+ -j TCPMSS --set-mss 1356
iptables -o eth0 -A FORWARD -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 800:1536 -j TCPMSS --clamp-mss-to-pmtu


主要是DNF port pre-routing那四行,VPN Server把接收到port為5063的UDP封包,

做轉送的動作,像是下面的圖:


A傳給B:
┌----> VPN Server ------┐
| |
| port:5063 | port:5063
| udp(out) ↓ udp(in)
A B

B傳給A:
┌----- VPN Server <-----┐
| |
| port:5063 | port:5063
↓ udp(in) | udp(out)
A B


這樣就解決了ARAD組隊不順暢的問題了,

本來還在想說,遊戲連線會很聰明的直接在A和B建立一個UDP,

就不需要在經由VPN Server說...(汗)


PS: 至於可不可以和外面的人組隊的話,我還沒測試過,基本上應該沒問題才對。
但是,如果組隊雙方都是用VPN連線的話,
就需要確定提供VPN主機的人,防火牆設定有沒有調整好,

不然,只有一方的VPN有設定,另一方沒設定,
也是會有不順暢的問題!
(這我測過了,A電腦用別人家的付費VPN,B電腦是連我自己架設的VPN)

至於別人家的VPN幫不幫你設定,只好看對方的誠意了。



2012年4月3日 星期二

[Debian] VPN架設

凌晨3:50


恩...最近買了一個VPS來用拉!!!

第一件事就是先架VPN來用囉....

基本上,我是參考 這個網站 的教學

apt-get update
apt-get upgrade
apt-get install pptpd


移除這兩個#的註解
vim /etc/pptpd.conf

localip 192.168.0.234-238,192.168.0.245
remoteip 192.168.1.234-238,192.168.1.245


VPN連線時的帳號密碼,請自己設定囉
vim /etc/ppp/chap-secrets
# Secrets for authentication using CHAP
# client        server  secret                  IP addresses
fu              pptpd   passwordhere            *


把#註解拿掉
vim /etc/sysctl.conf
net.ipv4.ip_forward=1


會出現剛剛你拿掉註解的那行,沒出現的話就是有錯誤,回去看看有沒有修改到
sysctl -p


iptables的設定,他的網站"減號"有大小寫的問題,當初改了一下才成功,沒出現錯誤。
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -o eth0 -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-m tcpmss --mss 800:1536 -j TCPMSS --clamp-mss-to-pmtu


chmod +x /etc/init.d/pptpd
/usr/sbin/update-rc.d -f pptpd defaults


設定防火牆 iptables的設定
vim /etc/iptables.sh
#!/bin/sh
IPT="/sbin/iptables"
$IPT -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$IPT -o eth0 -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-m tcpmss --mss 800:1536 -j TCPMSS --clamp-mss-to-pmtu


chown root /etc/iptables.sh
chmod 700 /etc/iptables.sh


加入 pre-up /etc/iptables.sh
vim /etc/network/interfaces
pre-up /etc/iptables.sh


重新開機,測試看看能不能連囉。

2011年11月6日 星期日

Nico Instant ( ニコニコ インスタント )

晚上10:40

前言:其實...這個在九月底就寫好了,只是...要放上Chorme套件平台,需要申請帳號並且要刷5塊美金,
因為沒有信用卡可刷,就這樣放置到現在...Orz

簡介:自己本身還蠻常逛nico動畫的,所以就趁閒暇的時候寫了一個搜尋工具。

套件名稱:Nico Instant (暫定)

下載點:https://sites.google.com/site/kilfu0701b/nico-instant/nico_instant.crx?attredirects=0&d=1
    http://goo.gl/xrGnM

使用介紹:
1. 基本上,安裝完成後會看到一個圖示,點圖示後會出現一個popup頁面(如下圖),
 這時候可以輸入你要搜尋影片的關鍵字...


2. 人氣標籤功能:當時只有寫search功能,但是...,當腦內一片空白的時候,
 連我自己也不知道要找什麼影片...(飛踢)。所以,就在左上角寫了一個小工具,
 可以找找人氣標籤。若找不到想要的名稱,可以點"人氣標籤"左鍵一下,
 會隨機抓取其他的名稱,或是直接"查看更多"



3. 一般使用:預設是關鍵字去搜尋,直接輸入要找的關鍵字,下面就會出現搜尋的結果。



4. 其他功能:其實可以用"關鍵字""標籤"去搜尋。然後,也有其他選項可排序,
 比如最新評論、上傳、撥放次數等等。



5. 若想保留剛剛的搜尋結果,不妨把頁面開到新的視窗吧。




誰適合使用此套件:
  經常逛nico、看nico影片的人

誰不適合使用此套件:
  嗯?? Nico是甚麼?好吃嗎?(誤很大)


其他:如果有任何使用問題,歡迎回報錯誤。
   若有其他想要的附加功能,也可推薦一下。







PS:目前作者轉戰Python BBS開發中,有想到其他功能再補上去!

2011年3月13日 星期日

Python with Notepad++

晚上7:46
前言
Notepad++真的是個神兵利器阿,

不只是功能齊全 還有一堆強大的外掛,

這裡就來說一下,如何使用Notepad++來開發Python


設定&使用
STEP 1:
下載安裝Notepad++

STEP 2:
安裝外掛模組...( 原本沒有安裝 )

點選 外掛模組 > plugin manager > show plugin manager

找到並勾選 NppExec,安裝他!

然後重新啟動Notepad++

STEP 3:
可以直接按F6 或是 外掛模組 > NppExec

在使用F6前,先把 外掛模組 > NppExec > Follow $(CURRENT_DIRECTORY) 勾選起來吧


然後,按F6會出現一個對話框,輸入下面這行
c:\Python27\python.exe -u "$(FULL_CURRENT_PATH)"

把它Save成你要的名稱,方便以後直接使用!

執行 GO!

下面就會出現執行的視窗...可以看執行過程。



備註:
1.
這個視窗不只是這樣而已,還可以當作一般的cmd來使用,
可以下指令yooo,還不錯用!

2.
還有就是,Notepad++預設tab可能要改一下,
不然compiler會有錯誤!
可以到 自訂 > 使用者自訂 > tab設定
在右邊的欄標(tab)設定,選python後...把"以space取代"勾起來!

3.
若真的遇到Tab卻又不知道藏在哪裡?
那可以在F6裡面加入一個新的指令:
c:\Python27\python.exe -m tabnanny "$(FULL_CURRENT_PATH)"

這樣就會跟你說哪邊會有tab問題了!