
Mozilla Public v 2.0
JavaScript
2021年02月23日
javascript:
/**
* @file クロスマーケット2のワールドをマイリストへ一括登録するブックマークレットです。
* 登録完了まで数秒ほどかかり、完了したことを通知するダイアログが表示されます。
* @version 1.0.0
* @license MPL-2.0
* @author 100の人
* @see {@link https://twitter.com/esperecyan}
*/
(async function () {
'use strict';
/**
* 何番目のマイリストへ登録するかを 1 〜 4 で指定。
* @constant {number}
*/
const NUMBER = 4;
/**
* 登録するワールドID。
* @constant {string[]}
*/
const WORLD_IDS = [
'wrld_3aaf1c48-05bf-4765-a100-8315b1c11ca4',
'wrld_54396534-69ad-4b1f-b9e2-48debe2025f1',
'wrld_00dc34ea-ffe3-483a-98a6-2f364d160432',
'wrld_eb1e11d2-28d2-468b-b913-be84f311225a',
'wrld_b64f814d-afe5-493d-8030-7e24435027c7',
'wrld_1a32bc38-ecf5-43c8-bd87-0cbe85ab3127',
'wrld_c187fd45-a9a5-44c8-87d2-8bc83389b8f8',
'wrld_f1061d17-ac82-4fce-b205-e71df5a1e3e8',
'wrld_abb15d41-df9a-4bd7-9292-f1f95572b9c2',
'wrld_18d313cf-2e96-45fb-84a6-c6954d7063af',
'wrld_89f83bfb-5651-451d-81c6-dd691d630fb7',
'wrld_f02d9269-200c-4b2f-9d2f-bc1eb361cbd9',
'wrld_c78bd309-b349-4e49-b1e4-33d8f006e517',
];
/**
* マイリストのグループ名。インデックス順。
* @constant {string[]}
*/
const MYLIST_NAMES = ['worlds0', 'worlds2', 'worlds3', 'worlds4'];
/**
* 一つのブックマークグループの最大登録数。
* @constant {number}
*/
const MAX_FAVORITES_COUNT_PER_GROUP = 32;
/**
* 一度に取得できる最大の要素数。
* @constant {number}
*/
const MAX_ITEMS_COUNT = 100;
/**
* JSONファイルをオブジェクトとして取得します。
* @param {RequestInfo} url
* @param {RequestInit}
* @returns {Promise.<(Object|Array)>} OKステータスでなければ失敗します。
*/
async function fetchJSON(input, requestInit = {credentials: 'same-origin'})
{
const response = await fetch(input, requestInit);
return response.ok
? response.json()
: Promise.reject(new Error(`${response.status} ${response.statusText}\n${await response.text()}`));
}
/**
* マイリストを全件取得します。
* @see [List Favorites — VRChat API Documentation]{@link https://vrchatapi.github.io/#/FavoritesAPI/ListAllFavorites}
* @returns {Promise.<(string|string[])>} ワールドID一覧の配列の、マイリスト順の配列。
*/
async function fetchMylistIndexWorldIdsPairs()
{
const mylistIndexWorldIdsPairs = [[], [], [], []];
let offset = 0;
while (true) {
const favorites = await fetchJSON(`/api/1/favorites/?type=world&n=${MAX_ITEMS_COUNT}&offset=${offset}`);
for (const favorite of favorites) {
mylistIndexWorldIdsPairs[MYLIST_NAMES.indexOf(favorite.tags[0])].push(favorite);
}
if (favorites.length < MAX_ITEMS_COUNT) {
break;
}
offset += favorites.length;
}
return mylistIndexWorldIdsPairs;
}
/**
* マイリストへワールドを追加します。
* @see [Add Favorite — VRChat API Documentation]{@link https://vrchatapi.github.io/#/FavoritesAPI/AddFavorite}
* @param {number} mylistIndex - 何番目のマイリストへ追加するか、0から始まるインデックス。
* @param {string} worldId
* @returns {Promise.<void>}
*/
async function addWorldToMylist(mylistIndex, worldId)
{
await fetch('/api/1/favorites', {
method: 'POST',
headers: { 'content-type': 'application/json' },
credentials: 'same-origin',
body: JSON.stringify({ type: 'world', favoriteId: worldId, tags: [ MYLIST_NAMES[mylistIndex] ] }),
});
}
const mylistIndexWorldIdsPairs = await fetchMylistIndexWorldIdsPairs();
const mylistWorldIds = mylistIndexWorldIdsPairs.flat();
const worldIds = WORLD_IDS.filter(id => !mylistWorldIds.includes(id));
if (worldIds.length > MAX_FAVORITES_COUNT_PER_GROUP - mylistIndexWorldIdsPairs[NUMBER - 1].length) {
alert(`${NUMBER}番目のマイリストには空きが不足しています。`);
return;
}
for (const worldId of worldIds.reverse()) {
await addWorldToMylist(NUMBER - 1, worldId);
}
alert(`${NUMBER}番目のマイリストへの登録が完了しました。`);
})().catch(function (exception) {
console.error(exception);
alert('エラーが発生しました: ' + exception + ('stack' in exception ? '\n\n' + exception.stack : ''));
});
登録完了まで数秒ほどかかり、完了したことを通知するダイアログが表示されます。
No one still commented. Please first comment.
Output