commit fdcc5dde6950dba515f0b8b4e54cbd6d3b06a137 Author: dedy_ira Date: Mon Sep 28 17:16:09 2026 +0700 Clean commit: remove all heavy binaries and history diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..bc1a2f3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.git +*.log +*.tar +*.zip +downloading +upload diff --git a/Dockerfile b/Dockerfile new file mode 100755 index 0000000..cbd52e4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM node:22-alpine + +WORKDIR /app + +COPY . /app + +EXPOSE 80 + +CMD ["node", "server.js"] diff --git a/Dockerfile.nginx.bak b/Dockerfile.nginx.bak new file mode 100755 index 0000000..f82da21 --- /dev/null +++ b/Dockerfile.nginx.bak @@ -0,0 +1,10 @@ +FROM nginx:alpine + +# Salin konfigurasi Nginx kustom +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# Salin file statis aplikasi speedtest ke direktori Nginx html +COPY . /usr/share/nginx/html + +# Expose port HTTP default +EXPOSE 80 diff --git a/License.md b/License.md new file mode 100755 index 0000000..b93a920 --- /dev/null +++ b/License.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 OpenSpeedTest™ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100755 index 0000000..76683ba --- /dev/null +++ b/README.md @@ -0,0 +1,119 @@ +# **Internal SpeedTest (Megakreasitech™)** +> A customized, premium self-hosted HTML5 network performance estimation tool. Powered by the open-source engine of OpenSpeedTestcom +--- + +## 🌟 Overview +This repository contains a highly customized version of the OpenSpeedTest™ engine. It is designed specifically for **internal network benchmarking** at **Megakreasitech™**, featuring a polished, modern, glassmorphic UI, responsive layout adjustments, and localized behavior. + +No client-side software, plugins, or flash are required. You can run speed tests from any modern device with a web browser (including smartphones, smart TVs, and desktop PCs). + +--- + +## ✨ Customizations & Enhancements +Compared to the default upstream OpenSpeedTest deployment, this repository includes several improvements and customizations: + +1. **Premium Modern UI (Design System)**: + - Clean, vibrant, and premium card layouts featuring modern typography (Google Fonts **Outfit** & **Inter**). + - Glassmorphism effects with soft shadows and tailored HSL colors. + - Smooth CSS transitions and micro-animations (e.g., hover effects on gauges, buttons, and logos). + - Support for **Dark Mode** and **Light Mode** out-of-the-box. +2. **Branding & Localization**: + - Custom outro display showing **Megakreasitech™** inside the gauge when the test finishes. + - Localized header, logo, and footer credits. +3. **Optimized IP Address Display**: + - The "Your IP Address" section has been repositioned **precisely above the gauge**. + - It is dynamically responsive: aligned left over the gauge on desktop (landscape) and centered above the gauge on mobile (portrait) with proportional spacing. + +--- + +## 🚀 Deployment Instructions + +### 1. Using Nginx (Recommended) +This application only consists of static HTML, CSS, JS, and SVG files. + +For maximum performance, we recommend deploying it on a bare-metal Linux server running Nginx with caching disabled for the testing endpoints. + +**Nginx Configuration Example:** +```nginx +server { + listen 80; + server_name localhost; + + root /path/to/Speed-Test-main; + index index.html; + + gzip on; + gzip_types text/css application/javascript image/svg+xml; + + # Caching disabled for download test endpoint + location = /downloading { + access_log off; + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, HEAD' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, X-Requested-With' always; + add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, max-age=0' always; + try_files /downloading =404; + } + + # Fetch client IP endpoint + location = /getIP { + access_log off; + default_type text/plain; + add_header 'Access-Control-Allow-Origin' '*' always; + return 200 $remote_addr; + } + + # Caching disabled for upload test endpoint + location = /upload { + access_log off; + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, HEAD' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, X-Requested-With' always; + client_max_body_size 50m; + + if ($request_method = POST) { + return 200; + } + if ($request_method = OPTIONS) { + return 200; + } + try_files /upload =200; + } +} +``` + +### 2. Using Docker Compose +You can spin up this customized application quickly using the provided `docker-compose.yml` file: + +```yaml +version: '3.3' +services: + speedtest: + build: . + restart: unless-stopped + container_name: mkt_speedtest + ports: + - '80:80' +``` + +To run: +```bash +docker-compose up -d +``` + +--- + +## ⚙️ Advanced URL Parameters +The underlying engine supports multiple URL configurations. You can combine parameters like so: `http:///?Run&Stress=30` + +- `?Run` / `?R`: Run the speed test automatically on page load. +- `?Stress=Low` / `?S=L`: Continuously loop speed test for benchmarking (values: `Low`, `Medium`, `High`, `Extreme`, or custom duration in seconds). +- `?Test=Download` / `?T=D`: Run only the download test. +- `?Test=Upload` / `?T=U`: Run only the upload test. +- `?Test=Ping` / `?T=P`: Run only the ping test. +- `?XHR=6` / `?X=6`: Set custom number of parallel connections (1 - 32). + +--- + +## 📜 Credits & Acknowledgments +This tool is built upon the free and open-source codebase of **OpenSpeedTest** diff --git a/assets/css/app.css b/assets/css/app.css new file mode 100755 index 0000000..d7fafb4 --- /dev/null +++ b/assets/css/app.css @@ -0,0 +1,643 @@ +/* app.css - Design System Premium untuk SpeedTest */ + +/* Impor font Roboto asli proyek */ +@font-face { + font-family: "Roboto"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url("../fonts/roboto-v30-latin-regular.eot"); + src: local(""), + url("../fonts/roboto-v30-latin-regular.eot?#iefix") format("embedded-opentype"), + url("../fonts/roboto-v30-latin-regular.woff2") format("woff2"), + url("../fonts/roboto-v30-latin-regular.woff") format("woff"), + url("../fonts/roboto-v30-latin-regular.ttf") format("truetype"), + url("../fonts/roboto-v30-latin-regular.svg#Roboto") format("svg"); +} + +@font-face { + font-family: "Roboto"; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url("assets/fonts/roboto-v30-latin-500.eot"); + src: local(""), + url("assets/fonts/roboto-v30-latin-500.eot?#iefix") format("embedded-opentype"), + url("assets/fonts/roboto-v30-latin-500.woff2") format("woff2"), + url("assets/fonts/roboto-v30-latin-500.woff") format("woff"), + url("assets/fonts/roboto-v30-latin-500.ttf") format("truetype"), + url("assets/fonts/roboto-v30-latin-500.svg#Roboto") format("svg"); +} + +html, +body { + margin: 0; + padding: 0; + width: 100%; + height: 100%; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + background: radial-gradient(circle at 50% 50%, #F8FAFC 0%, #E2E8F0 100%); + display: flex; + justify-content: center; + align-items: center; + overflow: hidden; + transition: background 0.4s ease; +} + +::-webkit-scrollbar { + display: none; +} + +html { + -ms-overflow-style: none; + scrollbar-width: none; +} + +/* Container Utama */ +.app-layout { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + max-width: 960px; + padding: 24px; + box-sizing: border-box; + gap: 24px; +} + +/* Header Dashboard */ +.app-header { + display: flex; + align-items: center; + gap: 16px; + animation: fadeInDown 0.6s cubic-bezier(0.16, 1, 0.3, 1) both; +} + +.header-logo-img { + width: 40px; + height: 40px; + object-fit: contain; + filter: drop-shadow(0 4px 12px rgba(79, 172, 254, 0.3)); +} + +.header-text { + display: flex; + align-items: center; + gap: 10px; +} + +.header-text h1 { + margin: 0; + font-family: 'Outfit', sans-serif; + font-size: 24px; + font-weight: 800; + letter-spacing: -0.02em; + color: #0F172A; +} + +.header-badge { + font-family: 'Inter', sans-serif; + font-size: 11px; + font-weight: 600; + color: #2563EB; + background: rgba(37, 99, 235, 0.08); + padding: 4px 10px; + border-radius: 12px; + border: 1px solid rgba(37, 99, 235, 0.15); + text-transform: uppercase; + letter-spacing: 0.03em; + margin-top: 4px; +} + +.client-ip-container { + position: absolute; + top: 20px; + left: calc(50% - 150px); + transform: translateX(-50%); + display: flex; + justify-content: center; + align-items: center; + gap: 6px; + font-family: 'Inter', sans-serif; + font-size: 13px; + font-weight: 500; + color: #64748B; + z-index: 20; + pointer-events: none; + white-space: nowrap; + transition: all 0.3s ease; +} + +@media only screen and (orientation: portrait) { + .client-ip-container { + left: 50%; + top: 12px; + } +} + +.client-ip-container span#client-ip-text { + color: #0EA5E9; + font-weight: 700; +} + +/* Card Wrapper Speed Test */ +.app-card { + position: relative; + width: 100%; + background: rgba(255, 255, 255, 0.7); + backdrop-filter: blur(24px) saturate(180%); + -webkit-backdrop-filter: blur(24px) saturate(180%); + border: 1px solid rgba(255, 255, 255, 0.4); + border-radius: 32px; + box-shadow: + 0 20px 40px -15px rgba(15, 23, 42, 0.05), + 0 0 80px rgba(15, 23, 42, 0.02), + inset 0 1px 0 rgba(255, 255, 255, 0.6); + padding: 40px; + box-sizing: border-box; + display: flex; + justify-content: center; + align-items: center; + transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1); + animation: scaleIn 0.8s cubic-bezier(0.16, 1, 0.3, 1) both; +} + +.app-card:hover { + transform: translateY(-4px); + box-shadow: + 0 30px 60px -20px rgba(15, 23, 42, 0.08), + 0 0 100px rgba(15, 23, 42, 0.03), + inset 0 1px 0 rgba(255, 255, 255, 0.8); + border-color: rgba(255, 255, 255, 0.6); +} + +/* SVG App Sizing */ +.openSpeedtestApp { + width: 100%; + max-width: 600px; + height: auto; + aspect-ratio: 586 / 346; + display: none; + overflow: hidden; +} + +/* Spinner Loader */ +.spinner { + position: absolute; + display: flex; + gap: 8px; + justify-content: center; + align-items: center; + z-index: 99; +} + +.spinner>div { + width: 12px; + height: 12px; + background: linear-gradient(135deg, #00F2FE 0%, #4FACFE 100%); + border-radius: 50%; + animation: bounceDelay 1.4s infinite ease-in-out both; +} + +.spinner .bounce1 { + animation-delay: -0.32s; +} + +.spinner .bounce2 { + animation-delay: -0.16s; +} + +/* ========================================== + KONTROL TAMPILAN ELEMENT (PENTING!) + Menyembunyikan komponen SVG secara default + agar tidak bertumpuk. + ========================================== */ +#UI-Desk { + display: none; +} + +#UI-Mob { + display: none; +} + +#ipMob { + display: none; +} + +#ipDesk { + display: none; +} + +#upSymbolDesk { + display: none; +} + +#downSymbolDesk { + display: none; +} + +#upSymbolMob { + display: none; +} + +#downSymbolMob { + display: none; +} + +.ConnectError { + display: none; +} + +/* ========================================== + TYPOGRAPHY DI DALAM SVG (ASLI ROBOTO) + Menggunakan font-family dan ukuran asli + agar layout & koordinat SVG tidak berantakan + ========================================== */ +.oDoLive-Speed { + font-family: 'Roboto', sans-serif !important; + font-size: 20px !important; + font-weight: 500 !important; + fill: #500516 !important; + text-anchor: middle !important; +} + +.oDoLive-Status { + font-family: 'Roboto', sans-serif !important; + font-size: 10px !important; + font-weight: 500 !important; + fill: #94A3B8 !important; + text-anchor: middle !important; +} + +.rtextnum { + font-family: 'Roboto', sans-serif !important; + font-size: 23px !important; + font-weight: 500 !important; + fill: #0F172A !important; + text-anchor: middle !important; +} + +.rtext { + font-family: 'Roboto', sans-serif !important; + font-size: 10px !important; + font-weight: 400 !important; + fill: #64748B !important; +} + +.rtextmbms { + font-family: 'Roboto', sans-serif !important; + font-size: 12px !important; + font-weight: 500 !important; + fill: #94A3B8 !important; + text-anchor: middle !important; +} + +.oDo-Meter { + font-family: 'Roboto', sans-serif !important; + font-size: 16.63px !important; + font-weight: 500 !important; + fill: #94A3B8 !important; +} + +.oDoTop-Speed { + font-family: 'Roboto', sans-serif !important; + font-size: 16.96px !important; + font-weight: 500 !important; + fill: #94A3B8 !important; + text-anchor: end !important; +} + +.jitter-Mob { + font-family: 'Roboto', sans-serif !important; + font-size: 9px !important; + font-weight: 500 !important; + fill: #64748B !important; + text-anchor: middle !important; +} + +.buttonTxt { + font-family: 'Roboto', sans-serif !important; + font-size: 40px !important; + font-weight: 500 !important; + fill: #ffffff !important; + text-anchor: middle !important; +} + +/* ========================================== + ESTETIKA DAN DESAIN ELEMEN SVG + ========================================== */ +.Cards { + fill: rgba(248, 250, 252, 0.8) !important; + stroke: rgba(226, 232, 240, 0.8) !important; + stroke-width: 1.5px !important; + transition: all 0.3s ease; +} + +.uiBg { + fill: #94A3B8 !important; +} + +.Symbol { + fill: url(#gradient) !important; +} + +.progressbg { + stroke: #E2E8F0 !important; + stroke-width: 8px !important; + stroke-linecap: round !important; + stroke-linejoin: round !important; + stroke-dasharray: 400 !important; + stroke-dashoffset: 0; +} + +.intro-Progress { + stroke: #4FACFE !important; + stroke-width: 8px !important; + stroke-linecap: round !important; + stroke-linejoin: round !important; + stroke-dasharray: 400 !important; + stroke-dashoffset: 0; +} + +.progressElmstart { + stroke: #4FACFE !important; + stroke-width: 8px !important; + stroke-linecap: round !important; + stroke-linejoin: round !important; + stroke-dasharray: 400 !important; + stroke-dashoffset: 0; + display: block !important; +} + +.main-Gaugebg { + fill: none !important; + stroke: #E2E8F0 !important; + stroke-linecap: round !important; + stroke-linejoin: round !important; + stroke-width: 22px !important; + stroke-dasharray: 681 !important; +} + +.main-GaugeBlue { + fill: none !important; + stroke: url(#gradient) !important; + stroke-linecap: round !important; + stroke-linejoin: round !important; + stroke-width: 22px !important; + stroke-dasharray: 681 !important; + stroke-opacity: 0; +} + +.main-GaugeWhite { + fill: none !important; + stroke: rgb(255, 255, 255) !important; + stroke-linecap: round !important; + stroke-linejoin: round !important; + stroke-width: 15px !important; + stroke-dasharray: 0, 681 !important; + stroke-dashoffset: 1; + stroke-opacity: 0; +} + +.deskStart { + fill: none !important; + stroke: url(#gradient) !important; + stroke-linecap: round !important; + stroke-linejoin: round !important; + stroke-dasharray: 681 !important; +} + +/* Button & Interactive elements */ +.startButton { + fill: url(#gradient) !important; + cursor: pointer; + filter: drop-shadow(0 8px 20px rgba(0, 242, 254, 0.25)); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + transform-box: fill-box; + transform-origin: center; +} + +.startButton:hover { + filter: drop-shadow(0 12px 28px rgba(0, 242, 254, 0.45)); + opacity: 0.95; + transform: scale(1.02); +} + +.startButton:active { + transform: scale(0.98); +} + +.Startsettings { + cursor: pointer; + opacity: 0.3; + transition: all 0.3s ease; + transform-box: fill-box; + transform-origin: center; +} + +.Startsettings:hover { + opacity: 0.9; + transform: rotate(30deg); +} + +/* Restyle logo di SVG menggunakan CSS */ +svg [style*="fill: #3da6ff"] { + fill: #2563EB !important; + /* Modern Royal Blue */ +} + +svg [style*="fill: #4d4d4d"] { + fill: #0F172A !important; + /* Slate 900 */ +} + +/* Dark mode toggle */ +.darkmode { + fill: #94A3B8 !important; + transition: all 0.3s ease; + transform-box: fill-box; + transform-origin: center; +} + +.darkmode:hover { + fill: #2563EB !important; + transform: scale(1.1); +} + +#daymode { + margin-right: 40px; +} + +/* Footer & Credits */ +.Credits { + margin-top: 10px; + text-align: center; + font-family: 'Inter', sans-serif; + font-size: 13px; + color: #64748B; + animation: fadeInUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) both; + animation-delay: 0.2s; +} + +.Credits p { + margin: 4px 0; +} + +.Credits a { + text-decoration: none; + color: #2563EB; + font-weight: 600; + transition: color 0.2s ease; +} + +.Credits a:hover { + color: #1d4ed8; +} + +.copyright { + font-size: 11px; + color: #94A3B8; +} + +/* Media Queries Responsif */ +.Mobile, +.Desktop { + visibility: hidden; + width: 100vw; + height: 100vh; +} + +@media only screen and (orientation: landscape) { + .Mobile { + visibility: hidden; + display: none; + } + + .Desktop { + visibility: visible; + display: block; + } +} + +@media only screen and (orientation: portrait) { + .app-card { + padding: 24px; + border-radius: 24px; + } + + .openSpeedtestApp { + width: 100%; + max-width: 320px; + aspect-ratio: 295.9 / 363.3; + } + + .Mobile { + visibility: visible; + display: block; + } + + .Desktop { + visibility: hidden; + display: none; + } +} + +@media only screen and (max-width: 360px) { + .Credits { + display: none; + } +} + +/* Animasi */ +@keyframes bounceDelay { + + 0%, + 80%, + 100% { + transform: scale(0); + opacity: 0.3; + } + + 40% { + transform: scale(1.0); + opacity: 1; + } +} + +@keyframes fadeInDown { + from { + opacity: 0; + transform: translateY(-20px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes scaleIn { + from { + opacity: 0; + transform: scale(0.96); + } + + to { + opacity: 1; + transform: scale(1); + } +} + +/* Tombol Refresh / Uji Lagi */ +.refresh-btn { + display: none; + /* Disembunyikan secara default */ + background: linear-gradient(135deg, #00F2FE 0%, #4FACFE 100%); + color: white; + border: none; + padding: 12px 28px; + font-family: 'Outfit', 'Inter', sans-serif; + font-size: 15px; + font-weight: 700; + border-radius: 50px; + cursor: pointer; + box-shadow: 0 8px 20px rgba(0, 242, 254, 0.25); + align-items: center; + gap: 10px; + z-index: 10; + margin-top: 10px; + margin-bottom: -6px; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + animation: fadeInUp 0.4s cubic-bezier(0.16, 1, 0.3, 1) both; +} + +.refresh-btn:hover { + transform: translateY(-2px); + box-shadow: 0 12px 28px rgba(0, 242, 254, 0.45); + filter: brightness(1.05); +} + +.refresh-btn:active { + transform: translateY(0); +} + +.refresh-btn svg { + transition: transform 0.4s ease; +} + +.refresh-btn:hover svg { + transform: rotate(180deg); +} \ No newline at end of file diff --git a/assets/css/darkmode.css b/assets/css/darkmode.css new file mode 100755 index 0000000..8172be8 --- /dev/null +++ b/assets/css/darkmode.css @@ -0,0 +1,133 @@ +/* darkmode.css - Style untuk Tema Gelap (Dark Mode) */ + +html, body { + background: radial-gradient(circle at 50% 50%, #0F172A 0%, #020617 100%) !important; +} + +/* Header */ +.header-text h1 { + color: #F8FAFC !important; +} + +.header-badge { + color: #38BDF8 !important; + background: rgba(56, 189, 248, 0.08) !important; + border-color: rgba(56, 189, 248, 0.15) !important; +} + +/* Card Utama */ +.app-card { + background: rgba(15, 23, 42, 0.45) !important; + border-color: rgba(255, 255, 255, 0.04) !important; + box-shadow: + 0 25px 50px -12px rgba(0, 0, 0, 0.5), + 0 0 100px rgba(0, 242, 254, 0.02), + inset 0 1px 0 rgba(255, 255, 255, 0.05) !important; +} + +.app-card:hover { + border-color: rgba(255, 255, 255, 0.08) !important; + box-shadow: + 0 35px 70px -15px rgba(0, 0, 0, 0.6), + 0 0 120px rgba(0, 242, 254, 0.03), + inset 0 1px 0 rgba(255, 255, 255, 0.08) !important; +} + +/* Elemen SVG dalam Mode Gelap */ +.Cards { + fill: rgba(30, 41, 59, 0.4) !important; + stroke: rgba(51, 65, 85, 0.4) !important; + stroke-width: 1.5px !important; +} + +.oDoLive-Speed { + fill: #F8FAFC !important; +} + +.oDoLive-Status { + fill: #E2E8F0 !important; +} + +.rtextnum { + fill: #F8FAFC !important; +} + +.rtext { + fill: #94A3B8 !important; +} + +.rtextmbms { + fill: #64748B !important; +} + +.oDo-Meter { + fill: #64748B !important; +} + +.oDoTop-Speed { + fill: #64748B !important; +} + +.main-Gaugebg { + stroke: rgba(30, 41, 59, 0.8) !important; +} + +.deskStart { + stroke: rgba(30, 41, 59, 0.8) !important; +} + +.progressbg { + stroke: rgba(30, 41, 59, 0.8) !important; +} + +.uiBg { + fill: #475569 !important; +} + +/* Penyesuaian Logo dalam Mode Gelap */ +svg [style*="fill: #4d4d4d"] { + fill: #F8FAFC !important; /* Warna Putih Slate untuk teks utama logo */ +} + +svg [style*="fill: #3da6ff"] { + fill: #38BDF8 !important; /* Neon Blue untuk aksen logo */ +} + +/* Tombol Mode Gelap */ +.darkmode { + fill: #64748B !important; +} + +.darkmode:hover { + fill: #38BDF8 !important; +} + +/* Footer & Credits */ +.Credits { + color: #64748B !important; +} + +.Credits a { + color: #38BDF8 !important; +} + +.Credits a:hover { + color: #7dd3fc !important; +} + +.copyright { + color: #475569 !important; +} + +.jitter-Mob { + fill: #94A3B8 !important; +} + +/* Dark Mode Overrides for Client IP Container */ +.client-ip-container { + color: #94A3B8 !important; +} + +.client-ip-container span#client-ip-text { + color: #38BDF8 !important; +} diff --git a/assets/fonts/roboto-v30-latin-500.eot b/assets/fonts/roboto-v30-latin-500.eot new file mode 100755 index 0000000..fec0361 Binary files /dev/null and b/assets/fonts/roboto-v30-latin-500.eot differ diff --git a/assets/fonts/roboto-v30-latin-500.svg b/assets/fonts/roboto-v30-latin-500.svg new file mode 100755 index 0000000..67eecf4 --- /dev/null +++ b/assets/fonts/roboto-v30-latin-500.svg @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/fonts/roboto-v30-latin-500.ttf b/assets/fonts/roboto-v30-latin-500.ttf new file mode 100755 index 0000000..4f515e2 Binary files /dev/null and b/assets/fonts/roboto-v30-latin-500.ttf differ diff --git a/assets/fonts/roboto-v30-latin-500.woff b/assets/fonts/roboto-v30-latin-500.woff new file mode 100755 index 0000000..d39bb52 Binary files /dev/null and b/assets/fonts/roboto-v30-latin-500.woff differ diff --git a/assets/fonts/roboto-v30-latin-500.woff2 b/assets/fonts/roboto-v30-latin-500.woff2 new file mode 100755 index 0000000..29342a8 Binary files /dev/null and b/assets/fonts/roboto-v30-latin-500.woff2 differ diff --git a/assets/fonts/roboto-v30-latin-regular.eot b/assets/fonts/roboto-v30-latin-regular.eot new file mode 100755 index 0000000..c244b08 Binary files /dev/null and b/assets/fonts/roboto-v30-latin-regular.eot differ diff --git a/assets/fonts/roboto-v30-latin-regular.svg b/assets/fonts/roboto-v30-latin-regular.svg new file mode 100755 index 0000000..627f5a3 --- /dev/null +++ b/assets/fonts/roboto-v30-latin-regular.svg @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/fonts/roboto-v30-latin-regular.ttf b/assets/fonts/roboto-v30-latin-regular.ttf new file mode 100755 index 0000000..d0e6325 Binary files /dev/null and b/assets/fonts/roboto-v30-latin-regular.ttf differ diff --git a/assets/fonts/roboto-v30-latin-regular.woff b/assets/fonts/roboto-v30-latin-regular.woff new file mode 100755 index 0000000..9eaa94f Binary files /dev/null and b/assets/fonts/roboto-v30-latin-regular.woff differ diff --git a/assets/fonts/roboto-v30-latin-regular.woff2 b/assets/fonts/roboto-v30-latin-regular.woff2 new file mode 100755 index 0000000..020729e Binary files /dev/null and b/assets/fonts/roboto-v30-latin-regular.woff2 differ diff --git a/assets/images/app.svg b/assets/images/app.svg new file mode 100755 index 0000000..b58f586 --- /dev/null +++ b/assets/images/app.svg @@ -0,0 +1,394 @@ + + + + + + + + + + + + + 0 + .5 + 1 + 10 + 100 + 500 + 1000+ + ... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DOWNLOAD + + + + + UPLOAD + + + + + + + + + + PING + + + + JITTER + + + --- + Mbps + + + --- + Mbps + + + -- + ms + + + -- + ms + + + + + + + + + -- + Jitter + -- + ms + + + + + + + + + + + + Start + + + + + + + + + + + + + + + + + + Network Error + + + SpeedTest by Megakreasitech™ + + + + + + + + + + + + + + + + + + + + + Megakreasitech Internal TestSpeed by OpenSpeedTest™ + + + + + + The download speed is how fast you can pull data from the server to you in the form of images, videos, text and more. Activities such as listening to music on Spotify, downloading large files or streaming videos on Netflix all require you to download data. + + + The upload speed is how fast you send data from you to others in the form of images, videos, text and more. Activities such as uploading to YouTube or Sending email, playing live games like PubG, Voice and Video calling a friend require fast upload speeds for you to send data to someone else’s server. + + + Ping "Round-trip time" is more or less well defined as the network delay from point A to B and back. This is the sum of all encoding, queueing, processing, decoding, and propagation delays in both directions. Essentially, it's the delay when A may be expecting an answer from B for a request that requires very little processing. A fast ping means a more responsive connection, especially in applications where timing is everything (like video games). Ping is measured in Milliseconds (ms). Jitter is simply the difference in Ping "Round-trip time" . In other words, jitter is measuring time difference in packet inter-arrival time. Jitter helps diagnose internet connection stability. The higher the jitter value, the worse the stability of the connection. + + + + + + + + + Download speed is measured in megabits per second (Mbps). + + + Upload speed is measured in megabits per second (Mbps). + + + + + Ping is measured in Milliseconds (ms). + + + Jitter is measured in Milliseconds (ms). + + + + + Shows you real-time network traffic graph for Upload! + + + Shows you real-time network traffic graph for Download! + + + Your download speed! + + + Your upload speed! + + + Your ping! + + + Your jitter! + + + + + + + + + + Download speed is measured in megabits per second (Mbps). + + + Upload speed is measured in megabits per second (Mbps). + + + + + Ping is measured in Milliseconds (ms). + + + Jitter is measured in Milliseconds (ms). + + + + + Shows you real-time network traffic graph for Upload! + + + Shows you real-time network traffic graph for Download! + + + Your download speed! + + + Your upload speed! + + + Your ping! + + + Your jitter! + + + + + Click here to Run a Speed Test! Or Press "Enter" + + + Options + + + + + + Megakreasitech Internal TestSpeed by OpenSpeedTest™ + + + + + + The download speed is how fast you can pull data from the server to you in the form of images, videos, text and more. Activities such as listening to music on Spotify, downloading large files or streaming videos on Netflix all require you to download data. + + + The upload speed is how fast you send data from you to others in the form of images, videos, text and more. Activities such as uploading to YouTube or Sending email, playing live games like PubG, Voice and Video calling a friend require fast upload speeds for you to send data to someone else’s server. + + + Ping "Round-trip time" is more or less well defined as the network delay from point A to B and back. This is the sum of all encoding, queueing, processing, decoding, and propagation delays in both directions. Essentially, it's the delay when A may be expecting an answer from B for a request that requires very little processing. A fast ping means a more responsive connection, especially in applications where timing is everything (like video games). Ping is measured in Milliseconds (ms). Jitter is simply the difference in Ping "Round-trip time" . In other words, jitter is measuring time difference in packet inter-arrival time. Jitter helps diagnose internet connection stability. The higher the jitter value, the worse the stability of the connection. + + + + + + + + + Download speed is measured in megabits per second (Mbps). + + + Upload speed is measured in megabits per second (Mbps). + + + Ping is measured in Milliseconds (ms). + + + + + + Shows you real-time network traffic graph for Download! + + + Upload speed is measured in megabits per second (Mbps). + + + Your ping! and Jitter + + + Your upload speed! + + + Your download speed! + + + + + + + + + Click here to run a speed! + + + Options + + + + + + + + + + + + + + diff --git a/assets/images/favicon.svg b/assets/images/favicon.svg new file mode 100755 index 0000000..58f4cee --- /dev/null +++ b/assets/images/favicon.svg @@ -0,0 +1,534 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/icons/android-chrome-192x192.png b/assets/images/icons/android-chrome-192x192.png new file mode 100755 index 0000000..df78b83 Binary files /dev/null and b/assets/images/icons/android-chrome-192x192.png differ diff --git a/assets/images/icons/android-chrome-512x512.png b/assets/images/icons/android-chrome-512x512.png new file mode 100755 index 0000000..559d3ea Binary files /dev/null and b/assets/images/icons/android-chrome-512x512.png differ diff --git a/assets/images/icons/apple-touch-icon.png b/assets/images/icons/apple-touch-icon.png new file mode 100755 index 0000000..14aec78 Binary files /dev/null and b/assets/images/icons/apple-touch-icon.png differ diff --git a/assets/images/icons/browserconfig.xml b/assets/images/icons/browserconfig.xml new file mode 100755 index 0000000..ef1658c --- /dev/null +++ b/assets/images/icons/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #ffc40d + + + diff --git a/assets/images/icons/favicon-16x16.png b/assets/images/icons/favicon-16x16.png new file mode 100755 index 0000000..0dd76a8 Binary files /dev/null and b/assets/images/icons/favicon-16x16.png differ diff --git a/assets/images/icons/favicon-32x32.png b/assets/images/icons/favicon-32x32.png new file mode 100755 index 0000000..e3ad751 Binary files /dev/null and b/assets/images/icons/favicon-32x32.png differ diff --git a/assets/images/icons/favicon.ico b/assets/images/icons/favicon.ico new file mode 100755 index 0000000..bebc152 Binary files /dev/null and b/assets/images/icons/favicon.ico differ diff --git a/assets/images/icons/launcher-icon-1x.png b/assets/images/icons/launcher-icon-1x.png new file mode 100755 index 0000000..50bdeae Binary files /dev/null and b/assets/images/icons/launcher-icon-1x.png differ diff --git a/assets/images/icons/launcher-icon-2x.png b/assets/images/icons/launcher-icon-2x.png new file mode 100755 index 0000000..9868799 Binary files /dev/null and b/assets/images/icons/launcher-icon-2x.png differ diff --git a/assets/images/icons/launcher-icon-3x.png b/assets/images/icons/launcher-icon-3x.png new file mode 100755 index 0000000..b612922 Binary files /dev/null and b/assets/images/icons/launcher-icon-3x.png differ diff --git a/assets/images/icons/launcher-icon-4x.png b/assets/images/icons/launcher-icon-4x.png new file mode 100755 index 0000000..5936c14 Binary files /dev/null and b/assets/images/icons/launcher-icon-4x.png differ diff --git a/assets/images/icons/mstile-150x150.png b/assets/images/icons/mstile-150x150.png new file mode 100755 index 0000000..eb66ae2 Binary files /dev/null and b/assets/images/icons/mstile-150x150.png differ diff --git a/assets/images/icons/safari-pinned-tab.svg b/assets/images/icons/safari-pinned-tab.svg new file mode 100755 index 0000000..e525e9b --- /dev/null +++ b/assets/images/icons/safari-pinned-tab.svg @@ -0,0 +1,108 @@ + + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + + + + + + diff --git a/assets/images/icons/site.webmanifest b/assets/images/icons/site.webmanifest new file mode 100755 index 0000000..058491f --- /dev/null +++ b/assets/images/icons/site.webmanifest @@ -0,0 +1,22 @@ +{ + "name": "OpenSpeedTest", + "short_name": "Speed Test", + "icons": [ + { + "src": "/assets/images/icons/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/assets/images/icons/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone", + "start_url": "/" + + +} diff --git a/assets/images/logoMKT.jpeg b/assets/images/logoMKT.jpeg new file mode 100755 index 0000000..e8f9d03 Binary files /dev/null and b/assets/images/logoMKT.jpeg differ diff --git a/assets/images/logoMKT.png b/assets/images/logoMKT.png new file mode 100755 index 0000000..8368358 Binary files /dev/null and b/assets/images/logoMKT.png differ diff --git a/assets/js/app-2.5.4.js b/assets/js/app-2.5.4.js new file mode 100755 index 0000000..2704ded --- /dev/null +++ b/assets/js/app-2.5.4.js @@ -0,0 +1,1421 @@ +/* + Official Website : https://OpenSpeedTest.COM | Email: support@openspeedtest.com + Developed by : Vishnu | https://Vishnu.Pro | Email : me@vishnu.pro + Like this Project? Please Donate NOW & Keep us Alive -> https://go.openspeedtest.com/Donate + Speed Test by OpenSpeedTest™️ is Free and Open-Source Software (FOSS) with MIT License. + Read full license terms @ http://go.openspeedtest.com/License + If you have any Questions, ideas or Comments Please Send it via -> https://go.openspeedtest.com/SendMessage +*/ +window.onload = function () { + var appSVG = document.getElementById("OpenSpeedTest-UI"); + appSVG.parentNode.replaceChild(appSVG.contentDocument.documentElement, appSVG); + ostOnload(); + OpenSpeedTest.Start(); +}; +(function (OpenSpeedTest) { + var Status; + var ProG; + var Callback = function (callback) { + if (callback && typeof callback === "function") { + callback(); + } + }; + function _(el) { + if (!(this instanceof _)) { + return new _(el); + } + this.el = document.getElementById(el); + } + _.prototype.fade = function fade(type, ms, callback00) { + var isIn = type === "in", opacity = isIn ? 0 : 1, interval = 14, duration = ms, gap = interval / duration, self = this; + if (isIn) { + self.el.style.display = "block"; + self.el.style.opacity = opacity; + } + function func() { + opacity = isIn ? opacity + gap : opacity - gap; + self.el.style.opacity = opacity; + if (opacity <= 0) { + self.el.style.display = "none"; + } + if (opacity <= 0 || opacity >= 1) { + window.clearInterval(fading, Callback(callback00)); + } + } + var fading = window.setInterval(func, interval); + }; + var easeOutQuint = function (t, b, c, d) { + t /= d; + t--; + return c * (t * t * t * t * t + 1) + b; + }; + var easeOutCubic = function (t, b, c, d) { + t /= d; + t--; + return c * (t * t * t + 1) + b; + }; + var openSpeedtestShow = function () { + this.YourIP = _("YourIP"); + this.ipDesk = _("ipDesk"); + this.ipMob = _("ipMob"); + this.downSymbolDesk = _("downSymbolDesk"); + this.upSymbolDesk = _("upSymbolDesk"); + this.upSymbolMob = _("upSymbolMob"); + this.downSymbolMob = _("downSymbolMob"); + this.settingsMob = _("settingsMob"); + this.settingsDesk = _("settingsDesk"); + this.oDoLiveStatus = _("oDoLiveStatus"); + this.ConnectErrorMob = _("ConnectErrorMob"); + this.ConnectErrorDesk = _("ConnectErrorDesk"); + this.downResult = _("downResult"); + this.upRestxt = _("upRestxt"); + this.pingResult = _("pingResult"); + this.jitterDesk = _("jitterDesk"); + this.pingMobres = _("pingMobres"); + this.JitterResultMon = _("JitterResultMon"); + this.JitterResultms = _("JitterResultms"); + this.UI_Desk = _("UI-Desk"); + this.UI_Mob = _("UI-Mob"); + this.oDoTopSpeed = _("oDoTopSpeed"); + this.startButtonMob = _("startButtonMob"); + this.startButtonDesk = _("startButtonDesk"); + this.intro_Desk = _("intro-Desk"); + this.intro_Mob = _("intro-Mob"); + this.loader = _("loading_app"); + this.OpenSpeedtest = _("OpenSpeedtest"); + this.mainGaugebg_Desk = _("mainGaugebg-Desk"); + this.mainGaugeBlue_Desk = _("mainGaugeBlue-Desk"); + this.mainGaugeWhite_Desk = _("mainGaugeWhite-Desk"); + this.mainGaugebg_Mob = _("mainGaugebg-Mob"); + this.mainGaugeBlue_Mob = _("mainGaugeBlue-Mob"); + this.mainGaugeWhite_Mob = _("mainGaugeWhite-Mob"); + this.oDoLiveSpeed = _("oDoLiveSpeed"); + this.progressStatus_Mob = _("progressStatus-Mob"); + this.progressStatus_Desk = _("progressStatus-Desk"); + this.graphc1 = _("graphc1"); + this.graphc2 = _("graphc2"); + this.graphMob2 = _("graphMob2"); + this.graphMob1 = _("graphMob1"); + this.text = _("text"); + this.scale = [{ degree: 680, value: 0 }, { degree: 570, value: 0.5 }, { degree: 460, value: 1 }, { degree: 337, value: 10 }, { degree: 220, value: 100 }, { degree: 115, value: 500 }, { degree: 0, value: 1000 },]; + this.element = ""; + this.chart = ""; + this.polygon = ""; + this.width = 200; + this.height = 50; + this.maxValue = 0; + this.values = []; + this.points = []; + this.vSteps = 5; + this.measurements = []; + this.points = []; + }; + openSpeedtestShow.prototype.reset = function () { + this.element = ""; + this.chart = ""; + this.polygon = ""; + this.width = 200; + this.height = 50; + this.maxValue = 0; + this.values = []; + this.points = []; + this.vSteps = 5; + this.measurements = []; + this.points = []; + }; + openSpeedtestShow.prototype.ip = function () { + var Self = this; + if (Self.ipDesk.el.style.display === "block") { + Self.ipDesk.el.style.display = "none"; + Self.ipMob.el.style.display = "none"; + } else { + Self.ipDesk.el.style.display = "block"; + Self.ipMob.el.style.display = "block"; + } + }; + openSpeedtestShow.prototype.prePing = function () { + this.loader.fade("out", 500); + this.OpenSpeedtest.fade("in", 1000); + }; + openSpeedtestShow.prototype.app = function () { + this.loader.fade("out", 500, this.ShowAppIntro()); + }; + openSpeedtestShow.prototype.ShowAppIntro = function () { + this.OpenSpeedtest.fade("in", 1000); + }; + openSpeedtestShow.prototype.userInterface = function () { + var Self = this; + this.intro_Desk.fade("out", 1000); + this.intro_Mob.fade("out", 1000, this.ShowUI()); + }; + openSpeedtestShow.prototype.ShowUI = function () { + this.UI_Desk.fade("in", 1000); + this.UI_Mob.fade("in", 1000, uiLoaded); + function uiLoaded(argument) { + Status = "Loaded"; + console.log("Update by MKTech. Email --\x3e [EMAIL_ADDRESS]"); + } + }; + openSpeedtestShow.prototype.Symbol = function (dir) { + if (dir == 0) { + this.downSymbolMob.el.style.display = "block"; + this.downSymbolDesk.el.style.display = "block"; + this.upSymbolMob.el.style.display = "none"; + this.upSymbolDesk.el.style.display = "none"; + } + if (dir == 1) { + this.downSymbolMob.el.style.display = "none"; + this.downSymbolDesk.el.style.display = "none"; + this.upSymbolMob.el.style.display = "block"; + this.upSymbolDesk.el.style.display = "block"; + } + if (dir == 2) { + this.downSymbolMob.el.style.display = "none"; + this.downSymbolDesk.el.style.display = "none"; + this.upSymbolMob.el.style.display = "none"; + this.upSymbolDesk.el.style.display = "none"; + } + }; + openSpeedtestShow.prototype.Graph = function (speed, select) { + if (!("remove" in Element.prototype)) { + Element.prototype.remove = function () { + if (this.parentNode) { + this.parentNode.removeChild(this); + } + }; + } + var Self = this; + var Remove; + if (select === 0) { + var Graphelement = this.graphc1.el; + Remove = "line"; + this.graphMob2.el.style.display = "none"; + this.graphMob1.el.style.display = "block"; + } else { + Graphelement = this.graphc2.el; + Remove = "line2"; + this.graphMob1.el.style.display = "none"; + this.graphMob2.el.style.display = "block"; + } + if (!isNaN(speed)) { + this.values.push(speed); + } else { + this.values.push(""); + } + function calcMeasure() { + for (x = 0; x < Self.vSteps; x++) { + var measurement = Math.ceil(Self.maxValue / Self.vSteps * (x + 1)); + Self.measurements.push(measurement); + } + Self.measurements.reverse(); + } + function createChart(element, values) { + calcMaxValue(); + calcPoints(); + calcMeasure(); + var removeLine = document.getElementsByClassName(Remove); + while (removeLine.length > 0) { + removeLine[0].remove(); + } + Self.polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); + Self.polygon.setAttribute("points", Self.points); + Self.polygon.setAttribute("class", Remove); + if (Self.values.length > 1) { + Graphelement.appendChild(Self.polygon); + } + } + function calcPoints() { + if (Self.values.length > 1) { + var points = "0," + Self.height + " "; + for (x = 0; x < Self.values.length; x++) { + var perc = Self.values[x] / Self.maxValue; + var steps = 130 / (Self.values.length - 1); + var point = (steps * x).toFixed(2) + "," + (Self.height - Self.height * perc).toFixed(2) + " "; + points += point; + } + points += "130," + Self.height; + Self.points = points; + } + } + var x; + function calcMaxValue() { + Self.maxValue = 0; + for (x = 0; x < Self.values.length; x++) { + if (Self.values[x] > Self.maxValue) { + Self.maxValue = Self.values[x]; + } + } + Self.maxValue = Math.ceil(Self.maxValue); + } + if (speed > 0) { + createChart(Graphelement, speed); + } + }; + openSpeedtestShow.prototype.progress = function (Switch, duration) { + var Self = this; + var Stop = duration; + var Stage = Switch; + var currTime = Date.now(); + var chan2 = 0 - 400; + var interval = setInterval(function () { + var timeNow = (Date.now() - currTime) / 1000; + var toLeft = easeOutCubic(timeNow, 400, 400, Stop); + var toRight = easeOutCubic(timeNow, 400, chan2, Stop); + if (Stage) { + Self.progressStatus_Desk.el.style.strokeDashoffset = toLeft; + Self.progressStatus_Mob.el.style.strokeDashoffset = toLeft; + } else { + Self.progressStatus_Desk.el.style.strokeDashoffset = toRight; + Self.progressStatus_Mob.el.style.strokeDashoffset = toRight; + } + if (timeNow >= Stop) { + clearInterval(interval); + ProG = "done"; + Self.progressStatus_Desk.el.style.strokeDashoffset = 800; + Self.progressStatus_Mob.el.style.strokeDashoffset = 800; + } + }, 14); + }; + openSpeedtestShow.prototype.mainGaugeProgress = function (currentSpeed) { + var Self = this; + var speed = currentSpeed; + if (speed < 0) { + speed = 0; + } + var mainGaugeOffset = Self.getNonlinearDegree(speed); + if (currentSpeed > 0) { + this.mainGaugeBlue_Desk.el.style.strokeOpacity = 1; + this.mainGaugeWhite_Desk.el.style.strokeOpacity = 1; + this.mainGaugeBlue_Mob.el.style.strokeOpacity = 1; + this.mainGaugeWhite_Mob.el.style.strokeOpacity = 1; + this.mainGaugeBlue_Desk.el.style.strokeDashoffset = mainGaugeOffset; + this.mainGaugeWhite_Desk.el.style.strokeDashoffset = mainGaugeOffset == 0 ? 1 : mainGaugeOffset + 1; + this.mainGaugeBlue_Mob.el.style.strokeDashoffset = mainGaugeOffset; + this.mainGaugeWhite_Mob.el.style.strokeDashoffset = mainGaugeOffset == 0 ? 1 : mainGaugeOffset + 1; + } + if (mainGaugeOffset == 0 && speed > 1000) { + this.mainGaugeBlue_Mob.el.style.strokeDashoffset = mainGaugeOffset >= 681 ? 681 : mainGaugeOffset; + this.mainGaugeWhite_Mob.el.style.strokeDashoffset = mainGaugeOffset == 0 ? 1 : mainGaugeOffset + 1; + this.mainGaugeWhite_Desk.el.style.strokeDashoffset = mainGaugeOffset == 0 ? 1 : mainGaugeOffset + 1; + this.mainGaugeBlue_Desk.el.style.strokeDashoffset = mainGaugeOffset >= 681 ? 681 : mainGaugeOffset; + } else if (mainGaugeOffset == 0 && speed <= 0) { + this.mainGaugeBlue_Mob.el.style.strokeDashoffset = 681.1; + this.mainGaugeWhite_Mob.el.style.strokeDashoffset = 0.1; + this.mainGaugeWhite_Desk.el.style.strokeDashoffset = 0.1; + this.mainGaugeBlue_Desk.el.style.strokeDashoffset = 681.1; + } + }; + openSpeedtestShow.prototype.showStatus = function (e) { + this.oDoLiveStatus.el.textContent = e; + }; + openSpeedtestShow.prototype.ConnectionError = function () { + this.ConnectErrorMob.el.style.display = "block"; + this.ConnectErrorDesk.el.style.display = "block"; + }; + openSpeedtestShow.prototype.uploadResult = function (upload) { + if (upload < 1) { + this.upRestxt.el.textContent = upload.toFixed(3); + } + if (upload >= 1 && upload < 9999) { + this.upRestxt.el.textContent = upload.toFixed(1); + } + if (upload >= 10000 && upload < 99999) { + this.upRestxt.el.textContent = upload.toFixed(1); + this.upRestxt.el.style.fontSize = "20px"; + } + if (upload >= 100000) { + this.upRestxt.el.textContent = upload.toFixed(1); + this.upRestxt.el.style.fontSize = "18px"; + } + }; + openSpeedtestShow.prototype.pingResults = function (data, Display) { + var ShowData = data; + if (Display === "Ping") { + if (ShowData >= 1 && ShowData < 10000) { + this.pingResult.el.textContent = Math.floor(ShowData); + this.pingMobres.el.textContent = Math.floor(ShowData); + } else if (ShowData >= 0 && ShowData < 1) { + if (ShowData == 0) { + ShowData = 0; + } + this.pingResult.el.textContent = ShowData; + this.pingMobres.el.textContent = ShowData; + } + } + if (Display === "Error") { + this.oDoLiveSpeed.el.textContent = ShowData; + } + }; + openSpeedtestShow.prototype.downloadResult = function (download) { + if (download < 1) { + this.downResult.el.textContent = download.toFixed(3); + } + if (download >= 1 && download < 9999) { + this.downResult.el.textContent = download.toFixed(1); + } + if (download >= 10000 && download < 99999) { + this.downResult.el.textContent = download.toFixed(1); + this.downResult.el.style.fontSize = "20px"; + } + if (download >= 100000) { + this.downResult.el.textContent = download.toFixed(1); + this.downResult.el.style.fontSize = "18px"; + } + }; + openSpeedtestShow.prototype.jitterResult = function (data, Display) { + var ShowData = data; + if (Display === "Jitter") { + if (ShowData >= 1 && ShowData < 10000) { + this.jitterDesk.el.textContent = Math.floor(ShowData); + if (ShowData >= 1 && ShowData < 100) { + this.JitterResultMon.el.textContent = Math.floor(ShowData); + } + if (ShowData >= 100) { + var kData = (ShowData / 1000).toFixed(1); + this.JitterResultMon.el.textContent = kData + "k"; + } + } else if (ShowData >= 0 && ShowData < 1) { + if (ShowData == 0) { + ShowData = 0; + } + this.jitterDesk.el.textContent = ShowData; + this.JitterResultMon.el.textContent = ShowData; + } + } + }; + openSpeedtestShow.prototype.LiveSpeed = function (data, Display) { + var ShowData = data; + if (Display === "countDown") { + var speed = ShowData.toFixed(0); + this.oDoLiveSpeed.el.textContent = speed; + return; + } + if (Display === "speedToZero") { + if (typeof ShowData == "number") { + ShowData = ShowData.toFixed(1); + } + if (ShowData <= 0) { + ShowData = 0; + } + this.oDoLiveSpeed.el.textContent = ShowData; + this.oDoTopSpeed.el.textContent = "1000+"; + this.oDoTopSpeed.el.style.fontSize = "16.9px"; + this.oDoTopSpeed.el.style.fill = "gray"; + return; + } + if (Display === "Ping") { + if (ShowData >= 1 && ShowData < 10000) { + this.oDoLiveSpeed.el.textContent = Math.floor(ShowData); + } else if (ShowData >= 0 && ShowData < 1) { + if (ShowData == 0) { + ShowData = 0; + } + this.oDoLiveSpeed.el.textContent = ShowData; + } + } else { + if (ShowData == 0) { + var speed = ShowData.toFixed(0); + this.oDoLiveSpeed.el.textContent = speed; + } + if (ShowData <= 1 && ShowData > 0) { + var speed = ShowData.toFixed(3); + this.oDoLiveSpeed.el.textContent = speed; + } + if (ShowData > 1) { + var speed = ShowData.toFixed(1); + this.oDoLiveSpeed.el.textContent = speed; + } + if (ShowData <= 1000) { + this.oDoTopSpeed.el.textContent = "1000+"; + this.oDoTopSpeed.el.style.fontSize = "16.9px"; + this.oDoTopSpeed.el.style.fill = "gray"; + } + if (ShowData >= 1010) { + this.oDoTopSpeed.el.textContent = Math.floor(ShowData / 1010) * 1000 + "+"; + this.oDoTopSpeed.el.style.fill = "gray"; + this.oDoTopSpeed.el.style.fontSize = "17.2px"; + } + } + }; + openSpeedtestShow.prototype.GaugeProgresstoZero = function (currentSpeed, status) { + var speed = currentSpeed; + var Self = this; + var duration = 3; + if (speed >= 0) { + var time = Date.now(); + var SpeedtoZero = 0 - speed; + var interval = setInterval(function () { + var timeNow = (Date.now() - time) / 1000; + var speedToZero = easeOutQuint(timeNow, speed, SpeedtoZero, duration); + Self.LiveSpeed(speedToZero, "speedToZero"); + Self.mainGaugeProgress(speedToZero); + if (timeNow >= duration || speedToZero <= 0) { + clearInterval(interval); + Self.LiveSpeed(0, "speedToZero"); + Self.mainGaugeProgress(0); + Status = status; + } + }, 16); + } + }; + openSpeedtestShow.prototype.getNonlinearDegree = function (mega_bps) { + var i = 0; + if (0 == mega_bps || mega_bps <= 0 || isNaN(mega_bps)) { + return 0; + } + while (i < this.scale.length) { + if (mega_bps > this.scale[i].value) { + i++; + } else { + return this.scale[i - 1].degree + (mega_bps - this.scale[i - 1].value) * (this.scale[i].degree - this.scale[i - 1].degree) / (this.scale[i].value - this.scale[i - 1].value); + } + } + return this.scale[this.scale.length - 1].degree; + }; + var openSpeedtestGet = function () { + this.OverAllTimeAvg = window.performance.now(); + this.SpeedSamples = []; + this.FinalSpeed; + }; + openSpeedtestGet.prototype.reset = function () { + this.OverAllTimeAvg = window.performance.now(); + this.SpeedSamples = []; + this.FinalSpeed = 0; + }; + openSpeedtestGet.prototype.ArraySum = function (Arr) { + var array = Arr; + if (array) { + var sum = array.reduce(function (A, B) { + if (typeof A === "number" && typeof B === "number") { + return A + B; + } + }, 0); + return sum; + } else { + return 0; + } + }; + openSpeedtestGet.prototype.AvgSpeed = function (Livespeed, Start, duration) { + var Self = this; + this.timeNow = (window.performance.now() - this.OverAllTimeAvg) / 1000; + this.FinalSpeed; + var StartRecoding = Start; + StartRecoding = duration - StartRecoding; + if (this.timeNow >= StartRecoding) { + if (Livespeed > 0) { + this.SpeedSamples.push(Livespeed); + } + Self.FinalSpeed = Self.ArraySum(Self.SpeedSamples) / Self.SpeedSamples.length; + } + return Self.FinalSpeed; + }; + openSpeedtestGet.prototype.uRandom = function (size, callback) { + var size = size; + var randomValue = new Uint32Array(262144); + function getRandom() { + var n = randomValue.length; + for (var i = 0; i < n; i++) { + randomValue[i] = Math.random() * 4294967296; + } + return randomValue; + } + var randomData = []; + var genData = function (dataSize) { + var dataSize = dataSize; + for (var i = 0; i < dataSize; i++) { + randomData[i] = getRandom(); + } + return randomData; + }; + return new Blob(genData(size), { type: "application/octet-stream" }, Callback(callback)); + }; + openSpeedtestGet.prototype.addEvt = function (o, e, f) { + o.addEventListener(e, f); + }; + openSpeedtestGet.prototype.remEvt = function (o, e, f) { + o.removeEventListener(e, f); + }; + var openSpeedtestEngine = function () { + var Get = new openSpeedtestGet(); + var Show = new openSpeedtestShow(); + Show.app(); + var SendData; + var myhostName = location.hostname; + var key; + var TestServerip; + var downloadSpeed; + var uploadSpeed; + var dataUsedfordl; + var dataUsedforul; + var pingEstimate; + var jitterEstimate; + var logData; + var return_data; + var ReQ = []; + var StartTime = []; + var CurrentTime = []; + var LiveSpeedArr; + var dLoaded = 0; + var uLoaded = 0; + var currentSpeed = 0; + var uploadTimeing; + var downloadTimeing; + var downloadTime; + var uploadTime; + var saveTestData; + var stop = 0; + function reSett() { + StartTime = 0; + CurrentTime = 0; + LiveSpeedArr = 0; + currentSpeed = 0; + } + var userAgentString; + if (window.navigator.userAgent) { + userAgentString = window.navigator.userAgent; + } else { + userAgentString = "Not Found"; + } + var ulFinal = ulDuration * 0.6; + var dlFinal = dlDuration * 0.6; + function setFinal() { + if (ulDuration * 0.6 >= 7) { + ulFinal = 7; + } + if (dlDuration * 0.6 >= 7) { + dlFinal = 7; + } + } + setFinal(); + var launch = true; + var init = true; + Get.addEvt(Show.settingsMob.el, "click", ShowIP); + Get.addEvt(Show.settingsDesk.el, "click", ShowIP); + Get.addEvt(Show.startButtonDesk.el, "click", runTasks); + Get.addEvt(Show.startButtonMob.el, "click", runTasks); + Get.addEvt(document, "keypress", hiEnter); + var addEvent = true; + var getParams = function (url) { + var params = {}; + var parser = document.createElement("a"); + parser.href = url; + var query = parser.search.substring(1); + var vars = query.split("&"); + for (var i = 0; i < vars.length; i++) { + var pair = vars[i].split("="); + params[pair[0]] = decodeURIComponent(pair[1]); + } + return params; + }; + var getCommand = getParams(window.location.href.toLowerCase()); + if (setPingSamples) { + if (typeof getCommand.ping === "string" || typeof getCommand.p === "string") { + var setPing; + if (typeof getCommand.ping !== "undefined") { + setPing = getCommand.ping; + } else if (typeof getCommand.p !== "undefined") { + setPing = getCommand.p; + } + if (setPing > 0) { + pingSamples = setPing; + pingSamples = setPing; + } + } + } + if (setPingTimeout) { + if (typeof getCommand.out === "string" || typeof getCommand.o === "string") { + var setOut; + if (typeof getCommand.out !== "undefined") { + setOut = getCommand.out; + } else if (typeof getCommand.o !== "undefined") { + setOut = getCommand.o; + } + if (setOut > 1) { + pingTimeOut = setOut; + pingTimeOut = setOut; + } + } + } + if (setHTTPReq) { + if (typeof getCommand.xhr === "string" || typeof getCommand.x === "string") { + var setThreads; + if (typeof getCommand.xhr !== "undefined") { + setThreads = getCommand.xhr; + } else if (typeof getCommand.x !== "undefined") { + setThreads = getCommand.x; + } + if (setThreads > 0 && setThreads <= 32) { + dlThreads = setThreads; + ulThreads = setThreads; + } + } + } + function isValidHttpUrl(str) { + var regex = /(?:https?):\/\/(\w+:?\w*)?(\S+)(:\d+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/; + if (!regex.test(str)) { + return false; + } else { + return true; + } + } + if (selectServer) { + if (typeof getCommand.host === "string" || typeof getCommand.h === "string") { + var severAddress; + if (typeof getCommand.host !== "undefined") { + severAddress = getCommand.host; + } else if (typeof getCommand.h !== "undefined") { + severAddress = getCommand.h; + } + if (isValidHttpUrl(severAddress)) { + openSpeedTestServerList = [{ ServerName: "Home", Download: severAddress + "/downloading", Upload: severAddress + "/upload", ServerIcon: "DefaultIcon", },]; + } + } + } + var custom = parseInt(getCommand.stress); + var customS = parseInt(getCommand.s); + var runStress; + var runStressCustom; + if (typeof getCommand.stress === "string") { + runStress = getCommand.stress; + runStressCustom = custom; + } else if (typeof getCommand.s === "string") { + runStress = getCommand.s; + runStressCustom = customS; + } + if (runStress && stressTest) { + if (runStress === "low" || runStress === "l") { + dlDuration = 300; + ulDuration = 300; + } + if (runStress === "medium" || runStress === "m") { + dlDuration = 600; + ulDuration = 600; + } + if (runStress === "high" || runStress === "h") { + dlDuration = 900; + ulDuration = 900; + } + if (runStress === "veryhigh" || runStress === "v") { + dlDuration = 1800; + ulDuration = 1800; + } + if (runStress === "extreme" || runStress === "e") { + dlDuration = 3600; + ulDuration = 3600; + } + if (runStress === "day" || runStress === "d") { + dlDuration = 86400; + ulDuration = 86400; + } + if (runStress === "year" || runStress === "y") { + dlDuration = 31557600; + ulDuration = 31557600; + } + if (custom > 12 || customS > 12) { + dlDuration = runStressCustom; + ulDuration = runStressCustom; + } + } + var overheadClean = parseInt(getCommand.clean); + var overheadCleanC = parseInt(getCommand.c); + var customOverHeadValue = 1; + if (overheadClean) { + customOverHeadValue = overheadClean; + } else if (overheadCleanC) { + customOverHeadValue = overheadCleanC; + } + if (enableClean) { + if (typeof getCommand.clean === "string" || typeof getCommand.c === "string") { + if (overheadClean >= 1 || overheadCleanC >= 1) { + if (overheadClean < 5 || overheadCleanC < 5) { + upAdjust = 1 + customOverHeadValue / 100; + dlAdjust = 1 + customOverHeadValue / 100; + } + } else { + upAdjust = 1; + dlAdjust = 1; + } + } + } + var OpenSpeedTestRun = parseInt(getCommand.run); + var OpenSpeedTestRunR = parseInt(getCommand.r); + var OpenSpeedTestStart; + if (enableRun) { + if (typeof getCommand.run === "string" || typeof getCommand.r === "string") { + if (OpenSpeedTestRun > 0) { + OpenSpeedTestStart = OpenSpeedTestRun; + } else if (OpenSpeedTestRunR > 0) { + OpenSpeedTestStart = OpenSpeedTestRunR; + } else { + OpenSpeedTestStart = 0; + } + } + } + if (OpenSpeedTestStart >= 0) { + if (launch) { + runTasks(); + } + } + var runTest = getCommand.test; + var runTestT = getCommand.t; + var SelectTest = false; + if (selectTest) { + if (typeof runTest === "string" || typeof runTestT === "string") { + var runTestC; + if (runTest) { + runTestC = runTest; + SelectTest = runTest; + } else if (runTestT) { + runTestC = runTestT; + SelectTest = runTestT; + } + if (runTestC === "download" || runTestC === "d") { + uploadSpeed = 0; + dataUsedforul = 0; + SelectTest = "Download"; + if (launch) { + runTasks(); + } + } else if (runTestC === "upload" || runTestC === "u") { + downloadSpeed = 0; + dataUsedfordl = 0; + SelectTest = "Upload"; + stop = 1; + if (launch) { + runTasks(); + } + } else if (runTestC === "ping" || runTestC === "p") { + uploadSpeed = 0; + dataUsedforul = 0; + downloadSpeed = 0; + dataUsedfordl = 0; + SelectTest = "Ping"; + if (launch) { + runTasks(); + } + } else { + SelectTest = false; + } + } + } + var Startit = 0; + function removeEvts() { + Get.remEvt(Show.settingsMob.el, "click", ShowIP); + Get.remEvt(Show.settingsDesk.el, "click", ShowIP); + Get.remEvt(Show.startButtonDesk.el, "click", runTasks); + Get.remEvt(Show.startButtonMob.el, "click", runTasks); + Get.remEvt(document, "keypress", hiEnter); + } + var requestIP = false; + function ShowIP() { + if (requestIP) { + Show.YourIP.el.textContent = "Please wait.."; + ServerConnect(7); + requestIP = false; + } + Show.ip(); + } + function runTasks() { + if (addEvent) { + removeEvts(); + addEvent = false; + } + if (OpenSpeedTestStart >= 0) { + launch = false; + Show.userInterface(); + init = false; + var AutoTme = Math.ceil(Math.abs(OpenSpeedTestStart)); + Show.showStatus("Automatic Test Starts in ..."); + var autoTest = setInterval(countDownF, 1000); + } + function countDownF() { + if (AutoTme >= 1) { + AutoTme = AutoTme - 1; + Show.LiveSpeed(AutoTme, "countDown"); + } else { + if (AutoTme <= 0) { + clearInterval(autoTest); + launch = true; + OpenSpeedTestStart = undefined; + runTasks(); + } + } + } + if (openSpeedTestServerList === "fetch" && launch === true) { + launch = false; + Show.showStatus("Fetching Server Info.."); + ServerConnect(6); + } + if (launch === true) { + if (SelectTest === "Ping") { + testRun(); + } else if (SelectTest === "Download") { + testRun(); + } else if (SelectTest === "Upload") { + testRun(); + } else if (SelectTest === false) { + testRun(); + } + } + } + var osttm = "\u2122"; + var myname = "OpenSpeedTest"; + var com = ".com"; + var ost = "Megakreasitech" + osttm; + function hiEnter(e) { + if (e.key === "Enter") { + runTasks(); + } + } + var showResult = 0; + if (openChannel === "web") { + showResult = webRe; + requestIP = true; + } + if (openChannel === "widget") { + showResult = widgetRe; + requestIP = true; + } + if (openChannel === "selfwidget") { + showResult = widgetRe; + TestServerip = domainx; + myhostName = TestServerip; + } + if (openChannel === "dev") { + } + function testRun() { + if (init) { + Show.userInterface(); + init = false; + } + OpenSpeedtest(); + } + function OpenSpeedtest() { + if (openChannel === "widget" || openChannel === "web") { + ServerConnect(1); + } + function readyToUP() { + uploadTime = window.performance.now(); + upReq(); + } + var Engine = setInterval(function () { + if (Status === "Loaded") { + Status = "busy"; + sendPing(0); + } + if (Status === "Ping") { + Status = "busy"; + Show.showStatus("Milliseconds"); + } + if (Status === "Download") { + Show.showStatus("Initializing.."); + Get.reset(); + reSett(); + Show.reset(); + downloadTime = window.performance.now(); + downReq(); + Status = "initDown"; + } + if (Status === "Downloading") { + Show.Symbol(0); + if (Startit == 0) { + Startit = 1; + Show.showStatus("Testing download speed.."); + var extraTime = (window.performance.now() - downloadTime) / 1000; + dReset = extraTime; + Show.progress(1, dlDuration + 2.5); + dlDuration += extraTime; + } + downloadTimeing = (window.performance.now() - downloadTime) / 1000; + reportCurrentSpeed("dl"); + Show.showStatus("Mbps download"); + Show.mainGaugeProgress(currentSpeed); + Show.LiveSpeed(currentSpeed); + Show.Graph(currentSpeed, 0); + downloadSpeed = Get.AvgSpeed(currentSpeed, dlFinal, dlDuration); + if (downloadTimeing >= dlDuration && ProG == "done") { + if (SelectTest) { + Show.GaugeProgresstoZero(currentSpeed, "SendR"); + Show.showStatus("All done"); + Show.Symbol(2); + } else { + Show.GaugeProgresstoZero(currentSpeed, "Upload"); + } + Show.downloadResult(downloadSpeed); + dataUsedfordl = dLoaded; + stop = 1; + Status = "busy"; + reSett(); + Get.reset(); + } + } + if (Status == "Upload") { + if (stop === 1) { + Show.Symbol(1); + Status = "initup"; + Show.showStatus("Initializing.."); + Show.LiveSpeed("...", "speedToZero"); + SendData = Get.uRandom(ulDataSize, readyToUP); + if (SelectTest) { + Startit = 1; + } + } + } + if (Status === "Uploading") { + if (Startit == 1) { + Startit = 2; + Show.showStatus("Testing upload speed.."); + currentSpeed = 0; + Get.reset(); + Show.reset(); + var extraUTime = (window.performance.now() - uploadTime) / 1000; + uReset = extraUTime; + Show.progress(false, ulDuration + 2.5); + ulDuration += extraUTime; + } + Show.showStatus("Mbps upload"); + uploadTimeing = (window.performance.now() - uploadTime) / 1000; + reportCurrentSpeed("up"); + Show.mainGaugeProgress(currentSpeed); + Show.LiveSpeed(currentSpeed); + Show.Graph(currentSpeed, 1); + uploadSpeed = Get.AvgSpeed(currentSpeed, ulFinal, ulDuration); + if (uploadTimeing >= ulDuration && stop == 1) { + dataUsedforul = uLoaded; + Show.uploadResult(uploadSpeed); + Show.GaugeProgresstoZero(currentSpeed, "SendR"); + SendData = undefined; + Show.showStatus("All done"); + Show.Symbol(2); + Status = "busy"; + stop = 0; + } + } + if (Status === "Error") { + Show.showStatus("Check your network connection status."); + Show.ConnectionError(); + Status = "busy"; + clearInterval(Engine); + var dummyElement = document.createElement("div"); + dummyElement.innerHTML = ''; + var htmlAnchorElement = dummyElement.querySelector("a"); + Show.oDoLiveSpeed.el.textContent = "Network Error"; + var circleSVG = document.getElementById("oDoLiveSpeed"); + htmlAnchorElement.innerHTML = circleSVG.innerHTML; + circleSVG.innerHTML = dummyElement.innerHTML; + } + if (Status === "SendR") { + Show.showStatus("All done"); + Show.oDoLiveSpeed.el.textContent = ost; + if (location.hostname != myname.toLowerCase() + com) { + saveTestData = "https://" + myname.toLowerCase() + com + "/results/show.php?" + "&d=" + downloadSpeed.toFixed(3) + "&u=" + uploadSpeed.toFixed(3) + "&p=" + pingEstimate + "&j=" + jitterEstimate + "&dd=" + (dataUsedfordl / 1048576).toFixed(3) + "&ud=" + (dataUsedforul / 1048576).toFixed(3) + "&ua=" + userAgentString; + saveTestData = encodeURI(saveTestData); + // var circleSVG2 = document.getElementById("resultsData"); + // circleSVG2.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", saveTestData); + // circleSVG2.setAttribute("target", "_blank"); + if (saveData) { + ServerConnect(5); + } + } else { + ServerConnect(3); + } + Status = "busy"; + clearInterval(Engine); + } + }, 100); + } + function downReq() { + for (var i = 0; i < dlThreads; i++) { + setTimeout(function (i) { + SendReQ(i); + }, dlDelay * i, i); + } + } + function upReq() { + for (var i = 0; i < ulThreads; i++) { + setTimeout(function (i) { + SendUpReq(i); + }, ulDelay * i, i); + } + } + var dLoad = 0; + var dDiff = 0; + var dTotal = 0; + var dtLoad = 0; + var dtDiff = 0; + var dtTotal = 0; + var dRest = 0; + var dReset; + var uReset; + var uLoad = 0; + var uDiff = 0; + var uTotal = 0; + var utLoad = 0; + var utDiff = 0; + var utTotal = 0; + var uRest = 0; + var dualReset; + var neXT = dlDuration * 1000 - 6000; + var dualupReset; + var neXTUp = ulDuration * 1000 - 6000; + function reportCurrentSpeed(now) { + if (now === "dl") { + var dTime = downloadTimeing * 1000; + if (dTime > dReset * 1000 + dlFinal / 2 * 1000 && dRest === 0) { + dRest = 1; + dtTotal = dtTotal * 0.01; + dTotal = dTotal * 0.01; + dualReset = dTime + 10000; + } + if (dTime >= dualReset && dualReset < neXT) { + dualReset += 10000; + dtTotal = dtTotal * 0.01; + dTotal = dTotal * 0.01; + } + dLoad = dLoaded <= 0 ? 0 : dLoaded - dDiff; + dDiff = dLoaded; + dTotal += dLoad; + dtLoad = dtDiff = 0 ? 0 : dTime - dtDiff; + dtDiff = dTime; + dtTotal += dtLoad; + if (dTotal > 0) { + LiveSpeedArr = dTotal / dtTotal / 125 * upAdjust; + currentSpeed = LiveSpeedArr; + } + } + if (now === "up") { + var Tym = uploadTimeing * 1000; + if (Tym > uReset * 1000 + ulFinal / 2 * 1000 && uRest === 0) { + uRest = 1; + utTotal = utTotal * 0.1; + uTotal = uTotal * 0.1; + dualupReset = Tym + 10000; + } + if (Tym >= dualupReset && dualupReset < neXTUp) { + dualupReset += 10000; + utTotal = utTotal * 0.1; + uTotal = uTotal * 0.1; + } + uLoad = uLoaded <= 0 ? 0 : uLoaded - uDiff; + uDiff = uLoaded; + uTotal += uLoad; + utLoad = utDiff = 0 ? 0 : Tym - utDiff; + utDiff = Tym; + utTotal += utLoad; + if (uTotal > 0) { + LiveSpeedArr = uTotal / utTotal / 125 * upAdjust; + currentSpeed = LiveSpeedArr; + } + } + } + function SendReQ(i) { + var lastLoaded = 0; + var OST = new XMLHttpRequest(); + ReQ[i] = OST; + ReQ[i].open("GET", fianlPingServer.Download + "?n=" + Math.random(), true); + ReQ[i].onprogress = function (e) { + if (stop === 1) { + ReQ[i].abort(); + ReQ[i] = null; + ReQ[i] = undefined; + delete ReQ[i]; + return false; + } + if (Status == "initDown") { + Status = "Downloading"; + } + var eLoaded = e.loaded <= 0 ? 0 : e.loaded - lastLoaded; + if (isNaN(eLoaded) || !isFinite(eLoaded) || eLoaded < 0) { + return false; + } + dLoaded += eLoaded; + lastLoaded = e.loaded; + }; + ReQ[i].onload = function (e) { + if (lastLoaded === 0) { + dLoaded += e.total; + } + if (Status == "initDown") { + Status = "Downloading"; + } + if (ReQ[i]) { + ReQ[i].abort(); + ReQ[i] = null; + ReQ[i] = undefined; + delete ReQ[i]; + } + if (stop === 0) { + SendReQ(i); + } + }; + ReQ[i].onerror = function (e) { + if (stop === 0) { + SendReQ(i); + } + }; + ReQ[i].responseType = "arraybuffer"; + ReQ[i].send(); + } + var uReQ = []; + function SendUpReq(i) { + var lastULoaded = 0; + var OST = new XMLHttpRequest(); + uReQ[i] = OST; + uReQ[i].open("POST", fianlPingServer.Upload + "?n=" + Math.random(), true); + uReQ[i].upload.onprogress = function (e) { + if (Status == "initup" && some === undefined) { + var some; + Status = "Uploading"; + } + if (uploadTimeing >= ulDuration) { + uReQ[i].abort(); + uReQ[i] = null; + uReQ[i] = undefined; + delete uReQ[i]; + return false; + } + var eLoaded = e.loaded <= 0 ? 0 : e.loaded - lastULoaded; + if (isNaN(eLoaded) || !isFinite(eLoaded) || eLoaded < 0) { + return false; + } + uLoaded += eLoaded; + lastULoaded = e.loaded; + }; + uReQ[i].onload = function () { + if (lastULoaded === 0) { + uLoaded += ulDataSize * 1048576; + if (uploadTimeing >= ulDuration) { + uReQ[i].abort(); + uReQ[i] = null; + uReQ[i] = undefined; + delete uReQ[i]; + return false; + } + } + if (Status == "initup" && some === undefined) { + var some; + Status = "Uploading"; + } + if (uReQ[i]) { + uReQ[i].abort(); + uReQ[i] = null; + uReQ[i] = undefined; + delete uReQ[i]; + } + if (stop === 1) { + SendUpReq(i); + } + }; + uReQ[i].onerror = function (e) { + if (uploadTimeing <= ulDuration) { + SendUpReq(i); + } + }; + uReQ[i].setRequestHeader("Content-Type", "application/octet-stream"); + if (i > 0 && uLoaded <= 17000) { + } else { + uReQ[i].send(SendData); + } + } + function sendPing() { + readServerList(); + } + var fianlPingServer; + var statusPing; + var statusPingFinal; + var statusJitter; + var statusJitterFinal; + var statusPingTest; + var pingSendStatus = -1; + var finalPing = []; + var pingServer = []; + var finalJitter = []; + var pingSendLength = openSpeedTestServerList.length; + function readServerList() { + pingSendLength = openSpeedTestServerList.length; + Status = "Ping"; + performance.clearResourceTimings(); + if (pingSendStatus < pingSendLength - 1) { + pingSendStatus++; + if (statusPingTest != "Stop") { + sendPingRequest(openSpeedTestServerList[pingSendStatus], readServerList); + } + } else { + if (pingServer.length >= 1) { + var finalLeastPingResult = Math.min.apply(Math, finalPing); + var finalLeastPingResultIndex = finalPing.indexOf(finalLeastPingResult); + fianlPingServer = pingServer[finalLeastPingResultIndex]; + statusPingFinal = finalLeastPingResult; + statusJitterFinal = finalJitter[finalLeastPingResultIndex]; + statusPingTest = "Busy"; + Show.LiveSpeed(statusPingFinal, "Ping"); + Show.pingResults(statusPingFinal, "Ping"); + Show.jitterResult(statusJitterFinal, "Jitter"); + pingEstimate = statusPingFinal; + jitterEstimate = statusJitterFinal; + if (SelectTest) { + if (SelectTest == "Ping") { + Status = "SendR"; + } else { + Status = SelectTest; + } + } else { + Status = "Download"; + } + } else { + if (pingServer.Download) { + } else { + Status = "Error"; + } + } + } + } + function sendPingRequest(serverListElm, callback) { + var pingSamplesSend = 0; + var pingResult = []; + var jitterResult = []; + function sendNewPingReq() { + if (pingSamplesSend < pingSamples) { + pingSamplesSend++; + if (statusPingTest != "Stop") { + PingRequest(); + } + } else { + if (pingResult.length > 1) { + jitterResult.sort(function (a, b) { + return a - b; + }); + jitterResult = jitterResult.slice(0, jitterResult.length * jitterFinalSample); + jitterResult = jitterResult.reduce(function (acc, val) { + return acc + val; + }, 0) / jitterResult.length; + var leastJitter = jitterResult.toFixed(1); + var leastPing = Math.min.apply(Math, pingResult); + finalPing.push(leastPing); + pingServer.push(serverListElm); + finalJitter.push(leastJitter); + if (typeof callback === "function") { + callback(); + } + } else { + if (typeof callback === "function") { + callback(); + } + } + } + } + function PingRequest() { + var OST = new XMLHttpRequest(); + var ReQ = OST; + if (statusPingTest != "Stop") { + ReQ.abort(); + } + ReQ.open(pingMethod, serverListElm[pingFile] + "?n=" + Math.random(), true); + ReQ.timeout = pingTimeOut; + var startTime = window.performance.now(); + ReQ.send(); + ReQ.onload = function () { + if (this.status === 200 && this.readyState === 4) { + var endTime = Math.floor(window.performance.now() - startTime); + var perfNum = performance.getEntries(); + perfNum = perfNum[perfNum.length - 1]; + var perfPing; + if (perfNum.initiatorType === "xmlhttprequest") { + perfPing = parseFloat(perfNum.duration.toFixed(1)); + } else { + perfPing = endTime; + } + if (pingSamplesSend > 250) { + perfPing = endTime; + } + if (perfPing <= 0) { + statusPing = 0.1; + pingResult.push(0.1); + } else { + statusPing = perfPing; + pingResult.push(perfPing); + } + if (pingResult.length > 1) { + var jitterCalc = Math.abs(pingResult[pingResult.length - 1] - pingResult[pingResult.length - 2]).toFixed(1); + jitterResult.push(parseFloat(jitterCalc)); + statusJitter = jitterCalc; + Show.LiveSpeed(perfPing, "Ping"); + Show.pingResults(perfPing, "Ping"); + Show.jitterResult(jitterCalc, "Jitter"); + } + sendNewPingReq(); + } + if (this.status === 404 && this.readyState === 4) { + pingSamplesSend++; + sendNewPingReq(); + } + }; + ReQ.onerror = function (e) { + pingSamplesSend++; + sendNewPingReq(); + }; + ReQ.ontimeout = function (e) { + pingSamplesSend++; + sendNewPingReq(); + }; + } + PingRequest(); + } + var ServerConnect = function (auth) { + var Self = this; + var xhr = new XMLHttpRequest(); + var url = OpenSpeedTestdb; + if (auth == 1) { + url = webIP; + } + if (auth == 5) { + url = saveDataURL; + } + if (auth == 7) { + url = get_IP; + } + xhr.open("POST", url, true); + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + xhr.onreadystatechange = function () { + if (xhr.readyState == 4 && xhr.status == 200) { + return_data = xhr.responseText.trim(); + if (auth == 2) { + key = return_data; + } + if (auth == 1) { + TestServerip = return_data; + } + if (auth == 3) { + setTimeout(function () { + location.href = showResult + return_data; + }, 1500); + } + if (auth == 6) { + openSpeedTestServerList = JSON.parse(return_data); + launch = true; + runTasks(); + } + if (auth == 7) { + Show.YourIP.el.textContent = return_data; + } + } + }; + if (auth == 2) { + logData = "r=n"; + } + if (auth == 3) { + logData = "r=l" + "&d=" + downloadSpeed + "&u=" + uploadSpeed + "&dd=" + dataUsedfordl / 1048576 + "&ud=" + dataUsedforul / 1048576 + "&p=" + pingEstimate + "&do=" + myhostName + "&S=" + key + "&sip=" + TestServerip + "&jit=" + jitterEstimate + "&ua=" + userAgentString; + } + if (auth == 5) { + logData = saveTestData; + } + if (auth == 6) { + logData = "r=s"; + } + xhr.send(logData); + }; + }; + OpenSpeedTest.Start = function () { + new openSpeedtestEngine(); + }; +})(window.OpenSpeedTest = window.OpenSpeedTest || {}); diff --git a/assets/js/app-2.5.4.min.js b/assets/js/app-2.5.4.min.js new file mode 100755 index 0000000..841d0bd --- /dev/null +++ b/assets/js/app-2.5.4.min.js @@ -0,0 +1,133 @@ +/* + Official Website : https://OpenSpeedTest.COM | Email: support@openspeedtest.com + Developed by : Vishnu | https://Vishnu.Pro | Email : me@vishnu.pro + Like this Project? Please Donate NOW & Keep us Alive -> https://go.openspeedtest.com/Donate + Speed Test by OpenSpeedTest™️ is Free and Open-Source Software (FOSS) with MIT License. + Read full license terms @ http://go.openspeedtest.com/License + If you have any Questions, ideas or Comments Please Send it via -> https://go.openspeedtest.com/SendMessage +*/ +window.onload = function () { var X = document.getElementById("OpenSpeedTest-UI"); X.parentNode.replaceChild(X.contentDocument.documentElement, X); ostOnload(); OpenSpeedTest.Start() }; +(function (X) { + function h(c) { if (!(this instanceof h)) return new h(c); this.el = document.getElementById(c) } var m, Ma, Na = function (c) { c && "function" === typeof c && c() }; h.prototype.fade = function (c, d, a) { var f = "in" === c, t = f ? 0 : 1, w = 14 / d, n = this; f && (n.el.style.display = "block", n.el.style.opacity = t); var q = window.setInterval(function () { t = f ? t + w : t - w; n.el.style.opacity = t; 0 >= t && (n.el.style.display = "none"); (0 >= t || 1 <= t) && window.clearInterval(q, Na(a)) }, 14) }; var Oa = function (c, d, a, f) { c /= f; c--; return a * (c * c * c + 1) + d }, r = function () { + this.YourIP = + h("YourIP"); this.ipDesk = h("ipDesk"); this.ipMob = h("ipMob"); this.downSymbolDesk = h("downSymbolDesk"); this.upSymbolDesk = h("upSymbolDesk"); this.upSymbolMob = h("upSymbolMob"); this.downSymbolMob = h("downSymbolMob"); this.settingsMob = h("settingsMob"); this.settingsDesk = h("settingsDesk"); this.oDoLiveStatus = h("oDoLiveStatus"); this.ConnectErrorMob = h("ConnectErrorMob"); this.ConnectErrorDesk = h("ConnectErrorDesk"); this.downResult = h("downResult"); this.upRestxt = h("upRestxt"); this.pingResult = h("pingResult"); this.jitterDesk = + h("jitterDesk"); this.pingMobres = h("pingMobres"); this.JitterResultMon = h("JitterResultMon"); this.JitterResultms = h("JitterResultms"); this.UI_Desk = h("UI-Desk"); this.UI_Mob = h("UI-Mob"); this.oDoTopSpeed = h("oDoTopSpeed"); this.startButtonMob = h("startButtonMob"); this.startButtonDesk = h("startButtonDesk"); this.intro_Desk = h("intro-Desk"); this.intro_Mob = h("intro-Mob"); this.loader = h("loading_app"); this.OpenSpeedtest = h("OpenSpeedtest"); this.mainGaugebg_Desk = h("mainGaugebg-Desk"); this.mainGaugeBlue_Desk = h("mainGaugeBlue-Desk"); + this.mainGaugeWhite_Desk = h("mainGaugeWhite-Desk"); this.mainGaugebg_Mob = h("mainGaugebg-Mob"); this.mainGaugeBlue_Mob = h("mainGaugeBlue-Mob"); this.mainGaugeWhite_Mob = h("mainGaugeWhite-Mob"); this.oDoLiveSpeed = h("oDoLiveSpeed"); this.progressStatus_Mob = h("progressStatus-Mob"); this.progressStatus_Desk = h("progressStatus-Desk"); this.graphc1 = h("graphc1"); this.graphc2 = h("graphc2"); this.graphMob2 = h("graphMob2"); this.graphMob1 = h("graphMob1"); this.text = h("text"); this.scale = [{ degree: 680, value: 0 }, { degree: 570, value: .5 }, + { degree: 460, value: 1 }, { degree: 337, value: 10 }, { degree: 220, value: 100 }, { degree: 115, value: 500 }, { degree: 0, value: 1E3 }]; this.polygon = this.chart = this.element = ""; this.width = 200; this.height = 50; this.maxValue = 0; this.values = []; this.points = []; this.vSteps = 5; this.measurements = []; this.points = [] + }; r.prototype.reset = function () { this.polygon = this.chart = this.element = ""; this.width = 200; this.height = 50; this.maxValue = 0; this.values = []; this.points = []; this.vSteps = 5; this.measurements = []; this.points = [] }; r.prototype.ip = function () { + "block" === + this.ipDesk.el.style.display ? (this.ipDesk.el.style.display = "none", this.ipMob.el.style.display = "none") : (this.ipDesk.el.style.display = "block", this.ipMob.el.style.display = "block") + }; r.prototype.prePing = function () { this.loader.fade("out", 500); this.OpenSpeedtest.fade("in", 1E3) }; r.prototype.app = function () { this.loader.fade("out", 500, this.ShowAppIntro()) }; r.prototype.ShowAppIntro = function () { this.OpenSpeedtest.fade("in", 1E3) }; r.prototype.userInterface = function () { + this.intro_Desk.fade("out", 1E3); this.intro_Mob.fade("out", + 1E3, this.ShowUI()) + }; r.prototype.ShowUI = function () { this.UI_Desk.fade("in", 1E3); this.UI_Mob.fade("in", 1E3, function (c) { m = "Loaded"; console.log("Developed by Vishnu. Email --\x3e me@vishnu.pro") }) }; r.prototype.Symbol = function (c) { + 0 == c && (this.downSymbolMob.el.style.display = "block", this.downSymbolDesk.el.style.display = "block", this.upSymbolMob.el.style.display = "none", this.upSymbolDesk.el.style.display = "none"); 1 == c && (this.downSymbolMob.el.style.display = "none", this.downSymbolDesk.el.style.display = "none", this.upSymbolMob.el.style.display = + "block", this.upSymbolDesk.el.style.display = "block"); 2 == c && (this.downSymbolMob.el.style.display = "none", this.downSymbolDesk.el.style.display = "none", this.upSymbolMob.el.style.display = "none", this.upSymbolDesk.el.style.display = "none") + }; r.prototype.Graph = function (c, d) { + function a(q, M) { + for (n = f.maxValue = 0; n < f.values.length; n++)f.values[n] > f.maxValue && (f.maxValue = f.values[n]); f.maxValue = Math.ceil(f.maxValue); if (1 < f.values.length) { + var F = "0," + f.height + " "; for (n = 0; n < f.values.length; n++) { + var Q = f.values[n] / f.maxValue; + Q = (130 / (f.values.length - 1) * n).toFixed(2) + "," + (f.height - f.height * Q).toFixed(2) + " "; F += Q + } F += "130," + f.height; f.points = F + } for (n = 0; n < f.vSteps; n++)f.measurements.push(Math.ceil(f.maxValue / f.vSteps * (n + 1))); f.measurements.reverse(); for (F = document.getElementsByClassName(w); 0 < F.length;)F[0].remove(); f.polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); f.polygon.setAttribute("points", f.points); f.polygon.setAttribute("class", w); 1 < f.values.length && t.appendChild(f.polygon) + } "remove" in Element.prototype || + (Element.prototype.remove = function () { this.parentNode && this.parentNode.removeChild(this) }); var f = this; if (0 === d) { var t = this.graphc1.el; var w = "line"; this.graphMob2.el.style.display = "none"; this.graphMob1.el.style.display = "block" } else t = this.graphc2.el, w = "line2", this.graphMob1.el.style.display = "none", this.graphMob2.el.style.display = "block"; isNaN(c) ? this.values.push("") : this.values.push(c); var n; 0 < c && a(t, c) + }; r.prototype.progress = function (c, d) { + var a = this, f = Date.now(), t = setInterval(function () { + var w = (Date.now() - + f) / 1E3, n = Oa(w, 400, 400, d), q = Oa(w, 400, -400, d); c ? (a.progressStatus_Desk.el.style.strokeDashoffset = n, a.progressStatus_Mob.el.style.strokeDashoffset = n) : (a.progressStatus_Desk.el.style.strokeDashoffset = q, a.progressStatus_Mob.el.style.strokeDashoffset = q); w >= d && (clearInterval(t), Ma = "done", a.progressStatus_Desk.el.style.strokeDashoffset = 800, a.progressStatus_Mob.el.style.strokeDashoffset = 800) + }, 14) + }; r.prototype.mainGaugeProgress = function (c) { + var d = c; 0 > d && (d = 0); var a = this.getNonlinearDegree(d); 0 < c && (this.mainGaugeBlue_Desk.el.style.strokeOpacity = + 1, this.mainGaugeWhite_Desk.el.style.strokeOpacity = 1, this.mainGaugeBlue_Mob.el.style.strokeOpacity = 1, this.mainGaugeWhite_Mob.el.style.strokeOpacity = 1, this.mainGaugeBlue_Desk.el.style.strokeDashoffset = a, this.mainGaugeWhite_Desk.el.style.strokeDashoffset = 0 == a ? 1 : a + 1, this.mainGaugeBlue_Mob.el.style.strokeDashoffset = a, this.mainGaugeWhite_Mob.el.style.strokeDashoffset = 0 == a ? 1 : a + 1); 0 == a && 1E3 < d ? (this.mainGaugeBlue_Mob.el.style.strokeDashoffset = 681 <= a ? 681 : a, this.mainGaugeWhite_Mob.el.style.strokeDashoffset = + 0 == a ? 1 : a + 1, this.mainGaugeWhite_Desk.el.style.strokeDashoffset = 0 == a ? 1 : a + 1, this.mainGaugeBlue_Desk.el.style.strokeDashoffset = 681 <= a ? 681 : a) : 0 == a && 0 >= d && (this.mainGaugeBlue_Mob.el.style.strokeDashoffset = 681.1, this.mainGaugeWhite_Mob.el.style.strokeDashoffset = .1, this.mainGaugeWhite_Desk.el.style.strokeDashoffset = .1, this.mainGaugeBlue_Desk.el.style.strokeDashoffset = 681.1) + }; r.prototype.showStatus = function (c) { this.oDoLiveStatus.el.textContent = c }; r.prototype.ConnectionError = function () { + this.ConnectErrorMob.el.style.display = + "block"; this.ConnectErrorDesk.el.style.display = "block" + }; r.prototype.uploadResult = function (c) { 1 > c && (this.upRestxt.el.textContent = c.toFixed(3)); 1 <= c && 9999 > c && (this.upRestxt.el.textContent = c.toFixed(1)); 1E4 <= c && 99999 > c && (this.upRestxt.el.textContent = c.toFixed(1), this.upRestxt.el.style.fontSize = "20px"); 1E5 <= c && (this.upRestxt.el.textContent = c.toFixed(1), this.upRestxt.el.style.fontSize = "18px") }; r.prototype.pingResults = function (c, d) { + var a = c; "Ping" === d && (1 <= a && 1E4 > a ? (this.pingResult.el.textContent = Math.floor(a), + this.pingMobres.el.textContent = Math.floor(a)) : 0 <= a && 1 > a && (0 == a && (a = 0), this.pingResult.el.textContent = a, this.pingMobres.el.textContent = a)); "Error" === d && (this.oDoLiveSpeed.el.textContent = a) + }; r.prototype.downloadResult = function (c) { + 1 > c && (this.downResult.el.textContent = c.toFixed(3)); 1 <= c && 9999 > c && (this.downResult.el.textContent = c.toFixed(1)); 1E4 <= c && 99999 > c && (this.downResult.el.textContent = c.toFixed(1), this.downResult.el.style.fontSize = "20px"); 1E5 <= c && (this.downResult.el.textContent = c.toFixed(1), this.downResult.el.style.fontSize = + "18px") + }; r.prototype.jitterResult = function (c, d) { var a = c; "Jitter" === d && (1 <= a && 1E4 > a ? (this.jitterDesk.el.textContent = Math.floor(a), 1 <= a && 100 > a && (this.JitterResultMon.el.textContent = Math.floor(a)), 100 <= a && (a = (a / 1E3).toFixed(1), this.JitterResultMon.el.textContent = a + "k")) : 0 <= a && 1 > a && (0 == a && (a = 0), this.jitterDesk.el.textContent = a, this.JitterResultMon.el.textContent = a)) }; r.prototype.LiveSpeed = function (c, d) { + var a = c; if ("countDown" === d) { var f = a.toFixed(0); this.oDoLiveSpeed.el.textContent = f } else "speedToZero" === + d ? ("number" == typeof a && (a = a.toFixed(1)), 0 >= a && (a = 0), this.oDoLiveSpeed.el.textContent = a, this.oDoTopSpeed.el.textContent = "1000+", this.oDoTopSpeed.el.style.fontSize = "16.9px", this.oDoTopSpeed.el.style.fill = "gray") : "Ping" === d ? 1 <= a && 1E4 > a ? this.oDoLiveSpeed.el.textContent = Math.floor(a) : 0 <= a && 1 > a && (0 == a && (a = 0), this.oDoLiveSpeed.el.textContent = a) : (0 == a && (f = a.toFixed(0), this.oDoLiveSpeed.el.textContent = f), 1 >= a && 0 < a && (f = a.toFixed(3), this.oDoLiveSpeed.el.textContent = f), 1 < a && (f = a.toFixed(1), this.oDoLiveSpeed.el.textContent = + f), 1E3 >= a && (this.oDoTopSpeed.el.textContent = "1000+", this.oDoTopSpeed.el.style.fontSize = "16.9px", this.oDoTopSpeed.el.style.fill = "gray"), 1010 <= a && (this.oDoTopSpeed.el.textContent = 1E3 * Math.floor(a / 1010) + "+", this.oDoTopSpeed.el.style.fill = "gray", this.oDoTopSpeed.el.style.fontSize = "17.2px")) + }; r.prototype.GaugeProgresstoZero = function (c, d) { + var a = this; if (0 <= c) var f = Date.now(), t = 0 - c, w = setInterval(function () { + var n = (Date.now() - f) / 1E3; var q = n / 3; q--; q = t * (q * q * q * q * q + 1) + c; a.LiveSpeed(q, "speedToZero"); a.mainGaugeProgress(q); + if (3 <= n || 0 >= q) clearInterval(w), a.LiveSpeed(0, "speedToZero"), a.mainGaugeProgress(0), m = d + }, 16) + }; r.prototype.getNonlinearDegree = function (c) { var d = 0; if (0 == c || 0 >= c || isNaN(c)) return 0; for (; d < this.scale.length;)if (c > this.scale[d].value) d++; else return this.scale[d - 1].degree + (c - this.scale[d - 1].value) * (this.scale[d].degree - this.scale[d - 1].degree) / (this.scale[d].value - this.scale[d - 1].value); return this.scale[this.scale.length - 1].degree }; var O = function () { + this.OverAllTimeAvg = window.performance.now(); this.SpeedSamples = + []; this.FinalSpeed + }; O.prototype.reset = function () { this.OverAllTimeAvg = window.performance.now(); this.SpeedSamples = []; this.FinalSpeed = 0 }; O.prototype.ArraySum = function (c) { return c ? c.reduce(function (d, a) { if ("number" === typeof d && "number" === typeof a) return d + a }, 0) : 0 }; O.prototype.AvgSpeed = function (c, d, a) { + this.timeNow = (window.performance.now() - this.OverAllTimeAvg) / 1E3; this.FinalSpeed; this.timeNow >= a - d && (0 < c && this.SpeedSamples.push(c), this.FinalSpeed = this.ArraySum(this.SpeedSamples) / this.SpeedSamples.length); + return this.FinalSpeed + }; O.prototype.uRandom = function (c, d) { for (var a = new Uint32Array(262144), f = [], t = Blob, w = 0; w < c; w++) { for (var n = w, q = a.length, M = 0; M < q; M++)a[M] = 4294967296 * Math.random(); f[n] = a } return new t(f, { type: "application/octet-stream" }, Na(d)) }; O.prototype.addEvt = function (c, d, a) { c.addEventListener(d, a) }; O.prototype.remEvt = function (c, d, a) { c.removeEventListener(d, a) }; var jb = function () { + function c() { fa && (e.YourIP.el.textContent = "Please wait..", Y(7), fa = !1); e.ip() } function d() { + function b() { + 1 <= l ? (--l, e.LiveSpeed(l, + "countDown")) : 0 >= l && (clearInterval(g), G = !0, Z = void 0, d()) + } Pa && (x.remEvt(e.settingsMob.el, "click", c), x.remEvt(e.settingsDesk.el, "click", c), x.remEvt(e.startButtonDesk.el, "click", d), x.remEvt(e.startButtonMob.el, "click", d), x.remEvt(document, "keypress", a), Pa = !1); if (0 <= Z) { G = !1; e.userInterface(); ua = !1; var l = Math.ceil(Math.abs(Z)); e.showStatus("Automatic Test Starts in ..."); var g = setInterval(b, 1E3) } "fetch" === openSpeedTestServerList && !0 === G && (G = !1, e.showStatus("Fetching Server Info.."), Y(6)); !0 === G && ("Ping" === + A ? f() : "Download" === A ? f() : "Upload" === A ? f() : !1 === A && f()) + } function a(b) { "Enter" === b.key && d() } function f() { ua && (e.userInterface(), ua = !1); t() } function t() { + function b() { va = window.performance.now(); n() } "widget" !== openChannel && "web" !== openChannel || Y(1); var l = setInterval(function () { + "Loaded" === m && (m = "busy", Q()); "Ping" === m && (m = "busy", e.showStatus("Milliseconds")); "Download" === m && (e.showStatus("Initializing.."), x.reset(), y = ha = 0, e.reset(), wa = window.performance.now(), w(), m = "initDown"); if ("Downloading" === m) { + e.Symbol(0); + if (0 == aa) { aa = 1; e.showStatus("Testing download speed.."); var g = (window.performance.now() - wa) / 1E3; Qa = g; e.progress(1, dlDuration + 2.5); dlDuration += g } xa = (window.performance.now() - wa) / 1E3; q("dl"); e.showStatus("Mbps download"); e.mainGaugeProgress(y); e.LiveSpeed(y); e.Graph(y, 0); R = x.AvgSpeed(y, ya, dlDuration); xa >= dlDuration && "done" == Ma && (A ? (e.GaugeProgresstoZero(y, "SendR"), e.showStatus("All done"), e.Symbol(2)) : e.GaugeProgresstoZero(y, "Upload"), e.downloadResult(R), ia = S, I = 1, m = "busy", y = ha = 0, x.reset()) + } "Upload" == + m && 1 === I && (e.Symbol(1), m = "initup", e.showStatus("Initializing.."), e.LiveSpeed("...", "speedToZero"), za = x.uRandom(ulDataSize, b), A && (aa = 1)); "Uploading" === m && (1 == aa && (aa = 2, e.showStatus("Testing upload speed.."), y = 0, x.reset(), e.reset(), Ra = g = (window.performance.now() - va) / 1E3, e.progress(!1, ulDuration + 2.5), ulDuration += g), e.showStatus("Mbps upload"), T = (window.performance.now() - va) / 1E3, q("up"), e.mainGaugeProgress(y), e.LiveSpeed(y), e.Graph(y, 1), U = x.AvgSpeed(y, Aa, ulDuration), T >= ulDuration && 1 == I && (ja = P, e.uploadResult(U), + e.GaugeProgresstoZero(y, "SendR"), za = void 0, e.showStatus("All done"), e.Symbol(2), m = "busy", I = 0)); if ("Error" === m) { + e.showStatus("Check your network connection status."); e.ConnectionError(); m = "busy"; clearInterval(l); g = document.createElement("div"); g.innerHTML = ''; var u = g.querySelector("a"); e.oDoLiveSpeed.el.textContent = "Network Error"; var C = document.getElementById("oDoLiveSpeed"); u.innerHTML = C.innerHTML; + C.innerHTML = g.innerHTML + } "SendR" === m && (e.showStatus("All done"), g = document.createElement("div"), g.innerHTML = '', u = g.querySelector("a"), e.oDoLiveSpeed.el.textContent = fb, C = document.getElementById("oDoLiveSpeed"), u.innerHTML = C.innerHTML, C.innerHTML = g.innerHTML, location.hostname != Ba.toLowerCase() + Sa ? (ba = "https://" + Ba.toLowerCase() + Sa + "/results/show.php?&d=" + R.toFixed(3) + "&u=" + U.toFixed(3) + "&p=" + + Ca + "&j=" + Da + "&dd=" + (ia / 1048576).toFixed(3) + "&ud=" + (ja / 1048576).toFixed(3) + "&ua=" + Ta, ba = encodeURI(ba), g = document.getElementById("resultsData"),/*g.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",ba),g.setAttribute("target","_blank"),*/saveData && Y(5)) : Y(3), m = "busy", clearInterval(l)) + }, 100) + } function w() { for (var b = 0; b < dlThreads; b++)setTimeout(function (l) { M(l) }, dlDelay * b, b) } function n() { for (var b = 0; b < ulThreads; b++)setTimeout(function (l) { F(l) }, ulDelay * b, b) } function q(b) { + if ("dl" === b) { + var l = 1E3 * xa; + l > 1E3 * Qa + ya / 2 * 1E3 && 0 === Ua && (Ua = 1, ka *= .01, ca *= .01, la = l + 1E4); l >= la && la < gb && (la += 1E4, ka *= .01, ca *= .01); Va = 0 >= S ? 0 : S - Wa; Wa = S; ca += Va; Xa = Ea = l - Ea; Ea = l; ka += Xa; 0 < ca && (y = ha = ca / ka / 125 * upAdjust) + } "up" === b && (b = 1E3 * T, b > 1E3 * Ra + Aa / 2 * 1E3 && 0 === Ya && (Ya = 1, ma *= .1, da *= .1, na = b + 1E4), b >= na && na < hb && (na += 1E4, ma *= .1, da *= .1), Za = 0 >= P ? 0 : P - $a, $a = P, da += Za, ab = Fa = b - Fa, Fa = b, ma += ab, 0 < da && (y = ha = da / ma / 125 * upAdjust)) + } function M(b) { + var l = 0; z[b] = new XMLHttpRequest; z[b].open("GET", Ga.Download + "?n=" + Math.random(), !0); z[b].onprogress = function (g) { + if (1 === + I) return z[b].abort(), z[b] = null, z[b] = void 0, delete z[b], !1; "initDown" == m && (m = "Downloading"); var u = 0 >= g.loaded ? 0 : g.loaded - l; if (isNaN(u) || !isFinite(u) || 0 > u) return !1; S += u; l = g.loaded + }; z[b].onload = function (g) { 0 === l && (S += g.total); "initDown" == m && (m = "Downloading"); z[b] && (z[b].abort(), z[b] = null, z[b] = void 0, delete z[b]); 0 === I && M(b) }; z[b].onerror = function (g) { 0 === I && M(b) }; z[b].responseType = "arraybuffer"; z[b].send() + } function F(b) { + var l = 0; v[b] = new XMLHttpRequest; v[b].open("POST", Ga.Upload + "?n=" + Math.random(), !0); + v[b].upload.onprogress = function (g) { "initup" == m && void 0 === u && (m = "Uploading"); if (T >= ulDuration) return v[b].abort(), v[b] = null, v[b] = void 0, delete v[b], !1; var u = 0 >= g.loaded ? 0 : g.loaded - l; if (isNaN(u) || !isFinite(u) || 0 > u) return !1; P += u; l = g.loaded }; v[b].onload = function () { if (0 === l && (P += 1048576 * ulDataSize, T >= ulDuration)) return v[b].abort(), v[b] = null, v[b] = void 0, delete v[b], !1; if ("initup" == m && void 0 === g) { var g; m = "Uploading" } v[b] && (v[b].abort(), v[b] = null, v[b] = void 0, delete v[b]); 1 === I && F(b) }; v[b].onerror = function (g) { + T <= + ulDuration && F(b) + }; v[b].setRequestHeader("Content-Type", "application/octet-stream"); 0 < b && 17E3 >= P || v[b].send(za) + } function Q() { + bb = openSpeedTestServerList.length; m = "Ping"; performance.clearResourceTimings(); if (Ha < bb - 1) Ha++, "Stop" != oa && ib(openSpeedTestServerList[Ha], Q); else if (1 <= pa.length) { var b = Math.min.apply(Math, Ia), l = Ia.indexOf(b); Ga = pa[l]; qa = b; Ja = cb[l]; oa = "Busy"; e.LiveSpeed(qa, "Ping"); e.pingResults(qa, "Ping"); e.jitterResult(Ja, "Jitter"); Ca = qa; Da = Ja; m = A ? "Ping" == A ? "SendR" : A : "Download" } else pa.Download || + (m = "Error") + } function ib(b, l) { + function g() { if (C < pingSamples) C++, "Stop" != oa && u(); else { if (1 < J.length) { K.sort(function (D, B) { return D - B }); K = K.slice(0, K.length * jitterFinalSample); K = K.reduce(function (D, B) { return D + B }, 0) / K.length; var L = K.toFixed(1), Ka = Math.min.apply(Math, J); Ia.push(Ka); pa.push(b); cb.push(L) } "function" === typeof l && l() } } function u() { + var L = new XMLHttpRequest; "Stop" != oa && L.abort(); L.open(pingMethod, b[pingFile] + "?n=" + Math.random(), !0); L.timeout = pingTimeOut; var Ka = window.performance.now(); L.send(); + L.onload = function () { if (200 === this.status && 4 === this.readyState) { var D = Math.floor(window.performance.now() - Ka), B = performance.getEntries(); B = B[B.length - 1]; B = "xmlhttprequest" === B.initiatorType ? parseFloat(B.duration.toFixed(1)) : D; 250 < C && (B = D); 0 >= B ? J.push(.1) : J.push(B); 1 < J.length && (D = Math.abs(J[J.length - 1] - J[J.length - 2]).toFixed(1), K.push(parseFloat(D)), e.LiveSpeed(B, "Ping"), e.pingResults(B, "Ping"), e.jitterResult(D, "Jitter")); g() } 404 === this.status && 4 === this.readyState && (C++, g()) }; L.onerror = function (D) { + C++; + g() + }; L.ontimeout = function (D) { C++; g() } + } var C = 0, J = [], K = []; u() + } var x = new O, e = new r; e.app(); var za, db = location.hostname, eb, La, R, U, Ca, Da, ea, V, z = [], ha, S = 0, P = 0, y = 0, T, xa, wa, va, ba, I = 0; var Ta = window.navigator.userAgent ? window.navigator.userAgent : "Not Found"; var Aa = .6 * ulDuration, ya = .6 * dlDuration; 7 <= .6 * ulDuration && (Aa = 7); 7 <= .6 * dlDuration && (ya = 7); var G = !0, ua = !0; x.addEvt(e.settingsMob.el, "click", c); x.addEvt(e.settingsDesk.el, "click", c); x.addEvt(e.startButtonDesk.el, "click", d); x.addEvt(e.startButtonMob.el, "click", + d); x.addEvt(document, "keypress", a); var Pa = !0, k = function (b) { var l = {}, g = document.createElement("a"); g.href = b; b = g.search.substring(1).split("&"); for (g = 0; g < b.length; g++) { var u = b[g].split("="); l[u[0]] = decodeURIComponent(u[1]) } return l }(window.location.href.toLowerCase()); if (setPingSamples && ("string" === typeof k.ping || "string" === typeof k.p)) { if ("undefined" !== typeof k.ping) var E = k.ping; else "undefined" !== typeof k.p && (E = k.p); 0 < E && (pingSamples = pingSamples = E) } if (setPingTimeout && ("string" === typeof k.out || "string" === + typeof k.o)) { if ("undefined" !== typeof k.out) var W = k.out; else "undefined" !== typeof k.o && (W = k.o); 1 < W && (pingTimeOut = pingTimeOut = W) } if (setHTTPReq && ("string" === typeof k.xhr || "string" === typeof k.x)) { if ("undefined" !== typeof k.xhr) var ra = k.xhr; else "undefined" !== typeof k.x && (ra = k.x); 0 < ra && 32 >= ra && (ulThreads = dlThreads = ra) } if (selectServer && ("string" === typeof k.host || "string" === typeof k.h)) { + if ("undefined" !== typeof k.host) var sa = k.host; else "undefined" !== typeof k.h && (sa = k.h); /(?:https?):\/\/(\w+:?\w*)?(\S+)(:\d+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/.test(sa) && + (openSpeedTestServerList = [{ ServerName: "Home", Download: sa + "/downloading", Upload: sa + "/upload", ServerIcon: "DefaultIcon" }]) + } E = parseInt(k.stress); W = parseInt(k.s); if ("string" === typeof k.stress) { var p = k.stress; var H = E } else "string" === typeof k.s && (p = k.s, H = W); if (p && stressTest) { + if ("low" === p || "l" === p) ulDuration = dlDuration = 300; if ("medium" === p || "m" === p) ulDuration = dlDuration = 600; if ("high" === p || "h" === p) ulDuration = dlDuration = 900; if ("veryhigh" === p || "v" === p) ulDuration = dlDuration = 1800; if ("extreme" === p || "e" === p) ulDuration = + dlDuration = 3600; if ("day" === p || "d" === p) ulDuration = dlDuration = 86400; if ("year" === p || "y" === p) ulDuration = dlDuration = 31557600; if (12 < E || 12 < W) ulDuration = dlDuration = H + } p = parseInt(k.clean); H = parseInt(k.c); E = 1; p ? E = p : H && (E = H); if (enableClean && ("string" === typeof k.clean || "string" === typeof k.c)) if (1 <= p || 1 <= H) { if (5 > p || 5 > H) upAdjust = 1 + E / 100, dlAdjust = 1 + E / 100 } else dlAdjust = upAdjust = 1; p = parseInt(k.run); H = parseInt(k.r); var Z; !enableRun || "string" !== typeof k.run && "string" !== typeof k.r || (Z = 0 < p ? p : 0 < H ? H : 0); 0 <= Z && G && d(); p = k.test; + k = k.t; var A = !1; if (selectTest && ("string" === typeof p || "string" === typeof k)) { var N; p ? A = N = p : k && (A = N = k); if ("download" === N || "d" === N) { var ja = U = 0; A = "Download"; G && d() } else if ("upload" === N || "u" === N) { var ia = R = 0; A = "Upload"; I = 1; G && d() } else "ping" === N || "p" === N ? (ia = R = ja = U = 0, A = "Ping", G && d()) : A = !1 } var aa = 0, fa = !1, Ba = "OpenSpeedTest", Sa = ".com", fb = "Megakreasitech" + "\u2122", ta = 0; "web" === openChannel && (ta = webRe, fa = !0); "widget" === openChannel && (ta = widgetRe, fa = !0); "selfwidget" === openChannel && (ta = widgetRe, db = La = domainx); var Va = 0, Wa = 0, ca = 0, + Xa = 0, Ea = 0, ka = 0, Ua = 0, Qa, Ra, Za = 0, $a = 0, da = 0, ab = 0, Fa = 0, ma = 0, Ya = 0, la, gb = 1E3 * dlDuration - 6E3, na, hb = 1E3 * ulDuration - 6E3, v = [], Ga, qa, Ja, oa, Ha = -1, Ia = [], pa = [], cb = [], bb = openSpeedTestServerList.length, Y = function (b) { + var l = new XMLHttpRequest, g = OpenSpeedTestdb; 1 == b && (g = webIP); 5 == b && (g = saveDataURL); 7 == b && (g = get_IP); l.open("POST", g, !0); l.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); l.onreadystatechange = function () { + 4 == l.readyState && 200 == l.status && (V = l.responseText.trim(), 2 == b && (eb = V), 1 == b && (La = + V), 3 == b && setTimeout(function () { location.href = ta + V }, 1500), 6 == b && (openSpeedTestServerList = JSON.parse(V), G = !0, d()), 7 == b && (e.YourIP.el.textContent = V)) + }; 2 == b && (ea = "r=n"); 3 == b && (ea = "r=l&d=" + R + "&u=" + U + "&dd=" + ia / 1048576 + "&ud=" + ja / 1048576 + "&p=" + Ca + "&do=" + db + "&S=" + eb + "&sip=" + La + "&jit=" + Da + "&ua=" + Ta); 5 == b && (ea = ba); 6 == b && (ea = "r=s"); l.send(ea) + } + }; X.Start = function () { new jb } +})(window.OpenSpeedTest = window.OpenSpeedTest || {}); diff --git a/assets/js/darkmode.js b/assets/js/darkmode.js new file mode 100755 index 0000000..c3f56b3 --- /dev/null +++ b/assets/js/darkmode.js @@ -0,0 +1,6 @@ +var dayMode,nightMode,darkStyle;window.addEventListener("load",changeSkin); +function changeSkin(){dayModeMob=document.getElementById("daymode-Mob");nightModeMob=document.getElementById("nightmode-Mob");dayMode=document.getElementById("daymode");nightMode=document.getElementById("nightmode");""===getCookieValue("mode")&&(nightMode.style.display="none",nightModeMob.style.display="none",dayMode.style.display="inline-block",dayModeMob.style.display="inline-block");"dark"===getCookieValue("mode")&&setSkin("dark");"light"===getCookieValue("mode")&&setSkin("light");window.matchMedia&& +window.matchMedia("(prefers-color-scheme: dark)").matches&&""===getCookieValue("mode")&&setSkin("dark")} +function setSkin(a){"dark"===a&&(dayModeMob.style.display="none",nightModeMob.style.display="inline-block",dayMode.style.display="none",nightMode.style.display="inline-block",darkStyle=document.getElementById("darkmode"),null==darkStyle&&(document.head.innerHTML+='',createCookie("mode","dark")));"light"===a&&(nightModeMob.style.display="none",dayModeMob.style.display="inline-block",nightMode.style.display="none", +dayMode.style.display="inline-block",(darkStyle=document.getElementById("darkmode"))&&darkStyle.parentNode.removeChild(darkStyle),createCookie("mode","light"))}function toggleSkin(){(darkStyle=document.getElementById("darkmode"))?setSkin("light"):setSkin("dark")}function createCookie(a,c,b){if(b){var d=new Date;d.setTime(d.getTime()+864E5*b);b="; expires="+d.toGMTString()}else b="";document.cookie=a+"="+c+b+"; path=/"} +function getCookieValue(a,c){return(c=document.cookie.match("(^|;)\\s*"+a+"\\s*=\\s*([^;]+)"))?c.pop():""}; \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100755 index 0000000..6f53ac9 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,34 @@ +services: + speedtest: + build: + context: . + dockerfile: Dockerfile + image: speedtest-premium:latest + container_name: speedtest-mkt + ports: + - "8085:80" + restart: unless-stopped + environment: + TZ: Asia/Jakarta + #labels: + # - "traefik.enable=true" + # - "traefik.docker.network=traefik-net" + # Router + # - "traefik.http.routers.speedtest.rule=Host(`speedtest.monitoring.mkt.id`)" + # - "traefik.http.routers.speedtest.entrypoints=websecure" + # - "traefik.http.routers.speedtest.tls=true" + # - "traefik.http.routers.speedtest.service=speedtest" + # Service + # - "traefik.http.services.speedtest.loadbalancer.server.port=80" + healthcheck: + test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1/"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + networks: + - public-net + +networks: + public-net: + external: true diff --git a/hosted.html b/hosted.html new file mode 100755 index 0000000..ea51ac3 --- /dev/null +++ b/hosted.html @@ -0,0 +1,25 @@ + + + + + + + Speedtest by OpenSpeedtest.com + + + + +
+ Speed Test by OpenSpeedTest™ +
+ + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100755 index 0000000..a203e8c --- /dev/null +++ b/index.html @@ -0,0 +1,174 @@ + + + + + MKTECH | OpenSpeedTest™ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Logo +
+

