async-vikunja
gem "async-vikunja"require "async/vikunja"
Async::Vikunja::Client.open("https://vikunja.example.com/api/v2/") do |client|
vikunja = client.authenticated(ENV.fetch("VIKUNJA_TOKEN"))
vikunja.info.version
vikunja.user.username
vikunja.test_token.message
endAsync::Vikunja::Client.open do |client|
vikunja = client.authenticated(ENV.fetch("VIKUNJA_TOKEN"))
endjwt = Async::Vikunja::Client.open(url) do |client|
client.login({username: "tester", password: "secret", long_token: true}).token
endvikunja.projects.map(&:title)
vikunja.projects(q: "inbox").first.id
vikunja.projects(is_archived: true).count
vikunja.projects.each_page(per_page: 25) do |page|
page.page
page.total
page.total_pages
page.items.size
page.metadata["content-type"]
page.each{|project| project.title}
end
vikunja.projects.take(2).map(&:title)project = vikunja.create_project({title: "Inbox", hex_color: "4287f5"})
project.id
project.identifier
project.owner.username
project.views.map(&:title)
vikunja.project(project.id).title
vikunja.project(project.id).update({id: project.id, title: "Renamed"})
vikunja.project(project.id).patch({title: "Patched"})
vikunja.project(project.id).deleteproject = vikunja.project(1)
task = project.create_task({title: "write the client", priority: 3})
project.tasks(filter: "done = false", sort_by: ["due_date"]).map(&:title)
project.task_by_index(1).title
vikunja.task(task.id).title
vikunja.task(task.id).update({id: task.id, title: "write the client", done: true})
vikunja.task(task.id).patch({percent_done: 0.5})
vikunja.task(task.id).mark_read
vikunja.task(task.id).deletevikunja.tasks(filter: "due_date > now", expand: "subtasks").each do |task|
task.title
task.due_date
task.project_id
task.done?
task.labels.map(&:title)
task.assignees.map(&:username)
endtask = vikunja.task(7)
comment = task.create_comment({comment: "shipped"})
comment.author.username
task.task_comments(order_by: "desc").map(&:comment)
task.comment(comment.id).update({id: comment.id, comment: "shipped twice"})
task.comment(comment.id).deletelabel = vikunja.create_label({title: "urgent", hex_color: "e8384f"})
vikunja.task(7).add_label(label.id)
vikunja.task(7).task_labels.map(&:title)
vikunja.task(7).replace_labels([{id: label.id}])
vikunja.task(7).remove_label(label.id)
vikunja.labels.map(&:title)
vikunja.label(label.id).patch({title: "later"})
vikunja.label(label.id).deletevikunja.task(7).add_assignee(2)
vikunja.task(7).task_assignees.map(&:username)
vikunja.task(7).replace_assignees([{id: 2}, {id: 3}])
vikunja.task(7).remove_assignee(2)vikunja.task(7).add_relation({other_task_id: 8, relation_kind: "subtask"})
vikunja.task(7).remove_relation("subtask", 8)
vikunja.task(7).duplicate.duplicated_task.title
vikunja.task(7).reposition({project_view_id: 4, position: 2.5})view = vikunja.project(1).view(4)
view.view_kind
view.tasks.map(&:title)
view.buckets.map(&:title)
view.buckets_with_tasks.items.flat_map{|bucket| bucket.tasks.map(&:title)}
bucket = view.create_bucket({title: "Doing", limit: 5})
view.move_task(bucket.id, {task_id: 7, project_view_id: view.id})
view.update_bucket(bucket.id, {id: bucket.id, title: "In progress"})
view.remove_bucket(bucket.id)entry = vikunja.create_time_entry({task_id: 7, start_time: Time.now.utc.iso8601, comment: "pairing"})
vikunja.time_entries(filter: "start_time > now/w").map(&:comment)
vikunja.task(7).task_time_entries.map(&:id)
vikunja.project(1).time_entries.sum{|each| each.id}
vikunja.stop_timer.end_time
vikunja.time_entry(entry.id).deleteteam = vikunja.create_team({name: "platform", is_public: false})
team.add_member({username: "tester"})
team.members.map(&:username)
team.toggle_admin("tester")
team.remove_member("tester")
vikunja.project(1).add_team({team_id: team.id, permission: 1})
vikunja.project(1).teams.map(&:name)
vikunja.project(1).remove_team(team.id)share = vikunja.project(1).create_share({permission: 0, name: "read only"})
vikunja.project(1).shares.map(&:hash)
vikunja.authenticate_share(share.hash, {password: "secret"}).token
vikunja.project(1).remove_share(share.id)
vikunja.project(1).add_user({username: "tester", permission: 1})
vikunja.project(1).users.map(&:username)
vikunja.project(1).search_users("test").map(&:username)
vikunja.project(1).remove_user("tester")Bytes go up as they are, so read a file in binary and say what it is. Several parts may share one field name.
result = vikunja.task(7).upload_attachments([
{name: "files", filename: "notes.txt", content_type: "text/plain", body: File.binread("notes.txt")},
{name: "files", filename: "diagram.png", content_type: "image/png", body: File.binread("diagram.png")},
])
result.success.map{|attachment| attachment.file.name}
result.errors.map(&:message)An attachment knows its own address wherever it arrived, so it downloads and deletes itself.
stored = result.success.first
stored.download.bytes
stored.delete
vikunja.task(7).task_attachments.map{|attachment| attachment.file.size}
vikunja.task(7).attachments.map{|attachment| attachment.download.bytes.bytesize}A download is the bytes the API answered with, not a document. It is fetched when it is first read, and the headers arrive with it.
file = vikunja.task(7).download_attachment(3)
file.media_type
file.bytes
vikunja.task(7).attachment(3).preview("sm").bytes
vikunja.task(7).attachment(3).deleteA file is as large as it is. Give a download a block and the body arrives a chunk at a time, so nothing holds the whole of it:
File.open("notes.txt", "wb") do |out|
vikunja.task(7).download_attachment(3) do |response|
response.body.each{|chunk| out.write(chunk)}
end
endEvery download takes a block the same way: avatar, background, preview, totp_qrcode,
notifications_atom and download_export.
An upload streams the other way. Hand a part an open file rather than its bytes, and it is read from disk as it goes on the wire:
vikunja.task(7).upload_attachments([
{name: "files", filename: "recording.mp4", content_type: "video/mp4", body: File.open("recording.mp4", "rb")},
])vikunja.project(1).upload_background({name: "background", filename: "wall.jpg", content_type: "image/jpeg", body: File.binread("wall.jpg")})
background = vikunja.project(1).background
background.media_type
background.bytes
vikunja.project(1).remove_backgroundfilter = vikunja.create_filter({title: "overdue", filters: {filter: "due_date < now && done = false"}})
vikunja.filter(filter.id).filters.filter
vikunja.filter(filter.id).patch({title: "late"})
vikunja.filter(filter.id).deletevikunja.notifications.map(&:name)
vikunja.update_notification(3, {id: 3, read: true})
vikunja.mark_notifications_read.message
vikunja.clear_notifications
vikunja.subscribe("projects", 1).entity
vikunja.unsubscribe("projects", 1)
vikunja.add_reaction("tasks", 7, {value: "👍"})
vikunja.reactions("tasks", 7).value
vikunja.remove_reaction("tasks", 7, {value: "👍"})webhook = vikunja.project(1).create_webhook({target_url: "https://example.com/hook", events: ["task.created"]})
vikunja.webhook_events.value
vikunja.project(1).webhooks.map(&:target_url)
vikunja.project(1).update_webhook(webhook.id, {id: webhook.id, events: ["task.updated"]})
vikunja.project(1).remove_webhook(webhook.id)token = vikunja.create_token({
title: "integration",
expires_at: (Time.now.utc + 86400).iso8601,
permissions: {projects: ["read_all", "create"]},
})
token.token
vikunja.tokens.map(&:title)
vikunja.delete_token(token.id)
vikunja.caldav_tokens.map(&:created)
vikunja.create_caldav_token.tokenvikunja.user.settings.timezone
vikunja.update_settings({name: "Tester", week_start: 1, timezone: "Europe/London"}).message
vikunja.upload_avatar({name: "avatar", filename: "me.png", content_type: "image/png", body: File.binread("me.png")})
vikunja.avatar("tester", size: 64).bytes
vikunja.set_avatar_provider(avatar_provider: "initials")
vikunja.enroll_totp.url
vikunja.enable_totp(passcode: "123456")
vikunja.totp_qrcode.bytes
vikunja.disable_totp(password: "secret")
vikunja.sessions.map(&:device_info)
vikunja.delete_session("abc")vikunja.users("test").map(&:username)
vikunja.timezones.value
vikunja.health.status
vikunja.routes.value
vikunja.notifications_atom.bytesbot = vikunja.create_bot({username: "ci-bot", name: "CI"})
vikunja.bots.map(&:username)
vikunja.bot(bot.id).patch({name: "CI runner"})
vikunja.bot(bot.id).deleteoverview = vikunja.admin_overview
overview.users
overview.projects
overview.shares.link_shares
overview.license.licensed
vikunja.admin_users(q: "test").map(&:username)
vikunja.create_admin_user({username: "new", email: "new@example.com", password: "secret"})
vikunja.set_admin(1, {is_admin: true})
vikunja.set_user_status(1, {status: 0})
vikunja.set_user_password(1, {new_password: "another"})
vikunja.send_password_reset_email(1)
vikunja.remove_admin_user(1, mode: "soft")
vikunja.admin_projects(q: "inbox").map(&:title)
vikunja.set_project_owner(1, {owner_id: 2})case vikunja.project(1)
in {title: String => title, owner: {username: String => owner}}
[title, owner]
end
case vikunja.task(7)
in {done: true, title:}
"#{title} is done"
in {done: false, due_date: String => due}
"#{title} is due #{due}"
endbegin
vikunja.create_project({})
rescue Async::Vikunja::Failure => error
error.status
error.code
error.title
error.detail
error.errors.map{|each| each[:message]}
error.retry_after
end
begin
vikunja.project(404).title
rescue Async::REST::ResponseError => error
error.response.status
rescue ::JSON::ParserError => error
error.message
endproject = vikunja.project(1)
project.title
project = vikunja.project(1) unless project.cacheable?
project.titletoken = vikunja.create_token({title: "ci"})
token.inspect
token.value[:token]Async::Vikunja::Client.open(url) do |client|
vikunja = client.authenticated(ENV.fetch("VIKUNJA_TOKEN"))
tasks = vikunja.projects.map do |project|
Async do
project.tasks.count
end
end
tasks.sum(&:wait)
end