219 lines
7.6 KiB
Python
219 lines
7.6 KiB
Python
import os
|
|
import sys
|
|
import traceback
|
|
|
|
try:
|
|
import oauth2client
|
|
except:
|
|
os.system('pip install oauth2client')
|
|
import oauth2client
|
|
|
|
from oauth2client import tools
|
|
from oauth2client.client import flow_from_clientsecrets
|
|
from oauth2client.file import Storage
|
|
|
|
try:
|
|
from apiclient.discovery import build
|
|
except:
|
|
os.system('pip install google-api-python-client')
|
|
from apiclient.discovery import build
|
|
|
|
try:
|
|
import time
|
|
|
|
import gspread
|
|
from gspread_formatting import (cellFormat, color, format_cell_range,
|
|
textFormat)
|
|
except:
|
|
os.system('pip3 install gspread')
|
|
os.system('pip3 install gspread_formatting')
|
|
import gspread, time
|
|
from gspread_formatting import cellFormat, textFormat, color, format_cell_range
|
|
|
|
from support import d, get_logger
|
|
|
|
logger = get_logger()
|
|
|
|
|
|
|
|
|
|
|
|
class GoogleSheetBase:
|
|
|
|
current_flow = None
|
|
|
|
color_format = {
|
|
'green' : cellFormat(
|
|
backgroundColor=color(0, 1, 0), #set it to yellow
|
|
textFormat=textFormat(foregroundColor=color(0, 0, 0)),
|
|
),
|
|
'yellow' : cellFormat(
|
|
backgroundColor=color(1, 1, 0), #set it to yellow
|
|
textFormat=textFormat(foregroundColor=color(0, 0, 0)),
|
|
),
|
|
'white' : cellFormat(
|
|
backgroundColor=color(1, 1, 1), #set it to yellow
|
|
textFormat=textFormat(foregroundColor=color(0, 0, 0)),
|
|
)
|
|
}
|
|
|
|
|
|
def __init__(self, doc_id, credentials_filepath, tab_index, unique_header):
|
|
self.credentials_filepath = credentials_filepath
|
|
self.credentials = self.get_credentials()
|
|
self.doc_id = doc_id
|
|
doc_url = f'https://docs.google.com/spreadsheets/d/{doc_id}'
|
|
gsp = gspread.authorize(self.credentials)
|
|
doc = gsp.open_by_url(doc_url)
|
|
self.tab_index = tab_index
|
|
self.ws = doc.get_worksheet(tab_index)
|
|
self.header_info = None
|
|
self.header_info_reverse = None
|
|
self.unique_header = unique_header
|
|
|
|
|
|
def get_credentials(self, project_filepath=None):
|
|
if os.path.exists(self.credentials_filepath) == False:
|
|
logger.info(f"credentials_filepath : {self.credentials_filepath}")
|
|
url = self.__make_token_cli(project_filepath)
|
|
logger.debug(f"Auth URL : {url}")
|
|
code = input("Input Code : ")
|
|
self.__save_token(self.credentials_filepath, code)
|
|
|
|
store = Storage(self.credentials_filepath)
|
|
credentials = store.get()
|
|
if not credentials or credentials.invalid:
|
|
logger.warning('credentials error')
|
|
#flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
|
|
#creds = tools.run_flow(flow, store)
|
|
os.remove(self.credentials_filepath)
|
|
return self.get_credentials(self.credentials_filepath)
|
|
return credentials
|
|
|
|
|
|
def __make_token_cli(self, project_filepath):
|
|
try:
|
|
if project_filepath == None:
|
|
project_filepath = os.path.join(os.path.dirname(__file__), 'cs.json')
|
|
self.current_flow = flow_from_clientsecrets(
|
|
project_filepath, # downloaded file
|
|
'https://www.googleapis.com/auth/drive', # scope
|
|
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
|
|
return self.current_flow.step1_get_authorize_url()
|
|
except Exception as e:
|
|
logger.error(f"Exception: {e}")
|
|
logger.error(traceback.format_exc())
|
|
|
|
|
|
def __save_token(self, credentials_filepath, code):
|
|
try:
|
|
credentials = self.current_flow.step2_exchange(code)
|
|
storage = Storage(credentials_filepath)
|
|
storage.put(credentials)
|
|
return True
|
|
except Exception as e:
|
|
logger.error(f"Exception: {e}")
|
|
logger.error(traceback.format_exc())
|
|
return False
|
|
|
|
|
|
def get_sheet_data(self):
|
|
tmp = self.ws.get_all_values()#[:-1]
|
|
self.set_sheet_header(tmp[0])
|
|
rows = tmp[1:]
|
|
ret = []
|
|
for row in rows:
|
|
item = {}
|
|
for idx, col in enumerate(row):
|
|
item[self.header_info_reverse[idx+1]] = col
|
|
ret.append(item)
|
|
return ret
|
|
|
|
|
|
def set_sheet_header(self, row):
|
|
self.header_info = {}
|
|
self.header_info_reverse = {}
|
|
for idx, col in enumerate(row):
|
|
self.header_info[col] = idx + 1
|
|
self.header_info_reverse[idx+1] = col
|
|
logger.debug(self.header_info)
|
|
|
|
|
|
def find_row_index(self, total_data, data):
|
|
find_row_index = -1
|
|
#find = False
|
|
#data['IDX'] = len(total_data)+1
|
|
for idx, item in enumerate(total_data):
|
|
if item[self.unique_header] == str(data[self.unique_header]):
|
|
#find = True
|
|
find_row_index = idx
|
|
#data['IDX'] = find_row_index + 1
|
|
break
|
|
|
|
if find_row_index == -1:
|
|
data['IDX'] = len(total_data)+1
|
|
|
|
return find_row_index
|
|
|
|
|
|
def sleep(self):
|
|
time.sleep(0.5)
|
|
|
|
def sleep_exception(self):
|
|
time.sleep(10)
|
|
|
|
|
|
def after_update_cell(self, sheet_row_index, sheet_col_index, key, value, old_value):
|
|
pass
|
|
|
|
|
|
def set_color(self, sheet_row, sheet_col1, sheet_col2, color):
|
|
format_cell_range(self.ws, gspread.utils.rowcol_to_a1(sheet_row,sheet_col1)+':' + gspread.utils.rowcol_to_a1(sheet_row,sheet_col2), color)
|
|
|
|
def set_color_row(self, sheet_row, color):
|
|
format_cell_range(self.ws, gspread.utils.rowcol_to_a1(sheet_row,1)+':' + gspread.utils.rowcol_to_a1(sheet_row,len(self.header_info)), color)
|
|
|
|
def set_color_cell(self, sheet_row, sheet_col, color):
|
|
format_cell_range(self.ws, gspread.utils.rowcol_to_a1(sheet_row,sheet_col)+':' + gspread.utils.rowcol_to_a1(sheet_row,sheet_col), color)
|
|
|
|
def write_data(self, total_data, data):
|
|
find_row_index = self.find_row_index(total_data, data)
|
|
|
|
write_count = 0
|
|
for key, value in data.items():
|
|
if key.startswith('_'):
|
|
continue
|
|
if value == None:
|
|
continue
|
|
if key not in self.header_info:
|
|
continue
|
|
while True:
|
|
try:
|
|
if find_row_index != -1 and str(total_data[find_row_index][key]) != str(value):
|
|
logger.warning(f"업데이트 : {key} {total_data[find_row_index][key]} ==> {value}")
|
|
self.ws.update_cell(find_row_index+2, self.header_info[key], value)
|
|
self.after_update_cell(find_row_index+2, self.header_info[key], key, value, total_data[find_row_index][key])
|
|
write_count += 1
|
|
self.sleep()
|
|
elif find_row_index == -1 and value != '':
|
|
logger.warning(f"추가 : {key} {value}")
|
|
self.ws.update_cell(len(total_data)+2, self.header_info[key], value)
|
|
self.after_update_cell(len(total_data)+2, self.header_info[key], key, value, None)
|
|
write_count += 1
|
|
self.sleep()
|
|
break
|
|
except gspread.exceptions.APIError:
|
|
self.sleep_exception()
|
|
except Exception as e:
|
|
logger.error(f"{key} - {value}")
|
|
logger.error(f"Exception:{str(e)}")
|
|
logger.error(traceback.format_exc())
|
|
logger.error(self.header_info)
|
|
self.sleep_exception()
|
|
|
|
if find_row_index == -1:
|
|
total_data.append(data)
|
|
else:
|
|
total_data[find_row_index] = data
|
|
return write_count
|