Last active
August 8, 2023 17:01
-
-
Save wevtimoteo/311dc62402bd61ab7ff81f680265ad28 to your computer and use it in GitHub Desktop.
Retry GitHub app - Deliveries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const GitHubDeliveryManager = { | |
retryReasons: [ | |
"Couldn't connect to server", | |
"Service Timeout", | |
"An Exception Occurred", | |
"502 Bad Gateway", | |
"timed out" | |
], | |
sleep: function(lf_ms) { | |
return new Promise(resolve => setTimeout(resolve, lf_ms)); | |
}, | |
submit: async function(form) { | |
var button = form.getElementsByClassName("btn"); | |
if (button.length > 0) { | |
console.log("Redelivering..."); | |
button[0].click(); | |
} | |
await sleep(10000); | |
}, | |
fetchForm: async function(delivery, wrapper) { | |
var form = delivery.getElementsByClassName("js-redeliver-hook-form"); | |
if (form.length == 0) { | |
wrapper.click(); | |
} else { | |
submit(form[0]); | |
} | |
}, | |
getResult: function(delivery) { | |
return delivery.children[0].children[0].children[0].getAttribute("aria-label"); | |
}, | |
hasDeliverySucceeded: function(delivery) { | |
const result = this.getResult(delivery); | |
const success = delivery.getElementsByClassName("icon-for-success")[0]; | |
if (typeof(success) == "undefined") { | |
return false; | |
} | |
const successDisplay = window.getComputedStyle(success).display; | |
return successDisplay != "none"; | |
}, | |
shouldRetry: function(delivery) { | |
const result = this.getResult(delivery); | |
return this.retryReasons.includes(result); | |
}, | |
clearSucceeded: function() { | |
const deliveries = [].slice.call(document.getElementsByClassName("hook-delivery-item")); | |
Array.prototype.forEach.call(deliveries, function(delivery) { | |
if (GitHubDeliveryManager.hasDeliverySucceeded(delivery)) { | |
delivery.remove() | |
} | |
}); | |
}, | |
clearTooManyRequestsErrors: function() { | |
const fetchFormErrorMessages = [].slice.call(document.getElementsByClassName("is-error")); | |
Array.prototype.forEach.call(fetchFormErrorMessages, function(fetchFormErrorMessage) { | |
const deliveryItem = fetchFormErrorMessage.closest('.hook-delivery-item'); | |
if (deliveryItem) { | |
deliveryItem.remove(); | |
} | |
}); | |
}, | |
expandForms: function(quantity) { | |
const deliveries = [].slice.call(document.getElementsByClassName("hook-delivery-item")).slice(0, quantity); | |
Array.prototype.forEach.call(deliveries, function(delivery) { | |
if (GitHubDeliveryManager.hasDeliverySucceeded(delivery)) { | |
delivery.remove() | |
} else if (GitHubDeliveryManager.shouldRetry(delivery)) { | |
const wrapper = delivery.children[0].children[0].children; | |
if (wrapper.length > 0) { | |
GitHubDeliveryManager.fetchForm(delivery, wrapper[1]); | |
} | |
} else { | |
delivery.remove(); | |
} | |
}); | |
}, | |
retry: function() { | |
const deliveryForms = document.getElementsByClassName("js-redeliver-hook-form"); | |
Array.prototype.forEach.call(deliveryForms, function(deliveryForm) { | |
GitHubDeliveryManager.redeliverPayload(deliveryForm); | |
}); | |
}, | |
loadMore: function() { | |
document.querySelector(".js-hook-deliveries-pagination-button").click(); | |
}, | |
generateBoundary: function() { | |
const randomChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | |
const randomPartLength = 16; | |
let boundary = '----WebKitFormBoundary'; | |
for (let i = 0; i < randomPartLength; i++) { | |
boundary += randomChars.charAt(Math.floor(Math.random() * randomChars.length)); | |
} | |
return boundary; | |
}, | |
redeliverPayload: async function(form) { | |
try { | |
const actionUrl = form.getAttribute('action'); | |
const authenticityToken = form.querySelector('input[name="authenticity_token"]').value; | |
const boundary = this.generateBoundary(); | |
const payload = `--${boundary}\r\n` + | |
`Content-Disposition: form-data; name="authenticity_token"\r\n\r\n${authenticityToken}\r\n` + | |
`--${boundary}--`; | |
const response = await fetch(actionUrl, { | |
method: 'POST', | |
body: payload, | |
headers: { | |
'Accept': 'text/html', | |
'X-Requested-With': 'XMLHttpRequest', | |
'Content-Type': `multipart/form-data; boundary=${boundary}` | |
} | |
}); | |
if (response.ok) { | |
const deliveryItem = form.closest('.hook-delivery-item'); | |
if (deliveryItem) { | |
deliveryItem.remove(); | |
} | |
} else { | |
console.error('Error redelivering payload.'); | |
} | |
} catch (error) { | |
console.error('An error occurred:', error); | |
} | |
}, | |
sleep: function(lf_ms) { | |
return new Promise(resolve => setTimeout(resolve, lf_ms)); | |
}, | |
startRetries: function(retryIntervalInSeconds) { | |
const retryInterval = setInterval(() => { | |
this.clearSucceeded(); | |
this.clearTooManyRequestsErrors(); | |
this.loadMore(); | |
await this.sleep(2000); | |
for (let i = 0; i < 3; i++) { | |
this.expandForms(10); | |
this.retry(); | |
await this.sleep(2000); | |
} | |
}, retryIntervalInSeconds * 1000); | |
return retryInterval; | |
}, | |
stopRetries: function(interval) { | |
clearInterval(interval); | |
} | |
}; | |
window.GitHubDeliveryManager = GitHubDeliveryManager; | |
const interval = GitHubDeliveryManager.startRetries(60); | |
// To stop the loop after a certain time | |
// GitHubDeliveryManager.stopRetries(interval); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you do not want to keep hitting
Load more deliveries
button: