Last active
May 9, 2017 17:34
-
-
Save XVicarious/3a27fd4f8ca54782f2a7542e0fdeb794 to your computer and use it in GitHub Desktop.
Arrows that Meme
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//META{"name":"MemeArrowsLite"}*// | |
function MemeArrowsLite() { | |
/** | |
* Runs the converting of ">text" to green text, or "MemeArrows" | |
*/ | |
function modifier() { | |
$('.message-text>.markup:not(.green-text)').each(function() { | |
if ($(this).text().substr(0, 1) === '>') { | |
$(this).addClass('green-text'); | |
} | |
}); | |
} | |
const mutationObserver = new MutationObserver(function(mutations) { | |
mutations.forEach(function(mutation) { | |
if (mutation.type === 'childList' && mutation.addedNodes.length) { | |
mutation.addedNodes.forEach(function(addedNode) { | |
if (addedNode.classList.contains('message-group') || | |
addedNode.classList.contains('message')) { | |
modifier(); | |
} | |
}); | |
} else if (mutation.type === 'characterData') { | |
modifier(); | |
} | |
}); | |
}); | |
const observerConfig = { | |
childList: true, | |
characterData: true, | |
subtree: true, | |
}; | |
const _ = this; | |
_.getName=()=>'MemeArrowsLite'; | |
_.getDescription=()=>'halfchan\'s green text has appeard! In Discord!'; | |
_.getVersion=()=>'1.1.0'; | |
_.getAuthor=()=>'XVicarious'; | |
_.load = function() { | |
BdApi.injectCSS('MemeArrows-InjectedStyleSheet', | |
'.markup.green-text{color:#789922!important}'); | |
}; | |
_.start = function() { | |
_.setupObservers(); | |
modifier(); | |
}; | |
_.stop = function() { | |
mutationObserver.disconnect(); | |
}; | |
_.onSwitch = function() { | |
_.setupObservers(); | |
}; | |
_.setupObservers = function() { | |
let $mainNode = $('div.scroller.messages').last(); | |
mutationObserver.observe($mainNode[0], observerConfig); | |
}; | |
_.getSettingsPanel = function() { | |
return 'settingsPane'; | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//META{"name":"MemeArrows"}*// | |
function MemeArrows() { | |
/** | |
* Runs the converting of ">text" to green text, or "MemeArrows" | |
*/ | |
function modifier() { | |
$('.message-text>.markup:not(.green-text)').each(function() { | |
if ($(this).text().substr(0, 1) === '>') { | |
$(this).addClass('green-text'); | |
} | |
}); | |
} | |
const mutationObserver = new MutationObserver(function(mutations) { | |
mutations.forEach(function(mutation) { | |
if (mutation.type === 'childList' && mutation.addedNodes.length) { | |
mutation.addedNodes.forEach(function(addedNode) { | |
if (addedNode.classList.contains('message-group') || | |
addedNode.classList.contains('message')) { | |
if (preferences.greentext) { | |
modifier(); | |
} | |
if (preferences.filters) { | |
filterModifier(); | |
} | |
} | |
}); | |
} else if (mutation.type === 'characterData') { | |
if (preferences.greentext) { | |
modifier(); | |
} | |
if (preferences.filters) { | |
filterModifier(); | |
} | |
} | |
}); | |
}); | |
const observerConfig = { | |
childList: true, | |
characterData: true, | |
subtree: true, | |
}; | |
/** | |
* Runs the converting of certain words to other words, with pretty colors | |
*/ | |
function filterModifier() { | |
$('.message-text>.markup:not(.filtered)').each(function() { | |
let $markup = $(this); | |
if ($markup.has('a').length) { | |
$markup = $markup.children('a')[0]; | |
} | |
let text; | |
try { | |
text = $markup.text(); | |
} catch (e) { | |
return true; | |
} | |
for (let i = 0; i < filters.length; i++) { | |
if (text.includes(filters[i][0])) { | |
let txtColor; | |
let bgColor; | |
let relLum = 1; | |
while (arraysEqual(txtColor, bgColor) || | |
relLum < preferences.luminosityThreshold) { | |
txtColor = [getRandomInt(0, 256), | |
getRandomInt(0, 256), | |
getRandomInt(0, 256)]; | |
bgColor = [getRandomInt(0, 256), | |
getRandomInt(0, 256), | |
getRandomInt(0, 256)]; | |
txtLum = getLuminance(txtColor[0], | |
txtColor[1], | |
txtColor[2]); | |
bgLum = getLuminance(bgColor[0], bgColor[1], bgColor[2]); | |
relLum = getLuminanceRatio(txtLum, bgLum); | |
} | |
let textColorString = pad(txtColor[0].toString(16)) + | |
pad(txtColor[1].toString(16)) + | |
pad(txtColor[2].toString(16)); | |
let bgColorString = pad(bgColor[0].toString(16)) + | |
pad(bgColor[1].toString(16)) + | |
pad(bgColor[2].toString(16)); | |
spanner = '<span style="' + | |
'color:#' +textColorString + '!important;' + | |
'background-color:#' + bgColorString + '!important;' + | |
'">' + | |
filters[i][1] + | |
'</span>'; | |
text = text.replace(filters[i][0], spanner); | |
} | |
try { | |
$markup.text(''); | |
} catch (e) { | |
return true; | |
} | |
$markup.html(text); | |
$markup.addClass('filtered'); | |
} | |
}); | |
} | |
const _ = this; | |
let preferences = { | |
'greentext': true, | |
'filters': true, | |
'filterurl': 'https://xvss.net/filters.json.php', | |
'luminosityThreshold': 3, | |
}; | |
let filters = [['yes', 'no'], ['no', 'yes']]; | |
_.getName=()=>'MemeArrows'; | |
_.getDescription=()=>'halfchan\'s green text has appeard! In Discord!'; | |
_.getVersion=()=>'1.0.0'; | |
_.getAuthor=()=>'XVicarious'; | |
_.load = function() { | |
_.readSettings(); | |
BdApi.injectCSS('MemeArrows-InjectedStyleSheet', | |
'.markup.green-text{color:#789922!important}'); | |
}; | |
_.start = function() { | |
if (preferences.greentext || preferences.filters) { | |
_.setupObservers(); | |
if (preferences.filters) { | |
$.get('https://xvss.net/filters.json.php').done(function(data) { | |
filters = JSON.parse(data); | |
filterModifier(); | |
}); | |
} | |
if (preferences.greentext) { | |
modifier(); | |
} | |
} | |
}; | |
_.stop = function() { | |
mutationObserver.disconnect(); | |
}; | |
_.onSwitch = function() { | |
if (preferences.greentext || preferences.filters) { | |
_.setupObservers(); | |
} | |
}; | |
_.setupObservers = function() { | |
let $mainNode = $('div.scroller.messages').last(); | |
mutationObserver.observe($mainNode[0], observerConfig); | |
}; | |
_.reloadFilters = function() { | |
$.get('https://xvss.net/filters.json.php').done(function(data) { | |
filters = JSON.parse(data); | |
$('.message-text>.markup.filtered').each(function() { | |
$(this).removeClass('filtered'); | |
}); | |
}); | |
}; | |
_.getSettingsPanel = function() { | |
// todo: make this not look like absolute shite | |
// todo: configurable invervals for updating things, currently set to 100ms | |
// todo: configurable luminosityThreshold, currently set to 3 | |
const settingsPane = '' + | |
'<div class="settings-wrapper settings-panel"><div class="bd-settings">' + | |
'<div class="bd-pane ma-pane control-group">' + | |
'<ul class="checkbox-group">' + | |
'<li>' + | |
'<div class="checkbox">' + | |
'<div class="checkbox-inner">' + | |
'<input type="checkbox" id="greentext"' + | |
(preferences.greentext ? 'checked' : '') + | |
'>' + | |
'<span></span>' + | |
'</div>' + | |
'<span>Meme Arrows?</span>' + | |
'</div>' + | |
'</li>' + | |
'<li>' + | |
'<div class="checkbox">' + | |
'<div class="checkbox-inner">' + | |
'<input type="checkbox" id="filters"' + | |
(preferences.filters ? 'checked' : '') + | |
'>' + | |
'<span></span>' + | |
'</div>' + | |
'<span>Meme Filters?</span>' + | |
'</div>' + | |
'</li>' + | |
'<li>' + | |
'<div class="control-group">' + | |
'<div>' + | |
'<input id="luminosityThreshold"' + | |
'value="' + preferences.luminosityThreshold + '"' + | |
'>' + | |
'<span>Luminosity Threshold</span>' + | |
'</div>' + | |
'</div>' + | |
'</li>' + | |
'</ul>' + | |
'</div>' + | |
'</div></div>'; | |
$(document).on('click', '.ma-pane .checkbox', function(e) { | |
let $checkbox = $(this).find('input[type="checkbox"]'); | |
let enabled = !$checkbox.is(':checked'); | |
preferences[$checkbox.attr('id')] = enabled; | |
$checkbox.prop('checked', enabled); | |
_.writeSettings(); | |
}); | |
$(document).on('blur', '.ma-pane .control-group input', function() { | |
if ($(this).val() >= 0 || | |
!$(this).val() || | |
typeof $(this).val() !== 'number') { | |
$(this).val(preferences[$(this).attr('id')]); | |
return false; | |
} | |
preferences[$(this).attr('id')] = $(this).val(); | |
_.writeSettings(); | |
}); | |
return settingsPane; | |
}; | |
_.writeSettings = function() { | |
const date = new Date(); | |
date.setTime(date.getTime()+(365*24*60*60*1000)); | |
const expires = '; expires=' + date.toGMTString(); | |
const settings = JSON.stringify(preferences); | |
document.cookie = 'MemeArrows=' + settings + expires + '; path=/'; | |
}; | |
_.readSettings = function() { | |
const name = 'MemeArrows='; | |
const ca = document.cookie.split(';'); | |
for (let i = 0; i < ca.length; i++) { | |
let c = ca[i]; | |
while (c.charAt(0) === ' ') { | |
c = c.substring(1, c.length); | |
} | |
if (c.indexOf(name) === 0) { | |
preferences = JSON.parse(c.substring(name.length, c.length)); | |
return; | |
} | |
} | |
return; | |
}; | |
} | |
const rgbCo = 0.03928; | |
const rgbTf = 12.92; | |
const rgbAd = 0.055; | |
const rgbAD = 1 + rgbAd; | |
const rgbM = 2.4; | |
const redM = 0.2126; | |
const greenM = 0.7152; | |
const blueM = 0.0722; | |
/** | |
* @param {int} r 0 to 255 inclusive, the amount of red | |
* @param {int} g 0 to 255 inclusive, the amount of green | |
* @param {int} b 0 to 255 inclusive, the amount of blue | |
* @return {int} the L of HSL | |
*/ | |
function getLuminance(r, g, b) { | |
// https://github.com/bgrins/TinyColor/blob/master/tinycolor.js | |
const rR = r/255; | |
const rG = g/255; | |
const rB = b/255; | |
if (rR <= rgbCo) { | |
R = rR / rgbTf; | |
} else { | |
R = Math.pow(((rR + rgbAd) / rgbAD), rgbM); | |
} | |
if (rG <= rgbCo) { | |
G = rG / rgbTf; | |
} else { | |
G = Math.pow(((rG + rgbAd) / rgbAD), rgbM); | |
} | |
if (rB <= rgbCo) { | |
B = rB / rgbTf; | |
} else { | |
B = Math.pow(((rB + rgbAd) / rgbAD), rgbM); | |
} | |
return (redM * R) + (greenM * G) + (blueM * B); | |
} | |
/** | |
* @param {int} ll luminosity of the left side | |
* @param {int} lr luminosity of the right side | |
* @return {int} the ratio of luminosity between both sides, always <=1 | |
*/ | |
function getLuminanceRatio(ll, lr) { | |
l1 = (ll > lr) ? ll : lr; | |
l2 = (ll < lr) ? ll : lr; | |
return (l1 + 0.05) / (l2 + 0.05); | |
} | |
/** | |
* @param {number} min the lowest number inclusive | |
* @param {number} max the highest number exclusive | |
* @return {int} an integer between min and max | |
*/ | |
function getRandomInt(min, max) { | |
min = Math.ceil(min); | |
max = Math.floor(max); | |
return Math.floor(Math.random() * (max - min)) + min; | |
} | |
/** | |
* @param {string} hexString a hexidecimal string | |
* @return {string} if the string was only 1 character, a new string with 0 | |
*/ | |
function pad(hexString) { | |
if (hexString.length === 1) { | |
return '0' + hexString; | |
} | |
return hexString; | |
} | |
/** | |
* @param {array} a an array of things | |
* @param {array} b another array of things | |
* @return {bool} if the two arrays contain the same things in the same order | |
*/ | |
function arraysEqual(a, b) { | |
if (a === b) return true; | |
if (a == null || b == null) return false; | |
if (a.length != b.length) return false; | |
for (let i = 0; i < a.length; ++i) { | |
if (a[i] !== b[i]) return false; | |
} | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment