Easy API for getting events filtered by not AFK?

I’ve been using the REST API by GET “http://localhost:5600/api/0/buckets/aw-watcher-window_host/events” with Python requests. However, this is complicated by the fact that this returns durations without regard for whether it is AFK data or not. I’ve been looking into using aw_core directly, but I’m not sure how up to date the docs are. Is Getting weekly totals still valid for example?

Is there any easy way to get all non-AFK events within a time frame directly through a REST API or with the core library?

You can do this either with aw_core and transforms, or as I prefer it with queries.

Here’s a query for getting a list of all window events intersected with the non-afk events.

afk_events = query_bucket(find_bucket('aw-watcher-afk_'));
window_events = query_bucket(find_bucket('aw-watcher-window_'));
RETURN = filter_period_intersect(window_events, filter_keyvals(afk_events, 'status', ['not-afk']));

You can either just paste it into the query textbox in the web-ui or use the query HTTP api to fetch it into some external program/script.

I was able to figure it out by looking through aw-client.py.

def get_nonafk_events():
        headers = {"Content-type": "application/json", "charset": "utf-8"}
        query = """afk_events = query_bucket(find_bucket('aw-watcher-afk_'));
window_events = query_bucket(find_bucket('aw-watcher-window_'));
window_events = filter_period_intersect(window_events, filter_keyvals(afk_events, 'status', ['not-afk']));
RETURN = merge_events_by_keys(window_events, ['app', 'title']);""".split(
        data = {
            "timeperiods": [
                "/".join(["1919-08-27T12:30:00.0", datetime.now().isoformat()])
            "query": query,
        r = requests.post(
            data=bytes(json.dumps(data), "utf-8"),
        return json.loads(r.text)[0]

Thanks for pointing me towards the right direction, I’m looking forward to better documentation for the APIs in the future.

Just noticed however that ActivityWatch is showing timestamps with a “+00:00”, meaning that I have to lie when I get datetime.now() by subtracting my timezone difference from Greenwich.

Shouldn’t ActivityWatch be using timezone aware timestamps? Or just naive ones since the API is limited to localhost right now.

Edit: Hmm, actually it seems like when I call the query endpoint directly I’m getting UTC times, but the web UI seems to present naive datetimes, not sure what’s causing that.

This shouldn’t be necessary as long as you send a “+01:00” in your timestamps as defined by the iso8601 standard. The response will be UTC, but your request can be in your local timezone and will be filtered correctly.

We discussed this a couple of years ago and decided that it should not. Timezones can make things very complicated. If someone for example travels to a different timezone it would mean that they could go back in time and have intersecting events in the same bucket making a timeline visualization completely broken. Having to support such odd scenarios is not in our interest.

We decided instead that it’s better if aw-server is not timezone aware and instead let the visualization in the web-ui depend on your current timezone.

Yeah, timezones always complicate things. I’ve resorted to just querying with a time range of 3 days and filtering timestamps myself with some datetime comparison logic because it’s difficult to confidently get an hour gap for example. If I can never figure it out I’ll ask another time.

Shouldn’t it be the other way around? Unless I’m misunderstanding you (I’m interpreting “not timezone aware” as naive datetimes), it seems to me that the backend should be timezone aware and the frontend show everything in local time. So wherever a user goes the backend records everything in UTC, and the UIs convert that to whatever timzeone the user is in. So there’s no “timetravel” going on so to speak.

Thanks to this email notification I now know about the Bismillah character ﷽

1 Like

Timestamps are normalized to UTC before being stored. So they are technically timezone aware, it’s just that the only timezone they are aware of is UTC (so no “timetravel” going on). We’ve discussed making the datastore handle other timezones, but it is not a priority.

The frontend shows everything in local time, as you’d expect.