// vim:set fileencoding=utf-8 sw=2 ts=2 sts=2:
// encoding test: rød grød med fløde æ ø å
// ==UserScript==
// @name TK-navne på Facebook
// @author Asger Hautop Drewsen
// @namespace http://tyilo.com/
// @description Ændrer folks navne til hvad de er kendt som på TÅGEKAMMERET
// @include https://www.facebook.com/*
// @include https://www.messenger.com/*
// @version 0.5.6
// @grant GM_getValue
// @grant GM_setValue
// @run-at document-end
// ==/UserScript==
var C = (''
+'\u2102');
window['TKconfig'] = ({
// We don't write RemToR anywhere
//'epsilon': 'e',
// Dollar sign used to write KA$$
'dollar': '$',
// C used to write CERM
'cermC': C,
// C used to write VC
'vcC': C,
// Whether exponents should be written as superscripts
'eksponent': true,
// From which year prefixes are computed
'gf': 2022,
// True if we should write a prefix in front of a FU title
'FUprefix': false
});
var EFUITcount = -1;
function TK(key) {
return window['TKconfig'][key];
}
function tk_prefix(year) {
var prefixes = ['', 'G', 'B', 'O', 'TO'];
if (0 <= year && year < prefixes.length) {
return prefixes[year];
}
if (year == -1) return 'K';
var negative = false;
var exponent = year - 3;
if (year < 0) { exponent = -year; negative = true; }
exponent = exponent+'';
var exponentString = '';
if (TK('eksponent')) {
var s = ['⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹']
for (var i = 0; i < exponent.length; ++i)
exponentString += s[exponent.charCodeAt(i) - 48];
} else {
exponentString = exponent;
}
return negative ? 'K'+exponentString : 'T'+exponentString+'O';
}
function year_prefix(year) {
return tk_prefix(TK('gf') - year);
}
function title_bling(title) {
if (title == "KASS") return "KA" + TK('dollar') + TK('dollar');
if (title == 'CERM') return TK('cermC') + "ERM";
if (title == 'VC') return "V" + TK('vcC');
return title;
}
var svg = {};
var html_TK = (
'TÅGEKAMMER');
var html_TKET = html_TK + 'ET';
///////////////////////////////////////////////////////////////////////////////
// Callback generator for add_alias.
///////////////////////////////////////////////////////////////////////////////
function insert_TK_html(h) {
return function (n, orig_string) {
var replaced = document.createElement('span');
replaced.style.fontFamily = 'monospace';
replaced.style.fontWeight = 'normal';
replaced.style.display = 'inline-block';
replaced.style.whiteSpace = 'nowrap';
replaced.className = 'tket';
replaced.innerHTML = h;
n.parentNode.insertBefore(replaced, n);
};
}
var aliases = {'replacements': {}, 'targets': []};
///////////////////////////////////////////////////////////////////////////////
// Add a text replacement.
//
// `source` is a string to watch for in DOM text nodes.
// Whenever `source` is found, the function `destination` is invoked with two
// parameters: the insertion point of the replacement text, and the original
// replaced text.
///////////////////////////////////////////////////////////////////////////////
function add_alias(source, destination) {
// June 12, 2013:
// On latin1 pages, the utf8 strings in this script do not match with
// non-ascii characters. I don't know how to do this for all
// characters, so give special treatment to those special letters.
// This appears to fix it for both Firefox 24 and Chromium 27.
source = (source
.replace(/æ/g, '\xe6')
.replace(/ø/g, '\xf8')
.replace(/å/g, '\xe5')
.replace(/Æ/g, '\xc6')
.replace(/Ø/g, '\xd8')
.replace(/Å/g, '\xc5'));
aliases.targets.push('\\b' + source + '\\b');
aliases.replacements[source] = destination;
}
function like_button(s) {
return function like_button_cb(ip, txt) {
if (ip.parentNode.classList.contains('UFILikeLink')) {
ip.parentNode.insertBefore(document.createTextNode(s), ip);
} else {
return false;
}
};
}
function like_verb(s) {
return function like_verb_cb(ip, txt) {
if (ip.parentNode.parentNode.parentNode.classList.contains('UFILikeSentenceText')) {
ip.parentNode.insertBefore(document.createTextNode(s), ip);
} else {
return false;
}
};
}
add_alias('TÅGEKAMMERET', insert_TK_html(html_TKET));
add_alias('TÅGEKAMMER', insert_TK_html(html_TK));
//add_alias('Like', like_button('Find this strange'));
//add_alias('Unlike', like_button('No longer find this strange'));
//add_alias('likes this', like_verb('finds this strange'));
//add_alias('like this', like_verb('find this strange'));
//add_alias('Synes godt om', like_button('Finder det unaturligt'));
//add_alias('Synes ikke længere godt om', like_button('Finder det ikke længere unaturligt'));
//add_alias('synes godt om dette', like_verb('finder dette unaturligt'));
var alias_regexp;
function compute_alias_regexp() {
alias_regexp = new RegExp(aliases.targets.join('|'));
}
compute_alias_regexp();
///////////////////////////////////////////////////////////////////////////////
// Parse input line to an object.
///////////////////////////////////////////////////////////////////////////////
function parse_alias(line) {
var prefixed = /^(\d+) +([^ ]+) +(.*)/.exec(line);
if (prefixed) {
var o = {'name': prefixed[3],
'year': parseInt(prefixed[1]),
'title': prefixed[2]};
if (o['title'] == 'EFUIT') {
EFUITcount = Math.max(EFUITcount, o['year']);
}
return o;
}
var hangaround = /^"([^"]*)" +(.*)/.exec(line);
if (hangaround) {
return {'name': hangaround[2],
'nickname': hangaround[1]};
}
return null;
}
///////////////////////////////////////////////////////////////////////////////
// Parse input lines, sending objects to a callback function.
///////////////////////////////////////////////////////////////////////////////
function parse_aliases(input, cb) {
var lineMatch;
var re = /^.+$/mg;
while (lineMatch = re.exec(input)) {
var line = lineMatch[0];
var parsed = parse_alias(line);
cb(parsed, line);
}
}
///////////////////////////////////////////////////////////////////////////////
// Given a parsed input line object, produce the fancy unicode text to insert.
///////////////////////////////////////////////////////////////////////////////
function make_title(o) {
if (o['nickname']) return o['nickname'];
var title = o['title'];
var fancy = title_bling(o['title']);
if ('year' in o) {
var year = o['year'];
var addPrefix = false;
var efuit = false;
if (title == 'FUAN') {
addPrefix = true;
} else if (title == 'FU') {
// Unnamed FU (e.g. KFU); always show prefix
addPrefix = true;
} else if (title == 'EFUIT') {
// EFUIT title
addPrefix = false;
efuit = true;
} else if (title.substring(0, 2) != 'FU') {
// BEST title
addPrefix = true;
} else {
// Ordinary FU
addPrefix = TK('FUprefix');
}
if (efuit) {
fancy = tk_prefix(EFUITcount - year) + fancy;
}
if (addPrefix) {
fancy = year_prefix(year) + fancy;
}
}
return fancy;
}
///////////////////////////////////////////////////////////////////////////////
// Callback generator for add_alias.
///////////////////////////////////////////////////////////////////////////////
function insert_alias(o) {
var cb = function (n, orig_string) {
var str = make_title(o);
var prefixSVG = o['title'] ? (/^FU/.exec(o['title']) ? 'FU' : o['title']) : (/^(T[0-9]*O|[GBO]?)EFUIT/.exec(o['nickname']) ? 'EFUIT' : '');
if (o['title'] == 'KASS' && o['year'] < 2014) {
prefixSVG = 'INKA';
}
// TODO make sure the svg is not separated by a line break from the title.
if (svg[prefixSVG]) {
var before = document.createElement('span');
before.innerHTML = svg[prefixSVG];
n.parentNode.insertBefore(before, n);
}
var replaced = document.createElement('span');
replaced.title = orig_string;
replaced.className = 'tk_title';
replaced.innerHTML = str;
n.parentNode.insertBefore(replaced, n);
};
return cb;
}
///////////////////////////////////////////////////////////////////////////////
// Given a parsed input line object, add the appropriate alias.
///////////////////////////////////////////////////////////////////////////////
function add_parsed_alias(o, origLine) {
if (!o) {
// parse error
console.log("Failed to parse input line: ["+origLine+"]");
return;
}
add_alias(o['name'], insert_alias(o));
}
///////////////////////////////////////////////////////////////////////////////
// Recursively apply transformation to all text nodes in a DOM subtree.
///////////////////////////////////////////////////////////////////////////////
function search_for_names(n) {
var to_visit = [n];
var l = 1;
var first = true;
while (l > 0) {
var n = to_visit[--l];
if (n.nodeType == 1) {
// Recurse through all child nodes of this DOM element.
var c = n.lastChild;
while (c) {
var n = c.previousSibling;
to_visit[l++] = c;
c = n;
}
} else if (n.nodeType == 3) {
if (n.parentNode.isContentEditable) continue;
// We are in a DOM text node.
// Replace every occurrence of a real name with an alias.
// If the node contains x substrings,
// we split this text node into 2x+1 parts.
var o = alias_regexp.exec(n.nodeValue);
while (o) {
// We currently have n.nodeValue == a+b+c,
// and b needs to be replaced with f(b).
// f(b) is not necessarily just a text string;
// it could be an arbitrary sequence of DOM nodes.
// Therefore, we split `n` into three parts:
// A text node containing `a`, the dom nodes `f(b)`,
// and a text node containing `c`.
// We have to recurse on `c` (the rest of the text),
// so in reality we just insert `a` and `f(b)`
// before `n` and replace `n` with `c`.
// Insert (possibly empty) text node `a` before `n`:
var prev = n.previousSibling;
var before = document.createTextNode(n.nodeValue.substring(0, o.index));
if (!first) n.parentNode.insertBefore(before, n);
var next = n;
// Insert nodes `f(b)` before n (might be a no-op if f(b) is empty):
if (aliases.replacements[o[0]](n, o[0]) === false) {
if (first) {
// Nothing was inserted and nothing has been done yet.
} else {
// Nothing was inserted, but we previously changed something.
n.parentNode.insertBefore(document.createTextNode(o[0]), n);
}
} else {
if (first) {
// The replacement inserted something but we didn't insert `before`.
var afterprev = ((prev === null)
? n.parentNode.firstChild
: prev = prev.nextSibling);
if (afterprev === null) {
n.parentNode.appendChild(before);
} else {
n.parentNode.insertBefore(before, afterprev);
}
first = false;
} else {
// The replacement inserted something and we already inserted `before`.
}
}
var i = before.nextSibling;
var oldText = o[0];
while (i && i != next) {
if (i.setAttribute)
i.setAttribute('data-tk-prev', oldText);
oldText = '';
i = i.nextSibling;
}
// Set the text of the `n` node to the remaining (maybe empty) text `c`:
if (!first) {
n.nodeValue =
n.nodeValue.substring(o.index + o[0].length, n.nodeValue.length);
}
// Find the next occurrence:
o = alias_regexp.exec(n.nodeValue);
}
}
}
if (first) {
//console.log("Nothing was changed");
} else {
//console.log("Something was changed");
}
}
///////////////////////////////////////////////////////////////////////////////
// Add aliases from input alias specification.
///////////////////////////////////////////////////////////////////////////////
function add_aliases(input) {
parse_aliases(input, add_parsed_alias);
}
function node_depth(v) {
var d = 0;
while (v) { ++d; v = v.parentNode; }
return d;
}
function lowest_common_ancestor(u, v) {
var du = node_depth(u), dv = node_depth(v);
while (du > dv) { u = u.parentNode; --du; }
while (dv > du) { v = v.parentNode; --dv; }
while (u != v && du > 0 && dv > 0) {
u = u.parentNode; --du;
v = v.parentNode; --dv;
}
return u;
}
function activate_fbtk() {
compute_alias_regexp();
search_for_names(document.body);
if (window.theTKTitleObserver) {
window.theTKTitleObserver.disconnect();
}
window.theTKTitleObserver = new MutationObserver(function (mutations) {
if (mutations.length == 0) return;
var p = mutations[0].target;
//var depths = [node_depth(p)];
for (var i = 1, l = mutations.length; i < l; ++i) {
p = lowest_common_ancestor(p, mutations[i].target);
//depths.push(node_depth(mutations[i].target));
}
//depths.sort();
//console.log("Node depths ("+depths.join(', ')+") combined to depth "+node_depth(p));
if (p) {
search_for_names(p);
}
});
window.theTKTitleObserver.observe(document.body, {
'childList': true,
'characterData': true,
'subtree': true
});
}
function deactivate_fbtk() {
if (window.theTKTitleObserver) {
window.theTKTitleObserver.disconnect();
window.theTKTitleObserver = null;
}
var q = [document.body];
var l = 1;
while (l > 0) {
var el = q[--l];
if (!el) continue;
q[l++] = el.nextSibling;
if (el.nodeType != 1) continue;
q[l++] = el.firstChild;
if (el.hasAttribute('data-tk-prev')) {
var txt = document.createTextNode(el.getAttribute('data-tk-prev'));
el.parentNode.insertBefore(txt, el);
el.parentNode.removeChild(el);
}
}
}
function toggle_fbtk() {
if (window.theTKTitleObserver) deactivate_fbtk();
else activate_fbtk();
}
function toggle_fu_prefix() {
window['TKconfig']['FUprefix'] = !TK('FUprefix');
deactivate_fbtk(); activate_fbtk();
}
window.TKsetgf = function TKsetgf(year) {
window['TKconfig']['gf'] = year;
deactivate_fbtk(); activate_fbtk();
}
window.TKsetup = function TKsetup(config) {
for (var k in config) {
if (!(k in window['TKconfig'])) throw('Unknown key '+k);
}
for (var k in config) {
window['TKconfig'][k] = config[k];
}
deactivate_fbtk(); activate_fbtk();
}
function save_prefs() {
if(!window.GM_setValue) {
return;
}
GM_setValue('FUprefix', window['TKconfig']['FUprefix']);
GM_setValue('gf', window['TKconfig']['gf']);
GM_setValue('enabled', !!window.theTKTitleObserver);
}
function tk_keypress(e) {
if (!e.target || e.target.nodeType != 1) return true;
var tgt = e.target;
var tag = tgt.tagName.toLowerCase();
if (tag == 'textarea' || tag == 'input' || tgt.isContentEditable) return true;
var cc = e.charCode;
var gf = TK('gf');
if (cc == 45) // minus
window.TKsetgf(gf-1);
else if (cc == 43) // plus
window.TKsetgf(gf+1);
else if (cc == 42) // asterisk
toggle_fbtk();
else if (cc == 33) // exclamation mark
toggle_fu_prefix();
else
return true;
save_prefs();
e.stopPropagation();
e.preventDefault();
return false;
}
window.addEventListener('keypress', tk_keypress, false);
var svg_style = 'style="height: 1em; width: 1.5em; margin-right: .3em"';
svg['CERM'] = (
''+
''
);
svg['FORM'] = (
''+
''
);
svg['INKA'] = (
''+
''
);
svg['NF'] = (
''+
''
);
svg['PR'] = (
''+
''
);
svg['SEKR'] = (
''+
''
);
svg['VC'] = (
''+
''
);
svg['KASS'] = '';
svg['FU'] = (
''+
''
);
svg['EFUIT'] = (
''+
''
);
add_aliases(
'1999 FORM Jacob Sherson\n'+
'2002 FORM Nikolaj Thomas Zinner\n'+
'2002 KASS Rasmus Villemoes\n'+
'2003 CERM Sune S. Thomsen\n'+
'2004 VC Christina Koch Perry\n'+
'2005 CERM Ole Søe Sørensen\n'+
'2005 FORM Dan Beltoft\n'+
'2005 KASS Tanja Kragbæk Vilhelmsen\n'+
'2005 VC Rasmus Ragnvald Olofsson\n'+
'2006 CERM Tine Vraast-Thomsen\n'+
'2006 FORM Michael Volf Henneberg\n'+
'2006 KASS Lars Thorhauge\n'+
'2006 NF Aslak Thorndahl Lindballe\n'+
'2006 PR Mia Dyhr Christensen\n'+
'2006 SEKR Lasse Kragbæk Vilhelmsen\n'+
'2006 VC Martin Studsgaard Christensen\n'+
'2007 CERM Johan Sigfred Abildskov\n'+
'2007 FORM Jan Munksgård Baggesen\n'+
'2007 KASS Mads Baggesen\n'+
'2007 NF Eva Lykkegaard Poulsen\n'+
'2007 PR Sidse Damgaard\n'+
'2007 SEKR Ninni Schaldemose\n'+
'2007 VC Kasper Søgaard Deleuran\n'+
'2008 CERM Sofie Kastbjerg\n'+
'2008 FORM Tue Christensen\n'+
'2008 KASS Adam Ehlers Nyholm Thomsen\n'+
'2008 PR Cecilie Vahlstrup\n'+
'2009 CERM Christian Bladt Brandt\n'+
'2009 FORM Jonas Bæklund\n'+
'2009 KASS Rikke Aagaard\n'+
'2009 NF Ditte Både Sandkamm\n'+
'2009 PR Nikolaj Andresen\n'+
'2009 SEKR Anne Clemmensen\n'+
'2009 VC Troels Tinggaard Hahn\n'+
'2010 FORM Mie Elholm Birkbak\n'+
'2010 KASS Torben Muldvang Andersen\n'+
'2010 NF Morten Jensen\n'+
'2010 PR Kristoffer L. Winge\n'+
'2010 PR Kristoffer Winge\n'+
'2010 PR Kristoffer Larsen Winge\n'+
'2010 SEKR Maria Kragelund\n'+
'2010 VC Morten Rasmussen\n'+
'2011 CERM Sabrina Tang Christensen\n'+
'2011 FORM Jakob Schultz-Falk\n'+
'2011 KASS Britt Videbæk Fredsgaard\n'+
'2011 NF Kasper Monrad\n'+
'2011 PR Marie Kirkegaard\n'+
'2011 SEKR Niels Ramskov Bøje\n'+
'2011 VC Maiken Haahr Hansen\n'+
'2012 CERM Mads Fabricius\n'+
'2012 FORM Steffen Videbæk Fredsgaard\n'+
'2012 KASS Eva Gjaldbæk Frandsen\n'+
'2012 NF Johannes Christensen\n'+
'2012 PR Nana Halle\n'+
'2012 SEKR Jakob Rørsted Mosumgaard\n'+
'2012 VC Peter Slemming-Adamsen\n'+
'2013 CERM Diana Christensen\n'+
'2013 FORM Mathias Rav\n'+
'2013 KASS Christina Moeslund Zeuthen\n'+
'2013 NF Christian Fretté\n'+
'2013 PR Mette Lysgaard Schulz\n'+
'2013 SEKR Karina Sunds Nielsen\n'+
'2013 VC Mathias Dannesbo\n'+
'2014 CERM Jonas Kielsholm\n'+
'2014 FORM Martin Sand Halle\n'+
'2014 INKA Henrik Lund Mortensen\n'+
'2014 KASS Mathias Jaquet Mavraganis\n'+
'2014 NF Jacob Schnedler\n'+
'2014 PR Alexandra Fabricius Porsgaard\n'+
'2014 SEKR Camilla Pedersen\n'+
'2014 VC Peter Matzen\n'+
'2015 CERM Andreas Bock Michelsen\n'+
'2015 FORM Christian Bonar Zeuthen\n'+
'2015 INKA Oliver Emil Harritslev Christensen\n'+
'2015 KASS Amalie Stokholm\n'+
'2015 NF Anne Dorte Rafn Spangsberg\n'+
'2015 PR Liv Medum Bundgaard\n'+
'2015 SEKR Janne Højmark Mønster\n'+
'2015 VC Lone Koed Thorhauge\n'+
'2016 CERM William Heyman\n'+
'2016 FORM Frederik Jerløv\n'+
'2016 INKA Halvor Høen Hval\n'+
'2016 KASS Emma Hillgaard\n'+
'2016 NF Martin Aakjær Jørgensen\n'+
'2016 PR Katrine Alice Glasscock\n'+
'2016 SEKR Anne Tarp\n'+
'2016 VC Hans Christian Tankred\n'+
'2017 CERM Nikolaj Færgemand Andersen\n'+
'2017 FORM Sofie Filskov Hermansen\n'+
'2017 INKA Klaus Skovgaard Olesen\n'+
'2017 INKA Klaus Olesen\n'+
'2017 KASS Magnus Graf Skou\n'+
'2017 KASS Magnus Graf\n'+
'2017 NF Julie Thiim Gadeberg\n'+
'2017 NF Julie Gadeberg\n'+
'2017 PR Kirstine Friis Jensen\n'+
'2017 SEKR Per Næsby Høgfeldt\n'+
'2017 SEKR Per Høgfeldt\n'+
'2017 VC Mark Lykke Winther\n'+
'2018 CERM Fredrik Egil Helsengreen\n'+
'2018 FORM Thomas Skovlund Hansen\n'+
'2018 INKA Jens Christian Jørgensen\n'+
'2018 KASS Johanne Tankred\n'+
'2018 NF Søren István Adorján Dyhr\n'+
'2018 PR Ida Meyer Granum\n'+
'2018 SEKR Luna Lynge Malzard\n'+
'2018 VC Sille P. Andresen\n'+
'2019 CERM Jesper Dam Knudgaard\n'+
'2019 FORM Jacob Fjerbæk Olsen\n'+
'2019 INKA Ida Rose Nielsen\n'+
'2019 KASS Tessa Cecilia Broeders\n'+
'2019 KASS Tessa Broeders\n'+
'2019 NF Johannes Jensen\n'+
'2019 PR Morten Hulbæk Fog\n'+
'2019 SEKR Sarah Eckholdt Jensen\n'+
'2019 SEKR Sarah Eckholdt\n'+
'2019 VC Jens Trolle\n'+
'2020 CERM Agnete Bie Westphael\n'+
'2020 FORM Maja Dybboe\n'+
'2020 INKA Nichlas Nordestgaard Vingtoft\n'+
'2020 INKA Nichlas Vingtoft\n'+
'2020 KASS Lærke Niclasen\n'+
'2020 NF Mathias Ravn Tversted\n'+
'2020 PR Mathilde Ørsted Toft\n'+
'2020 SEKR Mikala Mai Halbirk\n'+
'2020 SEKR Mikala Halbirk\n'+
'2020 VC Simon Bølling Nordentoft\n'+
'2021 CERM Ida Fricke Jørgensen\n'+
'2021 FORM Peter Juelsgaard\n'+
'2021 INKA Maria Askholm Nielsen\n'+
'2021 KASS Frederik Würtz Sørensen\n'+
'2021 NF Christian Børsen Smedegaard\n'+
'2021 PR Josefine Bjørndal Robl\n'+
'2021 SEKR Jakob Lauritsen\n'+
'2021 VC Christian Voldby\n'+
'2022 CERM Asger Weeth\n'+
'2022 FORM Casper Rysgaard\n'+
'2022 INKA Benjamin Nørmølle Buttenschøn\n'+
'2022 KASS Søren Kjærsgaard\n'+
'2022 NF Toke Marstrand Pontoppidan Lindhard\n'+
'2022 PR Marie-Louise Lykke Nielsen\n'+
'2022 SEKR Clara Bjergsø\n'+
'2022 VC Sif Floor\n'+
'2005 FUJA Jane Drejer\n'+
'2006 FUZA Sarah Zakarias\n'+
'2007 FUAN Kenneth Sejdenfaden Bøgh\n'+
'2007 FUHO Daniel Dalhoff Hviid\n'+
'2007 FUME Mette Aagaard\n'+
'2008 FUAN Andreas Sand Gregersen\n'+
'2008 FUNÉ René Søndergaard\n'+
'2008 FURU Jesper Unna\n'+
'2009 FUBR Rune Bjerring Haugaard\n'+
'2009 FUBS Sandra Pedersen\n'+
'2009 FUBS Sandra Bleuenn Picard Svejgaard Pedersen\n'+
'2009 FUBS Sandra Bleuenn Picard S. Pedersen\n'+
'2009 FUHN Mette Tranberg Hansen\n'+
'2009 FUØL Carina Kjeldahl Møller\n'+
'2009 FUØR Signe Grønborg\n'+
'2010 FUAN Andreas Nikolai Kyed Bovin\n'+
'2010 FUNI Asbjørn Stensgaard\n'+
'2010 FUPH Pernille Hornemann Jensen\n'+
'2010 FURØ Lærke Rønlev Reinholdt\n'+
'2011 FUFR Anders Friis Jensen\n'+
'2011 FUIØ Mathilde Biørn Madsen\n'+
'2011 FULA Camilla Skree Sørensen\n'+
'2011 FUNU Andreas Bendix Nuppenau\n'+
//'2011 FURI Frederik Jerløv\n'+
'2012 FULI Line Bjerg Sørensen\n'+
'2012 FULS Sara Poulsen\n'+
'2012 FUMO Marianne Ostenfeldt Mortensen\n'+
'2012 FUMY Rasmus Thygesen\n'+
'2013 FUAN Dennis Krongaard Mikkelsen\n'+
'2013 FUBI Benedikte Sofie Dalhoff Werk\n'+
'2013 FUGR Asger Holm Agergaard\n'+
'2013 FUSE Mie Christine Wilhelmsen\n'+
'2013 FUTN Anja T Nielsen\n'+
'2013 FUUS Rasmus Korsgaard Kjeldgaard\n'+
//'2014 FUAT Anne Kristine Tarp\n'+
//'2014 FUAT Anne Tarp\n'+
'2014 FUIS Astrid Christiansen\n'+
'2014 FUIK Frederik Riis Nielsen\n'+
'2014 FUFF Helle Weinkouff Petersen\n'+
'2014 FUAN Isaac Appelqvist Løge\n'+
'2014 FUAN Isaac Appelquist Løge\n'+
'2014 FUON Jonas Joachim Junker Zarling\n'+
'2014 FUON Jonas Zarling\n'+
'2014 FUSØ Søren Kenneth Højgaard Sørensen\n'+
//'2014 FUWI William Heyman Krill\n'+
//'2014 FUWI William Heyman\n'+
//'2015 FUAK Martin Aakjær Jørgensen\n'+
//'2015 FUAN Per Næsby Høgfeldt\n'+
//'2015 FUAN Per Høgfeldt\n'+
//'2015 FUGL Katrine Alice Glasscock\n'+
'2015 FUGO Asger Roed-Åstrøm\n'+
//'2015 FUIL Sille Eline Piilgard Andersen\n'+
//'2015 FUIL Sille P. Andresen\n'+
'2015 FUNN Anna Mie Hansen\n'+
'2015 FUPI Freja Frederikke Pinderup\n'+
//'2015 FUSJ Kirstine Friis Jensen\n'+
'2015 FUTØ Marcus Høgsholt Nilson\n'+
//'2015 FUVE Thomas Skovlund Hansen\n'+
//'2016 FUYE Ida Meyer Granum\n'+
//'2016 FUKS Sarah Eckholdt Jensen\n'+
//'2016 FUKS Sarah Eckholdt\n'+
//'2016 FUJI Julie Thiim Gadeberg\n'+
//'2016 FUJI Julie Gadeberg\n'+
//'2016 FULI Tessa Cecilia Broeders\n'+
//'2016 FULI Tessa Broeders\n'+
'2016 FUKI Rasmus Kimose Hvid Nielsen\n'+
'2016 FUAN Jesper Brink Andersen\n'+
'2016 FUAN Jesper Brink\n'+
'2016 FUBØ Mathias Bøjlesen Bertelsen\n'+
'2016 FUBØ Mathias Bertelsen\n'+
'2016 FUBL Jacob Bech-Larsen\n'+
'2016 FULK Jonas Folke Nielsen\n'+
//'2016 FUIV Nichlas Nordestgaard Vingtoft\n'+
//'2016 FUIV Nichlas Vingtoft\n'+
'2017 FUAN Christian Haag Frederiksen\n'+
//'2017 FUDL Ida Rose Nielsen\n'+
//'2017 FUDO Søren István Adorján Dyhr\n'+
'2017 FUFI Signe Fischer Lambertsen\n'+
'2017 FULA Bjørg Glad\n'+
//'2017 FULZ Luna Lynge Malzard\n'+
'2017 FUMI Martin Mikkelsen\n'+
'2017 FUOÜ Rolf Jürgensen Aaskov\n'+
'2017 FURE Kathrine Thorsøe\n'+
'2017 FUTR Viktor Hjorth Miltersen\n'+
'2017 FUTR Viktor Miltersen\n'+
'2018 FUAN Mathias K. Nielsen\n'+
'2018 FUEA Linnea Skafte\n'+
//'2018 FUES Jens Trolle\n'+
//'2018 FUFO Morten Hulbæk Fog\n'+
'2018 FUIB Sofie Behrmann\n'+
'2018 FUNØ Katrine Høholt Kaspersen\n'+
//'2018 FURA Maria Askholm Nielsen\n'+
'2018 FURO Frederik Kobemis Andersen\n'+
'2018 FUUF Albert Freud Abildgaard\n'+
//'2018 FUYO Maja Dybboe\n'+
'2019 FUAN Nicolaj Kuno Bræmhøj\n'+
'2019 FUDA Nikolaj Dahl Hansen\n'+
//'2019 FUHØ Christian Børsen Smedegaard\n'+
'2019 FULE Jacob Birkeland Steenstrup\n'+
//'2019 FULR Toke Marstrand Pontoppidan Lindhard\n'+
//'2019 FUOM Mathilde Ørsted Toft\n'+
'2019 FUSR Josephine Mai Scharf Andersen\n'+
'2019 FUTE Mette Rydder\n'+
//'2019 FUTÜ Frederik Würtz Sørensen\n'+
//'2019 FUWA Agnete Bie Westphael\n'+
//'2020 FUAN Jakob Lauritsen\n'+
'2020 FUDI Freja Marie Dithmer Gam\n'+
'2020 FUDI Freja Gam\n'+
'2020 FUEI Lea Vibe Pedersen\n'+
'2020 FUML Heidi Dueholm Lunde\n'+
'2020 FUML Heidi Lunde\n'+
'2020 FUMS Kurt Herlev Rasmussen\n'+
//'2020 FUMØ Benjamin Nørmølle Buttenschøn\n'+
'2020 FUNÉ André Slot Kristensen\n'+
'2020 FUNI Andrea Skadhede Kristensen\n'+
'2020 FUNI Andrea Skadhede\n'+
'2021 FUAN Jakob Sandø Lund\n'+
//'2021 FUFR Sif Floor\n'+
'2021 FUGA Caspar Agerskov Madsen\n'+
//'2021 FULU Marie-Louise Lykke Nielsen\n'+
'2021 FURP Jeppe Pedersen\n'+
'2021 FUSA David Kildahl Larsen\n'+
'2021 FUSB Johanne Bojsen Kjær\n'+
'2021 FUTM Emil Tejn Rasmussen\n'+
'2021 FUÄU Katrine Bräuner\n'+
'2021 FUØX Emil Sixhøj Mors\n'+
'2022 FUAN Julius Thomas\n'+
'2022 FUCI Alice Pernille Bach Hjort\n'+
'2022 FUDS Jens Magnus Lunding Kusk\n'+
'2022 FUEG Thomas Vang Jensen\n'+
'2022 FUGO Sigurd Lund Boytang\n'+
'2022 FUIR Ida Sofie Pedersen Damkjær\n'+
'2022 FUJR Rikke Johanning\n'+
'2022 FUND Anne Sofie Gam Husted\n'+
'2022 FUNO Simon Malthe Hansen\n'+
'2022 FUXR Alexander Arp Steenberg Johansen\n'+
//'2020 FURY Christian Voldby\n'+
'2020 FUUD Lotte Munkvad\n'+
'1 EFUIT Lauge Mølgaard Hoyer\n'+
'2 EFUIT Philip Tchernavskij\n'+
//'3 EFUIT Oliver Emil Harritslev Christensen\n'+
'4 EFUIT Jonas Tranberg Sørensen\n'+
//'5 EFUIT Johannes Jensen\n'+
'6 EFUIT Mathias Old Jensen\n'+
//'7 EFUIT Mathias Ravn Tversted\n'+
'8 EFUIT Mikkel Wienberg Madsen\n'+
//'9 EFUIT Ida Fricke Jørgensen\n'+
//'10 EFUIT Sofie Kirk Nielsen\n'+
'11 EFUIT Magnus Bech Wind\n'+
'"ADAM" Adam Etches\n'+
'"Nissen" Anders Hauge Nissen\n'+
'"Metal Bo" Bo Mortensen\n'+
'"CBM" Christian Brandt Møller\n'+
'"J-DAG" Jacob Damgaard Jensen\n'+
'"Jen_s" Jens Kusk Block\n'+
'"Have" Martin Anker Have\n'+
'"Vester" Mikkel Bak Vester\n'+
'"M3" Morten Schaumburg\n'+
'"Cramer" Morten \'Cramer\' Nikolaj Pløger\n'+
'"#" Rikke Hein\n'+
'"Sean" Sean Geggie\n'+
'"Køleren" Karsten Handrup\n'+
'"P∀" Palle Jørgensen\n'+
'"Thyregod" Klaus Eriksen\n'+
'"Graa mand" Per Graa\n'+
'"Łabich" Anders Labich\n'+
'"Onklen" Henrik Bindesbøll Nørregaard\n'+
'"Clausen" Jakob Clausen\n'+
'"Dobbelt Wester" Michael Westergaard\n'+
'"Brøl" Morten Grud Rasmussen\n'+
'"Stive-Anna" Anna Sejersen Riis\n'+
'"Ålen" Frederik Brinck Truelsen\n'+
'"Blomsterpenis" Morten Stockmarr Liljegren\n'+
'"Smør" Kenneth Lund Kjærgaard\n'+
//'"Kalus" Klaus Olesen\n'+
'"Ion" Rune Naujokat Troelsgaard Thorsen\n'+
'"HH" Hans-Henrik Sztuk Teut\n'+
''
);
var enabled = true;
if (window.GM_getValue) {
window['TKconfig']['FUprefix'] = GM_getValue('FUprefix', window['TKconfig']['FUprefix']);
window['TKconfig']['gf'] = GM_getValue('gf', window['TKconfig']['gf']);
enabled = GM_getValue('enabled', true);
}
activate_fbtk();
if (!enabled) {
deactivate_fbtk();
}