mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-03 16:40:05 +08:00
441 lines
17 KiB
VimL
441 lines
17 KiB
VimL
|
" =============================================================================
|
||
|
" Filename: autoload/calendar/google/task.vim
|
||
|
" Author: itchyny
|
||
|
" License: MIT License
|
||
|
" Last Change: 2021/09/18 13:24:16.
|
||
|
" =============================================================================
|
||
|
|
||
|
let s:save_cpo = &cpo
|
||
|
set cpo&vim
|
||
|
|
||
|
let s:cache = calendar#cache#new('google')
|
||
|
|
||
|
let s:task_cache = s:cache.new('task')
|
||
|
|
||
|
function! calendar#google#task#get_url(type) abort
|
||
|
return 'https://www.googleapis.com/tasks/v1/' . a:type
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#getTaskList() abort
|
||
|
let taskList = s:cache.get('taskList')
|
||
|
if type(taskList) != type({}) || calendar#timestamp#update('google_tasklist', 7 * 24 * 60 * 60)
|
||
|
call calendar#google#client#get_async(s:newid(['taskList', 0]),
|
||
|
\ 'calendar#google#task#getTaskList_response',
|
||
|
\ calendar#google#task#get_url('users/@me/lists'))
|
||
|
if type(taskList) != type({})
|
||
|
return {}
|
||
|
endif
|
||
|
endif
|
||
|
return taskList
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#getTaskList_response(id, response) abort
|
||
|
let [_tasklist, err; rest] = s:getdata(a:id)
|
||
|
if a:response.status =~# '^2'
|
||
|
let cnt = calendar#webapi#decode(a:response.content)
|
||
|
let content = type(cnt) == type({}) ? cnt : {}
|
||
|
if has_key(content, 'items') && type(content.items) == type([])
|
||
|
call s:cache.save('taskList', content)
|
||
|
silent! let b:calendar.task._updated = 1
|
||
|
silent! call b:calendar.update()
|
||
|
endif
|
||
|
elseif a:response.status == 401
|
||
|
if err == 0
|
||
|
call calendar#google#client#refresh_token()
|
||
|
call calendar#google#client#get_async(s:newid(['taskList', err + 1]),
|
||
|
\ 'calendar#google#task#getTaskList_response',
|
||
|
\ calendar#google#task#get_url('users/@me/lists'))
|
||
|
endif
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#getTasks() abort
|
||
|
if calendar#timestamp#update('google_task', 30 * 60)
|
||
|
call calendar#async#new('calendar#google#task#downloadTasks(1)')
|
||
|
endif
|
||
|
let allTaskList = []
|
||
|
let taskList = calendar#google#task#getTaskList()
|
||
|
if has_key(taskList, 'items') && type(taskList.items) == type([])
|
||
|
for tasklist in taskList.items
|
||
|
call add(allTaskList, tasklist)
|
||
|
let allTaskList[-1].items = []
|
||
|
unlet! cnt
|
||
|
let cnt = s:task_cache.new(tasklist.id).get('information')
|
||
|
if type(cnt) == type({}) && cnt != {}
|
||
|
let i = 0
|
||
|
let allTaskList[-1].etag = cnt.etag
|
||
|
let items = []
|
||
|
while type(cnt) == type({})
|
||
|
unlet! cnt
|
||
|
let cnt = s:task_cache.new(tasklist.id).get(i)
|
||
|
if type(cnt) == type({}) && cnt != {} && has_key(cnt, 'items') && type(cnt.items) == type([])
|
||
|
call extend(items, cnt.items)
|
||
|
endif
|
||
|
let i += 1
|
||
|
endwhile
|
||
|
for item in items
|
||
|
if has_key(item, 'due') && item.due =~# '\v\d+-\d+-\d+T'
|
||
|
let [y, m, d] = map(split(substitute(substitute(item.due, 'T.*', '', ''), '\s', '', 'g'), '[-/]'), 'substitute(v:val, "^0", "", "") + 0')
|
||
|
let item.title = calendar#day#join_date([y, m, d]) . ' ' . get(item, 'title', '')
|
||
|
call remove(item, 'due')
|
||
|
endif
|
||
|
if has_key(item, 'notes') && item.notes !=# ''
|
||
|
let item.title = get(item, 'title', '') . ' note: ' . get(item, 'notes', '')
|
||
|
endif
|
||
|
endfor
|
||
|
call sort(items, function('calendar#google#task#sorter'))
|
||
|
let i = 0
|
||
|
while i < len(items)
|
||
|
if !has_key(items[i], 'parent')
|
||
|
break
|
||
|
endif
|
||
|
let j = i + 1
|
||
|
let items[i].prefix = ' +- '
|
||
|
while j < len(items)
|
||
|
if items[j].id ==# items[i].parent
|
||
|
while j < len(items) - 1
|
||
|
if get(items[j + 1], 'parent', '') ==# items[i].parent
|
||
|
let items[j + 1].prefix = ' |- '
|
||
|
let j += 1
|
||
|
else
|
||
|
break
|
||
|
endif
|
||
|
endwhile
|
||
|
call insert(items, items[i], j + 1)
|
||
|
call remove(items, i)
|
||
|
let i -= 1
|
||
|
break
|
||
|
endif
|
||
|
let j += 1
|
||
|
endwhile
|
||
|
let i += 1
|
||
|
endwhile
|
||
|
let allTaskList[-1].items = items
|
||
|
else
|
||
|
call calendar#google#task#downloadTasks()
|
||
|
endif
|
||
|
endfor
|
||
|
endif
|
||
|
return allTaskList
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#sorter(x, y) abort
|
||
|
return has_key(a:x, 'parent') != has_key(a:y, 'parent')
|
||
|
\ ? (has_key(a:x, 'parent') ? -1 : 1)
|
||
|
\ : a:x.position ==# a:y.position
|
||
|
\ ? (a:x.updated > a:y.updated ? 1 : -1)
|
||
|
\ : a:x.position > a:y.position ? 1 : -1
|
||
|
endfunction
|
||
|
|
||
|
" Optional argument: Force download.
|
||
|
function! calendar#google#task#downloadTasks(...) abort
|
||
|
let taskList = calendar#google#task#getTaskList()
|
||
|
if has_key(taskList, 'items') && type(taskList.items) == type([]) && len(taskList.items)
|
||
|
let j = 0
|
||
|
while j < len(taskList.items)
|
||
|
let item = taskList.items[j]
|
||
|
unlet! cnt
|
||
|
let cnt = s:task_cache.new(item.id).get('information')
|
||
|
if type(cnt) != type({}) || cnt == {} || get(a:000, 0) && (a:0 <= 1 || item.id ==# get(a:000, 1, ''))
|
||
|
let opt = { 'tasklist': item.id, 'maxResults': 100 }
|
||
|
call calendar#google#client#get_async(s:newid(['download', 0, j, 0, item.id, a:000]),
|
||
|
\ 'calendar#google#task#response',
|
||
|
\ calendar#google#task#get_url('lists/' . item.id . '/tasks'), opt)
|
||
|
break
|
||
|
endif
|
||
|
let j += 1
|
||
|
endwhile
|
||
|
if j == len(taskList.items)
|
||
|
silent! let b:calendar.task._updated = 1
|
||
|
silent! call b:calendar.update()
|
||
|
endif
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#response(id, response) abort
|
||
|
let taskList = calendar#google#task#getTaskList()
|
||
|
let [_download, err, j, i, id, force; rest] = s:getdata(a:id)
|
||
|
let opt = { 'tasklist': id }
|
||
|
if a:response.status =~# '^2'
|
||
|
let cnt = calendar#webapi#decode(a:response.content)
|
||
|
let content = type(cnt) == type({}) ? cnt : {}
|
||
|
if has_key(content, 'items')
|
||
|
call s:task_cache.new(id).save(i, content)
|
||
|
if i == 0
|
||
|
call remove(content, 'items')
|
||
|
call s:task_cache.new(id).save('information', content)
|
||
|
endif
|
||
|
if has_key(content, 'nextPageToken')
|
||
|
let opt = extend(opt, { 'pageToken': content.nextPageToken })
|
||
|
call calendar#google#client#get_async(s:newid(['download', err, j, i + 1, id, force]),
|
||
|
\ 'calendar#google#task#response',
|
||
|
\ calendar#google#task#get_url('lists/' . id . '/tasks'), opt)
|
||
|
else
|
||
|
let k = i + 1
|
||
|
while filereadable(s:task_cache.new(id).path(k))
|
||
|
silent! call s:task_cache.new(id).delete(k)
|
||
|
let k += 1
|
||
|
endwhile
|
||
|
let j += 1
|
||
|
while j < len(taskList.items)
|
||
|
let item = taskList.items[j]
|
||
|
unlet! cnt
|
||
|
let cnt = s:task_cache.new(item.id).get('information')
|
||
|
let opt = { 'tasklist': item.id, 'maxResults': 100 }
|
||
|
if type(cnt) != type({}) || cnt == {} || get(force, 0) && (len(force) <= 1 || item.id ==# get(force, 1, ''))
|
||
|
call calendar#google#client#get_async(s:newid(['download', 0, j, 0, item.id, force]),
|
||
|
\ 'calendar#google#task#response',
|
||
|
\ calendar#google#task#get_url('lists/' . item.id . '/tasks'), opt)
|
||
|
break
|
||
|
endif
|
||
|
let j += 1
|
||
|
endwhile
|
||
|
if j == len(taskList.items)
|
||
|
silent! let b:calendar.task._updated = 1
|
||
|
silent! call b:calendar.update()
|
||
|
endif
|
||
|
endif
|
||
|
elseif i == 0 && has_key(content, 'etag')
|
||
|
let k = 0
|
||
|
while filereadable(s:task_cache.new(id).path(k))
|
||
|
silent! call s:task_cache.new(id).delete(k)
|
||
|
let k += 1
|
||
|
endwhile
|
||
|
if k > 0
|
||
|
silent! let b:calendar.task._updated = 1
|
||
|
silent! call b:calendar.update()
|
||
|
endif
|
||
|
endif
|
||
|
elseif a:response.status == 401
|
||
|
if i == 0 && err == 0
|
||
|
let opt = { 'tasklist': id }
|
||
|
call calendar#google#client#refresh_token()
|
||
|
call calendar#google#client#get_async(s:newid(['download', err + 1, j, i, id, force]),
|
||
|
\ 'calendar#google#task#response',
|
||
|
\ calendar#google#task#get_url('lists/' . id . '/tasks'), opt)
|
||
|
endif
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#insert(id, previous, parent, title, ...) abort
|
||
|
let opt = { 'tasklist': a:id }
|
||
|
if a:previous !=# ''
|
||
|
let opt.previous = a:previous
|
||
|
endif
|
||
|
if a:parent !=# ''
|
||
|
let opt.parent = a:parent
|
||
|
endif
|
||
|
let due = ''
|
||
|
if a:0
|
||
|
let due = get(a:1, 'due', '')
|
||
|
if due !=# ''
|
||
|
let due = due . (due =~# 'Z$' ? '' : 'Z')
|
||
|
endif
|
||
|
endif
|
||
|
let note = ''
|
||
|
if a:title =~# ' note: '
|
||
|
let note = matchstr(a:title, ' note: .*$')
|
||
|
let title = a:title[:(len(a:title) - len(note)) - 1]
|
||
|
let note = substitute(note, ' note:\s*', '', '')
|
||
|
else
|
||
|
let note = ''
|
||
|
let title = a:title
|
||
|
endif
|
||
|
call calendar#google#client#post_async(s:newid(['insert', 0, a:id, title, note, due, opt]),
|
||
|
\ 'calendar#google#task#insert_response',
|
||
|
\ calendar#google#task#get_url('lists/' . a:id . '/tasks'),
|
||
|
\ opt, extend({ 'title': title, 'notes': note }, due ==# '' ? {} : { 'due': due ==# '-1Z' ? function('calendar#webapi#null') : due }))
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#insert_response(id, response) abort
|
||
|
let [_insert, err, id, title, note, due, opt; rest] = s:getdata(a:id)
|
||
|
if a:response.status =~# '^2'
|
||
|
call calendar#google#task#downloadTasks(1, id)
|
||
|
elseif a:response.status == 401
|
||
|
if err == 0
|
||
|
call calendar#google#client#refresh_token()
|
||
|
call calendar#google#client#post_async(s:newid(['insert', 1, id, title, note, due, opt]),
|
||
|
\ 'calendar#google#task#insert_response',
|
||
|
\ calendar#google#task#get_url('lists/' . id . '/tasks'),
|
||
|
\ opt, extend({ 'title': title, 'notes': note }, due ==# '' ? {} : { 'due': due ==# '-1Z' ? function('calendar#webapi#null') : due }))
|
||
|
endif
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#move(id, taskid, previous, parent) abort
|
||
|
let opt = { 'tasklist': a:id }
|
||
|
if a:previous !=# ''
|
||
|
let opt.previous = a:previous
|
||
|
endif
|
||
|
if a:parent !=# ''
|
||
|
let opt.parent = a:parent
|
||
|
endif
|
||
|
call calendar#google#client#post_async(s:newid(['move', 0, a:id, a:taskid, opt]),
|
||
|
\ 'calendar#google#task#move_response',
|
||
|
\ calendar#google#task#get_url('lists/' . a:id . '/tasks/' . a:taskid . '/move'),
|
||
|
\ opt, {})
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#move_response(id, response) abort
|
||
|
let [_move, err, id, taskid, opt; rest] = s:getdata(a:id)
|
||
|
if a:response.status =~# '^2'
|
||
|
call calendar#google#task#downloadTasks(1, id)
|
||
|
elseif a:response.status == 401
|
||
|
if err == 0
|
||
|
call calendar#google#client#refresh_token()
|
||
|
call calendar#google#client#post_async(s:newid(['move', 1, id, taskid, opt]),
|
||
|
\ 'calendar#google#task#move_response',
|
||
|
\ calendar#google#task#get_url('lists/' . id . '/tasks/' . taskid . '/move'),
|
||
|
\ opt, {})
|
||
|
endif
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#clear_completed(id) abort
|
||
|
call calendar#google#client#post_async(s:newid(['clear_completed', 0, a:id]),
|
||
|
\ 'calendar#google#task#clear_completed_response',
|
||
|
\ calendar#google#task#get_url('lists/' . a:id . '/clear'),
|
||
|
\ { 'tasklist': a:id })
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#clear_completed_response(id, response) abort
|
||
|
let [_clear_completed, err, id; rest] = s:getdata(a:id)
|
||
|
if a:response.status =~# '^2'
|
||
|
call calendar#google#task#downloadTasks(1, id)
|
||
|
elseif a:response.status == 401
|
||
|
if err == 0
|
||
|
call calendar#google#client#refresh_token()
|
||
|
call calendar#google#client#post_async(s:newid(['clear_completed', 1, id]),
|
||
|
\ 'calendar#google#task#clear_completed_response',
|
||
|
\ calendar#google#task#get_url('lists/' . id . '/clear'),
|
||
|
\ { 'tasklist': id })
|
||
|
endif
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#update(id, taskid, title, ...) abort
|
||
|
let due = ''
|
||
|
if a:0
|
||
|
let due = get(a:1, 'due', '')
|
||
|
if due !=# ''
|
||
|
let due = due . (due =~# 'Z$' ? '' : 'Z')
|
||
|
endif
|
||
|
endif
|
||
|
let note = ''
|
||
|
if a:title =~# ' note: '
|
||
|
let note = matchstr(a:title, ' note: .*$')
|
||
|
let title = a:title[:(len(a:title) - len(note)) - 1]
|
||
|
let note = substitute(note, ' note:\s*', '', '')
|
||
|
else
|
||
|
let note = ''
|
||
|
let title = a:title
|
||
|
endif
|
||
|
call calendar#google#client#put_async(s:newid(['update', 0, a:id, a:taskid, title, note, due]),
|
||
|
\ 'calendar#google#task#update_response',
|
||
|
\ calendar#google#task#get_url('lists/' . a:id . '/tasks/' . a:taskid),
|
||
|
\ { 'tasklist': a:id, 'task': a:taskid },
|
||
|
\ extend({ 'id': a:taskid, 'title': title, 'notes': note }, due ==# '' ? {} : { 'due': due ==# '-1Z' ? function('calendar#webapi#null') : due }))
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#update_response(id, response) abort
|
||
|
let [_update, err, id, taskid, title, note, due; rest] = s:getdata(a:id)
|
||
|
if a:response.status =~# '^2'
|
||
|
call calendar#google#task#downloadTasks(1, id)
|
||
|
elseif a:response.status == 401
|
||
|
if err == 0
|
||
|
call calendar#google#client#refresh_token()
|
||
|
call calendar#google#client#put_async(s:newid(['update', 1, id, taskid, title, note, due]),
|
||
|
\ 'calendar#google#task#update_response',
|
||
|
\ calendar#google#task#get_url('lists/' . id . '/tasks/' . taskid),
|
||
|
\ { 'tasklist': id, 'task': taskid },
|
||
|
\ extend({ 'id': taskid, 'title': title, 'notes': note }, due ==# '' ? {} : { 'due': due ==# '-1Z' ? function('calendar#webapi#null') : due }))
|
||
|
endif
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#complete(id, taskid) abort
|
||
|
call calendar#google#client#patch_async(s:newid(['complete', 0, a:id, a:taskid]),
|
||
|
\ 'calendar#google#task#complete_response',
|
||
|
\ calendar#google#task#get_url('lists/' . a:id . '/tasks/' . a:taskid),
|
||
|
\ { 'tasklist': a:id, 'task': a:taskid },
|
||
|
\ { 'id': a:taskid, 'status': 'completed' })
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#complete_response(id, response) abort
|
||
|
let [_complete, err, id, taskid; rest] = s:getdata(a:id)
|
||
|
if a:response.status =~# '^2'
|
||
|
call calendar#google#task#downloadTasks(1, id)
|
||
|
elseif a:response.status == 401
|
||
|
if err == 0
|
||
|
call calendar#google#client#refresh_token()
|
||
|
call calendar#google#client#patch_async(s:newid(['complete', 1, id, taskid]),
|
||
|
\ 'calendar#google#task#complete_response',
|
||
|
\ calendar#google#task#get_url('lists/' . id . '/tasks/' . taskid),
|
||
|
\ { 'tasklist': id, 'task': taskid },
|
||
|
\ { 'id': taskid, 'status': 'completed' })
|
||
|
endif
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#uncomplete(id, taskid) abort
|
||
|
call calendar#google#client#patch_async(s:newid(['uncomplete', 0, a:id, a:taskid]),
|
||
|
\ 'calendar#google#task#uncomplete_response',
|
||
|
\ calendar#google#task#get_url('lists/' . a:id . '/tasks/' . a:taskid),
|
||
|
\ { 'tasklist': a:id, 'task': a:taskid },
|
||
|
\ { 'id': a:taskid, 'status': 'needsAction' })
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#uncomplete_response(id, response) abort
|
||
|
let [_uncomplete, err, id, taskid; rest] = s:getdata(a:id)
|
||
|
if a:response.status =~# '^2'
|
||
|
call calendar#google#task#downloadTasks(1, id)
|
||
|
elseif a:response.status == 401
|
||
|
if err == 0
|
||
|
call calendar#google#client#refresh_token()
|
||
|
call calendar#google#client#patch_async(s:newid(['uncomplete', 1, id, taskid]),
|
||
|
\ 'calendar#google#task#uncomplete_response',
|
||
|
\ calendar#google#task#get_url('lists/' . id . '/tasks/' . taskid),
|
||
|
\ { 'tasklist': id, 'task': taskid },
|
||
|
\ { 'id': taskid, 'status': 'needsAction' })
|
||
|
endif
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#delete(id, taskid) abort
|
||
|
call calendar#google#client#delete_async(s:newid(['delete', 0, a:id, a:taskid]),
|
||
|
\ 'calendar#google#task#delete_response',
|
||
|
\ calendar#google#task#get_url('lists/' . a:id . '/tasks/' . a:taskid),
|
||
|
\ { 'tasklist': a:id, 'task': a:taskid },
|
||
|
\ { 'id': a:taskid })
|
||
|
endfunction
|
||
|
|
||
|
function! calendar#google#task#delete_response(id, response) abort
|
||
|
let [_delete, err, id, taskid; rest] = s:getdata(a:id)
|
||
|
if a:response.status =~# '^2'
|
||
|
call calendar#google#task#downloadTasks(1, id)
|
||
|
elseif a:response.status == 401
|
||
|
if err == 0
|
||
|
call calendar#google#client#refresh_token()
|
||
|
call calendar#google#client#delete_async(s:newid(['delete', 1, id, taskid]),
|
||
|
\ 'calendar#google#task#delete_response',
|
||
|
\ calendar#google#task#get_url('lists/' . id . '/tasks/' . taskid),
|
||
|
\ { 'tasklist': id, 'task': taskid },
|
||
|
\ { 'id': taskid })
|
||
|
endif
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
let s:id_data = {}
|
||
|
function! s:newid(data) abort
|
||
|
let id = join([ 'google', 'task', a:data[0] ], '_') . '_' . calendar#util#id()
|
||
|
let s:id_data[id] = a:data
|
||
|
return id
|
||
|
endfunction
|
||
|
|
||
|
function! s:getdata(id) abort
|
||
|
return s:id_data[a:id]
|
||
|
endfunction
|
||
|
|
||
|
let &cpo = s:save_cpo
|
||
|
unlet s:save_cpo
|