PageSourceSearch

https://amusemap.com/link/sdvx.js?t=0&linkCode=$%7Bthis.linkCode%7D

js amusemap.com collected 2026-09-24 14:38:06 UTC 11,250 bytes, 294 lines download raw bytes

1(async function() {
2    const processFlag = location.href.match(/\/\/p.eagate.573.jp\/game\/sdvx\/vii\/playdata\/profile(|\/|\/index.html)(\?.*)?$/);
3    if (!processFlag) {
4        if (window.confirm('Sound Voltex의 프로필을 등록하기 위해 공식 페이지로 이동하시겠습니까?')) {
5            location.href = 'https://p.eagate.573.jp/game/sdvx/vii/playdata/profile/index.html';
6        }
7        return;
8    }
9
10    const currentSrc = document.currentScript && document.currentScript.src;
11    var query = scriptQuery(currentSrc);
12    console.log('Link Code:', query.linkCode);
13    console.log('t:', query.t);
14    
15    showDialog(query.linkCode, query.t);
16})();
17
18function scriptQuery(src) {
19    if (!src) return {};
20    const queryStringMatch = src.match(/\?([^#]+)/);
21    if (!queryStringMatch) return {};
22    const queryString = queryStringMatch[1];
23    const params = {};
24    queryString.replace(/([^&=]+)=?([^&]*)/g, (_, key, value) => {
25        params[decodeURIComponent(key)] = decodeURIComponent(value || '');
26        return '';
27    });
28    return params;
29}
30
31async function getProfileData(code, t){
32    var API_URL = 'https://api.amusemap.com/api/gameLink';
33    if(t == 0){
34        console.log('Production server connection');
35    } else {
36        console.log('Test server connection');
37        API_URL = 'http://localhost:3000/api/gameLink';
38    }
39    
40    const fetchHTML = async (url) => {
41        const response = await fetch(url, {cache: "no-store", referrer: url, credentials: "include"});
42        if (!response.ok) {
43            throw new Error(`Network error : ${response.statusText}`);
44        }
45        return response.text();
46    };
47
48    var profile = "";
49
50    try {
51        profile = await fetchHTML("https://p.eagate.573.jp/game/sdvx/vi/playdata/index.html");
52        profile = this.window.btoa(String.fromCharCode(...new TextEncoder().encode(profile)));
53    } catch (error) {
54        console.error('Error:', error);
55        throw error;
56    }
57
58    const response = await fetch(API_URL, {
59        method: 'POST',
60        headers: {
61            'Content-Type': 'application/json'
62        },
63        body: JSON.stringify({
64            mode : 'sdvx',
65            linkCode : code,
66            profileData: profile
67        })
68    });
69
70    if (!response.ok) {
71        throw new Error(`서버 응답 오류: ${response.status}`);
72    }
73}
74
75function showDialog(code, t) {
76    const old = document.getElementById('amusemap-dialog');
77    if (old) old.remove();
78
79    const playerIdElement = document.getElementById('player_id');
80    const a = playerIdElement ? playerIdElement.textContent.trim() : 'N/A';
81
82    const playerNameElement = document.getElementById('player_name');
83    const b = playerNameElement && playerNameElement.querySelectorAll('p')[1] ? playerNameElement.querySelectorAll('p')[1].textContent.trim() : 'N/A';
84
85    const dialog = document.createElement('div');
86    dialog.id = 'amusemap-dialog';
87    dialog.style.position = 'fixed';
88    dialog.style.top = '0';
89    dialog.style.left = '0';
90    dialog.style.width = '100vw';
91    dialog.style.height = '100vh';
92    dialog.style.background = 'rgba(0,0,0,0.7)';
93    dialog.style.zIndex = '99999';
94    dialog.style.display = 'flex';
95    dialog.style.alignItems = 'center';
96    dialog.style.justifyContent = 'center';
97    dialog.style.backdropFilter = 'blur(5px)';
98    dialog.style.userSelect = 'none';
99
100    const box = document.createElement('div');
101    box.style.background = '#0f0f1180';
102    box.style.border = '1px solid #2b2c2e';
103    box.style.padding = '1.5rem';
104    box.style.maxWidth = '90vw';
105    box.style.width = '400px';
106    box.style.margin = '0';
107    box.style.borderRadius = '12px';
108    box.style.boxShadow = '0 2px 16px #0008';
109    box.style.color = '#fff';
110    box.style.fontFamily = 'inherit';
111
112    const title = document.createElement('h5');
113    title.textContent = 'AmuseMap에 연동하기';
114    title.style.fontSize = '1.25rem';
115    title.style.fontWeight = 'bold';
116    title.style.margin = '0 0 1rem 0';
117    title.style.display = 'block';
118    box.appendChild(title);
119
120    const desc = document.createElement('div');
121    desc.innerHTML = `<span style="color:#bbb;font-size:0.95rem;">이 프로필을 연결하시겠습니까?<br>SV ID 또는 플레이어 이름이 변경되면 이 과정을 다시 수행해야합니다.<br>연동 해제는 AmuseMap에서 할 수 있습니다.</span>`;
122    box.appendChild(desc);
123
124    const profileSection = document.createElement('div');
125    profileSection.style.background = '#1a1a1a';
126    profileSection.style.borderRadius = '8px';
127    profileSection.style.padding = '1rem';
128    profileSection.style.marginTop = '1rem';
129    profileSection.style.display = 'flex';
130    profileSection.style.flexDirection = 'column';
131    profileSection.style.gap = '0.5rem';
132
133    const svIdLabel = document.createElement('div');
134    svIdLabel.textContent = 'SV ID:';
135    svIdLabel.style.fontSize = '0.9rem';
136    svIdLabel.style.color = '#bbb';
137    profileSection.appendChild(svIdLabel);
138
139    const svIdValue = document.createElement('div');
140    svIdValue.textContent = a;
141    svIdValue.style.fontSize = '1rem';
142    svIdValue.style.color = '#fff';
143    svIdValue.style.fontWeight = 'bold';
144    profileSection.appendChild(svIdValue);
145
146    const nicknameLabel = document.createElement('div');
147    nicknameLabel.textContent = '닉네임:';
148    nicknameLabel.style.fontSize = '0.9rem';
149    nicknameLabel.style.color = '#bbb';
150    profileSection.appendChild(nicknameLabel);
151
152    const nicknameValue = document.createElement('div');
153    nicknameValue.textContent = b;
154    nicknameValue.style.fontSize = '1rem';
155    nicknameValue.style.color = '#fff';
156    nicknameValue.style.fontWeight = 'bold';
157    profileSection.appendChild(nicknameValue);
158
159    box.appendChild(profileSection);
160
161    const btnArea = document.createElement('div');
162    btnArea.style.display = 'flex';
163    btnArea.style.flexDirection = 'column';
164    btnArea.style.gap = '0.5rem';
165    btnArea.style.marginTop = '2rem';
166
167    const linkBtn = document.createElement('button');
168    linkBtn.textContent = '연동하기';
169    linkBtn.style.background = '#fff';
170    linkBtn.style.color = '#222';
171    linkBtn.style.border = 'none';
172    linkBtn.style.borderRadius = '6px';
173    linkBtn.style.padding = '0.7rem 1rem';
174    linkBtn.style.fontWeight = 'bold';
175    linkBtn.style.cursor = 'pointer';
176    linkBtn.style.fontSize = '1rem';
177    linkBtn.style.transition = 'background 0.2s ease';
178    linkBtn.onmouseover = function() {
179        this.style.background = '#eee';
180    };
181    linkBtn.onmouseout = function() {
182        this.style.background = '#fff';
183    };
184    linkBtn.onclick = async function() {
185        desc.innerHTML = '<span style="color:#bbb;font-size:0.95rem;">프로필을 AmuseMap에 연동하는 중 입니다.</span>';
186
187        profileSection.style.display = 'none';
188
189        btnArea.style.display = 'none';
190
191        const loadingIcon = document.createElement('div');
192        loadingIcon.style.width = '40px';
193        loadingIcon.style.height = '40px';
194        loadingIcon.style.border = '4px solid #8f8f8fff';
195        loadingIcon.style.borderTop = '4px solid #fff';
196        loadingIcon.style.borderRadius = '50%';
197        loadingIcon.style.animation = 'spin 1s linear infinite';
198        loadingIcon.style.margin = '1rem auto';
199        box.appendChild(loadingIcon);
200
201        const style = document.createElement('style');
202        style.textContent = `
203            @keyframes spin {
204                0% { transform: rotate(0deg); }
205                100% { transform: rotate(360deg); }
206            }
207        `;
208        document.head.appendChild(style);
209
210        try {
211            await getProfileData(code, t);
212            loadingIcon.remove();
213            desc.innerHTML = '<span style="color:#bbb;font-size:0.95rem;">연동에 성공했습니다!</span>';
214
215            const closeBtn = document.createElement('button');
216            closeBtn.textContent = '닫기';
217            closeBtn.style.background = '#222';
218            closeBtn.style.color = '#fff';
219            closeBtn.style.border = 'none';
220            closeBtn.style.width = '100%';
221            closeBtn.style.borderRadius = '6px';
222            closeBtn.style.padding = '0.7rem 1rem';
223            closeBtn.style.fontWeight = 'bold';
224            closeBtn.style.cursor = 'pointer';
225            closeBtn.style.fontSize = '1rem';
226            closeBtn.style.transition = 'background 0.2s ease';
227            closeBtn.style.marginTop = '1rem';
228            closeBtn.onmouseover = function() {
229                this.style.background = '#333';
230            };
231            closeBtn.onmouseout = function() {
232                this.style.background = '#222';
233            };
234            closeBtn.onclick = function() {
235                dialog.remove();
236            };
237            box.appendChild(closeBtn);
238        } catch (error) {
239            loadingIcon.remove();
240            desc.innerHTML = `<span style="color:#bbb;font-size:0.95rem;">연동에 실패했습니다. 다시 시도해주세요.<br>오류: ${error.message}</span>`;
241
242            const closeBtn = document.createElement('button');
243            closeBtn.textContent = '닫기';
244            closeBtn.style.background = '#222';
245            closeBtn.style.color = '#fff';
246            closeBtn.style.border = 'none';
247            closeBtn.style.width = '100%';
248            closeBtn.style.borderRadius = '6px';
249            closeBtn.style.padding = '0.7rem 1rem';
250            closeBtn.style.fontWeight = 'bold';
251            closeBtn.style.cursor = 'pointer';
252            closeBtn.style.fontSize = '1rem';
253            closeBtn.style.transition = 'background 0.2s ease';
254            closeBtn.style.marginTop = '1rem';
255            closeBtn.onmouseover = function() {
256                this.style.background = '#333';
257            };
258            closeBtn.onmouseout = function() {
259                this.style.background = '#222';
260            };
261            closeBtn.onclick = function() {
262                dialog.remove();
263            };
264            box.appendChild(closeBtn);
265        }
266    };
267    btnArea.appendChild(linkBtn);
268
269    const cancelBtn = document.createElement('button');
270    cancelBtn.textContent = '취소';
271    cancelBtn.style.background = '#222';
272    cancelBtn.style.color = '#fff';
273    cancelBtn.style.border = 'none';
274    cancelBtn.style.borderRadius = '6px';
275    cancelBtn.style.padding = '0.7rem 1rem';
276    cancelBtn.style.fontWeight = 'bold';
277    cancelBtn.style.cursor = 'pointer';
278    cancelBtn.style.fontSize = '1rem';
279    cancelBtn.style.transition = 'background 0.2s ease';
280    cancelBtn.onmouseover = function() {
281        this.style.background = '#333';
282    };
283    cancelBtn.onmouseout = function() {
284        this.style.background = '#222';
285    };
286    cancelBtn.onclick = function() {
287        dialog.remove();
288    };
289    btnArea.appendChild(cancelBtn);
290
291    box.appendChild(btnArea);
292    dialog.appendChild(box);
293    document.body.appendChild(dialog);
294}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.