-
Notifications
You must be signed in to change notification settings - Fork 66
/
spambug.py
120 lines (93 loc) · 3.8 KB
/
spambug.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
from bugbot import people
from bugbot.bugbug_utils import get_bug_ids_classification
from bugbot.bzcleaner import BzCleaner
from bugbot.utils import nice_round
COMMENT = """
The [Bugbug](https://github.com/mozilla/bugbug/) bot thinks this bug is invalid.
If you think the bot is wrong, please reopen the bug and move it back to its prior component.
If your bug description is written in a non-English language, please use Google Translate or a similar service to translate it.
Please note that this is a production bug database used by the Mozilla community to develop Firefox, Thunderbird and other products.
Filing test bugs here will waste the time of our contributors, volunteers and employees.
Accounts that abuse bugzilla.mozilla.org will be disabled.
""".strip()
class SpamBug(BzCleaner):
def __init__(self):
super().__init__()
self.autofix_bugs = {}
self.people = people.People.get_instance()
def description(self):
return "[Using ML] Detect spam bugs"
def has_default_products(self):
return False
def columns(self):
return ["id", "summary", "confidence"]
def sort_columns(self):
return lambda p: (-p[2], -int(p[0]))
def handle_bug(self, bug, data):
reporter = bug["creator"]
if self.people.is_mozilla(reporter):
return None
return bug
def get_bz_params(self, date):
start_date, _ = self.get_dates(date)
return {
"include_fields": ["id", "groups", "summary", "creator"],
"bug_status": "UNCONFIRMED",
"f1": "reporter",
"v1": "%group.editbugs%",
"o1": "notsubstring",
"f2": "creation_ts",
"o2": "greaterthan",
"v2": start_date,
"n3": 1,
"f3": "product",
"o3": "changedfrom",
"v3": "Invalid Bugs",
}
def get_bugs(self, date="today", bug_ids=[]):
# Retrieve the bugs with the fields defined in get_bz_params
raw_bugs = super().get_bugs(date=date, bug_ids=bug_ids, chunk_size=7000)
if len(raw_bugs) == 0:
return {}
# Extract the bug ids
bug_ids = list(raw_bugs.keys())
# Classify those bugs
bugs = get_bug_ids_classification("spambug", bug_ids)
for bug_id in sorted(bugs.keys()):
bug_data = bugs[bug_id]
if not bug_data.get("available", True):
# The bug was not available, it was either removed or is a
# security bug
continue
if not {"prob", "index"}.issubset(bug_data.keys()):
raise Exception(f"Invalid bug response {bug_id}: {bug_data!r}")
bug = raw_bugs[bug_id]
prob = bug_data["prob"]
if prob[1] < self.get_config("confidence_threshold"):
continue
self.autofix_bugs[bug_id] = {
"id": bug_id,
"summary": bug["summary"],
"confidence": nice_round(prob[1]),
}
return self.autofix_bugs
def get_autofix_change(self):
result = {}
for bug_id in self.autofix_bugs:
result[bug_id] = {
"comment": {
"body": COMMENT.format(self.autofix_bugs[bug_id]["confidence"])
},
"product": "Invalid Bugs",
"component": "General",
"version": "unspecified",
"milestone": "---",
"status": "RESOLVED",
"resolution": "INVALID",
}
return result
if __name__ == "__main__":
SpamBug().run()