blob: 9a91203e6b9ceffa126af9fc3dc14f9e164f37e2 [file] [log] [blame]
Adrià Vilanova Martínez3465e772021-07-11 19:18:41 +02001import {parseUrl} from '../common/commonUtils.js';
2import {getAuthUser} from '../common/communityConsoleUtils.js';
avm99963f5923962020-12-07 16:44:37 +01003
4function recursiveParentElement(el, tag) {
5 while (el !== document.documentElement) {
6 el = el.parentNode;
7 if (el.tagName == tag) return el;
8 }
9 return undefined;
10}
11
12// Source:
13// https://stackoverflow.com/questions/33063774/communication-from-an-injected-script-to-the-content-script-with-a-response
14var contentScriptRequest = (function() {
15 var requestId = 0;
16 var prefix = 'TWPT-batchlock-generic';
17
18 function sendRequest(data) {
19 var id = requestId++;
20
21 return new Promise(function(resolve, reject) {
22 var listener = function(evt) {
23 if (evt.source === window && evt.data && evt.data.prefix === prefix &&
24 evt.data.requestId == id) {
25 // Deregister self
26 window.removeEventListener('message', listener);
27 resolve(evt.data.data);
28 }
29 };
30
31 window.addEventListener('message', listener);
32
33 var payload = {data, id, prefix};
34
35 window.dispatchEvent(
36 new CustomEvent('TWPT_sendRequest', {detail: payload}));
37 });
38 }
39
40 return {sendRequest: sendRequest};
41})();
42
43function enableEndButtons() {
44 var buttons = document.querySelectorAll(
45 '.pane[pane-id="default-1"] footer[data-footer-id="1"] material-button');
46 buttons.forEach(btn => {
47 btn.classList.remove('is-disabled');
48 });
49}
50
51function addLogEntry(success, action, url, threadId, errDetails = null) {
52 var p1 = contentScriptRequest.sendRequest({
53 action: 'geti18nMessage',
54 msg: 'inject_lockdialog_log_entry_beginning',
55 placeholders: [threadId],
56 });
57
58 var p2 = contentScriptRequest.sendRequest({
59 action: 'geti18nMessage',
60 msg: 'inject_lockdialog_log_entry_' + (success ? 'success' : 'error') +
61 '_' + action,
62 placeholders: [errDetails],
63 });
64
65 Promise.all([p1, p2]).then(strings => {
66 var log = document.getElementById('TWPT-lock-log');
67 var logEntry = document.createElement('p');
68 logEntry.classList.add(
69 'TWPT-log-entry', 'TWPT-log-entry--' + (success ? 'success' : 'error'));
70
71 var a = document.createElement('a');
72 a.href = url;
73 a.target = '_blank';
74 a.textContent = strings[0];
75
76 var end = document.createTextNode(': ' + strings[1]);
77
78 logEntry.append(a, end);
79 log.append(logEntry);
80 });
81}
82
83function lockThreads(action) {
84 var modal = document.querySelector('.pane[pane-id="default-1"]');
85 modal.querySelector('footer[data-footer-id="0"]').classList.add('is-hidden');
86 modal.querySelector('footer[data-footer-id="1"]')
87 .classList.remove('is-hidden');
88
89 var checkboxes = document.querySelectorAll(
90 '.thread-group material-checkbox[aria-checked="true"]');
91
92 var p = document.createElement('p');
93 p.style.textAlign = 'center';
94
95 var progress = document.createElement('progress');
96 progress.max = checkboxes.length;
97 progress.value = 0;
98
99 p.append(progress);
100
101 var log = document.createElement('div');
102 log.id = 'TWPT-lock-log';
103 log.classList.add('TWPT-log');
104
105 modal.querySelector('main').textContent = '';
106 modal.querySelector('main').append(p, log);
107
Adrià Vilanova Martínez3465e772021-07-11 19:18:41 +0200108 var authuser = getAuthUser();
avm999638d3b4ca2020-12-08 13:21:52 +0100109 var APIRequestUrl =
110 'https://support.google.com/s/community/api/SetThreadAttribute' +
111 (authuser == '0' ? '' : '?authuser=' + encodeURIComponent(authuser));
112
avm99963f5923962020-12-07 16:44:37 +0100113 checkboxes.forEach(checkbox => {
114 var url = recursiveParentElement(checkbox, 'A').href;
115 var thread = parseUrl(url);
116 if (thread === false) {
117 console.error('Fatal error: thread URL ' + url + ' could not be parsed.');
118 return;
119 }
avm999638d3b4ca2020-12-08 13:21:52 +0100120 fetch(APIRequestUrl, {
avm99963f5923962020-12-07 16:44:37 +0100121 'headers': {
122 'content-type': 'text/plain; charset=utf-8',
123 },
124 'body': JSON.stringify({
125 1: thread.forum,
126 2: thread.thread,
127 3: (action == 'lock' ? 1 : 2),
128 }),
129 'method': 'POST',
130 'mode': 'cors',
131 'credentials': 'include',
132 })
133 .then(res => {
134 if (res.status == 200 || res.status == 400) {
135 return res.json().then(data => ({
136 status: res.status,
137 body: data,
138 }));
139 } else {
140 throw new Error('Status code ' + res.status + ' was not expected.');
141 }
142 })
143 .then(res => {
144 if (res.status == 400) {
145 throw new Error(
146 res.body[4] ||
147 ('Response status: 400. Error code: ' + res.body[2]));
148 }
149 })
150 .then(_ => {
151 addLogEntry(true, action, url, thread.thread);
152 })
153 .catch(err => {
154 console.error(
155 'An error occurred while locking thread ' + url + ': ' + err);
156 addLogEntry(false, action, url, thread.thread, err);
157 })
158 .then(_ => {
159 progress.value = parseInt(progress.value) + 1;
160 if (progress.value == progress.getAttribute('max'))
161 enableEndButtons();
162 });
163 });
164}
165
166window.addEventListener('message', e => {
167 if (e.source === window && e.data && e.data.prefix === 'TWPT-batchlock' &&
168 e.data.action) {
169 switch (e.data.action) {
170 case 'lock':
171 case 'unlock':
172 console.info('Performing action ' + e.data.action);
173 lockThreads(e.data.action);
174 break;
175
176 default:
177 console.error(
178 'Action \'' + e.data.action +
179 '\' unknown to TWPT-batchlock receiver.');
180 }
181 }
182});