sachaos / todoist

Todoist CLI Client. I ❤️ Todoist and CLI.
MIT License
1.48k stars 104 forks source link

Any plans to support shared projects? #247

Open shanness opened 1 year ago

shanness commented 1 year ago

I've been using this for a few years, but have just got a co-worker onto it, and it's pretty broken without assigned handling and displaying.

i.e. todoist today has stuff that isn't mine, and no way to see that visually, nor filter it out.

Did lots of searching first (although can't seem to search Very surprised that no one else seems to have posted about this problem (although I found this fork and branch, which isn't showing up in searches (repo:psethwick/todoist AssignedExpr)).. Anyone know how to get around that? I only found it by manually looking at every branch on that fork.. I'll keep an eye on it (commits in the last 24 hrs, thanks @psethwick)

Seems it'll get more pressing with the new push for todoist workspaces.

psethwick commented 1 year ago

@shanness thank you!

I can't speak for the project, but I can talk about what I'm doing and planning.

I'm using this todoist /lib and filter code for my project tuidoist. Currently I'm using an ejected copy in that project, but I'll probably switch back to consuming sachaos/todoist (or my fork) as a library when I get to a more stable position.

The big piece in progress is the extend/filter-language branch that you found. The plan is to bring it up to what the filter language is described as on the filter help page. This will include the sharing features: assigned, assigned to: <user>, assigned by: <user> and added by: <user>. Current status: they parse, but I haven't written the evaluation code for them (yet). After that, I probably will update the display from the cli.

It will hit a PR at some point, but it is not yet ready. Right now, I'm working off a new branch from the one in #241, so hopefully that lands .. first.

The work I'm doing ought to close #191, #179, #164, #155 and #83. To be clear, it doesn't, yet, but that's the scope I'm aiming at.

shanness commented 1 year ago

Hey @psethwick and @sachaos ,

Sounds pretty good! But perhaps it's worth using the REST tasks API for the list function instead?

Taking the inspiration from the great Obsidian plugin obsidian-todoist-plugin That would mean you just pass in any valid filter (including and saved ones from your sync cache)?

Here's a pretty advanced one I tested it with that is busted in this cli one?

$ curl --silent -H "Authorization: Bearer <token>" --data-urlencode \
  filter='(today | overdue) & ##Inbox & (!assigned to: others) & (!@me)'
  -G 'https://api.todoist.com/rest/v2/tasks' | jq -r '.[] | [.id, .content] | @tsv'
7215998221  ApiFuse - where is it at
7255942445  Install obsidian-cli
7255968994  Get hassio back up
7256841158  Recover some space on /big
7256841817  Fix leaking hot tap in laundry

These are the fields you get from it

 jq '.[1]|keys'
[
  "assignee_id",
  "assigner_id",
  "comment_count",
  "content",
  "created_at",
  "creator_id",
  "description",
  "due",
  "id",
  "is_completed",
  "labels",
  "order",
  "parent_id",
  "priority",
  "project_id",
  "section_id",
  "url"
]
psethwick commented 1 year ago

thank you that filter makes for a good test:

func TestComplexFilter(t *testing.T) {
    timeNow := time.Date(2017, time.January, 2, 18, 0, 0, 0, testTimeZone)
    setNow(timeNow)
    assert.Equal(
        t,
        BoolInfixOpExpr{
            left: BoolInfixOpExpr{
                left: BoolInfixOpExpr{
                    left: BoolInfixOpExpr{
                        left: DateExpr{
                            operation: DUE_ON, 
                            datetime: time.Date(2017, time.January, 2, 0, 0, 0, 0, testTimeZone), 
                            allDay: true,
                        },
                        operator: '|',
                        right: DateExpr{
                            operation: DUE_BEFORE,
                            datetime: timeNow,
                            allDay: false,
                        },
                    },
                    operator: '&',
                    right: ProjectExpr{
                        isAll: true,
                        name:  "Inbox",
                    }},
                operator: '&',
                right: NotOpExpr{
                    expr: PersonExpr{person: "others"},
                }}, operator: '&',
            right: NotOpExpr{expr: LabelExpr{name: "me"}},
        },
        Filter("(today | overdue) & ##Inbox & (!assigned to: others) & (!@me)"),
    )
}

Passes on my branch!

I think I have 99% of the parsing sorted, next is evaluating all the new stuff I have parsing. I'm moving pretty quickly, this won't be months and might barely be weeks at current pace.

For my purposes, (and I think this cli as well), I think running filter locally is worth it. It is so much faster than http calls. However, I will absolutely use the /list endpoint to verify correctness. Might rope you in for testing at some point @shanness ?

shanness commented 1 year ago

Nice one mate! From my testing the API only took 0.3 seconds (for the above filter), and the same for (today | overdue) & (!assigned to: others) Although strangely took 0.7 seconds for (today | overdue) & !assigned to: others even though it returned the same tasks..

But yeah, the cached one in todoist-cli only took 0.021s

And sure, feel free to rope me in for testing. I don't know go (but know python, java, scala and bash well). But that said, I found this repos go code easy to read

psethwick commented 1 year ago

@shanness you can test this stuff in my fork if you want! I've shaken some of the bugs out, but in particular I don't really use the sharing features, so very possible I've missed some there. You can test on the extend-filter-language branch (or the tuidoist one, that one I'm merging all my changes into). Let me know if you need support on how to build or install it