(仮)Wizball の詳細ページを保存用に、ちょっといじる Fork

    
      
      
  • /*
     * @title (未完成)Wizball の詳細ページを保存用に、ちょっといじる
     * @description (未完成)Wizball の詳細ページを保存用に、ちょっといじる
     * @include https://m.wizball.io/questions/*
     * @license MIT License http://opensource.org/licenses/MIT
     * @javascript_url *
     */
    /*
    	全ページ読み込む
    
    	create 2019-07-03
    */
    (async _ => {
    	const d_ = document;
    	if (location.hostname != "m.wizball.io") {
    		alert("Please use at m.wizball.io !");
    		return;
    	}
    	async function display_comments() {
    		console.log("!!! load comments !!!");
    		const list = d_.querySelectorAll(".comment_list");
    		for (let i = 0 ; i < list.length ; ++i) {
    			const first_item = list[i].querySelector(".comment_txt");
    			if (! first_item) {		// 質問はコメントがなくても UL 要素がある
    				continue;
    			}
    			const orig_url = first_item.href;
    			const url_base = orig_url.replace(/questions/, "apis/v1/questions");
    			const comments = [];
    			let page = 1;
    			while (true) {
    				const url = `${url_base}?page=${page}&size=50&sort=LATEST`;
    				const resp = await fetch(url);
    				const json = await resp.json();
    				if (json.length > 0) {
    					comments.push(... json);
    					page += 1;
    				} else {
    					break;
    				}
    			}
    			console.log(comments);
    			list[i].innerHTML = "";
    			comments.forEach(c => {
    				let img;
    				if (c.author.image) {
    					img = `<img src="https://obs.line-scdn.net/${c.author.image.hash}/s150" class="user_20" title="${c.author.nickname}">`;
    				} else {
    					img = `<img src="" class="user_20" title="${c.author.nickname}">`;
    				}
    				const item = Object.assign(d_.createElement("li"), {
    					className: "comment_item",
    					innerHTML: `<div class="comment_item_inner"><div class="profile_img comment_icon">${img}</div><a href="/users/${c.author.id}" class="user_id">${c.author.nickname}</a> <a href="${orig_url}" class="comment_txt type_space">${c.text}</a></div>`,
    				});
    				list[i].appendChild(item);
    			});
    			const comment_value = list[i].parentNode.querySelector(".comment_list ~ .comment_value");
    			console.log(comment_value);
    			list[i].parentNode.insertBefore(comment_value, list[i]);
    		}
    	}
    
    	async function load_q(qid) {
    		const resp = await fetch(`/apis/v1/questions/${qid}`);
    		const json = await resp.json();
    		return json;
    	}
    	async function load_a(qid) {
    		const map = {};
    		for (let p = 1 ; p <= 300 ; ++p) {
    			const resp = await fetch(`/apis/v1/questions/${qid}/answers?page=${p}&size=50&sort=POPULAR`);
    			const json = await resp.json();
    			if (json.length == 0) {
    				break;
    			}
    			json.forEach(a => {
    				map[a.id] = a;
    			});
    		}
    		return map;
    	}
    	async function load_v(a) {
    		let ub;
    		if (a.questionId) {		// answer
    			ub = `/apis/v1/questions/${a.questionId}/answers/${a.id}/voters?size=50&sort=LATEST&`;
    		} else { // question
    			ub = `/apis/v1/questions/${a.id}/votes?size=50&sort=LATEST&`;
    		}
    		const list = [];
    		for (let p = 1 ; p <= 300 ; ++p) {
    			const resp = await fetch(ub + `page=${p}`);
    			const json = await resp.json();
    			if (json.length == 0) {
    				break;
    			}
    			list.push(... json);
    		}
    		return list;
    	}
    
    	function modify_time(e, q) {
    		const qt = e.querySelector(".user_info_detail.date");
    		qt.innerHTML = (new Date(q.createdAt)).toLocaleString();
    	}
    
    	async function display_voters(e, a) {
    		const eopt = e.querySelector(".qna_option_area");
    		const ea = d_.createElement("div");
    		ea.className = "vote_area";
    		eopt.parentNode.insertBefore(ea, eopt);
    //		eopt.parentNode.insertBefore(eul, eopt);
    		const v = await load_v(a);
    		ea.innerHTML = '<div class="vote_value">Vote : ' + v.length + '</div>';
    		const eul = d_.createElement("ul");
    		ea.appendChild(eul);
    		eul.className = "voter_list";
    		v.forEach(v => {
    			const li = eul.appendChild(d_.createElement("li"));
    			li.className = "voter_item profile_img";
    //			li.innerHTML = v.author.nickname + ", ";
    			if (v.author.image) {
    				li.innerHTML = `<img src="https://obs.line-scdn.net/${v.author.image.hash}/s150" class="user_20" title="${v.author.nickname}">`;
    			} else {
    				li.innerHTML = `<img src="" class="user_20" title="${v.author.nickname}">`;
    			}
    		});
    	}
    
    	async function modify_data() {
    		const m = /\/questions\/(\d+)/.exec(location.href);
    		const qid = m[1];
    		const q = await load_q(qid);
    		const qe = d_.querySelector(".qna_area.question");
    		modify_time(qe, q);
    //		const qv = await load_v(q);
    		await display_voters(qe, q);
    
    		const a = await load_a(qid);
    		const ae = d_.querySelectorAll(".qna_area.answer .answer_item");
    		console.log(ae);
    		for (let i = 0 ; i < ae.length ; ++i) {
    			const bc = ae[i].querySelector(".btn_comment");
    			const m = /answers\/(\d+)/.exec(bc.href);
    			const aid = m[1];
    			modify_time(ae[i], a[aid]);
    //			const av = await load_v(a);
    			await display_voters(ae[i], a[aid]);
    		}
    	}
    
    	async function modify_window() {
    		await display_comments();
    		await modify_data();
    	}
    
    	const more_btn = d_.querySelector(".qna_area.answer .btn_more_answer");
    	console.log(more_btn)
    	if (more_btn) {
    		d_.body.appendChild(Object.assign(d_.createElement("style"), {
    			innerHTML: `
    body: {
    	max-width: 640px;
    }
    .wrap.home_end .content .qna_area_inner .comment_area .comment_item_inner .comment_txt {
    	max-height: none;
    }
    .comment_item_inner .comment_icon, .voter_list .voter_item {
    	width: 20px;
    	height: 20px;
    	margin-right: 0.5ex;
    }
    .comment_item_inner .comment_icon {
    	float: left;
    }
    .user_20 {
    	border-radius: 50%;
    	width: 100%;
    }
    .wrap.home_end .content .question_logo {
    	font-size: inherit;
    	color: inherit;
    	font-size: 15px;
    	color: #959aa5;
    }
    .wrap.home_end .content .qna_area_inner .comment_area .comment .comment_value {
    	padding-top: 0;
    	padding-bottom: 10px;
    }
    .qna_area.question .vote_area {
    	padding: 14px 22px 0;
    }
    .vote_value {
    	padding-bottom: 10px;
    }
    .vote_area {
    	color: #959aa5;
    	font-size: 15px;
    }
    .voter_item {
    	display: inline-block;
    }
    			`,
    		}));
    		let n = 0;
    		const answer_list = d_.querySelector(".answer_list");
    		// https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
    		const MutationObserver = window.MutationObserver || window.WebkitMutationObserver;
    		const observer = new MutationObserver(async function (records) {
    			n += 1;
    			console.log(n);
    			if (more_btn.style.display != "none") {
    				more_btn.click();
    				if (n > 10) {
    					observer.disconnect();
    				}
    			} else {
    				await modify_window();
    			}
    		});
    		observer.observe(answer_list, { childList: true, /* subtree: true */ });
    
    		if (more_btn.style.display != "none") {
    			more_btn.click();
    		} else {
    			await modify_window();
    		}
    	}
    })();
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。