// ==UserScript==
// @name 5ch Plus
// @name:ja 5ch プラス
// @description 5ch を拡張します
// @author null-chan <[email protected]>
// @version 0.1.0
// @run-at document-body
// @include http*://*5ch.net/*
// @include http*://imgur.com/*
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js
// @namespace http://greasyfork.icu/users/379206
// ==/UserScript==
'use strict'
$(window).on('load', () => console.info('window.on(\'load\')'))
const parse_json = object => {
let x
let ret = ''
for (x in object) {
let y
let dec = ''
for (y in object[x]) dec += `${y}:${object[x][y]}!important;`
ret += `${x}{${dec}}`
}
return ret
}
const generateColor = () => {
// https://stackoverflow.com/questions/1484506/random-color-generator
const letters = '0123456789abcdef'
let color = ''
for (let i = 0; i < 6; i++)
color += letters[Math.floor(Math.random() * 16)]
return color
}
const preset = {
'imgur.com/[a-zA-Z0-9]{7}': {
script: () => (location.href = $('meta[name="twitter:image"]').attr('content')),
},
global: {
style: {
html: {
'font-family': 'メイリオ,Arial',
},
},
script: () => $(window).on('load', () => {
$('a[href^="https://"],a[href^="http://"],a[href^="/"]').each(function () {
let href = $(this).attr('href')
console.info(`Detected link: %c${$(this).html()}%c - %c${href}`, 'text-decoration:underline', '', 'text-decoration:underline')
if (/^(https?:)?\/\/jump[.]5ch[.]net\/[?]/.test($(this).attr('href'))) href = $(this).text()
$(this).addClass('rinku')
$(this).attr({
href: href,
rel: 'noreferrer noopener',
target: '_blank',
title: 'ページは新しいタブで開かれます (rel="noreferrer noopener")',
})
})
$(document).on('mouseenter', '.thread .rinku:not([data-tooltip])', function () {
console.info(`Hovered: ${$(this).attr('href')}`)
if ($(this).hasClass('loadeding')) return
$(this).addClass('loadeding')
const uralu = (new RegExp('^(https?:)?//.*5ch[.]net/').test($(this).attr('href')) ? '' : 'https://cors-anywhere.herokuapp.com/') + $(this).attr('href')
$(this).attr('title', 'Loading...')
console.log(`Loading: ${uralu}`)
$.get(uralu, (res, _, xhr) => {
const type = xhr.getResponseHeader('content-type')
console.info(`Loaded: ${uralu} - ${type}`)
let title
if (type.includes('text/html')) title = $(res).filter('title').text() || 'No title found'
else title = `The link destination is not HTML - ${type}`
$(this).attr('title', title)
$(this).after(`<br><span style='color:#808080'>${title}</span>`)
})
})
}),
},
'http://.*5ch[.]net.*': {
protocol: true,
script: () => location.href = location.href.replace(new RegExp('^http://'), 'https://'),
},
'.*[^jump][.]5ch[.]net/[a-z]{1,}/(#[0-9]{1,2})?': {
style: {
body: {
background: 'url(https://picsum.photos/1920/1080?blur=5) center no-repeat fixed',
'background-size': 'cover',
},
'div[style="margin: 0; padding: 0 0 0 0.5em; border-top: 0.5em solid #BEB; border-bottom: 0.5em solid #BEB; border-radius: 0.50em / 0.50em; padding: 0 0 1.0em 0.5em; height: 25em; overflow-y: scroll; background: #BEB;"]': {
height: 'auto',
'max-height': '25em',
},
'.ADVERTISE_AREA,div[style="margin-top:10px;margin-bottom:10px;width:100%;text-align:center;"]': {
display: 'none',
},
},
},
'.*[.]5ch[.]net/test/read.cgi/.*': {
style: {
'.navbar-fixed-top': {
background: 'rgba(0, 0, 0, 0.7)',
},
'.container_body': {
background: 'none',
margin: 0,
padding: 0,
},
'#background': {
height: '100%',
width: '100%',
background: 'url(https://picsum.photos/1920/1080) center no-repeat fixed',
'background-size': 'cover',
'z-index': -1,
position: 'fixed',
top: 0,
filter: 'blur(5px)',
transition: 'all 0.3s linear',
},
'#background.cleek': {
filter: 'blur(0)',
},
'#search-text,#search-button': {
'border-radius': '30px 0 0 30px',
background: 'none',
border: '1px solid rgba(255,255,255,0.5)',
filter: 'invert(0.4)',
},
'#search-button': {
'border-radius': '0 30px 30px 0',
'border-left': 'none',
transition: 'all 0.2s ease-in-out',
},
'#search-text:focus,#search-button:hover': {
filter: 'invert(0)',
},
'.title': {
'margin-top': '70px',
'font-size': '30px',
color: '#f5f5f5',
'text-shadow': '0 1px 10px #212121',
},
'.stoplight': {
background: 'rgba(255, 23, 68, 0.6)',
'margin-bottom': '10px',
'text-align': 'center',
},
'.thread': {
'margin-left': '30%',
},
'.post,.post_hover,.menuitem': {
'border-radius': '15px',
background: 'rgba(0, 0, 0, 0.7)',
'box-shadow': '5px 5px 30px black',
transition: 'all 0.2s ease-in-out',
},
'.post,.post_hover': {
'margin-bottom': '15px',
'max-width': '800px',
padding: 0,
},
'.post:hover': {
transform: 'scale(1.02, 1.02)',
'box-shadow': 'none',
},
'.meta': {
background: 'rgba(0, 0, 0, 0.4)',
'border-radius': '15px 15px 0 0',
padding: '5px 10px 5px 10px',
},
'.message': {
margin: '0 10px',
padding: '5px 0 10px',
},
'.message > .escaped': {
color: 'white',
},
'.message > .escaped > hr': {
'border-top': '1px solid #616161',
},
'.meta > .number,.date': {
color: '#bdbdbd',
},
'.be': {
'margin-left': '5px',
},
'.escaped > a': {
color: '#42a5f5',
'text-shadow': '1px 1px 10px white',
transition: 'all 0.2s ease-in-out',
},
'.escaped > a:hover': {
'text-shadow': 'none',
},
'.meta a': {
color: 'green',
},
'br,nav': {
'user-select': 'none',
},
'.menuitem': {
'box-shadow': '3px 3px 20px black',
},
'.menuitem:hover': {
'box-shadow': '1px 1px 20px black',
},
'.footer': {
padding: '50px 0 20px 0',
},
'.search-logo': {
filter: 'invert(0.5)',
transition: 'all 0.2s ease-in-out',
},
'.search-logo:hover': {
filter: 'invert(1)',
},
'#post-form-inner': {
background: 'rgba(0, 0, 0, 0.7)',
border: 'none',
},
'.navbar-fixed-top,.pagestats,.menuitem,.topmenu,.bottommenu,.post,.post_hover': {
border: 'none',
color: 'white',
},
'.socialmedia,#banner,.ad--right,.ad--bottom': {
display: 'none',
},
'.post[data-id="1002"]': {
display: 'none',
},
'.mail_parse': {
'margin-right': '5px',
},
},
lang: {
'.menuitem:contains(全部)': 'All',
'.menuitem:contains(最新50)': 'Latest 50',
'.menuitem:contains(スマホ版)': 'Mobile (Not Supported)',
'.menuitem:contains(掲示板に戻る)': 'Back to Board Top',
'.menuitem:contains(ULA版)': 'ULA (Not Supported)',
'.metastats:contains(コメント)': ['コメント', ' Comments'],
},
script: () => {
let long_timer
let long_cleek = false
$('.container_body').append('<div id="background"></div>')
$('#background')
.on('dblclick', () => $('#background').toggleClass('cleek'))
.on('mouseup', () => {
if (long_cleek) $('#background').attr('style', `background:url(https://picsum.photos/1920/1080?${new Date().getTime()}) center no-repeat fixed!important`)
long_cleek = false
clearTimeout(long_timer)
return true
})
.on('mousedown', () => {
long_timer = setTimeout(() => long_cleek = true, 500)
return true
})
$(window).on('load', () => {
const ids = []
$('.post[data-id="1001"] .name b').text('オーバースレッドゥ')
$('.uid').each(function () {
const id = $(this).text().slice(3)
const ids_ = ids.filter(item => item[0] === id)
if (!ids_.length) {
const color = generateColor()
ids.push([id, color])
console.log(`ID: ${[id, color]}`)
$(this).attr('title', `#${color}`)
return $(this).css('color', `#${color}`)
}
$(this).attr('title', `#${ids_[0][1]}`)
return $(this).css('color', `#${ids_[0][1]}`)
})
$('.name b a[href^="mailto:"]').each(function () {
let supeisharu = ['フメイ', $(this).attr('href').slice(7)]
if (supeisharu[1] === 'sage') supeisharu[0] = 'サゲ'
else if (supeisharu[1] === 'age') supeisharu[0] = 'アゲ'
else if (supeisharu[1].test(/@(yahoo.co.jp)$/)) supeisharu[0] === 'ヤホー'
else if (supeisharu[1].test(/@(protonmail.com|protonmail.ch|pm.me)$/)) supeisharu[0] === 'プロト'
$(this).parents('.meta').children('.date').before(`<a class='mail_parse' href='${$(this).attr('href')}' title='${supeisharu[1]}' style='color:#81c784!important'>(${supeisharu[0]})</a>`)
})
$('.name a[href^="mailto:"]').each(function () { $(this).removeAttr('href') })
})
$('.date').each(function () {
$(this).html($(this).text().replace(' ', '<span style="margin-right:5px!important"></span>'))
})
},
},
}
$('head').append(`<style type="text/css">${parse_json(preset.global.style)}</style>`)
preset.global.script()
Object.keys(preset).map(item => {
if (item === 'global') return
let path = preset[item]
let url = location.href
if (!preset[item].protocol) url = location.href.slice(location.protocol.length + 2)
const match = new RegExp(`^${item}$`).test(url)
console.info(`${match ? '\x1b[32m' : '\x1b[31m'}Match: ^${item}$ - ${url} - ${match}`)
if (match) {
if (typeof path.style === 'object') $('head').append(`<style type="text/css">${parse_json(path.style)}</style>`)
if (typeof path.lang === 'object') Object.keys(path.lang).map(item => {
if (typeof path.lang[item] === 'string')
$(item).text(path.lang[item])
else if (typeof path.lang[item] === 'object')
$(item).html($(item).html().replace(path.lang[item][0], path.lang[item][1]))
})
if (typeof path.script === 'function') path.script()
}
})