├── google_cal.py ├── notion_api.py ├── readme.md └── test.py /google_cal.py: -------------------------------------------------------------------------------- 1 | from apiclient.discovery import build 2 | from google_auth_oauthlib.flow import InstalledAppFlow 3 | 4 | import pickle 5 | import json 6 | import os.path 7 | 8 | class google_cal_api(): 9 | def __init__(self,need_generate=False,myCalid=""): 10 | if need_generate or (not os.path.exists("token.pkl")): 11 | self.get_credentials() 12 | self.load_credentials() 13 | self.current_cal_id = myCalid 14 | def get_credentials(self): 15 | scopes = ['https://www.googleapis.com/auth/calendar'] 16 | flow = InstalledAppFlow.from_client_secrets_file("client_secret.json", scopes=scopes) 17 | credentials = flow.run_console() 18 | pickle.dump(credentials, open("token.pkl", "wb")) 19 | 20 | def load_credentials(self): 21 | self.credentials = pickle.load(open("token.pkl", "rb")) 22 | self.service = build("calendar", "v3", credentials=self.credentials) 23 | def insert_calendar(self,summary,return_json=False): 24 | calendar = { 25 | 'summary': summary 26 | } 27 | created_calendar = self.service.calendars().insert(body=calendar).execute() 28 | #print created_calendar['id'] 29 | self.current_cal_id = created_calendar['id'] 30 | if return_json: 31 | return created_calendar 32 | def delete_calendar(self): 33 | if self.current_cal_id =="": 34 | return False 35 | self.service.calendars().delete(calendarId=self.current_cal_id ).execute() 36 | self.current_cal_id ="" 37 | return True 38 | def insert_event(self,calendar_event_entry=-1): 39 | if self.current_cal_id =="": 40 | return False 41 | if(calendar_event_entry==-1): 42 | return False 43 | ''' 44 | calendar_event_entry = { 45 | "end": { 46 | "date": str("") 47 | }, 48 | "start": { 49 | "date": str("") 50 | }, 51 | "summary": str(""), 52 | "description": str("") 53 | } 54 | ''' 55 | calendar_event_entry = self.service.events().insert(calendarId=self.current_cal_id , body=calendar_event_entry).execute() 56 | return calendar_event_entry.get('id') 57 | def update_event(self,event_Id,calendar_event_entry): 58 | if self.current_cal_id =="": 59 | return False 60 | updated_event = self.service.events().update(calendarId=self.current_cal_id , eventId=event_Id, body=calendar_event_entry).execute() 61 | def get_event(self,event_Id): 62 | if self.current_cal_id =="": 63 | return False 64 | event = self.service.events().get(calendarId=self.current_cal_id, eventId=event_Id).execute() 65 | return event 66 | -------------------------------------------------------------------------------- /notion_api.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import time 4 | import urllib 5 | import uuid 6 | import os 7 | import random 8 | import getpass 9 | import sys 10 | 11 | class notion_api(): 12 | def __init__(self,token = ''): 13 | self.USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36' 14 | self.session = requests.Session() 15 | self.session.cookies['token_v2'] = token 16 | def to_notion_uid(self,s): 17 | s = s[:8] + '-' + s[8:12] + '-' + s[12:16] + '-' + s[16:20] + '-' + s[20:] 18 | return s 19 | def getRecordValues(self,request_content): 20 | API_URL = 'https://www.notion.so/api/v3/getRecordValues' 21 | #form_data = json.loads('{"collectionId":"6566fb1f-6df1-4bb3-b5d4-17dc7736dc15","collectionViewId":"906231bd-65dd-4044-8f99-886fc8de465d","query":{"sort":[{"id":"2185123c-d38b-4f85-9f3d-3c0136d7b593","type":"date","property":"]=/L","direction":"ascending"}],"filter_operator":"and","filter":[],"aggregate":[]},"loader":{"type":"table","limit":70,"userTimeZone":"Asia/Taipei","userLocale":"en","loadContentCover":true}}') 22 | self.session.headers = {'user-agent' : self.USER_AGENT,'Content-type': 'application/json'} 23 | req = self.session.post(API_URL,json=request_content) 24 | return json.loads(req.text) 25 | def loadPageChunk(self,request_content): 26 | API_URL = 'https://www.notion.so/api/v3/loadPageChunk' 27 | #form_data = json.loads('{"collectionId":"6566fb1f-6df1-4bb3-b5d4-17dc7736dc15","collectionViewId":"906231bd-65dd-4044-8f99-886fc8de465d","query":{"sort":[{"id":"2185123c-d38b-4f85-9f3d-3c0136d7b593","type":"date","property":"]=/L","direction":"ascending"}],"filter_operator":"and","filter":[],"aggregate":[]},"loader":{"type":"table","limit":70,"userTimeZone":"Asia/Taipei","userLocale":"en","loadContentCover":true}}') 28 | self.session.headers = {'user-agent' : self.USER_AGENT,'Content-type': 'application/json'} 29 | req = self.session.post(API_URL,json=request_content) 30 | return json.loads(req.text) 31 | def get_page_collection_ID(self,pageID): 32 | form_data = json.loads('{"requests": [{"table": "block","id": "'+ pageID + '"}]}') 33 | r = self.getRecordValues(form_data) 34 | return r['results'][0]['value']['collection_id'] 35 | 36 | def get_event(self,page_url,max_limit=70): 37 | #page_url_s = page_url.split('/')[-1] 38 | page_uid = page_url.split('/')[-1].split('?v=')[0] 39 | view_uid = page_url.split('/')[-1].split('?v=')[1] 40 | page_uid = self.to_notion_uid(page_uid) 41 | view_uid = self.to_notion_uid(view_uid) 42 | collection_uid = self.get_page_collection_ID(page_uid) 43 | 44 | print('page_uid = ',page_uid) 45 | print('view_uid = ',view_uid) 46 | print('collection_uid = ',collection_uid) 47 | 48 | API_URL = 'https://www.notion.so/api/v3/queryCollection' 49 | form_data = json.loads('{"collectionId":"' + collection_uid + '","collectionViewId":"' + view_uid +'","query":{"sort":[{"id":"2185123c-d38b-4f85-9f3d-3c0136d7b593","type":"date","property":"]=/L","direction":"ascending"}],"filter_operator":"and","filter":[],"aggregate":[]},"loader":{"type":"table","limit":' + str(max_limit) + ',"userTimeZone":"Asia/Taipei","userLocale":"en","loadContentCover":true}}') 50 | self.session.headers = {'user-agent' : self.USER_AGENT,'Content-type': 'application/json'} 51 | req = self.session.post(API_URL,json=form_data) 52 | json_req = json.loads(req.text) 53 | 54 | #page_uid = 'da322135-7f35-4b12-8534-fe408f7fdefb' 55 | #view_uid = '906231bd-65dd-4044-8f99-886fc8de465d' 56 | #collection_uid = '6566fb1f-6df1-4bb3-b5d4-17dc7736dc15' 57 | 58 | return_data_package = {"properties" :[],"events" : []} 59 | 60 | properties_tag = json_req['recordMap']['collection_view'][view_uid]['value']['format']['list_properties'] 61 | 62 | for p in properties_tag: 63 | #print(p) 64 | if p['visible']== True: 65 | _properties={"name":"","uid_tag":""} 66 | _properties["name"] = json_req['recordMap']['collection'][collection_uid]['value']['schema'][p['property']]['name'] 67 | _properties["uid_tag"] = p['property'] 68 | _properties["type"] = json_req['recordMap']['collection'][collection_uid]['value']['schema'][p['property']]['type'] 69 | return_data_package['properties'].append(_properties) 70 | #print("get p = ",_properties["name"]) 71 | 72 | #print(return_data_package['properties']) 73 | for item in json_req['result']['blockIds']: 74 | event_data = {"title":"","date":"","content":"","notion_content_id":"","google_cal_event_id":""} 75 | properties = json_req['recordMap']['block'][item]['value']['properties'] 76 | _event={} 77 | for required_tag in return_data_package['properties']: 78 | _event['_name'] = properties['title'][0][0] 79 | if required_tag['uid_tag'] in properties.keys(): 80 | if required_tag['type'] == 'text': 81 | _event[required_tag['name']] = properties[required_tag['uid_tag']][0][0] 82 | elif required_tag['type'] == 'date': 83 | _event[required_tag['name']] = properties[required_tag['uid_tag']][0][1][0][1]['start_date'] 84 | elif required_tag['type'] == 'select': 85 | _event[required_tag['name']] = properties[required_tag['uid_tag']][0][0] 86 | _event['_link'] = page_url + '&p=' + item.replace('-','') 87 | return_data_package["events"].append(_event) 88 | 89 | 90 | return return_data_package 91 | 92 | 93 | def get_event_list(self): 94 | 95 | API_URL = 'https://www.notion.so/api/v3/queryCollection' 96 | form_data = json.loads('{"collectionId":"6566fb1f-6df1-4bb3-b5d4-17dc7736dc15","collectionViewId":"906231bd-65dd-4044-8f99-886fc8de465d","query":{"sort":[{"id":"2185123c-d38b-4f85-9f3d-3c0136d7b593","type":"date","property":"]=/L","direction":"ascending"}],"filter_operator":"and","filter":[],"aggregate":[]},"loader":{"type":"table","limit":70,"userTimeZone":"Asia/Taipei","userLocale":"en","loadContentCover":true}}') 97 | self.session.headers = {'user-agent' : self.USER_AGENT,'Content-type': 'application/json'} 98 | req = self.session.post(API_URL,json=form_data) 99 | json_req = json.loads(req.text) 100 | 101 | page_uid = 'da322135-7f35-4b12-8534-fe408f7fdefb' 102 | view_uid = '906231bd-65dd-4044-8f99-886fc8de465d' 103 | collection_uid = '6566fb1f-6df1-4bb3-b5d4-17dc7736dc15' 104 | 105 | data_tag_information={'date_property':{'name':'due day','uid_tag':''}, 106 | 'category_property':{'name':'Course Name','uid_tag':''}, 107 | 'content_property':{'name':'Task Content','uid_tag':''}} 108 | 109 | properties_tag = json_req['recordMap']['collection_view'][view_uid]['value']['format']['list_properties'] 110 | 111 | for p in properties_tag: 112 | tag_name = json_req['recordMap']['collection'][collection_uid]['value']['schema'][p['property']]['name'] 113 | if tag_name == data_tag_information['date_property']['name']: 114 | data_tag_information['date_property']['uid_tag'] = p['property'] 115 | elif tag_name == data_tag_information['category_property']['name']: 116 | data_tag_information['category_property']['uid_tag'] = p['property'] 117 | elif tag_name == data_tag_information['content_property']['name']: 118 | data_tag_information['content_property']['uid_tag'] = p['property'] 119 | 120 | events_to_add={"events":[]} 121 | for item in json_req['result']['blockIds']: 122 | event_data = {"title":"","date":"","content":"","notion_content_id":"","google_cal_event_id":""} 123 | properties = json_req['recordMap']['block'][item]['value']['properties'] 124 | #print(properties['title'][0][0]) 125 | event_data['title'] = properties['title'][0][0] 126 | if data_tag_information['date_property']['uid_tag'] in properties: 127 | event_data['date'] = properties[data_tag_information['date_property']['uid_tag']][0][1][0][1]['start_date'] 128 | if data_tag_information['category_property']['uid_tag'] in properties: 129 | event_data['title'] = '[' + properties[data_tag_information['category_property']['uid_tag']][0][0] + '] ' + event_data['title'] 130 | if data_tag_information['content_property']['uid_tag'] in properties: 131 | event_data['content'] = properties[data_tag_information['content_property']['uid_tag']][0][0] 132 | 133 | event_data['content'] = event_data['content'] + '\n' + 'Link: https://www.notion.so/da3221357f354b128534fe408f7fdefb?v=2115b96ea09941658fedd1095843e652&p=' + item.replace('-','') 134 | event_data['notion_content_id'] = item 135 | 136 | events_to_add['events'].append(event_data) 137 | print(event_data['title']) 138 | else: 139 | continue 140 | return events_to_add 141 | 142 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Notion_Google_Calendar_API 2 | 3 | The usage is demonstrated in test.py -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import notion_api as nta; 2 | import google_cal as gc 3 | 4 | obj_nta = nta.notion_api() 5 | 6 | 7 | #return a dict 8 | event_get = obj_nta.get_event('https://www.notion.so/da3221357f354b128534fe408f7fdefb?v=906231bd65dd40448f99886fc8de465d') 9 | 10 | obj_gc = gc.google_cal_api() 11 | 12 | #create a calendar 13 | obj_gc.insert_calendar('Notion') 14 | 15 | ###delete a calendar 16 | """ 17 | obj_gc = gc.google_cal_api("") 18 | obj_gc.delete_calendar() 19 | 20 | """ 21 | 22 | calendar_event_entry = { 23 | "end": { 24 | "date": "2019-10-1" 25 | }, 26 | "start": { 27 | "date": "2019-10-1" 28 | }, 29 | "summary": "the summary", 30 | "description": "the description..." 31 | } 32 | 33 | #create event and return event id 34 | obj_gc.insert_event(calendar_event_entry) 35 | 36 | #update event 37 | obj_gc.update_event(event_Id,calendar_event_entry) 38 | 39 | #get event info 40 | obj_gc.get_event(event_Id) --------------------------------------------------------------------------------