19
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2018-02-19

togglを使って作業の記録などを行っていたが,これをslackなどから管理できるようになるといいなとか,ログを見てみたいな,とか思ってtogglのapiを調べて見ました.

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

ソースコードはこちら

初期化

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

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から取得しておく.

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で一括で取得する方法がなかった.

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

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)を指定して,その期間に発生したログを一括で取得する,

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となる.

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に変換するメゾットを作成した.

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を格納しているので,引数などはなし.

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からたたけるようにするとか,ログを視覚化するとかやってみたいですね.

参考

19
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?