Edit: arivshort
Nama Worker
Kode Sumber
// worker-script.js // Definisi binding KV Namespace // Pastikan Anda mengikat KV Namespace ini di pengaturan Cloudflare Worker Anda // dengan nama variabel SHORTLINKS const KV_NAMESPACE = SHORTLINKS; // --- Konfigurasi --- const CUSTOM_MIN_LENGTH = 5; // Minimal 5 huruf untuk kode kustom const CUSTOM_MAX_LENGTH = 20; // Maksimal 20 huruf untuk kode kustom const RANDOM_SHORT_LENGTH = 6; // Panjang tetap 6 huruf untuk kode acak const AUTO_REDIRECT_DELAY_SECONDS = 5; // Waktu pengalihan otomatis dalam detik const DOMAIN = 'kudacuki.ggff.net'; // PENTING: Ganti dengan domain Worker Anda yang sebenarnya! const BASE_URL = `https://${DOMAIN}`; // --- Fungsi Pembantu --- // Fungsi untuk menghasilkan kode pendek acak (hanya huruf) function generateShortCode(length) { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; let result = ''; const charactersLength = characters.length; for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } // --- Template HTML --- // Fungsi untuk merender halaman pembuatan shortlink // Parameter shortUrlResult, message, isError digunakan untuk render awal jika ada function renderCreatePage(initialMessage = '', initialIsError = false, initialShortUrlResult = '') { // Pesan dan hasil akan ditampilkan langsung dari parameter yang diterima const messageClass = initialIsError ? 'text-red-400' : 'text-green-400'; const messageHtml = initialMessage ? `<p class="mt-4 ${messageClass} text-lg font-bold">${initialMessage}</p>` : ''; const shortUrlDisplay = initialShortUrlResult ? ` <div class="mt-8 p-4 bg-gray-800 border border-gray-700 rounded-lg text-left"> <label class="block text-lg font-semibold mb-2 text-white">Link Pendek Anda:</label> <div class="flex items-center space-x-2"> <input type="text" id="shortenedLink" value="${initialShortUrlResult}" readonly class="flex-grow bg-gray-700 border border-gray-600 text-white p-2 rounded-md"> <button onclick="copyToClipboard('shortenedLink')" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg transition duration-300"> Salin </button> </div> <p class="text-sm text-gray-400 mt-2">Bagikan link ini di media sosial!</p> </div> ` : ''; return ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Shortener - domain.com</title> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap" rel="stylesheet"> <style> body { font-family: 'Poppins', sans-serif; background-color: #0d0d1a; color: #e0e0e0; } input[type="text"], input[type="url"] { background-color: #1a1a2e; border: 2px solid #4a00e0; color: #e0e0e0; padding: 0.75rem 1rem; border-radius: 0.5rem; transition: border-color 0.3s ease, box-shadow 0.3s ease; } input[type="text"]:focus, input[type="url"]:focus { outline: none; border-color: #ff00ff; box-shadow: 0 0 8px rgba(255, 0, 255, 0.5); } button { transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease; } button:active { transform: translateY(2px); } .btn-pink-blue { background: linear-gradient(to right, #ff00ff, #00ffff); color: white; } .btn-pink-blue:hover { background: linear-gradient(to right, #e000e0, #00e0e0); box-shadow: 0 0 15px rgba(255, 0, 255, 0.4), 0 0 25px rgba(0, 255, 255, 0.4); } </style> <script> function copyToClipboard(elementId) { const copyText = document.getElementById(elementId); copyText.select(); copyText.setSelectionRange(0, 99999); document.execCommand("copy"); } // JavaScript untuk membersihkan URL dari parameter setelah halaman dimuat window.onload = function() { const url = new URL(window.location.href); // Cek apakah ada parameter yang perlu dibersihkan if (url.searchParams.has('message') || url.searchParams.has('isError') || url.searchParams.has('result')) { url.searchParams.delete('message'); url.searchParams.delete('isError'); url.searchParams.delete('result'); // Ganti URL di histori browser tanpa me-load ulang halaman history.replaceState({}, document.title, url.toString()); } }; </script> </head> <body class="flex flex-col min-h-screen items-center justify-center p-4"> <div class="bg-gradient-to-br from-indigo-900 to-purple-900 rounded-lg p-8 shadow-xl max-w-md w-full text-center border-4 border-white"> <h1 class="text-4xl font-bold mb-6 text-pink-400">Ariv Shortlink!</h1> <p class="text-lg mb-6 text-blue-300">Kamu bisa memendekkan tautan panjang menjadi lebih ringkas</p> ${messageHtml} <form action="/" method="POST" class="space-y-4"> <div> <input type="url" id="long_url" name="long_url" placeholder="Tempel tautan disini" required class="w-full text-lg"> </div> <div> <input type="text" id="short_code" name="short_code" placeholder="Ariv Tampan" minlength="${CUSTOM_MIN_LENGTH}" maxlength="${CUSTOM_MAX_LENGTH}" pattern="[a-zA-Z]+" title="Hanya boleh huruf (a-z, A-Z)" class="w-full text-lg"> </div> <button type="submit" class="w-full py-3 btn-pink-blue font-bold text-xl rounded-lg"> Shorten! </button> </form> ${shortUrlDisplay} </div> <div class="mt-8 text-center text-gray-400"> <p>Dibuat oleh Bang Ariv</p> </div> </body> </html> `; } // Fungsi untuk merender halaman "Pengalihan Aman" function renderSafeRedirectPage(shortUrl, longUrl) { return ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Lanjutkan ke Tujuan...</title> <script src="https://cdn.tailwindcss.com"></script> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap" rel="stylesheet"> <style> body { font-family: 'Poppins', sans-serif; background-color: #0d0d1a; color: #e0e0e0; } .btn-pink-blue { background: linear-gradient(to right, #ff00ff, #00ffff); color: white; } .btn-pink-blue:hover { background: linear-gradient(to right, #e000e0, #00e0e0); box-shadow: 0 0 15px rgba(255, 0, 255, 0.4), 0 0 25px rgba(0, 255, 255, 0.4); } button { transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease; } button:active { transform: translateY(2px); } </style> <script> // Skrip untuk pengalihan otomatis setelah 5 detik window.onload = function() { setTimeout(function() { window.location.href = "${longUrl}"; }, ${AUTO_REDIRECT_DELAY_SECONDS * 1000}); // Konversi detik ke milidetik }; </script> </head> <body class="flex flex-col min-h-screen items-center justify-center p-4"> <div class="bg-gradient-to-br from-indigo-900 to-purple-900 rounded-lg p-8 shadow-xl max-w-md w-full text-center border-4 border-white"> <h1 class="text-4xl font-bold mb-6 text-blue-300">🔐Link Aman! 🥳</h1> <p class="text-lg mb-6 text-white">Anda akan dialihkan sebentar lagi.</p> <p class="text-xl font-bold text-pink-400 break-words mb-8">Memproses pengalihan...</p> <p class="text-sm text-gray-300 mb-6">Kami telah memastikan link ini aman untuk Anda!</p> <a href="${longUrl}" target="_blank" rel="noopener noreferrer" class="w-full py-3 btn-pink-blue font-bold text-xl rounded-lg inline-block"> Lanjutkan Sekarang! </a> <p class="mt-6 text-sm text-gray-400">Jika Anda tidak dialihkan secara otomatis, klik tombol di atas.</p> </div> </body> </html> `; } // --- Main Event Listener --- addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); async function handleRequest(request) { const url = new URL(request.url); const path = url.pathname.slice(1); // Hapus garis miring di depan // Tangani permintaan POST untuk membuat shortlink if (request.method === 'POST') { if (url.pathname !== '/') { return new Response('Tidak Ditemukan', { status: 404 }); } return handleCreateShortlink(request); } // Tangani permintaan GET untuk halaman pembuatan if (path === '') { // Ambil parameter dari URL untuk inisialisasi halaman const message = url.searchParams.get('message') || ''; const isError = url.searchParams.get('isError') === 'true'; const result = url.searchParams.get('result') || ''; // Render halaman dengan pesan dan hasil jika ada return new Response(renderCreatePage(message, isError, result), { headers: { 'Content-Type': 'text/html' }, }); } // Tangani permintaan GET untuk mengalihkan shortlink const longUrl = await KV_NAMESPACE.get(path); if (longUrl) { return new Response(renderSafeRedirectPage(request.url, longUrl), { headers: { 'Content-Type': 'text/html' }, }); } else { // Jika shortlink tidak ditemukan, alihkan kembali ke halaman utama // dengan pesan error menggunakan parameter URL const redirectUrl = new URL(BASE_URL); redirectUrl.searchParams.set('message', 'Shortlink tidak ditemukan!'); redirectUrl.searchParams.set('isError', 'true'); return Response.redirect(redirectUrl.toString(), 302); } } async function handleCreateShortlink(request) { const formData = await request.formData(); const longUrl = formData.get('long_url'); let shortCode = formData.get('short_code'); let message = ''; let isError = false; let shortUrlResult = ''; if (!longUrl) { message = 'URL tidak boleh kosong.'; isError = true; } else { try { new URL(longUrl); } catch (e) { message = 'Format URL tidak valid. Pastikan dimulai dengan http:// atau https://'; isError = true; } } if (!isError) { let generatedCode; if (shortCode) { // Jika pengguna memasukkan kode kustom shortCode = shortCode.replace(/[^a-zA-Z]/g, ''); // Hanya izinkan huruf if (shortCode.length < CUSTOM_MIN_LENGTH || shortCode.length > CUSTOM_MAX_LENGTH) { message = `Kode pendek kustom harus ${CUSTOM_MIN_LENGTH} sampai ${CUSTOM_MAX_LENGTH} huruf.`; isError = true; } else { const existing = await KV_NAMESPACE.get(shortCode); if (existing) { message = `Kode pendek kustom "${shortCode}" sudah digunakan.`; isError = true; } else { generatedCode = shortCode; } } } else { // Jika pengguna TIDAK memasukkan kode kustom, generate acak 6 huruf let foundUnique = false; let attemptCount = 0; while (!foundUnique && attemptCount < 10) { // Batasi percobaan generatedCode = generateShortCode(RANDOM_SHORT_LENGTH); // Panjang tetap 6 huruf const existing = await KV_NAMESPACE.get(generatedCode); if (!existing) { foundUnique = true; } attemptCount++; } if (!foundUnique) { message = 'Gagal menghasilkan kode pendek unik setelah beberapa percobaan. Silakan coba lagi.'; isError = true; } } if (!isError && generatedCode) { await KV_NAMESPACE.put(generatedCode, longUrl); shortUrlResult = `${BASE_URL}/${generatedCode}`; message = 'Shortlink berhasil dibuat!'; isError = false; } } // Lakukan redirect ke halaman utama setelah pemrosesan POST // Sertakan pesan dan hasil sebagai parameter query string const redirectUrl = new URL(BASE_URL); if (message) { redirectUrl.searchParams.set('message', message); } if (isError) { redirectUrl.searchParams.set('isError', 'true'); } if (shortUrlResult) { redirectUrl.searchParams.set('result', shortUrlResult); } return Response.redirect(redirectUrl.toString(), 302); }
Bindings
Tambah KV
Tambah R2
Tambah D1
← Kembali
Simpan & Deploy
Hapus Script Worker Ini