Skip to content

Instantly share code, notes, and snippets.

@XVicarious
Last active May 9, 2017 17:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save XVicarious/3a27fd4f8ca54782f2a7542e0fdeb794 to your computer and use it in GitHub Desktop.
Save XVicarious/3a27fd4f8ca54782f2a7542e0fdeb794 to your computer and use it in GitHub Desktop.
Arrows that Meme
//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';
};
}
//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