1#!/usr/bin/env python3
2#
3# A small script to automatically reject idle Diffs
4#
5# you need to set the PHABBOT_USER and PHABBOT_TOKEN environment variable for authentication
6from __future__ import absolute_import, print_function
7
8import datetime
9import os
10import sys
11
12import phabricator
13
14MESSAGE = """There seems to have been no activities on this Diff for the past 3 Months.
15
16By policy, we are automatically moving it out of the `need-review` state.
17
18Please, move it back to `need-review` without hesitation if this diff should still be discussed.
19
20:baymax:need-review-idle:
21"""
22
23
24PHAB_URL = "https://phab.mercurial-scm.org/api/"
25USER = os.environ.get("PHABBOT_USER", "baymax")
26TOKEN = os.environ.get("PHABBOT_TOKEN")
27
28
29NOW = datetime.datetime.now()
30
31# 3 months in seconds
32DELAY = 60 * 60 * 24 * 30 * 3
33
34
35def get_all_diff(phab):
36    """Fetch all the diff that the need review"""
37    return phab.differential.query(
38        status="status-needs-review",
39        order="order-modified",
40        paths=[('HG', None)],
41    )
42
43
44def filter_diffs(diffs, older_than):
45    """filter diffs to only keep the one unmodified sin <older_than> seconds"""
46    olds = []
47    for d in diffs:
48        modified = int(d['dateModified'])
49        modified = datetime.datetime.fromtimestamp(modified)
50        d["idleFor"] = idle_for = NOW - modified
51        if idle_for.total_seconds() > older_than:
52            olds.append(d)
53    return olds
54
55
56def nudge_diff(phab, diff):
57    """Comment on the idle diff and reject it"""
58    diff_id = int(d['id'])
59    phab.differential.createcomment(
60        revision_id=diff_id, message=MESSAGE, action="reject"
61    )
62
63
64if not USER:
65    print(
66        "not user specified please set PHABBOT_USER and PHABBOT_TOKEN",
67        file=sys.stderr,
68    )
69elif not TOKEN:
70    print(
71        "not api-token specified please set PHABBOT_USER and PHABBOT_TOKEN",
72        file=sys.stderr,
73    )
74    sys.exit(1)
75
76phab = phabricator.Phabricator(USER, host=PHAB_URL, token=TOKEN)
77phab.connect()
78phab.update_interfaces()
79print('Hello "%s".' % phab.user.whoami()['realName'])
80
81diffs = get_all_diff(phab)
82print("Found %d Diffs" % len(diffs))
83olds = filter_diffs(diffs, DELAY)
84print("Found %d old Diffs" % len(olds))
85for d in olds:
86    diff_id = d['id']
87    status = d['statusName']
88    modified = int(d['dateModified'])
89    idle_for = d["idleFor"]
90    msg = 'nudging D%s in "%s" state for %s'
91    print(msg % (diff_id, status, idle_for))
92    # uncomment to actually affect phab
93    nudge_diff(phab, d)
94