您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Inject the information of a DLSite product to your restaurant.
- // ==UserScript==
- // @name DLSite Product Information Injector
- // @description Inject the information of a DLSite product to your restaurant.
- // @namespace dl_injecter
- // @version 2.0.0
- // @grant GM_xmlhttpRequest
- // @match https://arca.live/b/simya/*
- // @run-at document-end
- // @noframes
- // ==/UserScript==
- var fullRegexs = [/(RJ)[0-9]{6}\b|(RJ)[0-9]{8}\b/gi, /(VJ)[0-9]{6}\b|(VJ)[0-9]{8}\b/gi];
- var partialRegexs = [/[0-9]{8}|[0-9]{6}/gi];
- var languageRegexs = [/(거|퍼)[0-9]{6}\b|(거|퍼)[0-9]{8}\b/gi];
- var defaultPrefix = 'RJ';
- var default2Prefix = 'VJ';
- // Get matched products from text.
- function getMatchedProducts(text) {
- // Preprocess the inputted text.
- text = String(text);
- text = text.replace(/https?:\/\/(arca.live\/b\/simya\/)[0-9]*/g, ""); // Ignore arca live post url.
- // Get matches from the text with regexs.
- var matches = [];
- for (let i = 0; i < fullRegexs.length; i++) {
- let tempArr = [];
- tempArr = text.match(fullRegexs[i]);
- if (tempArr == null) {
- continue;
- }
- for (let j = 0; j < tempArr.length; j++) {
- if (tempArr[j] != null) {
- matches.push(tempArr[j].toUpperCase());
- }
- }
- }
- for (let i = 0; i < languageRegexs.length; i++) {
- let tempArr = [];
- tempArr = text.match(languageRegexs[i]);
- if (tempArr == null) {
- continue;
- }
- for (let j = 0; j < tempArr.length; j++) {
- if (tempArr[j] != null) {
- // If the product code is already exist, ignore current index.
- var text_check = tempArr[j].substr(0, 1);
- tempArr[j] = tempArr[j].substr(1);
- if ("거" == text_check) {
- matches.push(defaultPrefix.toUpperCase() + tempArr[j]);
- }
- if ("퍼" == text_check) {
- matches.push(default2Prefix.toUpperCase() + tempArr[j]);
- }
- }
- }
- }
- for (let i = 0; i < partialRegexs.length; i++) {
- let tempArr = [];
- tempArr = text.match(partialRegexs[i]);
- if (tempArr == null) {
- continue;
- }
- for (let j = 0; j < tempArr.length; j++) {
- if (tempArr[j] != null) {
- // If the product code is already exist, ignore current index.
- if (matches.includes("RJ" + tempArr[j]) || matches.includes("VJ" + tempArr[j])) {
- break;
- }
- if (matches.includes("거" + tempArr[j]) || matches.includes("퍼" + tempArr[j])) {
- break;
- }
- matches.push(defaultPrefix.toUpperCase() + tempArr[j]);
- }
- }
- }
- // Remove duplicated elements.
- var result = [];
- matches.forEach((element) => {
- if (!result.includes(element)) {
- result.push(element);
- }
- });
- return result;
- }
- // Provide Fetch feature.
- function doFetch(url, options = {
- method: 'GET',
- responseType: 'document'
- }, silent = false) {
- return new Promise((resolve, reject) => {
- GM_xmlhttpRequest({
- url: url,
- method: options.method,
- responseType: options.responseType,
- headers: options.headers,
- data: options.data,
- onload: result => {
- console.debug(result)
- if (result.status == 200) {
- resolve(result.response);
- } else {
- if (!silent) {
- console.log(result)
- alert("알 수 없는 오류로 인해 데이터를 불러오지 못했습니다. " + url)
- reject(result.status);
- } else {
- console.debug(result)
- reject(result.status);
- }
- }
- }
- });
- });
- }
- // Format number as bytes string.
- function formatBytes(bytes, decimals = 2) {
- if (bytes === 0) {
- return '-';
- }
- const k = 1024;
- const dm = decimals < 0 ? 0 : decimals;
- const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
- const i = Math.floor(Math.log(bytes) / Math.log(k));
- return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
- }
- // Convert a array to a string.
- function arr2str(arr, opt = ", ") {
- let idx = arr.indexOf("")
- while (idx > -1) {
- arr.splice(idx, 1)
- idx = arr.indexOf("")
- }
- return String(arr).replace(/"/g, '').replace('[', "").replace(']', "").replace(/,/g, opt)
- }
- // Get a product information from DLSite.
- function getProductInformation(productCode) {
- return new Promise((resolve, reject) => {
- const url = `https://www.dlsite.com/maniax/api/=/product.json?workno=${productCode}&locale=ko-KR`
- doFetch(url, {
- method: 'GET',
- responseType: 'application/json'
- })
- .then(result => {
- const json = JSON.parse(result)[0];
- if (json) {
- const processedJson = Object()
- processedJson.thumbnailImage = [`<img width='180' height='120' src='https:${json.image_main.url}' alt='이미지'>`]
- processedJson.workType = [`${json.work_type} / ${json.work_type_string}`]
- processedJson.title = [`<a target='_blank' href='https://www.dlsite.com/home/work/=/product_id/${productCode}.html'>${json.work_name}</a>`]
- processedJson.intro = [json.intro_s]
- processedJson.maker = [json.maker_name]
- if (json.genres) {
- processedJson.genres = []
- json.genres.forEach(genre => {
- processedJson.genres.push(genre.name)
- })
- processedJson.genres = [arr2str(processedJson.genres)]
- }
- processedJson.fileInfo = [`${json.file_type}(${formatBytes(json.contents_file_size)})`]
- processedJson.workUrl = [`<a target='_blank' href='https://www.dlsite.com/home/work/=/product_id/${productCode}.html'>${productCode}</a>`]
- processedJson.circleUrl = [`<a target='_blank' href='https://www.dlsite.com/home/circle/profile/=/maker_id/${json.circle_id}.html'>${processedJson.maker}</a>`]
- resolve(processedJson);
- } else {
- reject(new Error("Request is failed."));
- }
- })
- });
- }
- function createProductElement(productCode) {
- return new Promise((resolve, reject) => {
- getProductInformation(productCode).then(function(data) {
- var html = '<table width="100%" border="0">' +
- '<tbody>' +
- '<tr><!-- 첫번째 줄 시작 -->' +
- `<td style="width: 1px; white-space: nowrap;" rowspan="2">${data.thumbnailImage}</td>` +
- '<td valign="center">' +
- '<div>' +
- `<div><span class="badge badge-success" style="display:inline-block; margin:0px 0px 0px 10px">${data.workUrl}</span><span class="badge badge-success" style="display:inline-block; margin:0px 4px 0px 4px">${data.workType}</span>${data.title}</div>` +
- `<div style="display:block; margin:0px 0px 0px 16px; font-size: 0.8375em; opacity: 0.8;"><li>설명 : ${data.intro}</li></div>` +
- `<div style="display:block; margin:0px 0px 0px 16px; font-size: 0.8375em; opacity: 0.8;"><li>서클 : ${data.circleUrl}</li></div>` +
- `<div style="display:block; margin:0px 0px 0px 16px; font-size: 0.8375em; opacity: 0.8;"><li>태그 : ${data.genres}</li></div>` +
- `<div style="display:block; margin:0px 0px 0px 16px; font-size: 0.8375em; opacity: 0.8;"><li>파일(용량) : ${data.fileInfo}</li></div>` +
- `<div></div>` +
- '</div>' +
- '</td>' +
- '</tr><!-- 첫번째 줄 끝 -->' +
- '</tbody>' +
- '</table>';
- resolve(html);
- });
- });
- }
- (function() {
- 'use strict';
- // Get article wrapper element.
- let articleView = document.getElementsByClassName("article-view")[0];
- let articleWrapper = document.getElementsByClassName("article-wrapper")[0];
- // Add the headline.
- let contentsElement = document.createElement('p');
- contentsElement.innerHTML = '<span class="ion-android-archive" style="display:inline-block; width:20px; margin:4px 0px 0px 12px;"></span>게시글에서 언급된 게임 목록';
- articleView.insertBefore(contentsElement, articleWrapper);
- // Get product codes in article.
- var products = [];
- products = getMatchedProducts(articleWrapper.innerText);
- console.log(products);
- if (products.length > 0) {
- // Insert elements into article-view element.
- for (var i = 0; i < products.length; i++) {
- createProductElement(products[i]).then(function(html) {
- let contentsElement = document.createElement('div');
- contentsElement.setAttribute("class", "alert alert-info");
- contentsElement.innerHTML = html;
- articleView.insertBefore(contentsElement, articleWrapper);
- });
- }
- }
- })();