-
-
-
-
-
-
`;
const OMDB_INPUT = `
`;
///////////////////////////////////////////////////////////////////////////
// Shortcut Keys //
///////////////////////////////////////////////////////////////////////////
/**
* Handle keydown events to allow the user to hide the script with the "Escape" key
*
* @param {Event} event - The keydown event that occurred
*/
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
$('#omdb-generator').hide();
document.getElementById('show-template').style.display = 'block';
}
});
///////////////////////////////////////////////////////////////////////////
// Utility //
///////////////////////////////////////////////////////////////////////////
/**
* Hides the "Show" button and shows the OMDB template generator.
*
* @return {void} No return value.
*/
const ShowTemplate = () => {
document.getElementById('show-template').style.display = 'none';
$('#omdb-generator').show();
};
/**
* Shows the "Show" button and hides the OMDB template generator.
*
* @return {void} No return value.
*/
const HideTemplate = () => {
document.getElementById('show-template').style.display = 'block';
$('#omdb-generator').hide();
};
/**
* Sets the value of the 'message' input field to the provided forumBBCode
* optionally sets the value of the 'subject' input field to the provided title.
*
* @param {string} forumBBCode - The forum BBCode to be set as the value of the 'message' input field.
* @param {string} title - The title to be set as the value of the 'subject' input field (optional).
* @param {boolean} titleBool - A flag indicating whether the value of the 'subject' input field should be set or not (optional).
* @return {void} This function does not return anything.
*/
const SubmitToForum = (forumBBCode, title, titleBool) => {
try {
document.getElementsByName('message')[0].value = forumBBCode;
} catch (err) {
alert(
`Something went wrong! Please report to my Developer.... I get scared when I crash ☹️\n\n err`
);
} finally {
if (titleBool) {
document.getElementsByName('subject')[0].value = title;
}
}
};
///////////////////////////////////////////////////////////////////////////
// Network Requests //
///////////////////////////////////////////////////////////////////////////
/**
* This function makes asynchronous http requests using GM.xmlHttpRequest
* @param {string} method - HTTP method to use
* @param {string} url - URL of the request
* @param {object} data - Request payload
* @param {object} headers - Request headers
* @returns {Promise} - A promise that resolves with the response of the request
*/
const RequestUrl = async (method, url, data, headers) => {
return await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: method,
url: url,
data: data,
headers: headers,
onload: (response) => {
resolve(response);
},
onerror: (response) => {
reject(response);
},
});
});
};
///////////////////////////////////////////////////////////////////////////
// Search //
///////////////////////////////////////////////////////////////////////////
const SectionSearch = (apiKey) => {
let queryType = SUBSECTION_TYPE ? `&type=${SUBSECTION_TYPE}` : '';
var query = `https://www.omdbapi.com/?apikey=${apiKey}&r=JSON&s={query}${queryType}`;
$('#search-box').search({
type: 'category',
apiSettings: {
url: query,
onResponse: (myfunc) => {
var response = {
results: {},
};
$.each(myfunc.Search, (index, item) => {
var category = item.Type.toUpperCase() || 'Unknown',
maxResults = 10;
if (index >= maxResults) {
return false;
}
if (response.results[category] === undefined) {
response.results[category] = {
name: '~~~~~~~~~~' + category + '~~~~~~~~~~',
results: [],
};
}
var Name = `${item.Title} (${item.Year})`;
response.results[category].results.push({
title: Name,
description: Name,
imdbID: item.imdbID,
});
});
return response;
},
},
fields: {
results: 'results',
title: 'name',
},
onSelect: function (response) {
document.getElementById('hidden-id-value').value = response.imdbID;
document.getElementById('omdb-search-box').value = response.title;
},
minCharacters: 3,
});
};
///////////////////////////////////////////////////////////////////////////
// Parsers //
///////////////////////////////////////////////////////////////////////////
class Parser {
// parse download links
downloadLinks = (downloadLinks, megaDomains) => {
let downloadLinkBBCode = '[hide][b]';
if (downloadLinks == null) {
downloadLinkBBCode += '[url=][size=150]Download Link[/size][/url]';
} else {
for (let link of downloadLinks) {
if (megaDomains.some((el) => link.includes(el))) {
downloadLinkBBCode += `[url=${link}][size=150][color=#FF0000]MEGA[/color][/size][/url]\n`;
} else if (link.includes('zippyshare.com')) {
downloadLinkBBCode += `[url=${link}][size=150][color=#FFFF00]ZippyShare[/color][/size][/url]\n`;
} else if (link.includes('drive.google.com')) {
downloadLinkBBCode += `[url=${link}][size=150][color=#00FF00]Gdrive[/color][/size][/url]\n`;
} else {
downloadLinkBBCode += `[url=${link}][size=150]Download Link[/size][/url]\n`;
}
}
}
return `[size=200][color=#fac51c][B]Download Links:[/B][/COLOR][/size]\n\n[center]\n${downloadLinkBBCode}[/b][/hide][/CENTER]\n`;
};
// parse screenshot links
screenshots = (screenshots) => {
var screen = `\n[hr][/hr][size=200][color=#fac51c][b]Screenshots:[/b][/color][/size]\n\n`;
for (let ss of screenshots) {
screen += `[img]${ss}[/img]`;
}
screen += `\n`;
return screen;
};
// Parses Mediainfo for Title values
mediaInfo = (mediaInfo, premadeTitle) => {
let videoInfo = mediaInfo.match(/(Video|Video #1)$.^[\s\S]*?(?=\n{2,})/ms);
if (videoInfo) {
videoInfo = videoInfo[0];
let videoWidth = videoInfo.match(/Width.*/);
if (videoWidth) {
videoWidth = videoWidth[0];
if (videoWidth.includes('3 840')) {
premadeTitle += ' 2160p';
} else if (videoWidth.includes('1 920')) {
premadeTitle += ' 1080p';
} else if (videoWidth.includes('1 280')) {
premadeTitle += ' 720p';
} else if (videoWidth.includes('720')) {
premadeTitle += ' 480p';
}
}
let videoWritingLib = videoInfo.match(/Writing library.*/);
if (
videoWritingLib &
(videoWritingLib[0].includes('x265') |
videoWritingLib[0].includes('x264'))
) {
videoWritingLib = videoWritingLib[0];
if (videoWritingLib.includes('x265')) {
premadeTitle += ' x265';
} else if (videoWritingLib.includes('x264')) {
premadeTitle += ' x264';
}
} else {
let videoFormat = videoInfo.match(/Format.*/);
if (videoFormat) {
videoFormat = videoFormat[0];
if (videoFormat.includes('HEVC')) {
premadeTitle += ' HEVC';
} else if (videoFormat.includes('AVC')) {
premadeTitle += ' AVC';
}
}
}
let videoBitDepth = videoInfo.match(/Bit depth.*/);
if (videoBitDepth) {
videoBitDepth = videoBitDepth[0];
premadeTitle += videoBitDepth.match(/\d.*/)
? ` ${videoBitDepth.match(/\d.*/)[0].replace(' bits', 'bit')}`
: '';
}
}
let audioInfo = mediaInfo.match(/(Audio|Audio #1)$.^[\s\S]*?(?=\n{2,})/ms);
if (audioInfo) {
audioInfo = audioInfo[0];
let audioCodec = audioInfo.match(/Codec ID.*/);
if (audioCodec) {
audioCodec = audioCodec[0];
premadeTitle += audioCodec.match(/(?<=A_).*/)
? ` ${audioCodec.match(/(?<=A_).*/)[0]}`
: '';
}
}
if (SUBSECTION_TYPE === 'movie') {
let generalInfo = mediaInfo.match(/General$.^[\s\S]*?(?=\n{2,})/ms);
if (generalInfo) {
generalInfo = generalInfo[0];
let mediaSize = generalInfo.match(/File size.*/);
if (mediaSize) {
mediaSize = mediaSize[0];
premadeTitle += mediaSize.match(/\d.*/)
? ` [${mediaSize.match(/\d.*/)[0]}]`
: '';
}
}
}
return premadeTitle;
};
}
/**
* Saves the OMDB API key entered by the user.
* If successful, sets the API key in local storage and triggers the main function.
* Displays an alert and throws an error if the entered key is missing or invalid.
*
* @throws {Error} An error is thrown if the entered key is invalid or missing.
*
* @returns {void}
*/
const SaveApiKey = () => {
// Grab value from user input field
const omdbKey = document.getElementById('omdb-api-key').value;
// Throw error if we didn't get a value
if (!omdbKey) {
alert('Did you enter your omdb key?');
throw new Error(
`${SCRIPT_NAME}: No input was detected in the omdb-api-key element.`
);
}
// Validate api key before saving
RequestUrl('GET', `https://www.omdbapi.com/?apikey=${omdbKey}&i=tt0848228`)
.then((response) => {
if (response.status === 200) {
GM.setValue('APIKEY', omdbKey);
document.getElementById('template-generator-container').remove();
Main();
return;
}
if (response.status === 401) {
let data = JSON.parse(response.responseText);
alert(
`Unable to verify API key. Check the message from OMDB Below. \n${
data.message || data.Error
}`
);
console.error(`${SCRIPT_NAME}`, response);
throw Error(`${SCRIPT_NAME}: 401 Response`);
}
throw Error(
`${SCRIPT_NAME}: Unable To Verify API Key. \n HTTP STATUS CODE: ${response.status}`
);
})
.catch((error) => {
console.error(error);
if (error.message === `${SCRIPT_NAME}: 401 Response`) {
return;
}
alert(
'An error occurred while testing the validity of your omdb key.\nPlease try again later!\nThe error was sent to your browsers devtools.'
);
throw new Error(`${SCRIPT_NAME}: Unable to verify API Key.`);
});
};
const GenerateTemplate = async (apiKey) => {
var [imdbID, downloadLinks, mediainfo, screenshots] = [
document.getElementById('hidden-id-value').value
? document.getElementById('hidden-id-value').value
: document.getElementById('omdb-search-box').value,
document.getElementById('DownloadLink').value,
document.getElementById('mediainfo-textarea').value,
document.getElementById('screen-links').value,
];
if (!imdbID) {
alert("You Didn't Select A Title or Enter a IMDB ID!");
return;
}
if (imdbID.includes('imdb')) {
imdbID = imdbID.match(/tt\d+/)[0];
}
// Create Prefix placeholder per DDLs
let titleBool = !document.getElementsByName('subject')[0].value;
let titlePrefix = '';
var megaDomains = ['mega.nz', 'mega.co.nz']; // In case using old Mega link
if (titleBool) {
if (megaDomains.some((el) => downloadLinks.includes(el))) {
titlePrefix += '[Mega]';
}
if (downloadLinks.includes('zippyshare.com')) {
titlePrefix += '[Zippy]';
}
if (downloadLinks.includes('drive.google.com')) {
titlePrefix += '[Gdrive]';
}
}
screenshots = screenshots
? new Parser().screenshots(screenshots.split(' '))
: '';
const response = await RequestUrl(
'GET',
`http://www.omdbapi.com/?apikey=${apiKey}&i=${imdbID}&plot=full&y&r=json`
);
let json = JSON.parse(response.responseText);
let poster =
json.Poster && json.Poster !== 'N/A'
? `[center][img]${json.Poster}[/img]\n`
: '';
if (json.Title && json.Title !== 'N/A') {
var title = `${json.Title}`;
} else {
alert(
"You Messed Up! Check That You've Entered Something Into The IMDB Field!"
);
}
let year = json.Year && json.Year !== 'N/A' ? ` (${json.Year})` : '';
let fullName = `[b][size=150][url='/search.php?keywords=${imdbID}&sk=x']${title}${year}[/url][/size][/b]\n`;
let imdbId =
json.imdbID && json.imdbID !== 'N/A'
? `[url=https://www.imdb.com/title/${json.imdbID}][img]https://i.imgur.com/rcSipDw.png[/img][/url]`
: '';
let rating =
json.imdbRating && json.imdbRating !== 'N/A'
? `[size=150][b]${json.imdbRating}[/b]/10[/size]\n`
: '';
let imdbvotes =
json.imdbVotes && json.imdbVotes !== 'N/A'
? `[size=150][img]https://i.imgur.com/sEpKj3O.png[/img]${json.imdbVotes}[/size][/center]\n`
: '';
let plot =
json.Plot && json.Plot !== 'N/A'
? `[hr][/hr][size=200][color=#fac51c][b]Plot:[/b][/color][/size]\n\n ${json.Plot}\n`
: '';
let movieInfo = '';
if (json.Rated && json.Rated !== 'N/A') {
movieInfo += `[B]Rating: [/B] ${json.Rated}\n`;
}
if (json.Genre && json.Genre !== 'N/A') {
movieInfo += `[*][B]Genre: [/B] ${json.Genre}\n`;
}
if (json.Director && json.Director !== 'N/A') {
movieInfo += `[*][B]Directed By: [/B] ${json.Director}\n`;
}
if (json.Writer && json.Writer !== 'N/A') {
movieInfo += `[*][B]Written By: [/B] ${json.Writer}\n`;
}
if (json.Actors && json.Actors !== 'N/A') {
movieInfo += `[*][B]Starring: [/B] ${json.Actors}\n`;
}
if (json.Released && json.Released !== 'N/A') {
movieInfo += `[*][B]Release Date: [/B] ${json.Released}\n`;
}
if (json.Runtime && json.Runtime !== 'N/A') {
movieInfo += `[*][B]Runtime: [/B] ${json.Runtime}\n`;
}
if (json.Production && json.Production !== 'N/A') {
movieInfo += `[*][B]Production: [/B] ${json.Production}\n`;
}
if (movieInfo) {
movieInfo = `\n[hr][/hr][size=200][color=#fac51c][b]Movie Info:[/b][/color][/size]\n\n[LIST][*]${movieInfo}[/LIST]\n`;
}
let premadeTitle = titleBool
? `${titlePrefix} ${json.Title} (${json.Year})`
: '';
if (titleBool && mediainfo) {
premadeTitle = new Parser().mediaInfo(mediainfo, premadeTitle);
}
mediainfo = mediainfo
? `[hr][/hr][size=200][color=#fac51c][b]Media Info:[/b][/color][/size]\n\n[mediainfo]${mediainfo}\n[/mediainfo]\n`
: '';
let downloadLinkBBCode = new Parser().downloadLinks(
downloadLinks.split(' '),
megaDomains
);
let forumBBCode = `${poster}${fullName}${imdbId}${rating}${imdbvotes}${plot}${screenshots}${movieInfo}${mediainfo}${downloadLinkBBCode}`;
SubmitToForum(forumBBCode, premadeTitle, titleBool);
};
function Main() {
GM.getValue('APIKEY', 'foo').then((apiKey) => {
const htmlpush = document.getElementsByTagName('dl')[0];
if (apiKey !== 'foo') {
htmlpush.insertAdjacentHTML('afterend', HTML_TEMPLATE);
} else {
htmlpush.insertAdjacentHTML('afterend', OMDB_INPUT);
}
document.getElementById('hide-template').addEventListener(
'click',
() => {
HideTemplate();
},
false
);
document.getElementById('show-template').addEventListener(
'click',
() => {
ShowTemplate();
},
false
);
if (apiKey !== 'foo') {
SectionSearch(apiKey);
document.getElementById('generate-template').addEventListener(
'click',
() => {
GenerateTemplate(apiKey);
},
false
);
} else {
document.getElementById('save-key').addEventListener(
'click',
() => {
SaveApiKey();
},
false
);
}
});
}
// Add css to the page
GM_addStyle(`
@media screen and (min-width: 300px) {
.inputbox {
max-width: 330px;
}
.result {
max-height: 10px;
display: unset;
}
.content {
overflow: unset;
min-height: unset;
cursor: pointer;
padding-bottom: unset;
line-height: unset;
}
#mediainfo-textarea {
width: 100% !important;
}
}
`);
Main();