-
Notifications
You must be signed in to change notification settings - Fork 0
/
dwg_issue2ticket.user.js
167 lines (145 loc) · 5.45 KB
/
dwg_issue2ticket.user.js
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// ==UserScript==
// @name dwg_issue2ticket
// @namespace https://htmlblog.net
// @description Automatically creates OTRS tickets from OSM webpage issues
// @include https://www.openstreetmap.org/issues/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// ==/UserScript==
let queue = "Data Working Group";
let newlink;
try {
// find the existing "ignore" link on the page and add a nice matching "create OTRS ticket" link
let ignore_xpath = `//a[@href='${window.location.href}/ignore']`;
let anchor = document.evaluate(ignore_xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
let pipe = anchor.previousSibling.cloneNode();
newlink = document.createElement("A");
newlink.innerHTML="Create OTRS ticket";
newlink.href="#";
anchor.parentNode.insertBefore(newlink, anchor.nextSibling);
anchor.parentNode.insertBefore(pipe, newlink);
newlink.addEventListener("click", createOtrsTicket);
}
catch(e)
{
// if the "nice" link didn't work for any reason - maybe changed site layout - then at least do it ugly
console.log("Cannot find anchor - likely closed issue, or else layout change");
}
// workhorse function. invoked when link is clicked
async function createOtrsTicket()
{
// pick content div
let content = document.getElementById("content");
// determine the issue number for use in ticket title
let h2_array = content.getElementsByTagName("h2");
let h2 = h2_array[0];
let match = /Open (Issue #\d+)/.exec(h2.innerHTML);
if (!match) {
alert(`Cannot parse h2 of '${title}'`);
throw("");
}
// give user opportunity to amend title
let title = match[1];
title = prompt("ticket title:", title);
// determine username of complainant
match = /Reported as \S+ by <a[^>]+>([^<]+)</.exec(content.innerHTML);
if (!match) {
alert(`Cannot extract complainant username`);
throw("");
}
let complainant = match[1];
// now clean up the HTML of the issue, by
// 1. dropping unwanted links
// 2. dropping the input box at the end
// 3. fixing a href/img src URLs so they still work in OTRS
let clone = content.cloneNode(true);
let form = document.evaluate("//form", clone, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
form.parentNode.removeChild(form);
let anchors = clone.getElementsByTagName("a");
for (let anchor of anchors)
{
if (anchor.href.startsWith("https://www.openstreetmap.org/issues")) {
anchor.href= "";
anchor.innerHTML = "";
} else if (anchor.href.startsWith("/")) {
anchor.href = "https://www.openstreetmap.org " + anchor.href;
} else {
anchor.href = anchor.href;
}
}
let images = clone.getElementsByTagName("img");
for (let image of images) {
if (image.src.startsWith("/")) {
image.src = "https://www.openstreetmap.org " + image.src;
} else {
image.src = image.src;
}
}
// create JSON message for OTRS
let ticket = {
"Ticket" : {
"Queue" : queue,
"State" : "open",
"Priority" : "3 normal",
"CustomerUser" : `${encodeURI(complainant)}@thisdoesnotwork.users.openstreetmap.org`,
"Title" : title
},
"Article" : {
"CommunicationChannel" : "Phone",
"ContentType" : "text/html; charset=utf8",
"Subject" : title,
"Body" : clone.innerHTML
}
};
// try to retrieve username and password for OTRS from the GreaseMonkey variable store.
// if not present, ask user & save to store
let username = GM_getValue("otrs_username");
if (!username || username === "")
{
username = prompt("OTRS User Name:");
GM_setValue("otrs_username", username);
}
let password = GM_getValue("otrs_password");
if (!password || password === "")
{
password = prompt("OTRS Password:");
GM_setValue("otrs_password", password);
}
// add username and password to JSON payload.
ticket.UserLogin = username;
ticket.Password = password;
// prepare and execute POST request
let settings = {
"method" : "POST",
"body" : JSON.stringify(ticket)
};
let response = await fetch(`https://otrs.openstreetmap.org/otrs/nph-genericinterface.pl/Webservice/OsmWebsiteIntegration/createTicket`, settings);
let json = await response.json();
// check for error (note, a low-level error like host not responding would cause an exception above
// and break things)
if (json.Error) {
if (json.Error.ErrorCode == "TicketCreate.AuthFail") {
alert("OTRS Authentication failed. Try again.");
// we have to delete the stored user name and password so that the script asks again next time.
GM_deleteValue("otrs_username");
GM_deleteValue("otrs_password");
return;
} else {
alert("OTRS error: " + json.Error.ErrorMessage);
return;
}
}
// on success, plant message into textarea that user can then submit.
// we *could* close the ticket automatically but let's not do that at this point in time.
let textarea = document.getElementById("issue_comment_body");
textarea.value = `OTRS ticket created: #${json.TicketNumber}\nhttps://otrs.openstreetmap.org/otrs/index.pl?Action=AgentTicketZoom;TicketID=${json.TicketID}`;
// disable the "create ticket" link
if (newlink)
{
newlink.innerHTML = "<s>Create OTRS ticket</s>";
newlink.removeEventListener("click", createOtrsTicket);
newlink.removeAttribute("href");
newlink.style.enabled = false;
}
}