mirror of
https://github.com/jely2002/youtube-dl-gui.git
synced 2021-11-01 22:46:21 +03:00
chore: add 10+ new error definitions
This commit is contained in:
@@ -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 <span onclick="$('#authModal').modal('show');" class="openAuth">cookies</span> and try again.`,
|
||||
trigger: "ERROR: Private video"
|
||||
},
|
||||
{
|
||||
code: "No authentication",
|
||||
description: `Authenticate using <span onclick="$('#authModal').modal('show');" class="openAuth">cookies</span> and try again.`,
|
||||
trigger: "ERROR: This video is only available for registered users"
|
||||
},
|
||||
{
|
||||
code: "Members-only content",
|
||||
description: `Authenticate using <span onclick="$('#authModal').modal('show');" class="openAuth">cookies</span> 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 <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 <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;
|
||||
109
modules/exceptions/ErrorHandler.js
Normal file
109
modules/exceptions/ErrorHandler.js
Normal 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;
|
||||
228
modules/exceptions/errorDefinitions.json
Normal file
228
modules/exceptions/errorDefinitions.json
Normal file
@@ -0,0 +1,228 @@
|
||||
[
|
||||
{
|
||||
"code": "No authentication/private",
|
||||
"description": "Authenticate using <span onclick=\"$('#authModal').modal('show');\" class=\"openAuth\">cookies</span> 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 <span onclick=\"$('#authModal').modal('show');\" class=\"openAuth\">cookies</span> 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 <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 <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"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user