chore: add 10+ new error definitions

This commit is contained in:
Jelle Glebbeek
2021-06-15 02:32:56 +02:00
parent fa910b9b76
commit 4a8f19c4ea
3 changed files with 337 additions and 237 deletions

View File

@@ -1,237 +0,0 @@
const Sentry = require("@sentry/electron");
const Utils = require("./Utils");
class ErrorHandler {
constructor(win, queryManager, env) {
this.env = env;
this.queryManager = queryManager;
this.win = win;
this.unhandledErrors = [];
this.errorDefinitions = [
{
code: "No authentication",
description: `Authenticate using&nbsp;<span onclick="$('#authModal').modal('show');" class="openAuth">cookies</span>&nbsp;and try again.`,
trigger: "ERROR: Private video"
},
{
code: "No authentication",
description: `Authenticate using&nbsp;<span onclick="$('#authModal').modal('show');" class="openAuth">cookies</span>&nbsp;and try again.`,
trigger: "ERROR: This video is only available for registered users"
},
{
code: "Members-only content",
description: `Authenticate using&nbsp;<span onclick="$('#authModal').modal('show');" class="openAuth">cookies</span>&nbsp;and try again.`,
trigger: "ERROR: Join this channel to get access to members-only content"
},
{
code: "No connection could be made",
description: "The host or your internet/proxy connection is down.",
trigger: "getaddrinfo failed"
},
{
code: "URL not supported",
description: "This URL is currently not supported by YTDL.",
trigger: "is not a valid URL"
},
{
code: "URL not supported",
description: "This URL is currently not supported by YTDL.",
trigger: "Unsupported URL"
},
{
code: "Private or non-existent playlist",
description: `This playlist does not exist or is&nbsp;<span onclick="$('#authModal').modal('show');" class="openAuth">private</span>.`,
trigger: "ERROR: The playlist does not exist"
},
{
code: "Age restricted video",
description: `To download this video log-in using &nbsp;<span onclick="$('#authModal').modal('show');" class="openAuth">cookies</span>.`,
trigger: "ERROR: Sign in to confirm your age"
},
{
code: "Embed-only video",
description: "Try using the URL of the embed page.",
trigger: "ERROR: Cannot download embed-only video without embedding URL"
},
{
code: "Possible broken extractor (404)",
description: "YTDL isn't working, please wait for an update.",
trigger: "HTTP Error 404"
},
{
code: "Private or removed video",
description: "This video can not be extracted.",
trigger: "metadata.formats is not iterable"
},
{
code: "ffmpeg not found",
description: "Format merging requires ffmpeg.",
trigger: "ffmpeg or avconv not found"
},
{
code: "ffmpeg not found",
description: "Transcoding to mp3 or mp4 requires ffmpeg.",
trigger: "ffmpeg or avconv could not be found"
},
{
code: "ffmpeg not found",
description: "Transcoding to mp3 or mp4 requires ffmpeg.",
trigger: "ffprobe/avprobe and ffmpeg/avconv not found"
},
{
code: "Incomplete video ID",
description: "The URL you entered is incomplete.",
trigger: "Incomplete YouTube ID"
},
{
code: "Too many requests (429)",
description: "You are being ratelimited by the service.",
trigger: "HTTP Error 429"
},
{
code: "Unable to extract initial data",
description: "Please do try again in a moment.",
trigger: "ERROR: Unable to extract yt initial data"
},
{
code: "No write permission",
description: "No write permission in download folder.",
trigger: "[Errno 95]"
},
{
code: "Blocked by firewall/program",
description: "Check your firewall and or internet settings.",
trigger: "[WinError 10013]"
},
{
code: "SSL verification failed",
description: "Disable the 'Validate HTTPS certificates' setting.",
trigger: "<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed"
},
{
code: "Max fragment retries reached",
description: "The service did not respond in time.",
trigger: "giving up after 10 fragment retries"
},
{
code: "Connection timed out",
description: "Please try again in a moment.",
trigger: "EOF occurred in violation of protocol"
},
{
code: "Connection timed out",
description: "Please try again in a moment.",
trigger: "[Errno 60]"
},
{
code: "No connection could be made",
description: "Check your proxy and internet connection.",
trigger: "[WinError 10060]"
},
{
code: "Connection reset",
description: "The connection was closed by the remote host.",
trigger: "[WinError 10054]"
},
{
code: "File in use by another process",
description: "Don't open the file while it's downloading.",
trigger: "[WinError 32]"
},
{
code: "Binaries missing/corrupted",
description: "Please restart the app, or disable antivirus.",
trigger: "Command failed with ENOENT: resources\\app.asar.unpacked\\binaries\\youtube-dl.exe"
},
{
code: "Binaries missing/corrupted",
description: "Please restart the app, or disable antivirus.",
trigger: "Command failed with ENOENT: binaries/youtube-dl.exe"
},
{
code: "Missing dependency",
description: "Please install <a href=\"https://github.com/jely2002/youtube-dl-gui#how-to-use\" target=\"_blank\"> Microsoft Visual C++ 2010</a>",
trigger: "3221225781"
},
{
code: "Binaries missing/corrupted",
trigger: "is not recognized as an internal or external command",
description: "Please restart the app, or disable antivirus."
}
]
}
checkError(stderr, identifier) {
let foundError = false;
if(stderr == null) {
console.error("An error has occurred but no error message was given.")
return false;
}
for(const errorDef of this.errorDefinitions) {
if(stderr.includes(errorDef.trigger)) {
if(errorDef.code === "ffmpeg not found" && process.argv[2] === '--dev') return false; //Do not raise a 'ffmpeg not found' error when in dev mode
foundError = true;
this.raiseError(errorDef, identifier);
break;
}
}
if(!foundError) {
if(stderr.includes("ERROR")) {
foundError = true;
console.error(stderr)
this.raiseUnhandledError(stderr, stderr, identifier);
}
}
return foundError;
}
raiseUnhandledError(code, error, identifier) {
const video = this.queryManager.getVideo(identifier);
if(video == null) return;
if(video.type === "playlist") return;
let errorDef = {
identifier: identifier,
error_id: Utils.getRandomID(8),
unexpected: true,
error: {
code: error === code ? "Unhandled error" : code,
description: error,
}
};
Sentry.captureMessage(error === code ? error : code, scope => {
scope.setLevel(Sentry.Severity.Error);
if(code !== error) {
scope.setContext("error", {description: error});
}
scope.setTag("url", video.url);
scope.setTag("error_id", errorDef.error_id);
if(video.selected_format_index != null) {
scope.setContext("selected_format", video.formats[video.selected_format_index].serialize())
}
const { env, paths, ...settings } = this.env.settings;
scope.setContext("settings", settings);
});
this.win.webContents.send("error", errorDef);
this.unhandledErrors.push(errorDef);
this.queryManager.onError(identifier);
}
raiseError(errorDef, identifier) {
const video = this.queryManager.getVideo(identifier);
if(video == null) return;
if(video.type === "playlist") return;
console.error(errorDef.code + " - " + errorDef.description);
this.win.webContents.send("error", { error: errorDef, identifier: identifier, unexpected: false, url: video.url });
this.queryManager.onError(identifier);
}
async reportError(args) {
for(const err of this.unhandledErrors) {
if(err.identifier === args.identifier) {
return await this.env.analytics.sendReport(err.error_id);
}
}
}
}
module.exports = ErrorHandler;

