増井俊之
UserScript版EpisoPass
ChatGPTに綺麗にしてもらったもの
code:script.js
/* UserScript版 EpisoPass (cleaned) */
let nquestions = 10;
async function episoq() {
const project = scrapbox?.Project?.name;
if (!project) return;
// --- get my username -------------------------------------------------------
const meRes = await fetch("/api/users/me");
if (!meRes.ok) throw new Error("Failed to fetch /api/users/me");
const me = await meRes.json();
const username = me?.name ?? "";
// --- fetch pages -----------------------------------------------------------
const pagesRes = await fetch(/api/pages/${encodeURIComponent(project)}?limit=1000);
if (!pagesRes.ok) throw new Error("Failed to fetch pages list");
const { pages = [] } = await pagesRes.json();
const questions = [];
const answers = [];
for (const page of pages) {
const isSystemLike =
/^_/.test(page.title) ||
/_$/.test(page.title) ||
page.title === username ||
page.title === "settings" ||
page.pin !== 0;
if (isSystemLike) continue;
if (/\?$/.test(page.title)) {
// Title ends with "?" -> question
questions.push(page.title);
continue;
}
// Otherwise -> answer (maybe prefixed by numeric description)
let title = page.title;
for (const desc of page.descriptions ?? []) {
// original: /^\d(\d+)$/ (e.g. "12")
// keep same behavior:
if (/^\d(\d+)$/.test(desc)) {
title = ${desc} ${title};
}
}
answers.push(title);
}
// --- normalize answers (strip optional leading token like "12 " etc.) ------
const normalizedAnswers = answers
.sort()
.map((s) => (s.match(/^(\w+\s+)?(.*)$/)?.2 ?? s));
// --- pick random questions -------------------------------------------------
const pickedQuestions = questions
.slice()
.sort(() => 0.5 - Math.random())
.slice(0, nquestions);
const qstr = pickedQuestions.join(";");
const astr = normalizedAnswers.join(";");
// --- jump to EpisoPass -----------------------------------------------------
const url = new URL("http://episopass.com/");
url.searchParams.set("questions", qstr);
url.searchParams.set("answers", astr);
url.searchParams.set("n", String(nquestions));
location.href = url.toString();
}
document.addEventListener("keydown", async (e) => {
// Ctrl-C で実行
if (e.ctrlKey && e.key.toLowerCase() === "q") {
const input = window.prompt("問題の数を指定してください", "10");
const n = Number(input);
if (Number.isFinite(n) && n > 0) {
nquestions = n;
try {
await episoq();
} catch (err) {
console.error(err);
alert(String(err));
}
}
}
});
code:script.js___
var nquestions = 10;
async function episoq() {
var questions = []
var answers = []
var project = scrapbox.Project.name
var res = await fetch('/api/users/me')
var data = await(res.json())
var username = data.name
res = await fetch(/api/pages/${project}?limit=1000);
data = await res.json();
//alert(data.pages0.descriptions1)
data.pages.forEach ( page => {
var title = page.title
if(title.match(/^_/) || title.match(/_$/) || title == username || title == 'settings' || page.pin != 0){
}
else {
if(title.match(/\?$/)){
questions.push(title)
}
else {
page.descriptions.forEach ( description => {
if(description.match(/^\d(\d+)$/)){
title = description + ' ' + title;
}
})
answers.push(title)
}
}
})
answers = answers.sort().map ((e) => e.match(/^(\w+\s+)?(.*)$/)2 )
var qstr = questions.sort(() => 0.5 - Math.random()).slice(0,nquestions).join(';')
var astr = answers.join(';')
location.href = http://episopass.com/?questions=${qstr}&answers=${astr}&n=${nquestions}
}
document.addEventListener('keydown', e => {
if (e.key == 'c' && e.ctrlKey){ // Ctrl-Cで実行
nquestions = Number(window.prompt('問題の数を指定してください','10'))
if (nquestions != 0){
episoq()
}
}
})
デフォルトのPopup Menuを消す
code:style.css
.popup-menu .strike-button,
.popup-menu .italic-button,
.popup-menu .copy-plain-button,
.popup-menu .link-button,
.popup-menu .strong-button {
display: none !important;
}
PopupMenuからEpisoPassを呼ぶ
code:script.js
scrapbox.PopupMenu.addButton({
title: '暗号化/復号',
onClick: text => {
window.open(https://s3-ap-northeast-1.amazonaws.com/masui.org/e/a/eab4a39ed37c0c467874d8ec32a320e1.html?seed=${text})
}
})
🔑abcdefg みたいなのをクリックするとEpisoPassを開く
code:script.js
const KEY_EMOJI = '🔑';
const EPISOPASS_URL = 'http://masui.org/eab4a39ed37c0c467874d8ec32a320e1.html';
document.addEventListener('click', (event) => {
const link = event.target.closest('a.page-link');
if (!link) return;
const title = (link.getAttribute('title') || link.textContent || '').trim();
if (!title.startsWith(KEY_EMOJI)) return;
const seed = title.slice(KEY_EMOJI.length);
if (!seed) return;
event.preventDefault();
event.stopPropagation();
window.open(${EPISOPASS_URL}?seed=${encodeURIComponent(seed)}, '_blank');
}, true);