" ============================================================================= " Filename: autoload/calendar/google/client.vim " Author: itchyny " License: MIT License " Last Change: 2020/11/30 20:02:44. " ============================================================================= let s:save_cpo = &cpo set cpo&vim let s:cache = calendar#cache#new('google') let s:auth_url = 'https://accounts.google.com/o/oauth2/auth' let s:token_url = 'https://accounts.google.com/o/oauth2/token' function! s:client() abort return extend(deepcopy(calendar#setting#get('google_client')), { 'response_type': 'code' }) endfunction function! s:get_url() abort let client = s:client() let param = {} for x in ['client_id', 'redirect_uri', 'scope', 'response_type'] if has_key(client, x) let param[x] = client[x] endif endfor return s:auth_url . '?' . calendar#webapi#encodeURI(param) endfunction function! calendar#google#client#access_token() abort let cache = s:cache.get('access_token') if type(cache) != type({}) || type(cache) == type({}) && !has_key(cache, 'access_token') call calendar#google#client#initialize_access_token() let cache = s:cache.get('access_token') if type(cache) != type({}) || type(cache) == type({}) && !has_key(cache, 'access_token') return 1 endif let content = cache else let content = cache endif return content.access_token endfunction function! calendar#google#client#initialize_access_token() abort let client = s:client() let url = s:get_url() call calendar#webapi#open_url(url) try let code = input(printf(calendar#message#get('access_url_input_code'), url) . "\n" . calendar#message#get('input_code')) catch return endtry if code !=# '' let response = calendar#webapi#post_nojson(s:token_url, {}, { \ 'client_id': client.client_id, \ 'client_secret': client.client_secret, \ 'code': code, \ 'redirect_uri': client.redirect_uri, \ 'grant_type': 'authorization_code'}) let content = calendar#webapi#decode(response.content) if calendar#google#client#access_token_response(response, content) return endif else return endif let g:calendar_google_event_downloading_list = 0 let g:calendar_google_event_download = 3 silent! let b:calendar.event._updated = 3 endfunction function! calendar#google#client#refresh_token() abort let client = s:client() let cache = s:cache.get('refresh_token') if type(cache) == type({}) && has_key(cache, 'refresh_token') && type(cache.refresh_token) == type('') let response = calendar#webapi#post_nojson(s:token_url, {}, { \ 'client_id': client.client_id, \ 'client_secret': client.client_secret, \ 'refresh_token': cache.refresh_token, \ 'grant_type': 'refresh_token'}) let content = calendar#webapi#decode(response.content) if calendar#google#client#access_token_response(response, content) return 1 endif return content.access_token else return 1 endif endfunction function! calendar#google#client#access_token_response(response, content) abort if a:response.status == 200 if !has_key(a:content, 'access_token') call calendar#echo#error_message('google_access_token_fail') return 1 else call s:cache.save('access_token', a:content) if has_key(a:content, 'refresh_token') && type(a:content.refresh_token) == type('') call s:cache.save('refresh_token', { 'refresh_token': a:content.refresh_token }) endif endif else call calendar#echo#error_message('google_access_token_fail') return 1 endif endfunction function! calendar#google#client#get(url, ...) abort return s:request('get', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! calendar#google#client#put(url, ...) abort return s:request('put', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! calendar#google#client#post(url, ...) abort return s:request('post', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! calendar#google#client#delete(url, ...) abort return s:request('delete', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! s:request(method, url, param, body) abort let client = s:client() let access_token = calendar#google#client#access_token() if type(access_token) != type('') return 1 endif let param = extend(a:param, { 'oauth_token': access_token }) let response = calendar#webapi#{a:method}(a:url, param, a:body) if response.status == 200 return calendar#webapi#decode(response.content) elseif response.status == 401 unlet! access_token let access_token = calendar#google#client#refresh_token() if type(access_token) != type('') return 1 endif let param = extend(a:param, { 'oauth_token': access_token }) let response = calendar#webapi#{a:method}(a:url, param, a:body) if response.status == 200 return calendar#webapi#decode(response.content) endif endif return 1 endfunction function! calendar#google#client#get_async(id, cb, url, ...) abort call s:request_async(a:id, a:cb, 'get', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! calendar#google#client#delete_async(id, cb, url, ...) abort call s:request_async(a:id, a:cb, 'delete', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! calendar#google#client#put_async(id, cb, url, ...) abort call s:request_async(a:id, a:cb, 'put', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! calendar#google#client#patch_async(id, cb, url, ...) abort call s:request_async(a:id, a:cb, 'patch', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! calendar#google#client#post_async(id, cb, url, ...) abort call s:request_async(a:id, a:cb, 'post', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! s:request_async(id, cb, method, url, param, body) abort let access_token = calendar#google#client#access_token() if type(access_token) != type('') return 1 endif let param = extend(a:param, { 'oauth_token': access_token }) call calendar#webapi#{a:method}_async(a:id, a:cb, a:url, param, a:body) endfunction function! calendar#google#client#get_async_use_api_key(id, cb, url, ...) abort call s:request_async_use_api_key(a:id, a:cb, 'get', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! calendar#google#client#post_async_use_api_key(id, cb, url, ...) abort call s:request_async_use_api_key(a:id, a:cb, 'post', a:url, a:0 ? a:1 : {}, a:0 > 1 ? a:2 : {}) endfunction function! s:request_async_use_api_key(id, cb, method, url, param, body) abort let client = s:client() let param = extend(a:param, { 'key': client.api_key }) call calendar#webapi#{a:method}_async(a:id, a:cb, a:url, param, a:body) endfunction let &cpo = s:save_cpo unlet s:save_cpo