View File

@@ -0,0 +1,109 @@
const Sentry = require("@sentry/electron");
const Utils = require("../Utils");
const fs = require("fs").promises;
class ErrorHandler {
constructor(win, queryManager, env) {
this.env = env;
this.queryManager = queryManager;
this.win = win;
this.unhandledErrors = [];
this.errorDefinitions = [];
this.loadErrorDefinitions().then(errorDefs => this.errorDefinitions = errorDefs);
}
checkError(stderr, identifier) {
let foundError = false;
if(stderr == null) {
console.error("An error has occurred but no error message was given.")
return false;
}
for(const errorDef of this.errorDefinitions) {
if(Array.isArray(errorDef.trigger)) {
for(const trigger of errorDef.trigger) {
if(stderr.includes(trigger)) {
if(errorDef.code === "ffmpeg not found" && process.argv[2] === '--dev') return false; //Do not raise a 'ffmpeg not found' error when in dev mode
foundError = true;
errorDef.trigger = trigger;
this.raiseError(errorDef, identifier);
break;
}
}
} else if(stderr.includes(errorDef.trigger)) {
if(errorDef.code === "ffmpeg not found" && process.argv[2] === '--dev') return false; //Do not raise a 'ffmpeg not found' error when in dev mode
foundError = true;
this.raiseError(errorDef, identifier);
break;
}
}
if(!foundError) {
if(stderr.includes("ERROR")) {
foundError = true;
console.error(stderr)
this.raiseUnhandledError(stderr, stderr, identifier);
}
}
return foundError;
}
raiseUnhandledError(code, error, identifier) {
const video = this.queryManager.getVideo(identifier);
if(video == null) return;
if(video.type === "playlist") return;
let errorDef = {
identifier: identifier,
error_id: Utils.getRandomID(8),
unexpected: true,
error: {
code: error === code ? "Unhandled error" : code,
description: error,
}
};
Sentry.captureMessage(error === code ? error : code, scope => {
scope.setLevel(Sentry.Severity.Error);
if(code !== error) {
scope.setContext("error", {description: error});
}
scope.setTag("url", video.url);
scope.setTag("error_id", errorDef.error_id);
if(video.selected_format_index != null) {
scope.setContext("selected_format", video.formats[video.selected_format_index].serialize())
}
const { env, paths, ...settings } = this.env.settings;
scope.setContext("settings", settings);
});
this.win.webContents.send("error", errorDef);
this.unhandledErrors.push(errorDef);
this.queryManager.onError(identifier);
}
raiseError(errorDef, identifier) {
const video = this.queryManager.getVideo(identifier);
if(video == null) return;
if(video.type === "playlist") return;
console.error(errorDef.code + " - " + errorDef.description);
this.win.webContents.send("error", { error: errorDef, identifier: identifier, unexpected: false, url: video.url });
this.queryManager.onError(identifier);
}
async reportError(args) {
for(const err of this.unhandledErrors) {
if(err.identifier === args.identifier) {
return await this.env.analytics.sendReport(err.error_id);
}
}
}
async loadErrorDefinitions() {
try {
const data = await fs.readFile("modules/exceptions/errorDefinitions.json");
return JSON.parse(data.toString());
} catch (e) {
console.error("Failed loading error definitions.")
console.error(e);
Sentry.captureException(e);
}
}
}
module.exports = ErrorHandler;

