From 989c90e0d2ea55c2d7d828e28aae66c40b8c60bf Mon Sep 17 00:00:00 2001 From: abdullah samman Date: Fri, 24 Feb 2017 11:52:27 +0200 Subject: [PATCH] add .gitignore; add wox plugin files --- .gitignore | 3 + Images/app.png | Bin 0 -> 2002 bytes README.md | 8 ++- client_secret.json | 1 + credentials/__init__.py | 0 credentials/credentials.py | 67 +++++++++++++++++++++ main.py | 118 +++++++++++++++++++++++++++++++++++++ plugin.json | 12 ++++ 8 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 Images/app.png create mode 100644 client_secret.json create mode 100644 credentials/__init__.py create mode 100644 credentials/credentials.py create mode 100644 main.py create mode 100644 plugin.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..344ad5c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.credentials +*.DS_STORE +*.pyc diff --git a/Images/app.png b/Images/app.png new file mode 100644 index 0000000000000000000000000000000000000000..f6cb24f37827ad557cb625166947534e3d6b4821 GIT binary patch literal 2002 zcmcgtXHe7m7XAGbIwn*>K?y8Hq>IvoKe_#k>a`tvWq~F zB1;npgf2yjNaz^K(yMd~_;~ZazL_`g%lmN8IWuSOy)$>t%uTW|GeofoumJ#2MtD8T zbB6y_EKKLvrs>vuPEe?&p$;hPzp?@V^Djnv+SUYUBgfePiauvz@3*Saa@Bqbi7D?VqB1H zZwYe`rnk-<7bVMNQJEX`rIgAKFaTG@ z7n69Ppi%9s6x27*aNI}__wXT_jX1Oo0 zo)kK%Mzwt;(&=JM@B*EP?x9jv{ zqm_-cya!v_WRGrBz3uVTn+ZkIgSiSA@ z@E685^J(_@w$lrdqjho#Vf@?ef?beGBkE=DdnVgh7wbtxpL6!(UM)H+A)M2CwYiW3 zjlr@Y52u-sQnC0AD{O#vj^^iGA`@=JuWmua>x$=!<=uX%Ql< z>@MYPmEB4@^->U+5XW6ZpPjtI#7_K7`@^qxvfkSO^VjX8B8)MpcuzLJ0A?fs-JfjPLF@f?S>*B+0A*o?g&nzX7v%>o# z+xeUN2Y;1xH!7fMz*5y*6K_^;COA`pnEJ20n(E4qBVrcZ^9|qvI_4TKW3KdJP4S6| zTh=}cr}-yrVJox6ui2^KXoTZlewFEnH(SG7LqK0hmb&}zF}D*02Pg5*H%&!iwyq@| zi^F^OZd`RV?YOv>tIZy>X#AYTlxIJ?Q^pU#a%VVJe$yhKx0OurEj%%Ji1?&a$`ANB z@s$KJGJskEzC}jB9={o84}weF++09~!g631MA$S6<}~TnT%rZd7b& zX`Bl1Weq10d%KvQ$(cEkB7ch}8qa;k78jm7MC~5tDuuuMMw=tW%CCkg+SMc~0ku{) z0b7{@Gu2~9XQ%SW-!_r6<&NzF@Onf|8KI$+#T^~InSMP$r2+lWcP+l?{Mw0}u=~?Z z5gsOV?n%z+QKNF=6$3yuN8A+rsDhxS#hxX*(xwWnD#8ME*>PP>+d`17dZ!?0<+@*+ zj&quh@{B=cF4@pl_kN)5$Cw4|-W(mt@;}p5&U3n0DnN7Gut%m%f0!nH|K1R@*@|d9 zTzK4c7OhRr=qquw{9ScXdAFjb3aV>84z#Mo(ldJPkZ`jci5Rr}#{9d1=SSHdK0ayTB!9)g|wiABB8s#s-v(Bs!bp(}QyE zrjte-UeBsQG%vV(;0%Q!(+g&2XEt3-N}mWEBnz)|C9C0z@!u@G8um1vs?tx!0Yy}- z;;gUxkgo3CbqGU2PD{mm_@(!olD z6I9D?+uj^MQFyG7PAy6-Hkk1Kn!tc7|%FRn{__J>rLMrc}C=VtNm zic^?%j~ap2t?MN7@vq}OGisenEF_`Hxf_9o7z|rx-EHp&2prqY@6pv}`~}&T5ML;` z!`xBh0ztU))SYSsydy$YmjuiEH=1mKf@XUJGb12tc8;=v&c}9Jc_44J>&OA39C5B) zx=KUDKyzblZ!NW;PcefE)yg1+vV-!*Wi=BRszEil*_CfrA nUh+%9@XFn2o?<2YN3js4o|dAVC>wPCq=AvXnO>RB{kVSuuSk\Plugins\`, i.e.: C:\Users\evex\AppData\Local\Wox\app-1.3.183\Plugins +* restart Wox + +## Usage: +To use Logitvely on Wox, start wox and type `log` diff --git a/client_secret.json b/client_secret.json new file mode 100644 index 0000000..6ec4a5e --- /dev/null +++ b/client_secret.json @@ -0,0 +1 @@ +{"installed":{"client_id":"66116113965-ipj165bgcbsocir05oqee795inoh2en3.apps.googleusercontent.com","project_id":"divine-anthem-155809","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"MB8lFXAYQNT64ymiR9FDtf_8","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}} \ No newline at end of file diff --git a/credentials/__init__.py b/credentials/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/credentials/credentials.py b/credentials/credentials.py new file mode 100644 index 0000000..b91c201 --- /dev/null +++ b/credentials/credentials.py @@ -0,0 +1,67 @@ +from __future__ import print_function +import httplib2 +import os +import sys + +from apiclient import discovery +from oauth2client import client +from oauth2client import tools +from oauth2client.file import Storage + +# If modifying these scopes, delete your previously saved credentials +# at ~/.credentials/sheets.googleapis.com-python-quickstart.json +SCOPES = 'https://www.googleapis.com/auth/spreadsheets' +CLIENT_SECRET_FILE = 'client_secret.json' +APPLICATION_NAME = 'Google Sheets API Python Quickstart' +CREDS_FILENAME = 'sheets.googleapis.com-python-quickstart.json' +SPREADSHEET_ID = "17MlCBBriFSKC3gfWEIK0_6ENfLiIIB8E21hoDJRrPO8" + +def get_credentials(): + """Gets valid user credentials from storage. + + If nothing has been stored, or if the stored credentials are invalid, + the OAuth2 flow is completed to obtain the new credentials. + + Returns: + Credentials, the obtained credential. + """ + home_dir = os.path.expanduser('.') + credential_dir = os.path.join(home_dir, '.credentials') + if not os.path.exists(credential_dir): + os.makedirs(credential_dir) + credential_path = os.path.join(credential_dir, + CREDS_FILENAME) + + store = Storage(credential_path) + credentials = store.get() + if not credentials or credentials.invalid: + flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) + flow.user_agent = APPLICATION_NAME + credentials = tools.run_flow(flow, store) + return credentials + +def get_service_and_spreadsheetId(): + credentials = get_credentials() + http = credentials.authorize(httplib2.Http()) + discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?' + 'version=v4') + service = discovery.build('sheets', 'v4', http=http, + discoveryServiceUrl=discoveryUrl) + + spreadsheetId = SPREADSHEET_ID + sys.stderr.write("\nspreadsheetId %s\n" % (spreadsheetId)) + + return service, spreadsheetId + +def main(): + """Shows basic usage of the Sheets API. + + Creates a Sheets API service object and prints the names and majors of + students in a sample spreadsheet: + https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit + """ + credentials = get_credentials() + http = credentials.authorize(httplib2.Http()) + +if __name__ == '__main__': + main() diff --git a/main.py b/main.py new file mode 100644 index 0000000..3862285 --- /dev/null +++ b/main.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- + +from wox import Wox, WoxAPI +from credentials import credentials +import json, datetime, sys, os.path, subprocess + +def get_sheet_title_and_column(service, spreadsheetId): + spreadsheet = service.spreadsheets().get(spreadsheetId=spreadsheetId).execute() + dateCells = "C15:I15" + for sheet in spreadsheet['sheets']: + sheetTitle = sheet['properties']['title'] + rangeName = "%s!%s" % (sheetTitle, dateCells) + result = service.spreadsheets().values().get( + spreadsheetId=spreadsheetId, range=rangeName).execute() + values = result.get('values',[]) + colNum = 0 + # TODO: replace current year with actual cell year, see http://stackoverflow.com/q/42216491/766570 + for row in values: + for column in row: + dateStr = "%s %s" % (column, datetime.date.today().year) + try: + cellDate = datetime.datetime.strptime(dateStr, '%b %d %Y') + if cellDate.date() == datetime.date.today(): + return sheetTitle, colNum + except ValueError: + continue + + colNum +=1 + return sheetTitle, colNum + +def get_projects_and_hours(): + service, spreadsheetId = credentials.get_service_and_spreadsheetId() + sheetTitle, colNum = get_sheet_title_and_column(service, spreadsheetId) + projectCells = 'B16:I19' + initialProjectCellIndex = 16 + rangeName = "%s!%s" % (sheetTitle, projectCells) + result = service.spreadsheets().values().get( + spreadsheetId=spreadsheetId, range=rangeName, majorDimension='COLUMNS').execute() + values = result.get('values',[]) + return ( + colNum + , sheetTitle + , values and values[0] + , values and values[colNum+1] + ) + +def get_project_cell(projectStr, sheetTitle, colNum): + service, spreadsheetId = credentials.get_service_and_spreadsheetId() + cols = ['c','d','e','f','g','h','i'] + columnLetter = cols[colNum] + # it's not likely that there wil be more than 4 projects at a time + # but if there is, do logic that fetches all rows before the "total hours" row starts + projectCells = 'B16:%s19' % columnLetter + initialProjectCellIndex = 16 + rangeName = "%s!%s" % (sheetTitle, projectCells) + result = service.spreadsheets().values().get( + spreadsheetId=spreadsheetId, range=rangeName, majorDimension='COLUMNS').execute() + values = result.get('values',[]) + projectNames = list(map((lambda x: x.lower()), values and values[0])) + rowIndex = [i for i, s in enumerate(projectNames) if projectStr.lower() in s] or [0] + initialCellValue = values[colNum+1][rowIndex[0]] if len(values) > 1 and rowIndex else 0 + return '%s%s' % (columnLetter, initialProjectCellIndex + rowIndex[0]), float(initialCellValue), projectNames[rowIndex[0]] if projectNames else '' + +class Logtively(Wox): + def AutoComplete(self, project): + WoxAPI.change_query("log " + project) + + def query(self, query): + if not os.path.isfile('.credentials\\'+credentials.CREDS_FILENAME): + subprocess.Popen(['python', 'credentials\credentials.py'], creationflags=8, close_fds=True) + return [{ + "Title": "Logtively", + "SubTitle": "Login with your google account and try again", + "IcoPath": "Images/app.png", + }] + + colNum, sheetTitle, projects, hours = get_projects_and_hours() + + if query == '': + index = 0 + results = [] + for project in projects: + results.append({ + "Title":project + , "SubTitle": "hours logged: "+hours[index] + , "IcoPath": "Images/app.png" + , "JsonRPCAction":{ + "method": "AutoComplete" + , "parameters":[project] + , "dontHideAfterAction":True + } + }) + index+=1 + return results + + args = query.split(' ') + if len(args) >= 2: + input_project, input_hours = (' '.join(args[0:-1]), int(args[-1])) + if type(input_hours) in [int, float] and input_hours not in [0, 0.0]: + cell, initialCellValue, retrievedProjectStr = get_project_cell(input_project, sheetTitle, colNum) + rangeName = '%s!%s:%s' % (sheetTitle, cell, cell) + sys.stderr.write("updating range" + rangeName) + values = [[initialCellValue + float(input_hours)]] + body = { + 'values': values + } + + service, spreadsheetId = credentials.get_service_and_spreadsheetId() + service.spreadsheets().values().update( + spreadsheetId=spreadsheetId, range=rangeName, body=body, valueInputOption="USER_ENTERED").execute() + return [{ + "Title": "Logtively", + "SubTitle": "Added %s hours to %s" % (input_hours, input_project), + "IcoPath": "Images/app.png", + }] + +if __name__ == "__main__": + Logtively() diff --git a/plugin.json b/plugin.json new file mode 100644 index 0000000..93688f2 --- /dev/null +++ b/plugin.json @@ -0,0 +1,12 @@ +{ + "ID":"2f4e384e-76ce-45c3-aea2-b16f5e5c528f", + "ActionKeyword":"log", + "Name":"Logtively", + "Description":"Logtively", + "Author":"evex", + "Version":"1.0", + "Language":"python", + "Website":"https://github.com/Wox-launche/Wox", + "IcoPath":"Images\\app.png", + "ExecuteFileName":"main.py" +}