daydreamer-json's picture
Test build
d7d98b9 verified
raw
history blame
9.96 kB
const internalConfig = {
'network': {
'userAgent': {
'chromeWindows': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
'curl': 'curl/8.4.0',
'curlUnity': 'UnityPlayer/2021.3.14f1 (UnityWebRequest/1.0, libcurl/7.84.0-DEV)'
},
'timeout': 15000
}
};
const apiConnectDefaultHeader = {
'Access-Controll-Allow-Origin': '*'
}
const appSettingsStorageName = '018d2fc7-d0bb-7393-9ebc-6f6ec26b03ce_appSettings';
let appSettingsSaveData = new Object();
const appSettingsSaveDataDefault = {
'ui': {
'uiThemeMode': 'light'
}
};
let apiDataMasterDB = new Object();
let apiDataConfig = new Object();
//!========== ページ読み込み時に実行する処理 ==========
window.addEventListener('load', async function(){
if (checkAppSettingsExistsOnStorage() === true) {
loadAppSettingsFromLocalStorage();
} else {
loadAppSettingsFromLocalStorage();
if (window.matchMedia('(prefers-color-scheme:dark)').matches === true) {
console.warn(`prefers-color-scheme:dark detected`)
appSettingsSaveData.ui.uiThemeMode = 'dark';
writeAppSettingsToLocalStorage();
} else {
appSettingsSaveData.ui.uiThemeMode = 'light';
writeAppSettingsToLocalStorage();
}
}
appSettingsCheckedUiUpdate();
appSettingsApply();
await loadRequiredDatabase();
await decryptConfig();
pushToTrackListGroupUi();
});
document.querySelector('#loadDatabaseTestButton').addEventListener('click', async function() {
console.log('loadDatabaseTestButton clicked!');
await loadRequiredDatabase();
});
document.querySelector('#trackListingTestButton').addEventListener('click', () => {
console.log('trackListingTestButton clicked!');
pushToTrackListGroupUi();
});
// ========== 全てのトラックのリストをTrack Listing TestのListGroupに表示 ==========
function pushToTrackListGroupUi () {
const trackAllListGroup = document.querySelector('#trackAllListGroup');
while(trackAllListGroup.firstChild) {
trackAllListGroup.removeChild(trackAllListGroup.firstChild);
}
let headerElObj = new Object();
headerElObj.buttonNodeEl = document.createElement('button');
headerElObj.divArtistNodeEl = document.createElement('div');
headerElObj.divAlbumNodeEl = document.createElement('div');
headerElObj.divTrackNodeEl = document.createElement('div');
headerElObj.buttonNodeEl.classList.add('list-group-item', 'list-group-item-action', 'd-flex');
headerElObj.buttonNodeEl.setAttribute('type', 'button');
headerElObj.buttonNodeEl.disabled = true;
headerElObj.divArtistNodeEl.classList.add('flex-fill', 'w-100');
headerElObj.divAlbumNodeEl.classList.add('flex-fill', 'w-100');
headerElObj.divTrackNodeEl.classList.add('flex-fill', 'w-100');
headerElObj.divArtistNodeEl.innerHTML = 'Artist';
headerElObj.divAlbumNodeEl.innerHTML = 'Album';
headerElObj.divTrackNodeEl.innerHTML = 'Track';
headerElObj.buttonNodeEl.appendChild(headerElObj.divArtistNodeEl);
headerElObj.buttonNodeEl.appendChild(headerElObj.divAlbumNodeEl);
headerElObj.buttonNodeEl.appendChild(headerElObj.divTrackNodeEl);
trackAllListGroup.appendChild(headerElObj.buttonNodeEl);
apiDataMasterDB.response.data.albums.forEach((albumObject) => {
albumObject.tracks.forEach((trackObject) => {
let buttonNodeEl = document.createElement('button');
let divArtistNodeEl = document.createElement('div');
let divAlbumNodeEl = document.createElement('div');
let divTrackNodeEl = document.createElement('div');
buttonNodeEl.classList.add('list-group-item', 'list-group-item-action', 'd-flex');
buttonNodeEl.setAttribute('type', 'button');
divArtistNodeEl.classList.add('flex-fill', 'w-100');
divAlbumNodeEl.classList.add('flex-fill', 'w-100');
divTrackNodeEl.classList.add('flex-fill', 'w-100');
let albumArtistFilteredList = new Array();
albumObject.artist.forEach((str) => {
albumArtistFilteredList.push(apiDataMasterDB.response.data.artists.filter((obj) => obj.uuid === str)[0].name);
});
divArtistNodeEl.innerHTML = albumArtistFilteredList.join(', ');
divAlbumNodeEl.innerHTML = albumObject.title;
divTrackNodeEl.innerHTML = trackObject.title;
buttonNodeEl.appendChild(divArtistNodeEl);
buttonNodeEl.appendChild(divAlbumNodeEl);
buttonNodeEl.appendChild(divTrackNodeEl);
trackAllListGroup.appendChild(buttonNodeEl);
});
});
}
// ========== 設定画面のイベントリスナー登録など ==========
document.querySelector('#settingsApplyButton').addEventListener('click', () => {appSettingsApply()});
document.querySelector('#settingsUiSwitchUiModeDiv').addEventListener('click', function () {
appSettingsSaveData.ui.uiThemeMode = document.querySelector('#settingsUiSwitchUiMode').elements['settingsUiSwitchUiMode'].value;
console.log('settingsUiSwitchUiMode div clicked!');
});
// ========== 設定を変更後に保存、反映させる(ボタン押したときの動作) ==========
function appSettingsApply () {
writeAppSettingsToLocalStorage();
switch (appSettingsSaveData.ui.uiThemeMode) {
case 'light':
document.querySelector('html').setAttribute('data-bs-theme', 'light');
break;
case 'dark':
document.querySelector('html').setAttribute('data-bs-theme', 'dark');
}
}
// ========== appSettingsを元に設定画面の選択状態を更新 ==========
function appSettingsCheckedUiUpdate () {
const settingsUiSwitchUiModeElements = document.querySelector('#settingsUiSwitchUiMode').elements;
for (let i = 0; i < settingsUiSwitchUiModeElements.length; i++) {
if (settingsUiSwitchUiModeElements[i].value === appSettingsSaveData.ui.uiThemeMode) {
settingsUiSwitchUiModeElements[i].checked = true;
} else {
settingsUiSwitchUiModeElements[i].checked = false;
}
}
}
// ========== API関連の関数など ==========
async function apiConnect (axiosObj) {
let connectionTimerStart = performance.now();
try {
const response = await axios(axiosObj);
let connectionTimerEnd = performance.now();
return {
'apiConnectionTime': connectionTimerEnd - connectionTimerStart,
'response': response.data
};
} catch (error) {
let connectionTimerEnd = performance.now();
console.error(`API request failed: ${error.code}`);
alert(`API request failed: ${error.code}`);
throw error;
}
}
async function loadRequiredDatabase () {
document.querySelectorAll('.fetchingDataNowLabel').forEach((el) => {
el.classList.remove('d-none');
});
apiDataMasterDB = await apiConnect({
'method': 'get',
'url': `https://corsproxy.io/?${encodeURIComponent(`https://hf.co/datasets/DeliberatorArchiver/discography_v2_cdn/resolve/main/db/master.json`)}`,
'headers': apiConnectDefaultHeader,
'timeout': internalConfig.network.timeout
});
apiDataConfig = await apiConnect({
'method': 'get',
'url': `https://corsproxy.io/?${encodeURIComponent(`https://hf.co/spaces/DeliberatorArchiver/discography_v2_cdn_front/resolve/main/config.json`)}`,
'headers': apiConnectDefaultHeader,
'timeout': internalConfig.network.timeout
});
console.log(apiDataMasterDB);
console.log(apiDataConfig);
if (apiDataMasterDB) {
document.querySelector('#databaseTestInfoCodeEl').innerHTML = `OK (Time: ${Math.ceil(apiDataMasterDB.apiConnectionTime)} ms)`;
document.querySelector('#databaseTestOutputCodeEl').innerHTML = JSON.stringify(apiDataMasterDB.response, '', ' ');
} else {
document.querySelector('#databaseTestInfoCodeEl').innerHTML = `Failed`;
}
document.querySelectorAll('.fetchingDataNowLabel').forEach((el) => {
el.classList.add('d-none');
});
}
// ========== MasterDB/Configの暗号化を解く ==========
async function decryptConfig () {
apiDataConfig.response.config.decrypted = new Object();
console.log(`Decrypting config data using AES 128-bit CBC ...`)
const encryptKey = await CryptoJS.enc.Hex.parse(CryptoJS.enc.Base64.parse(apiDataConfig.response.config.encryption.key.split('').reverse().join('')).toString(CryptoJS.enc.Utf8));
const encryptIv = await CryptoJS.enc.Hex.parse(CryptoJS.enc.Base64.parse(apiDataConfig.response.config.encryption.iv.split('').reverse().join('')).toString(CryptoJS.enc.Utf8));
Object.keys(apiDataConfig.response.config.encrypted).forEach(async function (keyName) {
apiDataConfig.response.config.decrypted[keyName] = await CryptoJS.AES.decrypt({
'ciphertext': CryptoJS.enc.Base64.parse(apiDataConfig.response.config.encrypted[keyName])
}, encryptKey, {
'iv': encryptIv,
'mode': CryptoJS.mode.CBC,
'padding': CryptoJS.pad.Pkcs7
}).toString(CryptoJS.enc.Utf8);
});
console.log(`All config data has been decrypted`);
}
// ========== ブラウザのLocalStorageにあるAppSettingsを読み書きする ==========
function loadAppSettingsFromLocalStorage () {
if (localStorage.hasOwnProperty(appSettingsStorageName)) {
appSettingsSaveData = JSON.parse(CryptoJS.enc.Base64.parse(localStorage.getItem(appSettingsStorageName)).toString(CryptoJS.enc.Utf8));
console.warn(`LocalStorage key detected`);
console.log(`Loaded appSettings:`);
console.log(appSettingsSaveData);
} else {
appSettingsSaveData = appSettingsSaveDataDefault;
console.warn(`LocalStorage key not found\nUsing default settings`);
writeAppSettingsToLocalStorage();
}
}
function checkAppSettingsExistsOnStorage () {
if (localStorage.hasOwnProperty(appSettingsStorageName)) {
return true
} else {
return false
}
}
function writeAppSettingsToLocalStorage () {
// CryptoJS.enc.Utf8.parseを使うことでCryptoJS内部形式を強制
localStorage.setItem(appSettingsStorageName, CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(JSON.stringify(appSettingsSaveData))));
console.log(`Wrote appSettings:`);
console.log(appSettingsSaveData);
}