View File

@@ -0,0 +1,228 @@
[
{
"code": "No authentication/private",
"description": "Authenticate using&nbsp;<span onclick=\"$('#authModal').modal('show');\" class=\"openAuth\">cookies</span>&nbsp;and try again.",
"trigger": [
"ERROR: Private video",
"This video is private",
"Please sign in or sign up to view this video.",
"ERROR: This video is only available for registered users"
]
},
{
"code": "Members-only content",
"description": "Authenticate using&nbsp;<span onclick=\"$('#authModal').modal('show');\" class=\"openAuth\">cookies</span>&nbsp;and try again.",
"trigger": [
"ERROR: Join this channel to get access to members-only content",
"This video is available to this channel's members on level"
]
},
{
"code": "No connection could be made",
"description": "The host or your internet/proxy connection is down.",
"trigger": "getaddrinfo failed"
},
{
"code": "URL not supported",
"description": "This URL is currently not supported by YTDL.",
"trigger": [
"is not a valid URL",
"Unsupported URL"
]
},
{
"code": "Private or non-existent playlist",
"description": "This playlist does not exist or is&nbsp;<span onclick=\"$('#authModal').modal('show');\" class=\"openAuth\">private</span>.",
"trigger": "ERROR: The playlist does not exist"
},
{
"code": "Age restricted video",
"description": "To download this video log-in using &nbsp;<span onclick=\"$('#authModal').modal('show');\" class=\"openAuth\">cookies</span>.",
"trigger": [
"ERROR: Sign in to confirm your age",
"Verify your age"
]
},
{
"code": "Embed-only video",
"description": "Try using the URL of the embed page.",
"trigger": "ERROR: Cannot download embed-only video without embedding URL"
},
{
"code": "Possible broken extractor (404)",
"description": "YTDL isn't working, please wait for an update.",
"trigger": "HTTP Error 404"
},
{
"code": "Private or removed video",
"description": "This video can not be extracted.",
"trigger": "metadata.formats is not iterable"
},
{
"code": "ffmpeg not found",
"description": "Format merging requires ffmpeg.",
"trigger": "ffmpeg or avconv not found"
},
{
"code": "ffmpeg not found",
"description": "Transcoding to mp3 or mp4 requires ffmpeg.",
"trigger": [
"ffmpeg or avconv could not be found",
"ffprobe/avprobe and ffmpeg/avconv not found"
]
},
{
"code": "Incomplete video ID",
"description": "The URL you entered is incomplete.",
"trigger": "Incomplete YouTube ID"
},
{
"code": "Too many requests (429)",
"description": "You are being ratelimited by the service.",
"trigger": "HTTP Error 429"
},
{
"code": "Unable to extract initial data",
"description": "Please do try again in a moment.",
"trigger": "ERROR: Unable to extract yt initial data"
},
{
"code": "No write permission",
"description": "No write permission in download folder.",
"trigger": "[Errno 95]"
},
{
"code": "Blocked by firewall/program",
"description": "Check your firewall and or internet settings.",
"trigger": "[WinError 10013]"
},
{
"code": "Permission denied",
"description": "Unable to write files to your download location.",
"trigger": "[Errno 13]"
},
{
"code": "SSL verification failed",
"description": "Disable the 'Validate HTTPS certificates' setting.",
"trigger": "<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed"
},
{
"code": "Max fragment retries reached",
"description": "The service did not respond in time.",
"trigger": [
"giving up after 10 fragment retries",
"giving up after 10 retries"
]
},
{
"code": "Connection timed out",
"description": "Please try again in a moment.",
"trigger": [
"EOF occurred in violation of protocol",
"[Errno 60]"
]
},
{
"code": "No connection could be made",
"description": "Check your proxy and internet connection.",
"trigger": "[WinError 10060]"
},
{
"code": "Connection refused",
"description": "The service or your internet might be down.",
"trigger": "[WinError 10061]"
},
{
"code": "Connection reset",
"description": "The connection was closed by the remote host.",
"trigger": "[WinError 10054]"
},
{
"code": "No space left on device",
"description": "You have no space left on your drive.",
"trigger": "[Errno 28]"
},
{
"code": "This video is DRM protected",
"description": "Log in or use a proxy to download this video.",
"trigger": "This video is DRM protected"
},
{
"code": "File in use by another process",
"description": "Don't open the file while it's downloading.",
"trigger": "[WinError 32]"
},
{
"code": "HTTP error 403",
"description": "You may be ratelimited, try clearing the cache.",
"trigger": [
"HTTP Error 403",
"Error 403"
]
},
{
"code": "HTTP error 400",
"description": "Bad URL or broken extractor.",
"trigger": "HTTP Error 400"
},
{
"code": "HTTP error 405",
"description": "Bad URL or broken extractor.",
"trigger": "HTTP Error 405"
},
{
"code": "No video found",
"description": "This tweet does not contain a video.",
"trigger": "There's no video in this tweet"
},
{
"code": "Binaries missing/corrupted",
"description": "Please restart the app, or disable antivirus.",
"trigger": [
"Command failed with ENOENT: resources\\app.asar.unpacked\\binaries\\youtube-dl.exe",
"Command failed with ENOENT: binaries/youtube-dl.exe",
"is not recognized as an internal or external command"
]
},
{
"code": "Missing dependency",
"description": "Please install <a href=\"https://github.com/jely2002/youtube-dl-gui#how-to-use\" target=\"_blank\"> Microsoft Visual C++ 2010</a>",
"trigger": "3221225781"
},
{
"code": "Video not found",
"description": "This video does not exist.",
"trigger": [
"Video has not been found",
"does not exist"
]
},
{
"code": "Geo-locked content",
"description": "Try using a vpn or proxy.",
"trigger": [
"bbc.co.uk returned error: geolocation",
"This video is not available from your location due to geo restriction"
]
},
{
"code": "Access forbidden",
"description": "Not enough permissions to access the download URL.",
"trigger": "Access to this resource is forbidden by access policy"
},
{
"code": "Unknown URL type",
"description": "An invalid url scheme was used, try using http/https.",
"trigger": "urlopen error unknown url type"
},
{
"code": "Download file not found",
"description": "The download file was deleted/moved while it wasn't done yet.",
"trigger": "[WinError 2]"
},
{
"code": "Not premiered yet",
"description": "This video hasn't premiered yet.",
"trigger": "Premieres in"
}
]