Password Generator

Generate random passwords with Context Menu

Terá de instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

Terá de instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Terá de instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Terá de instalar uma extensão como Tampermonkey para instalar este script.

Terá de instalar uma extensão de gestão de scripts de utilizador para instalar este script.

(Já tenho um gestor de scripts de utilizador, deixe-me instalá-lo!)

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

(Já tenho um gestor de estilos de utilizador, deixe-me instalá-lo!)

// ==UserScript==
// @name            Password Generator
// @name:tr         Şifre Oluşturucu
// @namespace       https://aktolu.com/
// @version         0.6
// @description     Generate random passwords with Context Menu
// @description:tr  Sağ tık menüsünü kullanarak rastgele şifreler oluşturun
// @author          Muhammed Aktolu
// @match           *://*/*
// @icon            https://static-00.iconduck.com/assets.00/security-password-icon-1959x2048-sq0rdvok.png
// @grant           GM_addElement
// @grant           GM_addStyle
// @grant           GM_registerMenuCommand
// @grant           GM_setValue
// @grant           GM_getValue
// @grant           GM_setClipboard
// ==/UserScript==

/* jshint esversion: 11 */

(function() {
	'use strict';
	
	// Start Global
	const toast = function(text, type = 'success') {
		document.getElementById('myToast')?.remove();
		document.getElementById('myToastStyle')?.remove();
		
		// language=css
		let styleString = `
		#myToast {
			display: inline-block !important;
			padding: 20px !important;
			opacity: .6 !important;
			color: white !important;
			background-color: black !important;
			position: fixed !important;
			top: 20px !important;
			right: 20px !important;
			z-index: 9999999999999999999999 !important;
		}
		
		#myToast.success {
			background-color: green !important;
		}
		
		#myToast.warning {
			background-color: orange !important;
		}
		
		#myToast.danger {
			background-color: darkred !important;
		}
		`;
		let style = multilineCss(styleString, 'myToastStyle');
		
		let block = GM_addElement(document.body, 'div', {
			id: 'myToast',
			class: type,
		});
		
		block.innerText = text;
		
		setTimeout(() => {
			block.remove();
			style.remove();
		}, 5000);
	}
	
	const multilineCss = function(style, id = '') {
		let el = GM_addStyle(style);
		if (id !== '') {
			el.id = id;
		}
		
		return el;
	}
	// End Global
	
	// Start Password Generator
	const generatePassword = function(length = 16, minPerType = 2, uppercase = true, lowercase = true, number = true, symbol = false) {
		let string = '';
		let pass = {
			uppercase: true,
			lowercase: true,
			number: true,
			symbol: true,
		}
		let match;
		if (uppercase) {
			string += 'ABCDEFGHJKMNPQRSTUVWXYZ';
		}
		
		if (lowercase) {
			string += 'abcdefghjkmnpqrstuvwxyz';
		}
		
		if (number) {
			string += '23456789';
		}
		
		if (symbol) {
			string += '!";#$%&\'()*+,-./:;<=>?@[]^_`{|}~';
		}
		
		let password = Array.from(crypto.getRandomValues(new Uint32Array(length)))
			.map((x) => string[x % string.length])
			.join('');
		
		if (uppercase) {
			match = password.match(/[A-Z]/g);
			if (!match || match.length < minPerType) {
				pass.uppercase = false;
			}
		}
		
		if (lowercase) {
			match = password.match(/[a-z]/g);
			if (!match || match.length < minPerType) {
				pass.lowercase = false;
			}
		}
		
		if (number) {
			match = password.match(/\d/g);
			if (!match || match.length < minPerType) {
				pass.number = false;
			}
		}
		
		if (symbol) {
			match = password.match(/[^A-Za-z0-9]/g);
			if (!match || match.length < minPerType) {
				pass.symbol = false;
			}
		}
		
		if (password.match(/(.)\1/) || !pass.uppercase || !pass.lowercase || !pass.number || !pass.symbol) {
			return generatePassword(length, minPerType, uppercase, lowercase, number, symbol);
		} else {
			return password;
		}
	}
	// End Password Generator
	
	GM_registerMenuCommand('Generate Password', function() {
		if (document.getElementById('pgBlock')) {
			return false;
		}
		
		//let length = GM_getValue('passwordGeneratorLength', '16');
		let password = generatePassword(GM_getValue('pgLength', 16), GM_getValue('pgMinPerType', 2), GM_getValue('pgUppercase', true), GM_getValue('pgLowercase', true), GM_getValue('pgNumber', true), GM_getValue('pgSymbol', false));
		
		// language=css
		let styleString = `
		#pgBlock {
			position: fixed !important;
			width: 100vw !important;
			height: 100vh !important;
			z-index: 999999999999999999999 !important;
			display: flex !important;
			align-items: center !important;
			justify-content: center !important;
			background-color: rgba(0, 0, 0, .9) !important;
			left: 0 !important;
			top: 0 !important;
		}
		
		#pgBlock * {
			font-family: Helvetica, Arial, sans-serif !important;
			font-size: 15px !important;
			font-weight: 300 !important;
			letter-spacing: 0 !important;
			line-height: 100% !important;
			color: whitesmoke !important;
			float: none !important;
			border-radius: 0 !important;
		}
		
		#pgBlock div {
			display: block !important;
		}
		
		#pgBlock button {
			background-color: red !important;
			padding: 10px 30px !important;
			border: none !important;
			cursor: pointer !important;
		}
		
		#pgBlock input {
			margin-inline: 0 !important;
			font-size: 13px !important;
			display: inline !important;
		}
		
		#pgBlock input[type="number"] {
			background-color: black !important;
			border: 1px solid whitesmoke !important;
			width: 60px !important;
			padding: 1px 0 1px 2px !important;
			appearance: auto !important;
		}
		
		#pgBlock label {
			margin-right: 15px !important;
			cursor: pointer !important;
			-webkit-user-select: none !important;
			user-select: none !important;
		}

		.pgBox {
			text-align: center !important;
		}

		#pgPassword {
			font-size: 3rem !important;
			margin-bottom: 15px !important;
		}
		`;
		
		let style = multilineCss(styleString);
		let block = GM_addElement(document.body, 'div', {
			id: 'pgBlock',
		});
		
		// language=html
		block.innerHTML = `<div class="pgBox">
			<div id="pgPassword"></div>
			<div>
				<button id="pgCopyPassword">Copy</button>
				<button id="pgCancelPassword">Cancel</button>
			</div>
			<div style="margin-top: 100px">
				<div>
					Length: <input id="pgPasswordLength" type="number" value="`+GM_getValue('pgLength', 16)+`" style="margin-right: 60px" min="8" max="64">
					Min Chars Per Type: <input id="pgPasswordMinPerType" type="number" value="`+GM_getValue('pgMinPerType', 2)+`" min="0">
				</div>
				<div style="margin-top: 10px">
					<label>Uppercase: <input id="pgUppercase" type="checkbox"`+(GM_getValue('pgUppercase', true) ? ' checked' : '')+`></label>
					<label>Lowercase: <input id="pgLowercase" type="checkbox"`+(GM_getValue('pgLowercase', true) ? ' checked' : '')+`></label>
					<label>Number: <input id="pgNumber" type="checkbox"`+(GM_getValue('pgNumber', true) ? ' checked' : '')+`></label>
					<label>Symbol: <input id="pgSymbol" type="checkbox"`+(GM_getValue('pgSymbol', false) ? ' checked' : '')+`></label>
				</div>
				<button id="pgReGeneratePassword" style="margin-top: 25px">Regenerate Password</button>
			</div>
		</div>`;
		
		let passwordDiv = document.getElementById('pgPassword');
		let copyButton = document.getElementById('pgCopyPassword');
		let cancelButton = document.getElementById('pgCancelPassword');
		let passwordLengthInput = document.getElementById('pgPasswordLength');
		let minPerTypeInput = document.getElementById('pgPasswordMinPerType');
		let uppercaseCheckBox = document.getElementById('pgUppercase');
		let lowercaseCheckBox = document.getElementById('pgLowercase');
		let numberCheckBox = document.getElementById('pgNumber');
		let symbolCheckBox = document.getElementById('pgSymbol');
		let reGenerateButton = document.getElementById('pgReGeneratePassword');
		
		passwordDiv.innerText = password;
		
		copyButton.addEventListener('click', () => {
			navigator.clipboard.writeText(password)
				.then(r => toast('Password has been copied successfully.'));
			block.remove();
			style.remove();
		});
		
		cancelButton.addEventListener('click', () => {
			block.remove();
			style.remove();
		});
		
		[passwordLengthInput, minPerTypeInput].forEach(item => {
			item.addEventListener('click', () => {
				item.select();
			});
		});
		
		reGenerateButton.addEventListener('click', function() {
			GM_setValue('pgLength', parseInt(passwordLengthInput.value));
			GM_setValue('pgMinPerType', parseInt(minPerTypeInput.value));
			GM_setValue('pgUppercase', uppercaseCheckBox.checked);
			GM_setValue('pgLowercase', lowercaseCheckBox.checked);
			GM_setValue('pgNumber', numberCheckBox.checked);
			GM_setValue('pgSymbol', symbolCheckBox.checked);
			password = generatePassword(parseInt(passwordLengthInput.value), parseInt(minPerTypeInput.value), uppercaseCheckBox.checked, lowercaseCheckBox.checked, numberCheckBox.checked, symbolCheckBox.checked);
			passwordDiv.innerText = password;
		});
	});
})();