@@ -7,23 +7,37 @@ import { overlayHTML } from "./components/overlay.js";
77const apiUrl = "https://api.henrikdev.xyz/valorant" ;
88let playerData ;
99
10+ const nicknameLocal = localStorage . getItem ( 'nickname' ) ;
11+ const tagLocal = localStorage . getItem ( 'tag' ) ;
12+ const apiKeyLocal = localStorage . getItem ( 'api_key' ) ;
13+
1014async function checkNickname ( name , hdevApiKey ) {
1115 const regex = / ^ [ \p{ L} \p{ N} \s ] { 1 , 16 } # [ \p{ L} \p{ N} ] { 1 , 5 } $ / u;
1216
13- if ( name . length === 0 ) {
14- alertText . innerHTML = "Please enter a nickname" ;
17+ if ( ! name ) {
18+ alertText . innerHTML = "Please enter a nickname. " ;
1519 return false ;
1620 }
1721
1822 if ( ! regex . test ( name ) ) {
19- alertText . innerHTML = "Incorrect nickname format." ;
23+ alertText . innerHTML = "Incorrect nickname format. Use the format: Name#Tag " ;
2024 return false ;
2125 }
2226
27+
2328 const [ nickname , tag ] = name . split ( "#" ) ;
2429
30+ if ( ! hdevApiKey ) {
31+ alertText . innerHTML = "API key is missing. Please provide a valid API key." ;
32+ return false ;
33+ }
34+
2535 const HDEV_key = hdevApiKey ;
2636
37+ await updateLocalStorage ( 'nickname' , nickname ) ;
38+ await updateLocalStorage ( 'tag' , tag ) ;
39+ await updateLocalStorage ( 'api_key' , HDEV_key ) ;
40+
2741 try {
2842 const response = await fetch (
2943 `https://api.henrikdev.xyz/valorant/v1/account/${ nickname } /${ tag } ?api_key=${ HDEV_key } ` ,
@@ -32,25 +46,33 @@ async function checkNickname(name, hdevApiKey) {
3246 alertText . innerHTML = `${ name } not found.` ;
3347 return false ;
3448 } else if ( response . status === 429 ) {
35- alertText . innerHTML = "Too many request! Try again later" ;
49+ alertText . innerHTML = "Too many requests! Please try again later." ;
50+ return false ;
51+ } else if ( ! response . ok ) {
52+ alertText . innerHTML = "An unexpected error occurred. Please try again." ;
3653 return false ;
3754 }
38- return response . ok ;
55+ return true ;
3956 } catch ( error ) {
40- alertText . innerHTML = "An error occurred. Please try again later." ;
57+ alertText . innerHTML = "An error occurred. Please check your connection and try again." ;
58+ console . error ( "Fetch error:" , error ) ;
4159 return false ;
4260 }
4361}
4462
63+ async function updateLocalStorage ( key , value ) {
64+ localStorage . setItem ( key , value ) ;
65+ }
66+
4567document . querySelector ( "#app" ) . innerHTML = `
4668 <div
4769 class="start"
4870 x-data="
4971 {
5072 modal: false,
5173 alert: false,
52- nickname: '',
53- hdevApiKey: '',
74+ nickname: '${ nicknameLocal + "#" + tagLocal } ' || ' ',
75+ hdevApiKey: '${ apiKeyLocal } ' || ' ',
5476 infoContainer: true,
5577 contentContainer: false,
5678 generateContainer: false,
@@ -105,8 +127,8 @@ document.querySelector("#app").innerHTML = `
105127 </div>
106128 </div>
107129 <div class="info__buttons">
108- <button @click="modal = true">How it work</button>
109- <button @click="infoContainer = false; contentContainer = true" class="fill">Create your Overlay</button>
130+ <button @click="modal = true">How it work? </button>
131+ <button @click="infoContainer = false; contentContainer = true" class="fill">Create your Overlay! </button>
110132 </div>
111133 </div>
112134 <div class="content" x-show="contentContainer" x-cloak x-transition:enter.duration.250ms.opacity.0>
@@ -115,63 +137,60 @@ document.querySelector("#app").innerHTML = `
115137 <p>
116138 Find your profile in Valorant to link it to your stream overlay.
117139 </p>
118- <div class="nickname_input">
119- <span>
120- <svg
121- xmlns="http://www.w3.org/2000/svg"
122- viewBox="0 0 24 24"
123- width="24"
124- height="24"
125- >
126- <path
127- stroke="white"
128- d="m2.2 4 .1.1c.2.3 11.8 14.8 12.8 16v.1a.1.1 0 0 1-.1.1H8.8a.52.52 0 0 1-.4-.2c-.2-.2-4.4-5.4-6.3-7.9A.31.31 0 0 0 2 12V4.1a.349.349 0 0 1 .2-.1Zm19.8.2c0-.1-.1-.1-.1-.2h-.1l-.2.2c-.9 1.1-8.1 10.1-8.3 10.3l-.1.1c0 .1 0 .1.1.1h6.2c.1 0 .2-.1.3-.2l.2-.2c.5-.7 1.7-2.2 1.8-2.3 0-.1 0-.1.1-.2v-.1c.1-2.4.1-4.9.1-7.5Z"
129- ></path>
130- </svg>
131- </span>
132- <input
133- @keyup.enter="if (await checkNickname(nickname, hdevApiKey)) { getPreview(); search = true; main();} else { alert = true; setTimeout(() => alert = false, 5000)}"
134- x-model="nickname"
135- class="nickname"
136- id="nickname_with_tag"
137- placeholder="NICKNAME#TAG"
138- autocomplete="off"
139- />
140- <button class="icons" @click="if (await checkNickname(nickname, hdevApiKey)) { getPreview(); search = true; main();} else { alert = true; setTimeout(() => alert = false, 5000)}">
141- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
142- <path d="M21 21L15.0001 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
143- </svg>
144- </button>
140+ <div style="display: flex; flex-direction: column; gap: 10px">
141+ <div class="nickname_input">
142+ <span>
143+ <svg
144+ xmlns="http://www.w3.org/2000/svg"
145+ viewBox="0 0 24 24"
146+ width="24"
147+ height="24"
148+ >
149+ <path
150+ stroke="white"
151+ d="m2.2 4 .1.1c.2.3 11.8 14.8 12.8 16v.1a.1.1 0 0 1-.1.1H8.8a.52.52 0 0 1-.4-.2c-.2-.2-4.4-5.4-6.3-7.9A.31.31 0 0 0 2 12V4.1a.349.349 0 0 1 .2-.1Zm19.8.2c0-.1-.1-.1-.1-.2h-.1l-.2.2c-.9 1.1-8.1 10.1-8.3 10.3l-.1.1c0 .1 0 .1.1.1h6.2c.1 0 .2-.1.3-.2l.2-.2c.5-.7 1.7-2.2 1.8-2.3 0-.1 0-.1.1-.2v-.1c.1-2.4.1-4.9.1-7.5Z"
152+ ></path>
153+ </svg>
154+ </span>
155+ <input
156+ @keyup.enter="if (await checkNickname(nickname, hdevApiKey)) { getPreview(); search = true; main();} else { alert = true; setTimeout(() => alert = false, 5000)}"
157+ x-model="nickname"
158+ class="nickname"
159+ id="nickname_with_tag"
160+ placeholder="NICKNAME#TAG"
161+ autocomplete="off"
162+ />
163+ <button class="icons" @click="if (await checkNickname(nickname, hdevApiKey)) { getPreview(); search = true; main();} else { alert = true; setTimeout(() => alert = false, 5000)}">
164+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
165+ <path d="M21 21L15.0001 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
166+ </svg>
167+ </button>
168+ </div>
169+ <div class="nickname_input">
170+ <span>
171+ <svg width="24" height="24" viewBox="0 0 24 24" stroke="white" fill="none" xmlns="http://www.w3.org/2000/svg">
172+ <path d="M17 17L22 12L17 7M7 7L2 12L7 17M14 3L10 21" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"/>
173+ </svg>
174+ </span>
175+ <input
176+ @keyup.enter="if (await checkNickname(nickname, hdevApiKey)) { getPreview(); search = true; main();} else { alert = true; setTimeout(() => alert = false, 5000)}"
177+ x-model="hdevApiKey"
178+ class="nickname"
179+ id="hdevApi"
180+ placeholder="Henrik's API Key"
181+ autocomplete="off"
182+ />
183+ <button class="icons" @click="if (await checkNickname(nickname, hdevApiKey)) { getPreview(); search = true; main();} else { alert = true; setTimeout(() => alert = false, 5000)}">
184+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
185+ <path d="M21 21L15.0001 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
186+ </svg>
187+ </button>
188+ </div>
189+ <a href="/key.html" target="__blank" style="font-size: 0.825rem; line-height: 1.25rem; color: #008ffd; cursor: pointer">
190+ How do I get an API key?
191+ </a>
145192 </div>
146- <div class="nickname_input">
147- <span>
148- <svg
149- xmlns="http://www.w3.org/2000/svg"
150- viewBox="0 0 24 24"
151- width="24"
152- height="24"
153- >
154- <path
155- stroke="white"
156- d="m2.2 4 .1.1c.2.3 11.8 14.8 12.8 16v.1a.1.1 0 0 1-.1.1H8.8a.52.52 0 0 1-.4-.2c-.2-.2-4.4-5.4-6.3-7.9A.31.31 0 0 0 2 12V4.1a.349.349 0 0 1 .2-.1Zm19.8.2c0-.1-.1-.1-.1-.2h-.1l-.2.2c-.9 1.1-8.1 10.1-8.3 10.3l-.1.1c0 .1 0 .1.1.1h6.2c.1 0 .2-.1.3-.2l.2-.2c.5-.7 1.7-2.2 1.8-2.3 0-.1 0-.1.1-.2v-.1c.1-2.4.1-4.9.1-7.5Z"
157- ></path>
158- </svg>
159- </span>
160- <input
161- @keyup.enter="if (await checkNickname(nickname, hdevApiKey)) { getPreview(); search = true; main();} else { alert = true; setTimeout(() => alert = false, 5000)}"
162- x-model="hdevApiKey"
163- class="nickname"
164- id="hdevApi"
165- placeholder="HDEV API KEY"
166- autocomplete="off"
167- />
168- <button class="icons" @click="if (await checkNickname(nickname, hdevApiKey)) { getPreview(); search = true; main();} else { alert = true; setTimeout(() => alert = false, 5000)}">
169- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
170- <path d="M21 21L15.0001 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
171- </svg>
172- </button>
173193 </div>
174- </div>
175194 <div
176195 x-transition
177196 x-show="search"
@@ -444,7 +463,10 @@ document.querySelector("#app").innerHTML = `
444463 </button>
445464 </div>
446465 <footer>
447- <span>Made with ❤️ © 2023 Valory</span>
466+ <div class="text">
467+ <span>Powered by <a href="https://github.com/Henrik-3/unofficial-valorant-api" target="__blank">Henrik's API</a> 🥰</span>
468+ <span>Made with ❤️ © 2025 Valory</span>
469+ </div>
448470 <ul class="socials">
449471 <li>
450472 <a target="__blank" href="https://www.twitch.tv/magicxcmd">
@@ -469,6 +491,20 @@ document.querySelector("#app").innerHTML = `
469491 </svg>
470492 </a>
471493 </li>
494+ <li>
495+ <a target="__blank" href="https://t.me/magicxcmd">
496+ <svg data-v-0d95eef0="" height="18" width="18" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
497+ <g data-v-0d95eef0="" clip-path="url(#clip0_318_75)">
498+ <path data-v-0d95eef0="" clip-rule="evenodd" d="M48 24C48 37.2548 37.2548 48 24 48C10.7452 48 0 37.2548 0 24C0 10.7452 10.7452 0 24 0C37.2548 0 48 10.7452 48 24ZM24.8601 17.7179C22.5257 18.6888 17.8603 20.6984 10.8638 23.7466C9.72766 24.1984 9.13251 24.6404 9.07834 25.0726C8.98677 25.803 9.90142 26.0906 11.1469 26.4822C11.3164 26.5355 11.4919 26.5907 11.6719 26.6492C12.8973 27.0475 14.5457 27.5135 15.4026 27.5321C16.1799 27.5489 17.0475 27.2284 18.0053 26.5707C24.5423 22.158 27.9168 19.9276 28.1286 19.8795C28.2781 19.8456 28.4852 19.803 28.6255 19.9277C28.7659 20.0524 28.7521 20.2886 28.7372 20.352C28.6466 20.7383 25.0562 24.0762 23.1982 25.8036C22.619 26.3421 22.2081 26.724 22.1242 26.8113C21.936 27.0067 21.7443 27.1915 21.56 27.3692C20.4215 28.4667 19.5678 29.2896 21.6072 30.6336C22.5873 31.2794 23.3715 31.8135 24.1539 32.3463C25.0084 32.9282 25.8606 33.5085 26.9632 34.2313C27.2442 34.4155 27.5125 34.6068 27.7738 34.7931C28.7681 35.5019 29.6615 36.1388 30.7652 36.0373C31.4065 35.9782 32.0689 35.3752 32.4053 33.5767C33.2004 29.3263 34.7633 20.1169 35.1244 16.3219C35.1561 15.9895 35.1163 15.5639 35.0843 15.3771C35.0523 15.1904 34.9855 14.9242 34.7427 14.7272C34.4552 14.4939 34.0113 14.4447 33.8127 14.4482C32.91 14.4641 31.5251 14.9456 24.8601 17.7179Z" fill-rule="evenodd"></path>
499+ </g>
500+ <defs data-v-0d95eef0="">
501+ <clipPath data-v-0d95eef0="" id="clip0_318_75">
502+ <rect data-v-0d95eef0="" height="48" width="48"></rect>
503+ </clipPath>
504+ </defs>
505+ </svg>
506+ </a>
507+ </li>
472508 <li>
473509 <a target="__blank" href="https://www.donationalerts.com/r/haxgun">
474510 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -840,11 +876,25 @@ async function getPuuidWithRegion(nickname, tag, hdevApiKey) {
840876}
841877
842878async function getLeaderboard ( region , puuid , hdevApiKey ) {
843- const response = await fetch (
844- `${ apiUrl } /v1/leaderboard/${ region } ?puuid=${ puuid } &api_key=${ hdevApiKey } ` ,
845- ) ;
846- const data = await response . json ( ) ;
847- return data . status === 404 ? " " : data . data [ 0 ] . leaderboardRank ;
879+ try {
880+ const response = await fetch (
881+ `${ apiUrl } /v1/leaderboard/${ region } ?puuid=${ puuid } &api_key=${ hdevApiKey } `
882+ ) ;
883+
884+ if ( ! response . ok ) {
885+ return " " ;
886+ }
887+
888+ const data = await response . json ( ) ;
889+
890+ if ( data ?. data ?. [ 0 ] ?. leaderboardRank !== undefined ) {
891+ return data . data [ 0 ] . leaderboardRank ;
892+ } else {
893+ return " " ;
894+ }
895+ } catch ( error ) {
896+ return " " ;
897+ }
848898}
849899
850900async function getPlayerInformation ( region , puuid , hdevApiKey ) {
0 commit comments