Test build
Browse files- index.html +126 -17
- script.js +238 -0
- style.css +4 -26
index.html
CHANGED
@@ -1,19 +1,128 @@
|
|
1 |
<!DOCTYPE html>
|
2 |
-
<html>
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
</html>
|
|
|
1 |
<!DOCTYPE html>
|
2 |
+
<html lang="en" data-bs-theme="dark">
|
3 |
+
<head>
|
4 |
+
<meta charset="utf-8">
|
5 |
+
<title>discography_v2_cdn_front</title>
|
6 |
+
<!-- Responsive viewport meta -->
|
7 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
8 |
+
<!-- JavaScript load -->
|
9 |
+
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
10 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js"></script>
|
11 |
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/js/bootstrap.bundle.min.js"></script>
|
12 |
+
<!-- CSS load -->
|
13 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css">
|
14 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">
|
15 |
+
<link rel="preconnect" href="https://rsms.me">
|
16 |
+
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
|
17 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/distr/fira_code.css">
|
18 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
19 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
20 |
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;200;300;400;500;600;700;800;900&display=swap">
|
21 |
+
<link rel="stylesheet" href="style.css">
|
22 |
+
</head>
|
23 |
+
<body>
|
24 |
+
<div id="mainContainer" class="container my-4">
|
25 |
+
<h1 class="user-select-none text-center">discography_v2_cdn_front</h1>
|
26 |
+
<hr class="my-4">
|
27 |
+
<button id="showSettingsModalButton" class="btn btn-primary" type="button" data-bs-toggle="modal" data-bs-target="#settingsModal"><i class="bi bi-gear-wide-connected me-1"></i>Settings</button>
|
28 |
+
<div class="modal fade user-select-none" id="settingsModal" tabindex="-1">
|
29 |
+
<div class="modal-dialog modal-dialog-scrollable">
|
30 |
+
<div class="modal-content">
|
31 |
+
<div class="modal-header">
|
32 |
+
<h1 class="modal-title fs-5" id="settingsModalLabel"><i class="bi bi-gear-wide-connected me-2"></i>Settings</h1>
|
33 |
+
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
34 |
+
</div>
|
35 |
+
<div class="modal-body">
|
36 |
+
<!-- <ul class="nav nav-tabs" id="myTab" role="tablist">
|
37 |
+
<li class="nav-item" role="presentation">
|
38 |
+
<button class="nav-link active" id="home-tab" data-bs-toggle="tab" data-bs-target="#home-tab-pane" type="button" role="tab" aria-controls="home-tab-pane" aria-selected="true">Home</button>
|
39 |
+
</li>
|
40 |
+
<li class="nav-item" role="presentation">
|
41 |
+
<button class="nav-link" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile-tab-pane" type="button" role="tab" aria-controls="profile-tab-pane" aria-selected="false">Profile</button>
|
42 |
+
</li>
|
43 |
+
<li class="nav-item" role="presentation">
|
44 |
+
<button class="nav-link" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact-tab-pane" type="button" role="tab" aria-controls="contact-tab-pane" aria-selected="false">Contact</button>
|
45 |
+
</li>
|
46 |
+
<li class="nav-item" role="presentation">
|
47 |
+
<button class="nav-link" id="disabled-tab" data-bs-toggle="tab" data-bs-target="#disabled-tab-pane" type="button" role="tab" aria-controls="disabled-tab-pane" aria-selected="false" disabled>Disabled</button>
|
48 |
+
</li>
|
49 |
+
</ul>
|
50 |
+
<div class="tab-content" id="myTabContent">
|
51 |
+
<div class="tab-pane fade show active" id="home-tab-pane" role="tabpanel" aria-labelledby="home-tab" tabindex="0">...</div>
|
52 |
+
<div class="tab-pane fade" id="profile-tab-pane" role="tabpanel" aria-labelledby="profile-tab" tabindex="0">...</div>
|
53 |
+
<div class="tab-pane fade" id="contact-tab-pane" role="tabpanel" aria-labelledby="contact-tab" tabindex="0">...</div>
|
54 |
+
<div class="tab-pane fade" id="disabled-tab-pane" role="tabpanel" aria-labelledby="disabled-tab" tabindex="0">...</div>
|
55 |
+
</div> -->
|
56 |
+
<h1 class="fs-3">UI</h1>
|
57 |
+
<form id="settingsUiSwitchUiMode" class="d-flex justify-content-between align-items-center">
|
58 |
+
<label>Switch UI mode</label>
|
59 |
+
<div class="btn-group w-100%" id="settingsUiSwitchUiModeDiv" role="group">
|
60 |
+
<input type="radio" class="btn-check" name="settingsUiSwitchUiMode" id="settingsUiSwitchUiModeLight" autocomplete="off" value="light">
|
61 |
+
<label class="btn btn-outline-primary" for="settingsUiSwitchUiModeLight">Light</label>
|
62 |
+
<input type="radio" class="btn-check" name="settingsUiSwitchUiMode" id="settingsUiSwitchUiModeDark" autocomplete="off" value="dark">
|
63 |
+
<label class="btn btn-outline-primary" for="settingsUiSwitchUiModeDark">Dark</label>
|
64 |
+
</div>
|
65 |
+
</form>
|
66 |
+
</div>
|
67 |
+
<div class="modal-footer">
|
68 |
+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
69 |
+
<button type="button" class="btn btn-primary" id="settingsApplyButton">Save/Apply</button>
|
70 |
+
</div>
|
71 |
+
</div>
|
72 |
+
</div>
|
73 |
+
</div>
|
74 |
+
<hr class="my-4">
|
75 |
+
<h3 class="user-select-none">Track listing test</h3>
|
76 |
+
<button id="trackListingTestButton" class="btn btn-primary mb-3" type="button"><i class="bi bi-menu-button-wide me-1"></i>List track</button>
|
77 |
+
<div class="fetchingDataNowLabel user-select-none d-none">
|
78 |
+
<div class="d-inline-flex align-items-center mb-3">
|
79 |
+
<div class="spinner-border text-primary me-2" role="status">
|
80 |
+
<span class="visually-hidden">Loading...</span>
|
81 |
+
</div>
|
82 |
+
<span>Fetching data ...</span>
|
83 |
+
</div>
|
84 |
+
</div>
|
85 |
+
<div id="trackAllListGroup" class="list-group user-select-none">
|
86 |
+
<button type="button" class="list-group-item list-group-item-action d-flex" disabled>
|
87 |
+
<div class="flex-fill w-100">Artist</div>
|
88 |
+
<div class="flex-fill w-100">Album</div>
|
89 |
+
<div class="flex-fill w-100">Track</div>
|
90 |
+
</button>
|
91 |
+
</div>
|
92 |
+
<hr class="my-4">
|
93 |
+
<h3 class="user-select-none">Fetch data output testing</h3>
|
94 |
+
<button id="loadDatabaseTestButton" class="btn btn-primary mb-3" type="button"><i class="bi bi-database-down me-1"></i>Load Database</button>
|
95 |
+
<div class="fetchingDataNowLabel user-select-none d-none">
|
96 |
+
<div class="d-inline-flex align-items-center mb-3">
|
97 |
+
<div class="spinner-border text-primary me-2" role="status">
|
98 |
+
<span class="visually-hidden">Loading...</span>
|
99 |
+
</div>
|
100 |
+
<span>Fetching data ...</span>
|
101 |
+
</div>
|
102 |
+
</div>
|
103 |
+
<div class="accordion" id="databaseTestOutputAccordion">
|
104 |
+
<div class="accordion-item">
|
105 |
+
<h2 class="accordion-header">
|
106 |
+
<button class="accordion-button collapsed user-select-none" type="button" data-bs-toggle="collapse" data-bs-target="#databaseTestRawOutputCollapse">
|
107 |
+
Raw data output
|
108 |
+
</button>
|
109 |
+
</h2>
|
110 |
+
<div id="databaseTestRawOutputCollapse" class="accordion-collapse collapse" data-bs-parent="#databaseTestOutputAccordion">
|
111 |
+
<div class="accordion-body">
|
112 |
+
<pre class=""><code id="databaseTestInfoCodeEl"></code></pre>
|
113 |
+
<pre class=""><code id="databaseTestOutputCodeEl"></code></pre>
|
114 |
+
</div>
|
115 |
+
</div>
|
116 |
+
</div>
|
117 |
+
</div>
|
118 |
+
<hr class="my-4">
|
119 |
+
<iframe data-aa='2297053' src='//acceptable.a-ads.com/2297053' style='border:0px; padding:0; width:100%; height:100%; overflow:hidden; background-color: transparent;'></iframe>
|
120 |
+
<hr class="my-4">
|
121 |
+
<footer>
|
122 |
+
<p><small class="text-body-tertiary user-select-none">This page using: Bootstrap, Axios, CryptoJS, A-ADS, Inter, Fira Code, Noto Sans JP</small></p>
|
123 |
+
<p><small class="text-body-tertiary user-select-none">(C) 2024 daydreamer-json, and other contributer. All rights reserved.</small></p>
|
124 |
+
</footer>
|
125 |
+
</div>
|
126 |
+
<script src="script.js"></script>
|
127 |
+
</body>
|
128 |
</html>
|
script.js
ADDED
@@ -0,0 +1,238 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const internalConfig = {
|
2 |
+
'network': {
|
3 |
+
'userAgent': {
|
4 |
+
'chromeWindows': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
|
5 |
+
'curl': 'curl/8.4.0',
|
6 |
+
'curlUnity': 'UnityPlayer/2021.3.14f1 (UnityWebRequest/1.0, libcurl/7.84.0-DEV)'
|
7 |
+
},
|
8 |
+
'timeout': 15000
|
9 |
+
}
|
10 |
+
};
|
11 |
+
const apiConnectDefaultHeader = {
|
12 |
+
'Access-Controll-Allow-Origin': '*'
|
13 |
+
}
|
14 |
+
const appSettingsStorageName = '018d2fc7-d0bb-7393-9ebc-6f6ec26b03ce_appSettings';
|
15 |
+
let appSettingsSaveData = new Object();
|
16 |
+
const appSettingsSaveDataDefault = {
|
17 |
+
'ui': {
|
18 |
+
'uiThemeMode': 'light'
|
19 |
+
}
|
20 |
+
};
|
21 |
+
let apiDataMasterDB = new Object();
|
22 |
+
let apiDataConfig = new Object();
|
23 |
+
|
24 |
+
//!========== ページ読み込み時に実行する処理 ==========
|
25 |
+
|
26 |
+
window.addEventListener('load', async function(){
|
27 |
+
if (checkAppSettingsExistsOnStorage() === true) {
|
28 |
+
loadAppSettingsFromLocalStorage();
|
29 |
+
} else {
|
30 |
+
loadAppSettingsFromLocalStorage();
|
31 |
+
if (window.matchMedia('(prefers-color-scheme:dark)').matches === true) {
|
32 |
+
console.warn(`prefers-color-scheme:dark detected`)
|
33 |
+
appSettingsSaveData.ui.uiThemeMode = 'dark';
|
34 |
+
writeAppSettingsToLocalStorage();
|
35 |
+
} else {
|
36 |
+
appSettingsSaveData.ui.uiThemeMode = 'light';
|
37 |
+
writeAppSettingsToLocalStorage();
|
38 |
+
}
|
39 |
+
}
|
40 |
+
appSettingsCheckedUiUpdate();
|
41 |
+
appSettingsApply();
|
42 |
+
await loadRequiredDatabase();
|
43 |
+
await decryptConfig();
|
44 |
+
pushToTrackListGroupUi();
|
45 |
+
});
|
46 |
+
|
47 |
+
document.querySelector('#loadDatabaseTestButton').addEventListener('click', async function() {
|
48 |
+
console.log('loadDatabaseTestButton clicked!');
|
49 |
+
await loadRequiredDatabase();
|
50 |
+
});
|
51 |
+
|
52 |
+
document.querySelector('#trackListingTestButton').addEventListener('click', () => {
|
53 |
+
console.log('trackListingTestButton clicked!');
|
54 |
+
pushToTrackListGroupUi();
|
55 |
+
});
|
56 |
+
|
57 |
+
// ========== 全てのトラックのリストをTrack Listing TestのListGroupに表示 ==========
|
58 |
+
|
59 |
+
function pushToTrackListGroupUi () {
|
60 |
+
const trackAllListGroup = document.querySelector('#trackAllListGroup');
|
61 |
+
while(trackAllListGroup.firstChild) {
|
62 |
+
trackAllListGroup.removeChild(trackAllListGroup.firstChild);
|
63 |
+
}
|
64 |
+
let headerElObj = new Object();
|
65 |
+
headerElObj.buttonNodeEl = document.createElement('button');
|
66 |
+
headerElObj.divArtistNodeEl = document.createElement('div');
|
67 |
+
headerElObj.divAlbumNodeEl = document.createElement('div');
|
68 |
+
headerElObj.divTrackNodeEl = document.createElement('div');
|
69 |
+
headerElObj.buttonNodeEl.classList.add('list-group-item', 'list-group-item-action', 'd-flex');
|
70 |
+
headerElObj.buttonNodeEl.setAttribute('type', 'button');
|
71 |
+
headerElObj.buttonNodeEl.disabled = true;
|
72 |
+
headerElObj.divArtistNodeEl.classList.add('flex-fill', 'w-100');
|
73 |
+
headerElObj.divAlbumNodeEl.classList.add('flex-fill', 'w-100');
|
74 |
+
headerElObj.divTrackNodeEl.classList.add('flex-fill', 'w-100');
|
75 |
+
headerElObj.divArtistNodeEl.innerHTML = 'Artist';
|
76 |
+
headerElObj.divAlbumNodeEl.innerHTML = 'Album';
|
77 |
+
headerElObj.divTrackNodeEl.innerHTML = 'Track';
|
78 |
+
headerElObj.buttonNodeEl.appendChild(headerElObj.divArtistNodeEl);
|
79 |
+
headerElObj.buttonNodeEl.appendChild(headerElObj.divAlbumNodeEl);
|
80 |
+
headerElObj.buttonNodeEl.appendChild(headerElObj.divTrackNodeEl);
|
81 |
+
trackAllListGroup.appendChild(headerElObj.buttonNodeEl);
|
82 |
+
apiDataMasterDB.response.data.albums.forEach((albumObject) => {
|
83 |
+
albumObject.tracks.forEach((trackObject) => {
|
84 |
+
let buttonNodeEl = document.createElement('button');
|
85 |
+
let divArtistNodeEl = document.createElement('div');
|
86 |
+
let divAlbumNodeEl = document.createElement('div');
|
87 |
+
let divTrackNodeEl = document.createElement('div');
|
88 |
+
buttonNodeEl.classList.add('list-group-item', 'list-group-item-action', 'd-flex');
|
89 |
+
buttonNodeEl.setAttribute('type', 'button');
|
90 |
+
divArtistNodeEl.classList.add('flex-fill', 'w-100');
|
91 |
+
divAlbumNodeEl.classList.add('flex-fill', 'w-100');
|
92 |
+
divTrackNodeEl.classList.add('flex-fill', 'w-100');
|
93 |
+
let albumArtistFilteredList = new Array();
|
94 |
+
albumObject.artist.forEach((str) => {
|
95 |
+
albumArtistFilteredList.push(apiDataMasterDB.response.data.artists.filter((obj) => obj.uuid === str)[0].name);
|
96 |
+
});
|
97 |
+
divArtistNodeEl.innerHTML = albumArtistFilteredList.join(', ');
|
98 |
+
divAlbumNodeEl.innerHTML = albumObject.title;
|
99 |
+
divTrackNodeEl.innerHTML = trackObject.title;
|
100 |
+
buttonNodeEl.appendChild(divArtistNodeEl);
|
101 |
+
buttonNodeEl.appendChild(divAlbumNodeEl);
|
102 |
+
buttonNodeEl.appendChild(divTrackNodeEl);
|
103 |
+
trackAllListGroup.appendChild(buttonNodeEl);
|
104 |
+
});
|
105 |
+
});
|
106 |
+
}
|
107 |
+
|
108 |
+
// ========== 設定画面のイベントリスナー登録など ==========
|
109 |
+
|
110 |
+
document.querySelector('#settingsApplyButton').addEventListener('click', () => {appSettingsApply()});
|
111 |
+
document.querySelector('#settingsUiSwitchUiModeDiv').addEventListener('click', function () {
|
112 |
+
appSettingsSaveData.ui.uiThemeMode = document.querySelector('#settingsUiSwitchUiMode').elements['settingsUiSwitchUiMode'].value;
|
113 |
+
console.log('settingsUiSwitchUiMode div clicked!');
|
114 |
+
});
|
115 |
+
|
116 |
+
|
117 |
+
// ========== 設定を変更後��保存、反映させる(ボタン押したときの動作) ==========
|
118 |
+
|
119 |
+
function appSettingsApply () {
|
120 |
+
writeAppSettingsToLocalStorage();
|
121 |
+
switch (appSettingsSaveData.ui.uiThemeMode) {
|
122 |
+
case 'light':
|
123 |
+
document.querySelector('html').setAttribute('data-bs-theme', 'light');
|
124 |
+
break;
|
125 |
+
case 'dark':
|
126 |
+
document.querySelector('html').setAttribute('data-bs-theme', 'dark');
|
127 |
+
}
|
128 |
+
}
|
129 |
+
|
130 |
+
// ========== appSettingsを元に設定画面の選択状態を更新 ==========
|
131 |
+
|
132 |
+
function appSettingsCheckedUiUpdate () {
|
133 |
+
const settingsUiSwitchUiModeElements = document.querySelector('#settingsUiSwitchUiMode').elements;
|
134 |
+
for (let i = 0; i < settingsUiSwitchUiModeElements.length; i++) {
|
135 |
+
if (settingsUiSwitchUiModeElements[i].value === appSettingsSaveData.ui.uiThemeMode) {
|
136 |
+
settingsUiSwitchUiModeElements[i].checked = true;
|
137 |
+
} else {
|
138 |
+
settingsUiSwitchUiModeElements[i].checked = false;
|
139 |
+
}
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
// ========== API関連の関数など ==========
|
144 |
+
|
145 |
+
async function apiConnect (axiosObj) {
|
146 |
+
let connectionTimerStart = performance.now();
|
147 |
+
try {
|
148 |
+
const response = await axios(axiosObj);
|
149 |
+
let connectionTimerEnd = performance.now();
|
150 |
+
return {
|
151 |
+
'apiConnectionTime': connectionTimerEnd - connectionTimerStart,
|
152 |
+
'response': response.data
|
153 |
+
};
|
154 |
+
} catch (error) {
|
155 |
+
let connectionTimerEnd = performance.now();
|
156 |
+
console.error(`API request failed: ${error.code}`);
|
157 |
+
alert(`API request failed: ${error.code}`);
|
158 |
+
throw error;
|
159 |
+
}
|
160 |
+
}
|
161 |
+
|
162 |
+
async function loadRequiredDatabase () {
|
163 |
+
document.querySelectorAll('.fetchingDataNowLabel').forEach((el) => {
|
164 |
+
el.classList.remove('d-none');
|
165 |
+
});
|
166 |
+
apiDataMasterDB = await apiConnect({
|
167 |
+
'method': 'get',
|
168 |
+
'url': `https://corsproxy.io/?${encodeURIComponent(`https://hf.co/datasets/DeliberatorArchiver/discography_v2_cdn/resolve/main/db/master.json`)}`,
|
169 |
+
'headers': apiConnectDefaultHeader,
|
170 |
+
'timeout': internalConfig.network.timeout
|
171 |
+
});
|
172 |
+
apiDataConfig = await apiConnect({
|
173 |
+
'method': 'get',
|
174 |
+
'url': `https://corsproxy.io/?${encodeURIComponent(`https://hf.co/spaces/DeliberatorArchiver/discography_v2_cdn_front/resolve/main/config.json`)}`,
|
175 |
+
'headers': apiConnectDefaultHeader,
|
176 |
+
'timeout': internalConfig.network.timeout
|
177 |
+
});
|
178 |
+
console.log(apiDataMasterDB);
|
179 |
+
console.log(apiDataConfig);
|
180 |
+
if (apiDataMasterDB) {
|
181 |
+
document.querySelector('#databaseTestInfoCodeEl').innerHTML = `OK (Time: ${Math.ceil(apiDataMasterDB.apiConnectionTime)} ms)`;
|
182 |
+
document.querySelector('#databaseTestOutputCodeEl').innerHTML = JSON.stringify(apiDataMasterDB.response, '', ' ');
|
183 |
+
} else {
|
184 |
+
document.querySelector('#databaseTestInfoCodeEl').innerHTML = `Failed`;
|
185 |
+
}
|
186 |
+
document.querySelectorAll('.fetchingDataNowLabel').forEach((el) => {
|
187 |
+
el.classList.add('d-none');
|
188 |
+
});
|
189 |
+
}
|
190 |
+
|
191 |
+
// ========== MasterDB/Configの暗号化を解く ==========
|
192 |
+
|
193 |
+
async function decryptConfig () {
|
194 |
+
apiDataConfig.response.config.decrypted = new Object();
|
195 |
+
console.log(`Decrypting config data using AES 128-bit CBC ...`)
|
196 |
+
const encryptKey = await CryptoJS.enc.Hex.parse(CryptoJS.enc.Base64.parse(apiDataConfig.response.config.encryption.key.split('').reverse().join('')).toString(CryptoJS.enc.Utf8));
|
197 |
+
const encryptIv = await CryptoJS.enc.Hex.parse(CryptoJS.enc.Base64.parse(apiDataConfig.response.config.encryption.iv.split('').reverse().join('')).toString(CryptoJS.enc.Utf8));
|
198 |
+
Object.keys(apiDataConfig.response.config.encrypted).forEach(async function (keyName) {
|
199 |
+
apiDataConfig.response.config.decrypted[keyName] = await CryptoJS.AES.decrypt({
|
200 |
+
'ciphertext': CryptoJS.enc.Base64.parse(apiDataConfig.response.config.encrypted[keyName])
|
201 |
+
}, encryptKey, {
|
202 |
+
'iv': encryptIv,
|
203 |
+
'mode': CryptoJS.mode.CBC,
|
204 |
+
'padding': CryptoJS.pad.Pkcs7
|
205 |
+
}).toString(CryptoJS.enc.Utf8);
|
206 |
+
});
|
207 |
+
console.log(`All config data has been decrypted`);
|
208 |
+
}
|
209 |
+
|
210 |
+
// ========== ブラウザのLocalStorageにあるAppSettingsを読み書きする ==========
|
211 |
+
|
212 |
+
function loadAppSettingsFromLocalStorage () {
|
213 |
+
if (localStorage.hasOwnProperty(appSettingsStorageName)) {
|
214 |
+
appSettingsSaveData = JSON.parse(CryptoJS.enc.Base64.parse(localStorage.getItem(appSettingsStorageName)).toString(CryptoJS.enc.Utf8));
|
215 |
+
console.warn(`LocalStorage key detected`);
|
216 |
+
console.log(`Loaded appSettings:`);
|
217 |
+
console.log(appSettingsSaveData);
|
218 |
+
} else {
|
219 |
+
appSettingsSaveData = appSettingsSaveDataDefault;
|
220 |
+
console.warn(`LocalStorage key not found\nUsing default settings`);
|
221 |
+
writeAppSettingsToLocalStorage();
|
222 |
+
}
|
223 |
+
}
|
224 |
+
|
225 |
+
function checkAppSettingsExistsOnStorage () {
|
226 |
+
if (localStorage.hasOwnProperty(appSettingsStorageName)) {
|
227 |
+
return true
|
228 |
+
} else {
|
229 |
+
return false
|
230 |
+
}
|
231 |
+
}
|
232 |
+
|
233 |
+
function writeAppSettingsToLocalStorage () {
|
234 |
+
// CryptoJS.enc.Utf8.parseを使うことでCryptoJS内部形式を強制
|
235 |
+
localStorage.setItem(appSettingsStorageName, CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(JSON.stringify(appSettingsSaveData))));
|
236 |
+
console.log(`Wrote appSettings:`);
|
237 |
+
console.log(appSettingsSaveData);
|
238 |
+
}
|
style.css
CHANGED
@@ -1,28 +1,6 @@
|
|
1 |
body {
|
2 |
-
|
3 |
-
font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
|
4 |
-
}
|
5 |
-
|
6 |
-
h1 {
|
7 |
-
font-size: 16px;
|
8 |
-
margin-top: 0;
|
9 |
-
}
|
10 |
-
|
11 |
-
p {
|
12 |
-
color: rgb(107, 114, 128);
|
13 |
-
font-size: 15px;
|
14 |
-
margin-bottom: 10px;
|
15 |
-
margin-top: 5px;
|
16 |
-
}
|
17 |
-
|
18 |
-
.card {
|
19 |
-
max-width: 620px;
|
20 |
-
margin: 0 auto;
|
21 |
-
padding: 16px;
|
22 |
-
border: 1px solid lightgray;
|
23 |
-
border-radius: 16px;
|
24 |
-
}
|
25 |
-
|
26 |
-
.card p:last-child {
|
27 |
-
margin-bottom: 0;
|
28 |
}
|
|
|
|
|
|
|
|
1 |
body {
|
2 |
+
font-family: 'Inter', 'Noto Sans JP', system-ui, sans-serif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
}
|
4 |
+
pre, code {
|
5 |
+
font-family: 'Fira Code', SFMono-Regular, SF Mono, 'Noto Sans JP', ui-monospace, monospace, sans-serif;
|
6 |
+
}
|