タイムトラッカーのtogglのapiをPythonで実行

[toggl](https://toggl.com/)を使って作業の記録などを行っていたが，これをslackなどから管理できるようになるといいなとか，ログを見てみたいな，とか思ってtogglのapiを調べて見ました．

そして，今後何かしら使うときにすぐ使えるようにと，機能のいくつかをTogglDriverとしてクラス化しました．python勉強中なので，何かしら変なコード多いかも．

ソースコードは[こちら](https://gist.github.com/sey323/cd2aa32afd380db243f6196dc0456f70)

#初期化
togglAPIを利用するときに必要となるのは，メールアドレスとapiトークンの二つだけ．基本的に呼び出し時は，この二つを引数で渡してもらえればよい．

```python:TogglDriver.py
class TogglDriver:
    def __init__( self  , _token = None , _mail_address = None , _workspace_id = None ):
        self._token = _token# api_token
        self._mail_address = _mail_address # your mailaddres
        self._workspace_id = _workspace_id
        self.usr = None

        self._headers = {'Content-Type': 'application/json'}
        self._pid_dict = {}
        self._now_id = None

        self.day_logs = []        

        #初期化時にself._pid_dictの更新
        self.get_workspace_id()
        self.request_pid()
```
togglでは，ログを取得するのに，個人のプロジェクトを管理するワークスペースのid(workspace_id)が必要になる．これはapi_tokenがあればapiで取得できるようなので，初期化時にapiから取得しておく．

```python:TogglDriver.py

    '''
    workcpace_idの取得
    '''
    def get_workspace_id( self ):
        #TogglのMy profileから、API_Tokenを取得(入力)
        _api_token = self._token

        r = requests.get('https://www.toggl.com/api/v8/workspaces',
                        auth=(_api_token, 'api_token'))

        #JSON形式でデータのエクスポート
        data = r.json()
        Data = data[0]
        id = Data['id']

        self._workspace_id =  id
```
togglのタイマーを動かしたり，プロジェクトのログをとりたいときに，プロジェクトのid(pid)と呼ばれるものが必要になるらしい．しかし，自分の持っているプロジェクトのpidのみを，apiで一括で取得する方法がなかった．

そこで１年分のログをapiで持ってきて，その中からプロジェクト名とpidを保存する辞書配列の作成を行った．

```python:TogglDriver.py

    '''
    過去一年分のpidを取得
    '''
    def request_pid( self ):
        # 日付の取得
        end_day = dt.now().strftime('%Y-%m-%d')
        t = timedelta(days = 1)
        start_day = dt.now() - t

        #Togglのデータ取得
        _params = {
            'user_agent': self._mail_address,   #登録しているメールアドレス
            'workspace_id': self._workspace_id,      # TogglのworkspaceID
            'start': start_day,          # データ取得開始
            'until': end_day          # データ取得終了
        }

        # TogglのAPIに接続
        r = requests.get('https://toggl.com/reports/api/v2/details',
                            auth=HTTPBasicAuth(self._token, 'api_token'),
                            params=_params)

        print( 'HTTP status :'  , r.status_code )

        # JSONファイルからのデータ取得
        data = r.json()
        Data = data['data']

        #データを1行ずつ読み，pidを取得
        for dataset in Data:
            if dataset["pid"] not in self._pid_dict and not dataset["pid"] is None:  
                print(dataset["pid"])         
                self._pid_dict[str(dataset["project"]).lower()] = dataset["pid"]    
```
#ログの取得
ログの取得は基本的にこのrequest_logメゾットで取得する．開始日(start_day)と終了日(end_day)を指定して，その期間に発生したログを一括で取得する，

```python:TogglDriver.py
    '''
    start_day~end_dayのlogをとる
    '''
    def request_log( self , start_day , end_day):        
        #パラメータ設定
        _params = {
            'user_agent': self._mail_address,   #登録しているメールアドレス
            'workspace_id': self._workspace_id,      # TogglのworkspaceID
            'start': start_day,          # データ取得開始
            'until': end_day          # データ取得終了
        }

        # TogglのAPIに接続
        r = requests.get('https://toggl.com/reports/api/v2/details',
                            auth=HTTPBasicAuth(self._token, 'api_token'),
                            params=_params)

        print( 'HTTP status :'  , r.status_code )

        # JSONファイルからのデータ取得?
        data = r.json()
        Data = data['data']

        row = 0
        #データを1行ずつ整形
        for i in Data:
            dataset = Data[row]
            if dataset["pid"] not in self._pid_dict and not dataset["pid"] is None:           
                self._pid_dict[str(dataset["project"]).lower()] = dataset["pid"]

            #タスク名を取得
            project = dataset["project"]
            data01 = dataset['description']

            #開始日ー開始時間
            start = dataset['start']
            sd = start[0:10]
            st = start[11:19]

            #文字コードを日時に変換
            s = sd + ' ' + st
            date_s = dt.strptime(s,'%Y-%m-%d %H:%M:%S')

            # 終了時間を取得
            end = dataset['end']
            ed = end[0:10]
            et = end[11:19]

            #文字コードを日時に変換
            e = ed + ' ' + et
            date_e = dt.strptime(e,'%Y-%m-%d %H:%M:%S')

            #かかった時間を取得
            dur = date_e - date_s

            #データを保存
            data02 = sd
            data03 = st
            data04 = ed
            data05 = et
            data06 = dur

            #次の行に移動
            row += 1
            
            data_log = {  'Project':project ,'Description':data01 , 'start_day':data02 , 'start_time':data03 , 'end_day':data04 , 'end_time':data05 , 'during':data06 }
            self.day_logs.append( data_log )
```

#時間の計測
##計測のスタート
apiからtogglのタイマーをスタートさせるメゾット．`descriotion`にプロジェクトの説明，`pid`が計測をスタートするプロジェクトのidとなる．

```python:TogglDriver.py
    '''
    プロジェクトをスタート
    '''
    def start( self , description , pid ):
        try:
            _pid = self.convert_pid( pid )
        except KeyError:# 存在しないときにpidの更新
            self.request_pid()
            _pid = self.convert_pid( pid )
        

        params = {"time_entry":{"description":description,"pid": _pid ,"created_with":"python"}}
        
        # TogglのAPIに接続
        r = requests.post('https://www.toggl.com/api/v8/time_entries/start',  
                            auth=HTTPBasicAuth(self._token, 'api_token'),
                            headers = self._headers,
                            data = json.dumps(params))
                            
        data = r.json()
        self._now_id = data['data']['id']
        print( 'HTTP status :'  , r.status_code )

```
ここで引数がpidだと直感的にわかりにくいので，プロジェクト名からpidに変換するメゾットを作成した．

```python:TogglDriver.py
    '''
    プロジェクト名の文字列をpidに変換
    '''
    def convert_pid( self , pid ):
        pid_format = pid.lower()
        if isinstance( pid_format , str):
            _pid = int(self._pid_dict[ pid_format ])
        else:
            _pid = int(pid)
        
        return _pid   
```


##計測をストップ
先ほどのプログラムでスタートしたタイマーを止める．スタート時にpidを格納しているので，引数などはなし．

```python:TogglDriver.py
    '''
    プロジェクトをストップ
    '''
    def stop( self ):
        # TogglのAPIに接続
        url = 'https://www.toggl.com/api/v8/time_entries/'+str(self._now_id)+'/stop'
        r = requests.put( url,auth=HTTPBasicAuth(self._token, 'api_token'),headers = self._headers)

        print( 'HTTP status :'  , r.status_code )
        return r
```
#おわりに
とりあえずやりたい機能の下地はできたので，あとはslackからたたけるようにするとか，ログを視覚化するとかやってみたいですね．

#参考
- https://github.com/toggl/toggl_api_docs
- http://toricago.hatenablog.com/entry/2017/03/11/220000