Internal SPEEDTEST

+ Megakreasitech™ +
+
+ +
+
+
+
+
+
+ + + + +
+ Your IP Address : + Fetching... +
+
+ + + + +
+

+ SpeedTest by Megakreasitech™ +

+ +
+
+ + + + + + + \ No newline at end of file diff --git a/nginx.conf b/nginx.conf new file mode 100755 index 0000000..4f01374 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,62 @@ +server { + listen 80; + server_name localhost; + + # Direktori tempat file index.html dan assets berada + root /usr/share/nginx/html; + index index.html; + + # Mengaktifkan kompresi gzip untuk aset teks + gzip on; + gzip_types text/css application/javascript image/svg+xml; + + # Konfigurasi untuk uji Download + location = /downloading { + # Menonaktifkan pencatatan log untuk menghindari polusi berkas log + access_log off; + + # Konfigurasi CORS + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, HEAD' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, X-Requested-With' always; + + # Hindari penyimpanan cache agar pengukuran bandwidth akurat + add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, max-age=0' always; + + try_files /downloading =404; + } + + # Konfigurasi untuk mendapatkan IP client + location = /getIP { + access_log off; + default_type text/plain; + add_header 'Access-Control-Allow-Origin' '*' always; + return 200 $remote_addr; + } + + # Konfigurasi untuk uji Upload + location = /upload { + # Menonaktifkan pencatatan log + access_log off; + + # Konfigurasi CORS + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, HEAD' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, X-Requested-With' always; + + # Batasan ukuran payload upload (30MB+ untuk kebutuhan speedtest) + client_max_body_size 50m; + + # Selalu kembalikan 200 OK untuk metode POST (agar upload speedtest berhasil) + if ($request_method = POST) { + return 200; + } + + # Selalu kembalikan 200 OK untuk metode OPTIONS (Preflight request) + if ($request_method = OPTIONS) { + return 200; + } + + try_files /upload =200; + } +} diff --git a/server.js b/server.js new file mode 100755 index 0000000..eb9a09e --- /dev/null +++ b/server.js @@ -0,0 +1,168 @@ +const http = require('http'); +const fs = require('fs'); +const path = require('path'); +const url = require('url'); + +const PORT = 80; +const ROOT = '/app'; + +function corsHeaders(extra = {}) { + return { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, HEAD', + 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With', + ...extra + }; +} + +function sendFile(req, res, filePath, contentType) { + if (!fs.existsSync(filePath)) { + res.writeHead(404); + return res.end('Not Found'); + } + + const stat = fs.statSync(filePath); + + res.writeHead(200, { + ...corsHeaders(), + 'Content-Type': contentType, + 'Content-Length': stat.size, + 'Cache-Control': 'no-store, no-cache, must-revalidate, max-age=0' + }); + + if (req.method !== 'HEAD') { + fs.createReadStream(filePath).pipe(res); + } else { + res.end(); + } +} + +function contentType(file) { + const ext = path.extname(file).toLowerCase(); + + const types = { + '.html': 'text/html', + '.css': 'text/css', + '.js': 'application/javascript', + '.json': 'application/json', + '.svg': 'image/svg+xml', + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.gif': 'image/gif', + '.ico': 'image/x-icon', + '.woff': 'font/woff', + '.woff2': 'font/woff2' + }; + + return types[ext] || 'application/octet-stream'; +} + +const server = http.createServer((req, res) => { + const parsed = url.parse(req.url); + const pathname = parsed.pathname; + + // CORS preflight + if (req.method === 'OPTIONS') { + res.writeHead(200, corsHeaders()); + return res.end(); + } + + // Get client IP + if (pathname === '/getIP') { + const ip = + req.headers['x-forwarded-for']?.split(',')[0].trim() || + req.socket.remoteAddress || + ''; + + res.writeHead(200, { + ...corsHeaders(), + 'Content-Type': 'text/plain', + 'Cache-Control': 'no-store' + }); + + return res.end(ip); + } + + // Upload endpoint + if (pathname === '/upload') { + if (req.method !== 'POST') { + res.writeHead(200, corsHeaders()); + return res.end('OK'); + } + + let bytes = 0; + + req.on('data', chunk => { + bytes += chunk.length; + }); + + req.on('end', () => { + res.writeHead(200, { + ...corsHeaders(), + 'Content-Type': 'text/plain', + 'Cache-Control': 'no-store' + }); + + res.end('OK'); + }); + + req.on('error', () => { + if (!res.headersSent) { + res.writeHead(500, corsHeaders()); + } + res.end('ERROR'); + }); + + return; + } + + // Download endpoint + if (pathname === '/downloading') { + const file = path.join(ROOT, 'downloading'); + + if (!fs.existsSync(file)) { + res.writeHead(404); + return res.end('Not Found'); + } + + const stat = fs.statSync(file); + + res.writeHead(200, { + ...corsHeaders(), + 'Content-Type': 'application/octet-stream', + 'Content-Length': stat.size, + 'Cache-Control': 'no-store, no-cache, must-revalidate, max-age=0', + 'Content-Disposition': 'inline' + }); + + if (req.method !== 'HEAD') { + fs.createReadStream(file).pipe(res); + } else { + res.end(); + } + + return; + } + + // Static files + let requested = pathname === '/' ? '/index.html' : pathname; + const filePath = path.normalize(path.join(ROOT, requested)); + + // Prevent path traversal + if (!filePath.startsWith(ROOT)) { + res.writeHead(403); + return res.end('Forbidden'); + } + + if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile()) { + res.writeHead(404); + return res.end('Not Found'); + } + + sendFile(req, res, filePath, contentType(filePath)); +}); + +server.listen(PORT, '0.0.0.0', () => { + console.log(`Speedtest server listening on port ${PORT}`); +}); diff --git a/upload b/upload new file mode 100755 index 0000000..e69de29