// ==UserScript==
// @name Fiction.Live Merged
// @namespace http://tampermonkey.net/
// @version 61.008
// @description An attempt to improve fiction.live through the addition of various features.
// @author You
// @match https://fiction.live/*
// @match https://beta.fiction.live/*
// @grant none
// @run-at document-idle
// @noframes
// ==/UserScript==
(function () {
'use strict';
try{
function insertCSS() {
var css = `/*
CSS For: Script Settings Outer Container
*/
#confDisp {
height: 100%;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 9999;
display: none;
overflow-y: auto;
pointer-events: auto;
}
/*
CSS For: Script Settings Inner Container
*/
#confBox {
height: auto;
min-height: 60%;
background: #2a2c3b;
width: auto;
min-width: 60%;
position: relative;
top: 10px;
margin:5%;
margin-top:1%;
padding: 1%;
display: flex;
flex-flow: column;
background: #2a2c3b;
box-shadow: 0 0 10px #000000;
pointer-events: auto;
}
/*
CSS For: Script Settings Inner Container Children
*/
#confBox * {
color: white;
background: #2a2c3b;
}
/*
CSS For: Script Settings Inner Container Title
*/
#confBox h1 {
text-rendering: optimizelegibility;
font-weight: 700;
font-size: 4vmin;
margin: 11.999999999999998px 0;
line-height: 1.2em
}
/*
CSS For: Script Settings Inner Container Tooltips
*/
#confBox .toolt {
height: 2.5vmin;
width: 2.5vmin;
background-color: #db722c;
color: #2a2c3b;
border-radius: 50%;
border: 0.1vmin solid #bebeff;
display: inline-block;
text-align: center;
font-weight: 700;
margin-left: 1vmin;
cursor: help;
}
/*
CSS For: Script Settings Inner Container Inputs
*/
#confBox select,
#confBox textarea,
#confBox input[type=text],
#confBox input[type=password],
#confBox input[type=datetime],
#confBox input[type=datetime-local],
#confBox input[type=date],
#confBox input[type=month],
#confBox input[type=time],
#confBox input[type=week],
#confBox input[type=number],
#confBox input[type=email],
#confBox input[type=url],
#confBox input[type=search],
#confBox input[type=tel],
#confBox input[type=color],
#confBox .uneditable-input {
display: inline-block;
height: auto;
padding: 0.4vmin 0.6vmin;
margin-bottom: 10px;
font-size: 1.4vmin;
line-height: 1.5;
vertical-align: middle;
width: 100%;
height: 3.2vmin;
}
/*
CSS For: Chat Editing Container
*/
.msgModBox {
display: none;
padding-bottom: 0.5em;
}
.delOn .msgModBox,
.vis .msgModBox,
.visAll .msgModBox {
display: unset;
}
/*
CSS For: Chat Editing Buttons
*/
.msgModEdit,
.msgModSave,
.msgModDiscard,
.msgModDelete {
width: auto;
color: white;
font-weight: bold;
padding: 0 0.5em 0 0.5em;
margin: 0 3em 0 0;
display: none;
}
.dark > .msgMod {
color: unset;
}
.delOn .msgModDelete {
display: unset;
}
.visAll .msgModEdit,
.visAll.editMode .msgModSave,
.visAll.editMode .msgModDiscard,
.visAll .msgModDelete,
.vis .msgModEdit,
.vis.editMode .msgModSave,
.vis.editMode .msgModDiscard {
display: unset;
}
.imgMsg .msgModEdit,
.imgMsg .msgModSave,
.imgMsg .msgModDiscard {
/*display: none !important;*/
}
/*
CSS For:
*/
.description {
font-size: 1.6vmin;
}
.purgeButton {
height: 100%;
border: thin solid red
}
.borderBottom {
width: 100%;
border-bottom: thin solid white;
margin: 5px 0 0 0;
}
#innerAlertSearch {
background: rgb(42, 44, 59) none repeat scroll 0% 0%;
padding-top: 10px;
margin-top: 0px;
display: inline-block;
width: 100%;
}
.listView-grid {
grid-auto-rows: unset;
}
#loginMenu .dropdown-menu {
right: -6.2em;
}
.cssBtn {
/*! height: 30px; */
height: 3.2vmin;
font-size: 1.4vmin;
padding: 0.2vmin;
line-height: normal;
/*! border: vmin solid #393a4d; */
border-color: #393a4d;
border-width: 0.5vmin;
}
.chatListed {
display: none;
}
#scriptTitle h1 {
margin: 0;
}
.blacklistEntry p.colors {
display: inline-block;
width: 85%;
}
#reportDiv {
padding: 5px;
}
.contactMain {
font-size: 2vmin;
}
#confScript {
text-shadow='-1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000';
font-weight='bold';
}
#scriptTitle * {
margin: 0;
display: inline;
}
#scriptTitle {}
.settingsSelect {
max-height: 80px;
padding-top: 5px;
}
.settingsSelectDiv {
display: inline-block;
background: #4b4f6b;
box-sizing: border-box;
height: 3.2vmin;
}
.settingsSelectBTN {
width: 100% !important;
height: 100%;
font-size: 2vmin;
color: white !important;
text-decoration: none;
background: #373952 !important;
box-sizing: border-box;
border: .1vmin #21222b solid;
line-height: normal;
}
.settingsSelectBTN:disabled {
background: #4b4f6b !important;
}
.settingsTab {
/*padding: 0.5vmin;*/
display: none;
}
.entryTitle {
min-width: 100%;
font-size: 2vmin;
color: white !important;
float: left;
}
.settingsToggle {
/*
min-height: 2.5vmin;
max-height: 35px;
*/
height: 3.5vmin;
min-width: 33%;
color: white;
border: 0.1vmin solid silver;
padding: 0.5vmin;
float: left;
font-size: 1.75vmin;
line-height: normal;
}
.settingsToggle div {
display: inline;
}
.toggleCheck {
-webkit-appearance: none;
background: white !important;
color: black !important;
padding: 1vmin;
display: inline-block;
position: relative;
/*! height: 4.4vmin; */
/*
height: 100% !important;
max-height: 100% !important;
*/
margin-top: 0 !important;
margin-bottom: 0 !important;
margin-left: 0.5vmin !important;
margin-right: 0 !important;
color: black;
font-size: 2.5vmin;
}
.toggleCheck:active,
.toggleCheck:checked:active {}
.toggleCheck:checked {}
.toggleCheck:checked:after {
content: '\\2714';
}
.toggleCheck:after {
content: '\\2716';
position: absolute;
top: -0.8vmin;
left: 0vmin;
}
.settingsBlacklist {
padding: 1vmin;
}
#settingsBox {
margin-bottom: 0.5vmin;
}
.settingsInput {
color: white;
max-width: 40%;
height: 30px;
margin: 0 !important;
}
.blacklistEntry {
font-size: 2vmin;
/*
float: left;
*/
min-width: 50%;
color: white;
display: inline-block;
border: 0.1vmin solid silver;
padding: 0.5vmin;
}
.blacklistEntry p {
margin: 0;
display: inline;
font-size: 2vmin !important;
}
.blacklistRemove {
color: white !important;
font-size: 2vmin;
display: inline-block;
border: 0.3vmin solid black;
background: #4b4f6b !important;
float: right;
padding-left: 0.5vmin;
padding-right: 0.5vmin;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.blacklistRemove:hover {
color: white;
}
#settingsAlertBox {
margin-bottom: 5px;
}
#styleEntries {}
.styleEntry * {
display: inline-block;
vertical-align: unset;
}
.styleEntry {
display: inline-block;
border: thin solid black;
padding: 2px 4px 0 4px;
margin: 0 5px 5px 5px;
background: #373952;
}
.styleTitle {
margin: 0;
height: 100%;
}
.colorSet {
width: 7em;
margin: 0 1em 0.25em 1em !important;
color: white;
max-width: 40%;
height: 30px;
}
.colorPick * {
all: unset;
}
.colorPick {
width: 25px !important;
height: 1.5em !important;
border: none !important;
padding: 0 !important;
margin: 0 0 0.25em 0 !important;
}
#styleInput {
height: 500px;
resize: none;
}
#liveBox {
display: block;
height: 100%;
width: auto;
float: right;
padding-left: 1%;
padding-right: 1%;
border-left: solid;
border-Right: solid;
border-color: #ebf3f7;
box-sizing: border-box;
font-weight: bold;
color: black;
text-shadow: -1px -1px 0 #ebf3f7, 1px -1px 0 #ebf3f7, -1px 1px 0 #ebf3f7, 1px 1px 0 #ebf3f7;
}
#liveBox.dark {
border-color: #36394d;
color: white !important;
text-shadow: -1px -1px 0 #36394d, 1px -1px 0 #36394d, -1px 1px 0 #36394d, 1px 1px 0 #36394d !important;
}
.blacklist {
height: auto;
width: 0px;
}
.linkDiv {
width: 100%;
overflow: auto;
}
.linkDiv img {
width: 100%;
display: block;
}
.functionalLink {
padding: 0.5em;
}
.functionalContainer {
position: relative;
width: 100%;
padding-bottom: 100%;
}
.functionalVideo {
position: absolute;
width: 100%;
height: 100%;
}
.toggleBtn {
//-webkit-appearance: none;
//padding: 9px;
//border-radius: 3px;
//display: inline-block;
//position: relative;
//height:100% !important;
//max-height:100% !important;
//margin-top:0 !important;
//margin-bottom:0 !important;
margin-left: 1vmin; //margin-right:0 !important;
border: solid #393a4d;
border-width: .3vmin .3vmin .3vmin .3vmin;
box-shadow: .2vmin .2vmin .2vmin .2vmin #4f516b;
height: 2.4vmin;
font-size: 1.5vmin;
padding: 0 1vmin 0 1vmin;
line-height: initial;
}
.editMode textarea {
resize: none;
height: 100px;
}
.contactMain, .contactL, .contactR, .topicMessage {
background: #2a2c3b !important;
color: white !important;
}
.contactL {
float: left;
width: 50%;
}
.contactR {
float: right;
width: 50%;
}
.contactR input {
background: #2a2c3b !important;
}
.topicMessage {
resize: none;
}
.colors {
background: #2a2c3b !important;
color: white !important;
}
input[type="button"].textModBtn,
.textModBtn {
height: 100%;
width: 25%;
display: inline-block;
text-align: center;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.textMod {
display: none;
position: relative;
height: auto;
width: 100%;
z-index: 20;
background-color: #428bca;
color: white;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.textMod.vis {
display: block;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.linkImg:before {
content: '\\1F517';
display: block;
position: absolute;
right: 50px;
top: 25px;
cursor: pointer;
font: normal normal normal 0.9rem/1 FontAwesome;
}
.linkInput {
display: block;
bottom: 5em;
width: 100%;
height: auto;
background: #323448;
z-index: 10000;
margin: 0 !important;
}
.linkInput > textarea {
padding: 0.25em !important;
margin: 0 !important;
resize: none;
height: 50px;
width: 90%;
float: left;
}
.linkInput > input {
display: block !important;
float: left;
padding: 0 !important;
margin: 0 !important;
height: 25px;
width: 10%;
}
.eCSSRow {
margin-bottom: 10px;
}
.ExternalLink{
height: 3.2vmin;
width:min-content;
}
.eCSSRow .ExternalLink:first-of-type {
width: 80%;
}
.eCSSRow input.ExternalLink {
height: 3.2vmin;
width: 10%;
margin: 0 !important;
}
.eCSS {
margin: none;
}
`;
var style = document.createElement('style');
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
};
document.getElementsByTagName('head')[0].appendChild(style);
};
insertCSS();
function darkCheck(){
if (/\-dark/.test(document.head.querySelector('link[rel="stylesheet"]').href)){
window.FL_Script.darkMode=true;
}
else{
window.FL_Script.darkMode=false;
}
};
var rolled = false;
var lastURL = window.location.href;
var settings = JSON.parse(localStorage.getItem('FL_Settings'));
var defaultSettings = {
'imageResize': false,
'questRemove': true,
'questAuthorRemove': true,
'removeTaggedAuthor': false,
'anonToggle': false,
'removeUsernames': false,
'autoRoller': false,
'removeTopicForm': true,
'removeBlankTopics': true,
'authorHighlight': true,
'authorBlacklist': ['0jordinio0','vexin980','reeeanon'],
'chatBlacklist': true,
'chatBlacklistReplies': true,
'chatBlacklisted': ['reeeanon'],
'tagBlacklist': [],
'alertBlacklist': [],
'sortAlerts': false,
'highlightColor': '#393c59',
'highlightLight': '#fc8c03',
'highlightLightToggle': false,
'liveRestore': true,
'liveLight': false,
'functionalLinks': false,
'functionalVideos': false,
'removeNSFW': false,
'updateRequestDismiss': false,
'alertContainer': 999,
'akunPlus': 'Ignore',
'customCSS': [{}, ``],
'userReveal':false,
'unpublishBTN':false,
'messageEdit':false,
'textStyle':false,
'diceButton':false,
'autoHide':false,
'imageLink':false,
'reviewDismiss':false,
'followDismiss':false,
'likeDismiss':false,
'alertFilter':false,
'externalCSS':[],
'spamRemoval':false,
'maxWords':500,
'bannedString':['muyumuyu'],
'deletedString':[],
'messageBlacklist':false,
'gifDisable':false,
'qmSort':false,
'spaceFix':false,
'questBlock':false,
'imgSourceBtn':false
};
//Updates settings when there is a change between versions.
if (!settings) {
console.log('Settings set to defaults.');
settings = defaultSettings
}
else if (Object.keys(settings).length !== Object.keys(defaultSettings).length) {
console.log('Settings differ in length.');
Object.keys(defaultSettings).forEach(
function (key) {
if (!(key in settings)) {
settings[key] = defaultSettings[key];
console.log('Added ' + key + ' to the current settings.');
};
});
if (Object.keys(settings).length > Object.keys(defaultSettings).length) {
Object.keys(settings).forEach(
function (key) {
if (!(key in defaultSettings)) {
//console.log(`Removed invalid variable and value from settings, ${key}:${settings[key]}.`);
//delete settings[key]
};
});
}
};
//settings.uiden={}
//console.log(settings.uiden)
window.FL_Script={};
let purgeButtonAdd;
try{
if (settings.followLike==true){
settings.likeDismiss == true;
delete settings.followLike;
}
}catch(error){}
localStorage.setItem('FL_Settings', JSON.stringify(settings));
window.FL_Script.USERNAME = getUser();
var USERNAME = window.FL_Script.USERNAME;
document.addEventListener("mouseover", function (e) {
//SauceNao Mouseover Event
//console.log('clicked',e.target)
try{
if (settings.imgSourceBtn != true){return;}
function genSource(){
var sourceIt = document.createElement('a');
sourceIt.classList.add('FL_Source');
sourceIt.style.position = 'relative';
sourceIt.style.top = '10px';
sourceIt.style.float = 'right';
sourceIt.style.fontWeight = 'bold';
sourceIt.style.zIndex = '1000';
sourceIt.onclick = function(){
var url = encodeURIComponent(e.target.src);
window.open('https://saucenao.com/search.php?url='+url, '_blank');
}
sourceIt.innerText = 'SauceNao'
return sourceIt;
}
if (e.target.matches('img')){
if (e.target.classList.contains('avatar') ||
e.target.classList.contains('mfp-img')||
e.target.classList.contains('profilePic')||
document.body.classList.contains('mfp-zoom-out-cur')){
return;
}
else if (
e.target.closest('.chatItemDetail')||
//e.target.closest('.chapterContent')||
e.target.closest('.storyListItem ')||
e.target.closest('.authorPane')||
e.target.closest('.editContainer')){
return;
}
else if (e.target.closest('.logItem') != null &&
e.target.closest('.logItem').querySelector('a.FL_Source')){
return;
}
else if (e.target.closest('.fieldBody') &&
(!e.target.parentNode.previousSibling ||
(e.target.parentNode.previousSibling &&
!e.target.parentNode.previousSibling.classList.contains('FL_Source')))){
console.log('1')
e.target.closest('.fieldBody').insertBefore(new genSource,e.target.parentNode);
}
else if (e.target.closest('.logItem')){
e.target.closest('.logItem').insertBefore(new genSource,e.target.closest('.logItem').childNodes[0]);
}
}
}catch(error){
console.log('Error - SauceNao Broken',error)
};
});
function getUser(){
try{
if (window.ty.currentUser.name){
USERNAME = window.ty.currentUser.name;
return USERNAME;
}
}
catch(error){}
if (document.querySelector('.user')){
//console.log(document.querySelector('.user').href.replace(/.*user\//,''))
try{
USERNAME = document.querySelector('.user').href.replace(/.*user\//,'')
return USERNAME
}catch(error){
console.log('Username detect 1 failed',error);
};}
try{
var cookies = document.cookie;
cookies = cookies.split("; ")
for (let i = 0; i < cookies.length; i++) {
var cookie = cookies[i].split("=")
if (/.*distinct_id.*/.test(cookie)) {
var cookieName = cookie[0].replace(/_posthog/, '')
cookieName = cookieName.replace('ph_', '')
USERNAME = JSON.parse(decodeURIComponent(cookie[1])).distinct_id
break
}
}
return USERNAME
}catch(error){
console.log('Username detect 1 failed',error);
return '-'
};
};
function tooltipGen(desc){
var tip = document.createElement('span')
tip.classList.add('toolt');
tip.innerText = '?';
tip.title = desc;
return tip
}
function sortQuestTags() {
//ignore this
var list = document.querySelector('span.tags');
var l2 = [...list.children];
var l3 = l2.filter(
function (value, index, arr) {
if (value.className !== 'tag more ng-scope') {
return value
};
});
l3.sort((a, b) => a.innerText > b.innerText ? 1 : -1).forEach(node => list.appendChild(node));
};
function blacklistRemove(item) {
if (settings.alertBlacklist.includes(item)) {
let position = settings.alertBlacklist.indexOf(item);
settings.alertBlacklist.splice(position, 1);
localStorage.setItem('FL_Settings', JSON.stringify(settings));
};
};
function removeNSFW(){
if (settings.removeNSFW == true) {
Array.from(document.getElementsByClassName('nsfwCover')).forEach(qst=>qst.classList.remove('nsfwCover'));
}
}
function repeatChecker() {
try {
let thisPage = window.location.href;
if (thisPage !== lastURL) {
try {
questCheck.observerQst.disconnect();
} catch (error) {}
try {
questCheck.observerTopic.disconnect();
} catch (error) {}
pageCheck();
lastURL = window.location.href;
};
} catch (error) {
console.log('Error with repeatChecker', error);
};
};
setInterval(repeatChecker, 500);
function chatSend(info) {
let body = info[1]
try {
//var encodedBody = encodeURI(body);
fetch("https://fiction.live/api/anonkun/dice", {
"credentials": "include",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0",
"Accept": "*/*",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
"referrer": window.location.href,
"body": body,
"method": "POST",
"mode": "cors"
});
} catch (error) {
console.log('Error with chatSend', error);
}
try {
let chapterID = info[0][0]
let dataID = info[0][1]
let roll = info[0][2]
var cookies = document.cookie;
cookies = cookies.split("; ")
for (let i = 0; i < cookies.length; i++) {
var cookie = cookies[i].split("=")
if (/.*distinct_id.*/.test(cookie)) {
var cookieName = cookie[0].replace(/_posthog/, '')
cookieName = cookieName.replace('ph_', '')
}
}
fetch("https://fiction.live/api/node", {
"credentials": "include",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0",
"Accept": "*/*",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
"referrer": `https://fiction.live/stories/${body}`,
"body": encodeURI(`r[]=${chapterID}&r[]=${dataID}&nt=chat&b=%2Froll+`) + encodeURIComponent(`${roll}`) + encodeURI(`&ra[hide]=true&ra[_id]=${dataID}&ra[b]=chapter+${dataID}&token=${cookieName}`),
"method": "POST",
"mode": "cors"
});
} catch (error) {
console.log('Error with RollSend', error);
}
};
function authorCheck(quest) {
if (quest == null){console.log('Quest is NULL.');return;}
if (/fiction.live\/explore|reviews.*/.test(window.location.href)){return}
var author = quest.querySelector('div.authorPane');
if (author == null) {
try {
author = quest.parentNode.parentNode.querySelector('span.name').innerText
quest = quest.parentNode.parentNode.parentNode
} catch (error) {console.log('authorCheck Null',{quest}, error)};
} else {
try{
author = author.innerText;
}catch(error){console.log('authorCheck text fail', error)}
}
if (settings.authorBlacklist.includes(author)) {
try {
while (true) {
if (quest.parentNode == null ) {
break
}
if (quest.parentNode.classList.contains('ng-scope') && quest.parentNode.tagName == 'LI') {
try{
quest.parentNode.remove()
}catch(error){console.log('authorCheck 2 fail', error)}
break
} else {
quest = quest.parentNode
}
}
return
} catch (error) {
console.log('authorCheck remove',error)
};
return;
};
};
function tagCheck(quest) {
var tagsContainer = quest.querySelector('.tags');
if (tagsContainer == null) {
console.log('TCN')
let tag = quest.parentNode.parentNode.querySelector('div.displayedTag');
if (tag != null | '' | undefined) {
if (settings.tagBlacklist.includes(tag.innerText)) {
try {
while (true) {
if (quest.parentNode == null) {
break;
}
if (quest.parentNode.classList.contains('ng-scope') && quest.parentNode.tagName == 'LI') {
quest.parentNode.remove();
break;
} else {
quest = quest.parentNode;
}
}
return;
} catch (error) {
console.log('tagCheck remove', error);
};
};
return;
} else {
return;
};
};
var tags = tagsContainer.children;
for (let i = 0; i < tags.length; i++) {
let tag = tags[i];
if (settings.tagBlacklist.includes(tag.innerText)) {
var title = quest.querySelector('h2').innerText;
var classes = Array.from(quest.classList);
try {
//quest.parentNode.parentNode.remove();
//return
//await new Promise(r => setTimeout(r, 20000));
if (!quest.classList || !quest.classList.contains('storyListItem')){
//console.log('Type 1',{title, classes});
tagsContainer.closest('.storyListItem').remove();
}else{
//console.log('Type 2',{title, classes});
tagsContainer.closest('.storyListItem').remove();
}
} catch (error) {
console.log('tagCheck remove',{title, classes}, error);
};
break;
};
};
};
function removeBlacklisted() {
let quests = document.querySelectorAll('div.storyListItem');
for (let i = 0; i < quests.length; i++) {
if (settings.questRemove == true) {
tagCheck(quests[i].children[0]);
}
if (settings.questAuthorRemove == true) {
authorCheck(quests[i].children[0]);
}
};
};
function liveRestore() {
var navBar = document.querySelector('[id="mainMenuReplacement"][class="navbar navbar-default navbar-fixed-top"]');
var liveTimer = document.querySelectorAll('[class="next-live ng-scope"]');
var myLive = document.createElement('div');
myLive.setAttribute('id', 'liveBox');
if (document.querySelector('#liveBox')){
document.querySelector('#liveBox').appendChild(liveTimer[0].children[0])
return;
}
darkCheck()
if (window.FL_Script.darkMode == true) {
myLive.classList.add('dark')
}
while (liveTimer[0].children.length > 0) {
myLive.appendChild(liveTimer[0].children[0]);
}
navBar.appendChild(myLive);
liveTimer[0].style.display = 'none';
};
function waitForTimer() {
if (settings.liveRestore == false) {
return
};
var observerTimer = new MutationObserver(awaitTimer);
function awaitTimer(mutations) {
for (let mutation of mutations) {
try {
var canvas = document.querySelector('header[class="next-live ng-scope"]');
} catch (error) {}
if (canvas && (canvas !== undefined && canvas.length != 0)) {
observerTimer.disconnect(); // stop observing
liveRestore()
return;
};
};
};
observerTimer.observe(document, {
childList: true,
subtree: true
});
setTimeout(function () {
try {
observerTimer.disconnect();
} catch (error) {}
}, 1000);
};
function questCheck(){
if (settings.questRemove !== true && settings.questAuthorRemove !== true && settings.removeNSFW !== true) {
return;
}
try {
var options = {
childList: true,
subtree: true
};
function qstMod(mutations) {
for (let mutation of mutations) {
try {
var quest = mutation.addedNodes[0];
if (quest) {
try {
if (quest.classList.contains('storiesList') || quest.closest('nav')){return;}
if (quest.classList.contains('storyListItem') && !quest.classList.contains('checked')){
removeBlacklisted();
if (settings.questRemove == true) {
tagCheck(quest);
}
if (settings.questAuthorRemove == true) {
authorCheck(quest);
}
removeNSFW();
try{
quest.classList.add('checked');
}catch(error){console.log('error',error)}
}
else if (quest.parentNode.classList.contains('storyListItem') && !quest.parentNode.classList.contains('checked')) {
try{
if (settings.questRemove == true) {
tagCheck(quest);
}
if (settings.questAuthorRemove == true) {
authorCheck(quest);
}
removeNSFW();
try{
quest.parentNode.classList.add('checked');
}catch(error){console.log('error',error)}
}catch(error){console.log('error',error)}
}
else if (quest.parentNode.parentNode.parentNode.parentNode.classList.contains('storyListItem') && /.*fiction.live\/$/.test(URL)) {
if (settings.questRemove == true) {
if (quest) {
tagCheck(quest);
}
}
try {
if (settings.questAuthorRemove == true) {
if (quest) {
authorCheck(quest);
}
}
} catch (error) {
console.log(error)
}
removeNSFW();
}
else if (quest.querySelector('.storyListItem')!= null && !quest.querySelector('.storyListItem').classList.contains('checked')){
//return
// For fiction.live
if (settings.questRemove == true) {
if (quest) {
tagCheck(quest.querySelector('.storyListItem'));
}
}
try {
if (settings.questAuthorRemove == true) {
if (quest.querySelector('.storyListItem') != null) {
authorCheck(quest.querySelector('.storyListItem'));
}
}
} catch (error) {
console.log(error)
}
removeNSFW();
try{if (quest.querySelector('.storyListItem')){
quest.querySelector('.storyListItem').classList.add('checked');}
}catch(error){console.log('error',quest,error)}
}
} catch (error) {
//console.log('If this appears more than twice, make an issue.')
if (error instanceof TypeError) {}
else {
console.log(error)
}
}
}
//observerMessage.disconnect();
} catch (error) {
console.log('New quest Error', error);
}
};
};
let observerQst = new MutationObserver(qstMod);
observerQst.observe(document, options);
questCheck.observerQst = observerQst;
removeBlacklisted();
} catch (error) {
console.log('questCheck', error)
};
};
function exploreBlacklistCheck(){
function checkTagGroup(x){
if (settings.tagBlacklist.includes(x.querySelector('h2').innerText.replace('/',''))){
x.remove();
}else{
var tags = x.getElementsByClassName('displayedTag');
let tt=function(tag){
if (settings.tagBlacklist.includes(tag.innerText)){
tag.closest('.embla__slide').remove()
}
}
Array.from(tags).forEach(tag=>{tt(tag)});
}
}
function elementAwaitExplore(mutations) {
for (let mutation of mutations) {
try {
let topic = mutation.addedNodes[0];
if (topic) {
try {
if (!topic.classList){continue};
if (topic.classList.contains('popular-tags-list')){
observerTopic.disconnect();
Array.from(topic.children).forEach(tag=>{checkTagGroup(tag)});
removeNSFW()
};
} catch (error) {
console.log(error)
}
}
} catch (error) {
console.log('New quest Error', error);
}
};
};
let observerTopic = new MutationObserver(elementAwaitExplore);
observerTopic.observe(document, {childList: true, subtree: true});
questCheck.observerTopic = observerTopic;
};
function foryouBlacklistCheck(){
function checkTag(storyListing){
try{
var tag = storyListing.getElementsByClassName('displayedTag')[0]
if (!tag || tag.length == 0){return}
if (settings.tagBlacklist.includes(tag.innerText)){
storyListing.parentNode.remove()
}}catch(error){}
};
function checkAuthor(storyListing){
try{
var name = storyListing.querySelector('span.name').innerText
if (!name || name.length == 0){return}
if (settings.authorBlacklist.includes(name)){
storyListing.parentNode.remove()
}}catch(error){}
};
function elementAwaitForYou(mutations) {
for (let mutation of mutations) {
try {
var topic = mutation.addedNodes[0];
if (topic) {
try {
if (!topic.classList){return}
if (topic.classList.contains('storyListItem')){}
var SLIs=document.getElementsByClassName('storyListItem');
//console.log('SLIs',SLIs)
if (!SLIs || topic.id != 'main'){continue};
if (SLIs){
observerTopicx.disconnect();
Array.from(SLIs).forEach(SLI=>{checkTag(SLI)});
Array.from(SLIs).forEach(SLI=>{checkAuthor(SLI)});
removeNSFW();
};
} catch (error) {
console.log(error);
}
}
removeNSFW();
} catch (error) {
console.log('New quest Error', error);
}
};
};
let observerTopicx = new MutationObserver(elementAwaitForYou);
observerTopicx.observe(document, {childList: true, subtree: true});
questCheck.observerTopic = observerTopicx;
};
function storyThings(){
//Detects when the content of a quest is displayed, the rolls/text
var options = {
childList: true,subtree:true
};
var observeDoc = new MutationObserver(function(mutations){
for (let mutation of mutations) {
try{
if (!mutation.addedNodes[0] ||
mutation.addedNodes == null ||
mutation.addedNodes == undefined ||
mutation.addedNodes.length == 0){
return;
}
if (mutation.addedNodes[0].classList.contains('nextLive')||
mutation.addedNodes[0].classList.contains('nextLive')||
mutation.target.tagName == 'head'||
mutation.target.tagName == 'ins'){
return;
}
else{
//console.log(mutation.addedNodes[0]);
var node = mutation;
}
if (node.addedNodes[0].tagName == 'footer'){console.log(node)}
if (node.addedNodes[0].classList.contains('storyListItem')){
//console.log(node);
fetchQuestInfo(node.addedNodes[0]);
}
var storyPosts = document.getElementById('storyPosts').children[0];
if (typeof(storyPosts) != undefined && storyPosts != undefined){
observeDoc.disconnect();
checkStory(storyPosts);
monitorStory(storyPosts);
break;
}
} catch (error) {};
}
});
observeDoc.observe(document, options);
async function fetchQuestInfo(questNode){
try{
let questID = questNode.href.match('.*\/stories\/.*\/(.*)\/?')[1];
await fetch("https://fiction.live/api/node/"+questID, {
"credentials": "include",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0",
"Accept": "application/json, text/plain, */*",
"Accept-Language": "en-GB,en;q=0.5",
"Cache-Control": "max-age=0"
},
"referrer": "https://fiction.live/stories/A-Hopefully-Super-Simple-Quest/NADtB24rEMDR8ybY9",
"method": "GET",
"mode": "cors"
}).then(response => response.json())
.then(r=>{
let QM = r.u[0].n;
//console.log(questNode,QM);
if (settings.authorBlacklist.includes(QM)){questNode.remove()};
})
}catch(error){console.log('fetchQuestInfo Error')}
}
function createRollButton(roll){
var inp=document.createElement('input');
inp.setAttribute('type','button');
inp.setAttribute('class','rollButton');
if (window.FL_Script.darkMode == true){
inp.style = 'height:auto;width:auto;margin:1;padding:1;background:rgb(57, 60, 89);';
}else{
inp.style = 'height:auto;width:auto;margin:1;padding:1;background:rgb(255, 172, 71);';
}
inp.value = 'Roll '+roll;
inp.onclick = function (){
var latestUpdate = document.querySelector('div#storyPosts').firstChild.lastChild;
var poll = latestUpdate.firstChild.firstChild;
if (latestUpdate.classList.contains('readerPost') == false || poll.classList.contains('closed')) {
return;
} else if (!(poll.classList.contains('closed'))) {
var dataID = this.closest('article').getAttribute('data-id');
var chapterID = document.querySelector('article.threads').getAttribute('threads');
chapterID = chapterID.replace(/\/.*/, '');
var rollSend = `/roll ${roll}`;
var template = `sid=${chapterID}&dice=${encodeURIComponent(rollSend)}`;
chatSend([[chapterID, dataID, roll], template]);
}
this.style.display='none';
};
return inp
};
function imageInsert(element){
try{
if (/\[.*\]/.test(element.innerText)){
let info = element.innerText.replace(/(\[|\])/g,'').split(',')
if (!/.*\.(gif|jpe?g|bmp|png|webp|webm|apng|jfif|pjpeg|pjp|svg|bmp|cur|ico|tif|tiff)$/igm.test(info[0])){return};
let image = document.createElement('img');
image.src = info[0]
let q = document.createElement('br');
console.log(info)
if (info[1].toString().toLowerCase() == 'hide'){
let hidden = document.createElement('input');
hidden.value = 'Show hidden image, potential spoilers.'
hidden.setAttribute('type','button');
hidden.onclick = function(){
try{
if (this.parentNode.lastChild != this){this.parentNode.insertBefore(q, this.nextSibling)};
this.replaceWith(this.children[0]);
}catch(error){console.log(error)};
};
hidden.appendChild(image);
element.replaceWith(hidden);
}
else{
if (element.parentNode.lastChild != element){
element.parentNode.insertBefore(q, element.nextSibling);
}
element.replaceWith(image);
}
};
}catch(error){console.log(error)};
};
function imageInsertbtn(){
let li = document.createElement('li')
let btn = document.createElement('button');
btn.setAttribute('class','fa fa-photo');
btn.setAttribute('tooltip-position','top');
btn.setAttribute('tooltip-content','Add an image to the quest visible only to script users. Pick show or hide depending if the image is a spoiler.');
btn.onclick = function(){
let p = document.createElement('p')
p.setAttribute('class','aaaaax');
p.innerText = '[ImageURLhere,Show/Hide]';
try{
if (window.getSelection().anchorNode.tagName != 'DIV'){
window.getSelection().anchorNode.parentNode.append(p);
}
else{
window.getSelection().anchorNode.append(p);
}
}catch(error){
console.log(error)
console.log(window.getSelection().anchorNode)
}
};
li.appendChild(btn);
return li;
};
function checkStory(storyPosts){
try{
for (let post of storyPosts.childNodes){
if (post.className.includes('chapter') && post.innerText.match(/\[.*\]/)){
post.querySelectorAll('p').forEach(p=>imageInsert(p))
};
}
}catch(error){
console.log('Error with checkStory');
}
}
function monitorStoryQM(){
document.querySelectorAll('.medium-editor-toolbar').forEach(tb=>{
let btn = new imageInsertbtn;
tb.children[0].insertBefore(btn,tb.children[0].children[tb.children[0].children.length-1]);
});
let A = document.createElement('div');
A.setAttribute('class','monitorStoryQM');
document.body.appendChild(A);
let options = {childList: true};
let observeToolbars = new MutationObserver(function (mutations) {
for (let mutation of mutations) {
try {
if (mutation.addedNodes.length != 0){
let node=mutation.addedNodes[0];
if (node.classList.contains('medium-editor-toolbar')){
let btn = new imageInsertbtn;
node.children[0].insertBefore(btn,node.children[0].children[node.children[0].children.length-1]);
};
}
} catch (error) {
console.log('monitorStory Error',error);
};
};
});
observeToolbars.observe(document.body, options);
};
let addInsert = function (event) {
document.removeEventListener("dblclick", addInsert, false);
let QM = document.querySelector('.goLive');
let Started = document.querySelector('.monitorStoryQM');
if (Started){return};
if (QM){monitorStoryQM()};
};
document.addEventListener("dblclick", addInsert, false);
function monitorStory(storyPosts){
function rollPro(roll,elm){
elm.querySelector('.chapterContent').appendChild(createRollButton(roll));
setTimeout(function(){elm.querySelector('.rollButton').remove()},60000);
};
function sortPoll(table){
var l3 = [...table.children].filter(
function (value, index, arr) {
if (value.className !== '') {
//Ignore the 'Votes' header
return value;
};
});
//Order the poll by total votes
l3.sort((a, b) => parseInt(a.querySelector('span[data-hint="Total Votes"]').innerText) < parseInt(b.querySelector('span[data-hint="Total Votes"]').innerText) ? 1 : -1).forEach(node => table.appendChild(node));};
//Checks if new posts are saying that there is a roll, if so, add a button to roll.
let options = {childList: true};
let observerPosts = new MutationObserver(function (mutations) {
for (let mutation of mutations) {
try {
try{
if (!window.FL_Script.customA){
window.FL_Script.customA = true;
}
}catch(error){}
if (mutation.addedNodes.length != 0){
let elm = mutation.addedNodes[0];
var diceRegex = /[0-9]+d[0-9]+(?<!1d1)((\+|\-)[0-9]+)?( ?)(([ie]+)?([ut][0-9]+)?)+/g;
//If text post like an update
if (elm.className.includes('chapter')){
if (elm.innerText.match(/\[.*\]/)){
elm.querySelectorAll('p').forEach(p=>imageInsert(p))
};
continue
}
//Auto sort poll results by votes
else if (elm.className.includes('chapter choice')){
console.log('A poll has been created.')
let pollState = elm.children[0].children[0];
let observePoll = new MutationObserver(function(mutations){
for (let mutation of mutations) {
try{
//When the poll gets closed, sort the results and start a timer to stop monitoring.
//console.log(mutation)
if (pollState.className.includes('closed')){
//console.log('sort')
let table = pollState.querySelector('tbody');
sortPoll(table);
setInterval(function(){try{observePoll.disconnect}catch(e){}},120000)
};
} catch (error) {
console.log(error);
};
};
});
observePoll.observe(pollState, {attributes: true});
}
//a
else if (elm.querySelector('.fieldBody > b')){continue;}
else if (diceRegex.test(elm.innerText)){
if (settings.diceButton == true){
let rolls = elm.innerText.match(diceRegex);
rolls.forEach(roll => rollPro(roll,elm))
};
};
};
} catch (error) {
console.log('monitorStory Error',error);
};
};
});
if (window.FL_Script.monSto != undefined){observerPosts.disconnect();};
observerPosts.observe(storyPosts, options);
window.FL_Script.monSto = observerPosts;
};
};
function pageCheck(){
try{window.FL_ULA()}catch(error){}
try {
let URL = window.location.href;
if ((/.*(fiction.live\/stories\/).*/.test(URL))) {
chatThings();
waitForTimer();
storyThings();
} else if (/.*(fiction.live$)/.test(URL)) {
questCheck();
} else if (/.*(fiction.live\/stories\/?).*/.test(URL) || /.*(fiction.live\/.*\?.*(contentRating|storyStatus|rInteract|sort)).*/.test(URL)) {
questCheck();
} else if (/.*(fiction.live\/social\/(threads\/)?).*/.test(URL)) {
chatThings();
} else if (/.*(fiction.live\/live\?).*/.test(URL)) {
questCheck();
} else if (/.*(fiction.live\/social).*/.test(URL)) {
removeBlankTopics();
} else if (/.*fiction.live\/$/.test(URL)) {
questCheck();
} else if (/.*fiction.live\/explore/.test(URL)) {
exploreBlacklistCheck();
} else if (/.*fiction.live\/foryou/.test(URL)) {
foryouBlacklistCheck();
} else if (/.*fiction.live\/user\/.*\/(stories$||collections\/.*)/.test(URL)) {
questCheck();
removeNSFW();
} else if (/.*fiction.live\/reviews/.test(URL)) {
questCheck()
} else {
console.log('Page currently has no specific functions.');
}
} catch (error) {
console.log('Error with pageCheck', error);
};
};
function removeBlankTopics() {
if (settings.removeBlankTopics !== true) {
return;
};
try {
var options = {
childList: true,
subtree: true
};
function topicWatch(mutations) {
for (let mutation of mutations) {
try {
let topic = mutation.addedNodes[0];
if (topic) {
try {
if (typeof(topic.classList) == 'undefined') {}
else if (topic.classList.contains('threadList')) {
let topicItem = topic.querySelectorAll('li.threadListItem');
for (let i = 0; i < topicItem.length; i++) {
if (topicItem[i].querySelector('div.row.title.header').innerText.length == 0) {
topicItem[i].remove();
};
};
};
} catch (error) {
console.log(error);
};
};
} catch (error) {
console.log('New quest Error', error);
};
};
};
let observerTopic = new MutationObserver(topicWatch);
observerTopic.observe(document, options);
questCheck.observerTopic = observerTopic;
} catch (error) {
console.log('topicCheck', error)
};
};
function newThemeChange(){
if (settings.useThemeChange != true){
return;
};
if (window.FL_Script.TChange == true){
return;
};
//return
function cookieCreate(name,value,days){
var expires;
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 *1000));
expires = "; expires=" + date.toGMTString();
} else {
expires = "";
}
document.cookie = name + "=" + value + expires + "; path=/";
};
document.addEventListener("mousedown", function (event) {
if (settings.useThemeChange != true){
return;
};
try{
let themeBTN = document.querySelector('[ng-click="changeTheme()"]');
if (themeBTN == (null || undefined) || !themeBTN.contains(event.target)){
return;
}
darkCheck();
let style=document.head.querySelector('link[rel="stylesheet"]')
if (window.FL_Script.darkMode==true){
style.href=style.href.replace('style-dark.css','style.css');
cookieCreate('themeColor','default','300')
}
else{
style.href=style.href.replace('style.css','style-dark.css');
cookieCreate('themeColor','dark','300')
}
}catch(error){
console.log('newThemeChange.',error)
};
});
try{
let themeBTN = document.querySelector('[ng-click="changeTheme()"]');
if (themeBTN != null || undefined){
themeBTN.outerHTML = themeBTN.outerHTML;
}
}catch(error){console.log(error)};
};
function imageLinkButton(){
if (settings.imageLink != true){try{document.querySelector('.linkImg').remove()}catch(error){};return;};
//if (!/.*fiction.live.stories\/.*\/.*/.test(window.location)){return;};
if (document.querySelector('.chatInputContainer') == null){setTimeout(imageLinkButton(),1000);return;}
if (document.querySelectorAll('.chatInputContainer').length == null){setTimeout(imageLinkButton(),1000);return;};
//if (document.querySelector('.linkImg')){return;}
function imageSend(info) {
try {
let chapterID = info[0]
let dataID = info[1]
let imageURL = info[2]
let body = encodeURI(`r[]=${chapterID}&r[]=${dataID}&nt=chat&`) + `i=${imageURL}` + encodeURI(`&ra[hide]=true&ra[_id]=${dataID}&ra[b]=chapter+${dataID}`)
if (!chapterID){
body = encodeURI(`&r[]=${dataID}&nt=chat&`) + `i=${imageURL}`
}
fetch("https://fiction.live/api/node", {
"headers": {
"User-Agent": "",
"Accept": "*/*",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
"body": body,
"method": "POST",
"mode": "cors"
});
} catch (error) {
console.log('Error with RollSend', error);
}
};
document.querySelectorAll('.chatInputContainer').forEach(x=>{
try{
var inp=document.createElement('div');
inp.setAttribute('class','linkImg');
inp.onclick=function(){
if (settings.imageLink != true){try{document.querySelector('.linkImg').remove()}catch(error){};return;};
try{
//if (document.querySelector('.linkInput')){return;};
var linkInputCont=document.createElement('div');
linkInputCont.setAttribute('class','linkInput');
var linkInputSend=document.createElement('input');
linkInputSend.setAttribute('type','button');
linkInputSend.value = 'Send';
linkInputSend.onclick = function(){
try{
let reply='';
let imageURL = linkInput.value;
//if (imageURL == '' || !/.*\.(gif|jpe?g|bmp|png|webp)$/i.test(imageURL)){return;};
let dataID;
if (/.*\/threads\/.*/.test(window.location)){
dataID = document.querySelector('#page-body').querySelector('article[chat]').getAttribute('chat');
imageSend(['', dataID, imageURL, reply]);
}
else{
//Old? Doesnt work now anyway
//dataID = document.querySelector('div#storyPosts').firstChild.lastChild.firstChild.firstChild.getAttribute('data-id');
if (this.closest('.chatItemDetail')){
let ArticleID, ReplyID, ImageURL, MessageText, MessageAuthor, MessageAuthorID;
ReplyID = this.closest('.chatItemDetail').getAttribute('data-id');
ArticleID = document.querySelector('div#storyPosts').firstChild.lastChild.getAttribute('data-id');
let ChapterID = document.querySelector('article.threads').getAttribute('threads');
//MessageAuthor = this.closest('.chatItemDetail').querySelector('.user > .content a').innerText;
try{
MessageText = this.closest('.chatItemDetail').querySelector('.fieldBody').innerText;
}catch(error){
MessageText = null;
}
ChapterID = ChapterID.replace(/\/.*/, '');
MessageAuthorID='';
ImageURL = imageURL
let body;
if (MessageText != null){
body = "r%5B%5D="+ChapterID+"&r%5B%5D="+ArticleID+"&r%5B%5D="+ReplyID+"&nt=chat&i="+ImageURL+
"&ra%5B_id%5D="+ReplyID+"&ra%5Bb%5D="+MessageText+"&ra%5Bu%5D%5Bn%5D="+MessageAuthor+"&ra%5Bu%5D%5B_id%5D="+MessageAuthorID
}
else{
body = "r%5B%5D="+ChapterID+"&r%5B%5D="+ArticleID+"&r%5B%5D="+ReplyID+"&nt=chat&i="+ImageURL+
"&ra%5B_id%5D="+ReplyID+"&ra%5Bu%5D%5Bn%5D="+MessageAuthor+"&ra%5Bu%5D%5B_id%5D="+MessageAuthorID
}
//+"&token=phc_yFaXlxPuv5BU2WbCujfLxNFetXTmh5DjtUesJyA28TF"
//console.log(body)
//return
fetch("https://fiction.live/api/node", {
"headers": {
"User-Agent": "",
"Accept": "*/*",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
"body": body,
"method": "POST",
"mode": "cors"
});
return
}else{
dataID = document.querySelector('div#storyPosts').firstChild.lastChild.getAttribute('data-id');
let chapterID = document.querySelector('article.threads').getAttribute('threads');
chapterID = chapterID.replace(/\/.*/, '');
imageSend([chapterID, dataID, imageURL]);
}
}
}catch(error){
console.log(error);
}
}
var linkInputExit=document.createElement('input');
linkInputExit.setAttribute('type','button');
linkInputExit.value = 'Exit';
linkInputExit.onclick = function(){this.parentNode.remove()}
var linkInput=document.createElement('textarea');
linkInput.setAttribute("placeholder", "Input the image link here.");
linkInput.setAttribute("cols", "1");
linkInput.setAttribute("rows", "2");
linkInputCont.appendChild(linkInput);
linkInputCont.appendChild(linkInputSend);
linkInputCont.appendChild(linkInputExit);
//document.querySelector('#right').appendChild(linkInputCont);
this.parentNode.appendChild(linkInputCont);
//imageSend([chapterID, dataID, imageURL]);
}catch(error){console.log(error)};
};
x.children[0].after(inp);
}catch(error){console.log(error)};
})
};
function chatThings(){
try{}catch(error){};
try{
document.addEventListener("mousedown", function (e) {
//console.log('clicked',e.target)
try{
function fetchMessages() {
try{
let test=target.querySelector('.jadeRepeat');
}catch(error){
console.log('F1');
}
try{
if (target.querySelector('.jadeRepeat').childNodes == null){
console.log('F2.0');
}
let test=target.querySelector('.jadeRepeat').childNodes;
}catch(error){
console.log('F2');
}
if ((target.querySelector('.jadeRepeat') || target.querySelector('.jadeRepeat').childNodes) == (null || undefined)){
setTimeout(fetchMessages, 500);
console.log('Refetch Required.')
}
try{
target.querySelector('.jadeRepeat').childNodes.forEach(d => handleMsg(d));
}catch(error){
console.log('F3')
}
};
//If the users clicked a chat button below a story post.
let target;
function purgeNonImages(){
if (e.target.closest('footer.chapter-footer').querySelector('.FL_IMG')){return;}
var removeTextLI=document.createElement('li');
removeTextLI.classList.add('FL_IMG');
removeTextLI.onclick=function(){
this.parentNode.parentNode.querySelector('div.tab-content').querySelectorAll('.chatMsg .message').forEach(
msg=> {
if (!msg.querySelector('img')){msg.parentNode.parentNode.remove();}
})
}
var removeTextA=document.createElement('a');
removeTextA.innerText = 'Remove non-images';
removeTextLI.appendChild(removeTextA);
let q = e.target.closest('footer.chapter-footer')
q.querySelector('ul.nav.btn-set').appendChild(removeTextLI);
};
function inlineChatMessageMonitor(mutations) {
for (let mutation of mutations) {
try {
var newN = mutation.addedNodes[0];
if (!newN || newN.length == 0){return}
if (newN.matches('div.chatLog.chapterComments div')){
//console.log('Added ICMM');
fetchMessages();
}
observerMessage.disconnect();
} catch (error) {
console.log('inlineChatMessageMonitor Error',error);
}
};
};
let observerMessage = new MutationObserver(inlineChatMessageMonitor);
if (e.target.matches(".expandComments.showWhenDiscussionOpened")) {
//var b = e.target.parentNode.parentNode.parentNode;
target = e.target.closest('.tabbable');
setTimeout(fetchMessages, 500);
observerMessage.observe(target, {
childList: true,
subtree: true
});
purgeNonImages();
}
else if (e.target.matches(".btn.expandComments")) {
target = e.target.closest('footer');
setTimeout(fetchMessages, 500);
observerMessage.observe(target, {
childList: true,
subtree: true
});
purgeNonImages();
}
else if (e.target.parentNode.matches(".btn.expandComments")) {
target = e.target.parentNode.closest('footer');
//setTimeout(fetchMessages, 500);
observerMessage.observe(target, {
childList: true,
subtree: true
});
purgeNonImages();
}
}catch(error){
console.log('Error - Post Chat Mousedown',error)
};
});
function chatBlacklist(message) {
try{
let username = message.querySelector('.user span').innerText;
if (settings.chatBlacklist != true || settings.chatBlacklisted.length == 0) {return;};
if (settings.chatBlacklisted.includes(username)) {
message.classList.add('chatListed');
return;
} else {
if (settings.chatBlacklistReplies == true) {
replyCheck();
};
};
async function replyCheck() {
let msgData = '';
let msgData2 = '';
if (message.querySelector('.replyAt')) {
await fetch(`https://fiction.live/api/node/${message.firstChild.getAttribute('data-id')}`).then(response => response.json()).then(data => {
msgData = data
})
await fetch(`https://fiction.live/api/node/${msgData.ra._id}`).then(response => response.json()).then(data => {
msgData2 = data
});
try{
if (settings.chatBlacklisted.includes(msgData2)) {
message.classList.add('chatListed');
setTimeout(function () {
try {
document.querySelectorAll('.chatListed').forEach(mm => mm.remove());
} catch (error) {
//console.log(error);
};
}, 500);
};
}catch(error){
console.log(message)}
};
};
async function delMSG(name) {
try {
var msgID = message.firstChild.getAttribute('data-id');
} catch (error) {
console.log('id fail');
};
try {
if (name == message.querySelector('div.user span').innerText) {
message.remove();
return;
} else {
var commentName = '', replyName = '', msgData = '';
await fetch("https://fiction.live/api/node/" + msgID, {}).then(response => response.json()).then(data => {msgData = data});
commentName = msgData.u[0].n;
try {
replyName = msgData.ra.u.n;
} catch (error) {
console.log('reply fail');
};
if (settings.chatBlacklisted.includes(replyName)) {
message.remove();
} else if (settings.chatBlacklisted.includes(commentName)) {
message.remove();
};
};
} catch (error) {
console.log('total fail', message.parentNode);
};
};
} catch (error) {};
};
function akunPlus(message) {
try {
if (settings.akunPlus == 'Ignore') {
return;
} else if (settings.akunPlus == 'Remove') {
message.querySelector('.chatMsg').removeAttribute('plan');
} else {
message.querySelector('.chatMsg').setAttribute('plan', '1');
}
} catch (error) {
//console.log(message.querySelector('span.name'),message.querySelector('.message').innerText,error)
}
};
function functionalLinks(message) {
function isVisible(element){
try{
let bounding = element.getBoundingClientRect();
if(bounding.top >= 0 && bounding.left >= 0 &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight))
{
return true;
}else{
return false;
}
} catch (error) {}
};
try{
try {
if (message.querySelector('.message').querySelector('img') ||
message.querySelector('.linkDiv')){
return;
}
} catch (error) {
}
let Control = [0, 0, 0]
var elmDiv = document.createElement('div');
elmDiv.setAttribute('class', 'linkDiv');
var elmDivControl = document.createElement('div');
var elmDivControlA = document.createElement('input');
elmDivControlA.setAttribute("type", "button");
elmDivControlA.setAttribute("hide", 'false');
elmDivControlA.value = 'Disable Link(s)'
elmDivControlA.onclick = function () {
if (this.getAttribute('hide') == 'true' || null) {
this.setAttribute('hide', 'false');
this.value = 'Disable Link(s)';
this.parentNode.parentNode.querySelector('.linkDivA').style.display = 'initial';
} else {
this.setAttribute('hide', 'true');
this.value = 'Enable Link(s)';
this.parentNode.parentNode.querySelector('.linkDivA').style.display = 'none';
}
}
var elmDivControlB = document.createElement('input');
elmDivControlB.setAttribute("type", "button");
elmDivControlB.setAttribute("hide", 'false');
elmDivControlB.value = 'Disable Image(s)'
elmDivControlB.onclick = function () {
if (this.getAttribute('hide') == 'true' || null) {
this.setAttribute('hide', 'false');
this.value = 'Disable Image(s)';
this.parentNode.parentNode.querySelector('.linkDivB').style.display = 'initial';
} else {
this.setAttribute('hide', 'true');
this.value = 'Enable Image(s)';
this.parentNode.parentNode.querySelector('.linkDivB').style.display = 'none';
}
}
var elmDivControlC = document.createElement('input');
elmDivControlC.setAttribute("type", "button");
elmDivControlC.setAttribute("hide", 'true');
elmDivControlC.value = 'Enable Video(s)'
elmDivControlC.onclick = function () {
if (this.getAttribute('hide') == 'true' || null) {
this.setAttribute('hide', 'false');
this.value = 'Disable Video(s)';
this.parentNode.parentNode.querySelector('.linkDivC').style.display = 'initial';
} else {
this.setAttribute('hide', 'true');
this.value = 'Enable Video(s)';
this.parentNode.parentNode.querySelector('.linkDivC').style.display = 'none';
}
}
var elmDivA = document.createElement('div');
elmDivA.setAttribute('class', 'linkDivA');
elmDiv.appendChild(elmDivA);
var elmDivB = document.createElement('div');
elmDivB.setAttribute('class', 'linkDivB');
elmDiv.appendChild(elmDivB);
var elmDivC = document.createElement('div');
elmDivC.setAttribute('class', 'linkDivC');
elmDivC.style.display = 'none'
elmDiv.appendChild(elmDivC);
function link(type, type2, link) {
var elm = document.createElement(type);
if (type2 == 1) {
elm.src = link;
elmDiv.childNodes[1].appendChild(elm);
} else if (type2 == 2) {
elm.href = link;
elm.innerHTML = 'Link';
elm.setAttribute('class', 'functionalLink');
elm.rel = "noopener noreferrer";
elm.target = "_blank";
elmDiv.childNodes[0].appendChild(elm);
} else if (type2 == 3) {
elm = document.createElement('iframe');
elm.setAttribute('frameborder', '0')
elm.setAttribute('allowFullScreen', '')
elm.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture';
elm.src = link;
elm.setAttribute('class', 'functionalVideo');
let functionalContainer = document.createElement('div');
functionalContainer.setAttribute('class', 'functionalContainer');
functionalContainer.appendChild(elm);
elmDiv.childNodes[2].appendChild(functionalContainer);
}
return elmDiv
}
function linkProcess(match) {
try {
//If theres already a link container, check if the links been embedded
if (message.querySelector('.linkDiv')) {
var qq = message.querySelector('.linkDiv').querySelectorAll('a').forEach(
x => {
if (x.href == match) {
return;
};
});
};
} catch (error) {
console.log(error);
};
if (typeof match == 'undefined' || match.startsWith('/') || match.length < 5 || /.+\..+/.test(match) == false) {}
else {
try {
if (/([a-z]*\.{2,}[a-z]*)/.test(match) == true) {
return
};
var elm;
if (/https?:\/\//.test(match) == false) {
match = 'https://'.concat(match)
};
if (/.*(jpg|jpeg|png|gif|webm|webp)/.test(match)) {
elm = new link('img', 1, match);
Control[1] = 1;
} else if (settings.functionalVideos == true && (/youtu\.?be/.test(match))) {
if (/.*v=((\w|-)+).*/.test(match)) {
let src = `https://www.youtube.com/embed/${(match.match(/v=((\w|-)+)/)[1])}`;
elm = new link('iframe', 3, src);
message.querySelector('.chatMsg').parentNode.appendChild(elm);
} else if (/be\/(\w|-)+/.test(match)) {
let src = `https://www.youtube.com/embed/${(match.match(/be\/((\w|-)+)/)[1])}`;
elm = new link('iframe', 3, src)
message.querySelector('.chatMsg').parentNode.appendChild(elm);
}
Control[2] = 1;
} else {
elm = new link('a', 2, match);
Control[0] = 1;
}
} catch (error) {
console.log(error)
};
}
};
if (settings.functionalLinks != true) {return;};
try {
//var regex = new RegExp(/(https?:\/\/(www\.)?)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)*/g);
var regex = new RegExp(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)*/g);
var text = message.querySelector('div.fieldBody').innerText;
if (regex.test(text)) {
var matches = text.match(regex), mCount = 0;
matches.forEach(match => linkProcess(match));
if (Control[0] == 1) {
elmDivControl.appendChild(elmDivControlA);
};
if (Control[1] == 1) {
elmDivControl.appendChild(elmDivControlB);
};
if (Control[2] == 1) {
elmDivControl.appendChild(elmDivControlC);
};
elmDiv.prepend(elmDivControl);
message.querySelector('.chatMsg').parentNode.appendChild(elmDiv);
let bounding = message.getBoundingClientRect();
if(isVisible(message)){
message.scrollIntoView();
}
};
} catch (error) {
//console.log(error)
}
} catch (error) {}
};
function removeUsernames(message) {
//return;
//console.log('this shouldnt be seen')
if (settings.removeUsernames == true && message.querySelector('span.name')) {
message.querySelector('span.name').style.display = 'none';
let authorList = document.querySelectorAll('.page-author')[0].children
let authors = []
//authorList.forEach(element => authors.push(element.querySelector('span.name').innerText))
Array.from(authorList).forEach(
element=>{
if (element.innerText != ''){
authors.push(element.querySelector('span.name').innerText)
}
}
)
try {
if (authors.includes(message.querySelector('span.name').innerText)) {
message.querySelector('span.name').style.display = 'initial';
return;
} else {
setTimeout(function () {
try {
message.querySelector('img.avatar').remove()
} catch (error) {};
try {
message.querySelector('span.name').innerText = 'anon'
message.querySelector('span.name').style.display = 'initial';
} catch (error) {
console.log('Error forcing anon', error);
};
setTimeout(function () {
if (message.querySelector('span.name').innerText != 'anon') {
message.querySelector('span.name').innerText = 'anon'
}
}, 100);
}, 100);
}
} catch (error) {
console.log('removeUsernames failed', error);
};
} else{
return}
};
function authorHighlight(message) {
try{
if (settings.authorHighlight == true && message.querySelector('span.name')) {
var currentColor;
if (window.FL_Script.darkMode == false) {
currentColor = settings.highlightLight;
}else{
currentColor = settings.highlightColor;
}
let authorList = document.querySelectorAll('.page-author')[0].children
let authors = []
Array.from(authorList).forEach(
element=>{
if (element.innerText != ''){
authors.push(element.querySelector('span.name').innerText)
}
}
)
try {
if (authors.includes(message.querySelector('span.name').innerText)) {
if (settings.highlightColor) {
try {
message.style.backgroundColor = currentColor;
} catch (error) {
console.log('Failed using custom color', error);
}
}
};
} catch (error) {
console.log('Author highlighter failed', error);
};
}
else{
return;
};
}catch(error){};
};
function imageResize(message) {
try{
if (settings.imageResize == true) {
let msgImage = message.querySelector('div.message').querySelector('img');
if (msgImage != null && msgImage != undefined) {
let image = message.querySelector('div.message').querySelector('img');
if (image.src.includes('?')){
image.src = image.src.split('?')[0];
}
else{
image.src = image.src.replace(/(h[0-9]+\-w[0-9]+)/, 'h5600-w5600');
let page = image.src;
image.setAttribute('onclick', "window.open('" + page + "', '_blank');")
try {
image.onerror = (function () {
try{
if (this.retries && this.retries < 5){this.retries = this.retries + 1;}
else if (this.retries == 5){return;}
else{this.retries = 1;}
console.log('Source failed. Retrying. Retries',this.retries,'of 5.');
setTimeout(this.src = this.src, 500);
}catch(error){
console.log('ImageResizeRetryError');
}
})
} catch (error) {
console.log('img error add fail',error)
};
}
};
} else{
return;
};
}catch(error){console.log('ImageResizer',error)}
};
async function userReveal(message){
if (settings.userReveal != true || settings.removeUsernames == true){return}
try{
var messageID=message.firstChild.getAttribute('data-id')
var returnedData=message.firstChild.getAttribute('data-id')
try{
await fetch(`https://fiction.live/api/node/${messageID}`).then(response => response.json()).then(data => {returnedData=data});
if (!returnedData.u[0]._id){
//console.log('no _id')
//console.log(returnedData.u)
return;
};
//console.log('got_id',returnedData.u[0]._id)
var userID=returnedData.u[0]._id;
await fetch(`https://fiction.live/api/anonkun/userCollections/${userID}`, {
}).then(response => response.json()).then(data => {userID=data});
if (userID.length == 0){
//console.log('len=0',userID,message);
return
}
if (userID[0].u[0].n == 'Anon'){
return;
}
message.querySelector('.user span').innerText=userID[0].u[0].n;
}catch(error){
//console.log('no collections',message,error);
return;
}
}catch(error){
//console.log(error);
return;
}
};
function messageEdit(message){
try{
if (!message.querySelector('span.name') ||
//message.querySelector('.message img') != null ||
USERNAME == ''){return}
} catch (error) {
//console.log('err',error);
}
try{
if (message.querySelector('span.name').innerText != USERNAME){return;}
let messageID=message.firstChild.getAttribute('data-id');
let messageCont = document.createElement('div');
messageCont.setAttribute('class','msgModBox')
let messageEdit = document.createElement('input');
messageEdit.setAttribute('type','button')
messageEdit.setAttribute('class','msgMod const msgModEdit')
messageEdit.onclick = editMsg;
messageEdit.value = 'Open Edit Mode';
function editMsg(){
if (settings.messageEdit != true){return}
if (messageEdit.closest('.logItem').classList.contains('editMode')){
messageEdit.value = 'Open Edit Mode';
messageEdit.closest('.logItem').classList.remove('editMode');
message.querySelector('textarea').remove();
message.querySelector('.chatMsg').style.display = '';
}
else{
messageEdit.value = 'Close Edit Mode';
messageEdit.closest('.logItem').classList.add('editMode');
var messageText = document.createElement('textarea');
messageText.setAttribute('placeholder', 'Add text to alter the message.');
messageText.setAttribute("cols", "1");
messageText.setAttribute("rows", "5");
messageText.addEventListener("keydown", function(press) {
// 13 = Enter, 27 = Escape
if (press.keyCode === 13 &! (press.keyCode === 13 && press.shiftKey)) {
press.preventDefault(); // Cancel the default action, if needed
messageSave.click();
}
else if (press.keyCode === 27) {
press.preventDefault();
messageEdit.click();
}
});
var type=1;
if (messageEdit.closest('.logItem').classList.contains('imgMsg')){
type = 0;
}
fetch(`https://fiction.live/api/node/`+messageID).then(response => response.json()).then(data => {
messageText.value = data.i;
if (type == 1){messageText.value = data.b};
message.querySelector('.chatMsg').style.display = 'none';
message.appendChild(messageText);
});
};
};
let messageSave = document.createElement('input');
messageSave.setAttribute('type','button')
messageSave.setAttribute('class','msgMod edit msgModSave')
messageSave.onclick = saveMsg;
messageSave.value = 'Save';
function saveMsg(){
var messageContent = message.querySelector('textarea').value.replace(/\n+/g,'\\n');
var body = '';
if (messageEdit.closest('.logItem').classList.contains('imgMsg')){
body = `{\"_id\":\"${messageID}\",\"i\":\"${messageContent}\"}`
}
else{
body = `{\"_id\":\"${messageID}\",\"b\":\"${messageContent}\"}`
}
fetch("https://fiction.live/api/node", {
"headers": {
"User-Agent": "",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest"
},
"body": body,
"method": "PUT",
"mode": "cors"
});
messageCont.closest('.logItem').classList.remove('editMode');
messageEdit.value = 'Open Edit Mode';
message.querySelector('textarea').remove();
message.children[1].style.display = '';
};
let messageDiscard = document.createElement('input');
messageDiscard.setAttribute('type','button')
messageDiscard.setAttribute('class','msgMod edit msgModDiscard')
messageDiscard.onclick = discardMsg;
messageDiscard.value = 'Discard';
function discardMsg(){
message.children[2].value = '';
};
let messageDelete = document.createElement('input');
messageDelete.setAttribute('type','button')
messageDelete.setAttribute('class','msgMod const msgModDelete')
messageDelete.onclick = deleteMsg;
messageDelete.value = 'Delete';
function deleteMsg(){
if (settings.unpublishBTN != true){return}
fetch("https://fiction.live/api/node", {
"headers": {
"User-Agent": "",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest"
},
"body": `{\"_id\":\"${messageID}\",\"trash\":true}`,
"method": "PUT",
"mode": "cors"
});
//messageDelete.remove()
message.remove()
};
if (window.FL_Script.darkMode != true){
messageCont.classList.add('dark');
}
messageCont.appendChild(messageEdit);
messageCont.appendChild(messageSave)
messageCont.appendChild(messageDiscard)
messageCont.appendChild(messageDelete)
message.prepend(messageCont)
} catch (error) {
console.log('Error',error);
}
};
function onX(message){
try{
if (!message.querySelector('span.name') ||
//message.querySelector('.message img') != null ||
USERNAME == ''){return}
} catch (error) {
//console.log('err',error);
}
try{
if (message.querySelector('.message img')){
message.classList.add('imgMsg');
}
message.addEventListener('mouseover',function(){
if (this.querySelector('div.user span').innerText != USERNAME){return;};
if (this.querySelectorAll('input').length <= 3){messageEdit(this)};
//If delete is enabled and delete class is missing.
if (settings.unpublishBTN != true && settings.messageEdit != true){return}
if (settings.unpublishBTN == true && settings.messageEdit == true){
this.classList.add('visAll');
}
else if (settings.unpublishBTN == true && settings.messageEdit != true){
this.classList.add('delOn');
}
else if (settings.unpublishBTN != true && settings.messageEdit == true){
this.classList.add('vis');
}
if (message.querySelector('.msgModBox').isReallyVisible() == true && message.querySelector('footer').isReallyVisible() == false){
//console.log('1')
//console.log(message.offsetHeight)
if (message.offsetHeight < 300){
if (message.classList.contains('editMode')){return}
message.closest('article.chatLog').scrollTop += message.querySelector('.msgModBox').offsetHeight
}
}
})
}
catch (error) {
//console.log('Er0',error);
}
try{
message.addEventListener('mouseout',function(){
this.classList.remove('vis','visAll','delOn');
})
} catch (error) {
//console.log('Er1',error);
}
};
function spamCheck(message){
if (settings.spamRemoval != true){return}
if (message){
try{
if (message.innerText.length > settings.maxWords){
message.innerHTML='';
}
}catch(error){
console.log('SC',error);
}}
};
async function messageBlacklist(message){
if (settings.messageBlacklist != true){return}
try{
let questIDregex = '.*\/stories\/.*\/(.*)\/?';
let questID = window.location.href.match('.*\/stories\/.*\/(.*)\/?')[1];
let messageID = message.childNodes[0].getAttribute('data-id');
if (settings.bannedString.includes(message.childNodes[0].childNodes[1].innerText)){
fetch("https://fiction.live/api/anonkun/ban", {
"credentials": "include",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0",
"Accept": "*/*",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
"body": "blockFor="+messageID+"&blockFrom="+questID,
"method": "POST",
"mode": "cors"
});
fetch("https://fiction.live/api/anonkun/node", {
"credentials": "include",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
"referrer": "https://fiction.live/stories/X/fD9TaJwHrfoqb6jBQ",
"body": "deleteFrom="+questID+"&nid="+messageID,
"method": "DELETE",
"mode": "cors"
});
console.log('Banned & Deleted',message);
message.remove();
};
if (settings.deletedString.includes(message.childNodes[0].childNodes[1].innerText)){
fetch("https://fiction.live/api/anonkun/node", {
"credentials": "include",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
"referrer": "https://fiction.live/stories/X/fD9TaJwHrfoqb6jBQ",
"body": "deleteFrom="+questID+"&nid="+messageID,
"method": "DELETE",
"mode": "cors"
});
console.log('Deleted',message);
message.remove();
};
}catch(error){console.log('messageBlacklist',error)}
};
function gifDisable(message){
if (settings.gifDisable != true){return}
let gif = message.querySelector('.user img')
if (gif != (undefined || null) && gif.src.includes('gif')){
gif.remove()
}
}
function whenNewMessage(chat) {
try{
function autoRoll(change) {
if (settings.autoRoller !== true) {
return;
}
else{
try {
var rollRegex = /[0-9]+d[0-9]+(?<!1d1)((\+|\-)[0-9]+)?( ?)(([ie]+)?([ut][0-9]+)?)+/
if (rollRegex.test(change.innerText)) {
var roll = change.innerText.match(rollRegex)[0];
var latestUpdate = document.querySelector('div#storyPosts').firstChild.lastChild;
var poll = latestUpdate.firstChild.firstChild;
if (change.querySelector('span.name') && change.querySelector('span.name').innerText == USERNAME){
poll.classList.add('rolled');
return
}
if (latestUpdate.classList.contains('readerPost') == false || poll.classList.contains('closed') || poll.classList.contains('rolled')) {
return
} else if (!(poll.classList.contains('closed'))) {
var dataID = latestUpdate.getAttribute('data-id');
var chapterID = document.querySelector('article.threads').getAttribute('threads');
chapterID = chapterID.replace(/\/.*/, '');
var rollSend = `/roll ${roll}`;
var template = `sid=${chapterID}&dice=${encodeURIComponent(rollSend)}`;
chatSend([[chapterID, dataID, roll], template]);
poll.classList.add('rolled');
}
}
} catch (error) {}
};
};
var options = {
childList: true
};
function messageMod(mutations) {
for (let mutation of mutations) {
try {
var message = mutation.addedNodes[0];
if (!message || message.length == 0){return}
messageBlacklist(message);
spamCheck(message);
chatBlacklist(message);
userReveal(message);
removeUsernames(message);
authorHighlight(message);
imageResize(message);
autoRoll(message);
functionalLinks(message);
akunPlus(message);
onX(message);
messageFocus(message);
gifDisable(message);
//observerMessage.disconnect();
} catch (error) {
console.log('New Message Error',error);
}
};
};
let observerMessage = new MutationObserver(messageMod);
observerMessage.observe(chat, options);
}catch(error){
if (error instanceof TypeError){
return
};
console.log(error)
}
};
function withOldMessage(chat) {
var messages = chat.childNodes;
try {
for (let message of messages){
try {
spamCheck(message);
chatBlacklist(message);
imageResize(message);
userReveal(message);
authorHighlight(message);
removeUsernames(message);
functionalLinks(message);
akunPlus(message);
onX(message);
messageFocus(message);
gifDisable(message);
} catch (error) {
};}
} catch (error) {
console.log('OldMsg', error)
};
};
function handleMsg(message) {
if (message.tagName == 'HEADER') {
return;
}try{
spamCheck(message);
chatBlacklist(message);
imageResize(message);
authorHighlight(message);
functionalLinks(message);
removeUsernames(message);
akunPlus(message);
gifDisable(message);
} catch (error) {};
};
function textStyle(){
function getSelectionText(){
var text = "";
var activeEl = document.activeElement;
var activeElTagName = activeEl ? activeEl.tagName.toLowerCase() : null;
if ((activeElTagName == "textarea") || (activeElTagName == "input" && /^(?:text|search|password|tel|url)$/i.test(activeEl.type)) && (typeof activeEl.selectionStart == "number")){
text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd);
} else if (window.getSelection) {
text = window.getSelection().toString();
}
return text;
};
function textMod(){
function textEffect(){
let selected = getSelectionText();
let text = this.closest('form').querySelector('textarea');
let effect = this.getAttribute('name')
let regex = new RegExp(`<${effect}>|<\/${effect}>`,'g')
let selectedN;
if (selected == '' ){return;}
else if (regex.test(selected)){
selectedN=selected.replace(regex,'');
let activeEl = document.activeElement;
let len = Math.abs(selectedN.length - selected.length)
let SS=activeEl.selectionStart,SE=activeEl.selectionEnd-len;
text.value = text.value.replace(selected,selectedN);
activeEl.selectionStart = SS
activeEl.selectionEnd = SE
}
else{
selectedN=`<${effect}>${selected}</${effect}>`;
let activeEl = document.activeElement;
let len = Math.abs(selectedN.length - selected.length);
let SS=activeEl.selectionStart,SE=activeEl.selectionEnd+len;
text.value = text.value.replace(selected,selectedN);
activeEl.selectionStart = SS;
activeEl.selectionEnd=SE;
}
};
var textMod = document.createElement('div')
textMod.setAttribute('class','textMod');
textMod.addEventListener('mousedown',function(event){
event.stopPropagation();
event.preventDefault();
})
var textModB = document.createElement('input')
textModB.setAttribute('class','textModBtn');
textModB.setAttribute('name','b');
textModB.setAttribute('type','button');
textModB.value = 'Bold';
textModB.onclick = textEffect;
var textModI = document.createElement('input')
textModI.setAttribute('class','textModBtn');
textModI.setAttribute('name','i');
textModI.setAttribute('type','button');
textModI.value = 'Italicize';
textModI.onclick = textEffect;
var textModU = document.createElement('input')
textModU.setAttribute('class','textModBtn');
textModU.setAttribute('name','u');
textModU.setAttribute('type','button');
textModU.value = 'Underline';
textModU.onclick = textEffect;
var textModS = document.createElement('input')
textModS.setAttribute('class','textModBtn');
textModS.setAttribute('name','strike');
textModS.setAttribute('type','button');
textModS.value = 'Strikethrough';
textModS.onclick = textEffect;
textMod.appendChild(textModB);
textMod.appendChild(textModI);
textMod.appendChild(textModU);
textMod.appendChild(textModS);
return textMod
};
if (settings.textStyle != true){return;}
try{
var chatInput = document.querySelectorAll('form.chatInputContainer');
Array.from(chatInput).forEach(CI=>{
CI.addEventListener('select',function(event){
try{
if (document.querySelector('.textMod') != null){
return
}
var T = event.target
var elem = new textMod()
if(document.querySelector('#mainChat').contains(T)){
elem.style.bottom = elem.offsetHeight+'px';
}
elem.classList.add('vis');
T.parentNode.prepend(elem);
}catch(error){
console.log('erx',error)
};
});
CI.querySelector('textarea').addEventListener('keyup',function(event){
if (!CI.querySelector('.textMod') == null){return;};
if (CI.querySelector('.textMod') != null && CI.querySelector('textarea').value == ''){
CI.querySelector('.textMod').remove();
}
})
});
document.addEventListener('mousedown',function(event){
if (
event.target.getAttribute('name')=='chapterTitle' ||
event.target.closest('.addAchievement') ||
event.target.closest('.nextLive') ||
event.target.closest('.editStory') ||
event.target.closest('.collectionForm') ||
event.target.closest('.choicesInterface') ||
event.target.closest('#storyTagsAndFilters')||
event.target.closest('#innerAlertSearch')
){
return
}
try{
if (document.querySelector('#confBox').contains(event.target)){
return;
};
}catch(error){};
var list = event.target.classList;
if (event.target.tagName == 'INPUT' || list.contains('textModBtn')){
//event.preventDefault();
}
else if (list.contains('textMod') || list.contains('chatInput') || event.target.closest('form') != null ){
if (getSelectionText() == ''){
if (document.querySelector('.textMod') != null){
document.querySelector('.textMod').remove()
}
}
}
else{
if (document.querySelector('.textMod') != null){
document.querySelector('.textMod').remove()
}
}
});
}catch(error){console.log(error)};
};
function chatHide(){
if (settings.autoHide != true){
return;
};
if (window.FL_Script.observerTC != undefined){
observerTC.disconnect();
}
try{
}catch(error){
}
var observerTC = new MutationObserver(function (mutations){
for (let mutation of mutations) {
if (!document.querySelector('#mainChat')){continue}
try{
let hideChatBTN=document.getElementsByClassName('section row themeControls')[0].children[3];
if (hideChatBTN != (undefined || null)){
//console.log('hideChatBTN')
hideChatBTN.click();
observerTC.disconnect();
}
}catch(error){
};
}
});
observerTC.observe(document, {
childList: true,
subtree: true
})
};
function messageFocus(message){
try{
message.addEventListener('mouseup',function(event){
var messageAwait = new MutationObserver(function (mutations){
for (let mutation of mutations) {
try{
let id=message.querySelector('.chatMsg').getAttribute('data-id')
let focus;
try{
focus = document.querySelector('.chatItemDetail[data-id="'+id+'"]')
if (focus != (null || undefined)){
messageAwait.disconnect();
imageLinkButton();
}}catch(error){console.log('messageFocus error',error)}
}catch(error){
};
}
});
messageAwait.observe(document.body, {childList: true})},false);
}catch(error){}
};
function purgeButton(){
try{
if (settings.messageBlacklist != true){
try{document.querySelector('.purgeButton').remove();}catch(error){};
return;
};
if (document.querySelector('#mainChat .pagination-dropdown .purgeButton')){return;};
var purge = document.createElement('a');
purge.setAttribute('class','settings btn dim-font-color hover-font-color purgeButton');
purge.setAttribute('title','Click to run the chat black/ban lists after adding any entries.');
purge.onclick = function(){window.FL_Script.deleteListedMessages();}
purge.innerText = 'Purge Messages'
var main = document.querySelector('#mainChat .pagination-dropdown');
if (main == null){
setTimeout(function(){
main = document.querySelector('#mainChat .pagination-dropdown');
if (!document.querySelector('.purgeButton')){
main.appendChild(purge);
}
},5000);
}
else{
main.appendChild(purge);
};
}catch(error){}
};
purgeButtonAdd = purgeButton;
function waitForChat() {
//waits for chat to exist
var observerChat = new MutationObserver(awaitChat);
observerChat.observe(document, {
childList: true,
subtree: true
})
function awaitChat(mutations) {
function observeChat(){
try{
var chat=document.querySelector('#mainChat').querySelector('article.chatLog').children[0];
var observerChatExist = new MutationObserver(function(mutations){
for (let mutation of mutations) {
try{
if (mutation.removedNodes.length != 0 && mutation.removedNodes[0].tagName != undefined){
//console.log(mutation.removedNodes[0])
}
if (mutation.addedNodes.length != 0){
chat=document.querySelector('#mainChat').querySelector('article.chatLog').children[0];
if (mutation.addedNodes[0].tagName == 'DIV' &&
mutation.addedNodes[0].classList.contains('jadeRepeat')){
whenNewMessage(chat.querySelector('div.jadeRepeat'));
withOldMessage(chat.querySelector('div.jadeRepeat'))
}
}} catch (error) {
console.log('new thing error',error)
console.log('chat.querySelector(div.jadeRepeat)',chat.querySelector('div.jadeRepeat'))
};
}}
);
observerChatExist.observe(document.querySelector('#mainChat').querySelector('article.chatLog'), {childList: true, subtree: true})
}catch(error){console.log(error)}
};
for (let mutation of mutations) {
try {
var chat = document.querySelector('article.chatLog').querySelector('div.jadeRepeat');
} catch (TypeError) {};
if (chat && chat !== (undefined || null) && chat.length != 0) {
observerChat.disconnect();
if (settings.messageBlacklist == true){
purgeButton();
}
var chatLog = document.querySelectorAll('article.chatLog');
for (var i = 0; i < chatLog.length; i++) {
whenNewMessage(chatLog[i].querySelector('div.jadeRepeat'));
withOldMessage(chatLog[i].querySelector('div.jadeRepeat'));
textStyle();
setTimeout(function(){observeChat();},1000);
chatHide();
newThemeChange();
imageLinkButton();
}
break;
};
};
};
};
waitForChat();
}
catch(error){console.log(error)};
};
function deleteTopicCreate() {
let styleS = `.postForm div.formItem{display:none !important;`;
let style = document.createElement('style');
style.setAttribute("name", "topicHideStyle");
try {
if (settings.removeTopicForm == true) {
//let formItem = document.querySelector('div.formItem');
//if (formItem) {
// formItem.parentNode.remove();
//};
style.appendChild(document.createTextNode(styleS));
document.getElementsByTagName('head')[0].appendChild(style);
}
else{
if (document.querySelector('[name="topicHideStyle"]')) {
document.querySelector('[name="topicHideStyle"]').remove();
style.appendChild(document.createTextNode(styleS));
}
}
} catch (error) {
console.log('Error with removing topic form', error);
};
};
function blacklistAdd() {
let title = this.parentNode.querySelector('[set-text="item.value.value"]').textContent.replace(' went live', '');
let author = this.parentNode.querySelector('span.user').innerText;
let entry = title + '___' + author;
settings.alertBlacklist.push(entry);
localStorage.setItem('FL_Settings', JSON.stringify(settings));
let dismiss = this.parentNode.querySelector('a.dismiss');
simClick(dismiss);
document.querySelector('.settingsTab[name="Alerts"]').querySelector('div.settingsBlacklist').appendChild(elementBlacklisted(entry));
};
function blacklistCheck(alert) {
function alertBlacklistButton(alert) {
function createBlacklistButton() {
var blacklistButton = document.createElement('a');
blacklistButton.setAttribute('class', 'blacklist');
blacklistButton.innerText = '∅';
blacklistButton.onclick = blacklistAdd;
return blacklistButton
}
alert.childNodes[0].after(createBlacklistButton());
};
try {
var title = alert.querySelector('[set-text="item.value.value"]').textContent.replace(' went live', '');
var author = alert.querySelector('span.user').innerText;
var dismiss = alert.querySelector('a.dismiss');
if (settings.alertBlacklist.includes(title + '___' + author)) {
simClick(dismiss);
try{dismiss.click()}catch(e){}
try{alert.remove()}catch(e){}
} else {
if (!alert.querySelector('a.blacklist')){
alertBlacklistButton(alert);
}
};
} catch (error) {
console.log('blacklist checker error', error)
};
};
function updateCheck(alert) {
if (settings.updateRequestDismiss == false) {
return;
}
else if (alert.classList.length == 0) {
return
}
try {
var title = alert.querySelector('[set-text="item.value.value"]').innerText;
if (/.*Looks forward to the next update for.*/.test(title)) {
var dismiss = alert.querySelector('a.dismiss');
simClick(dismiss);
}
} catch (error) {
console.log('updateCheck error', error)
};
};
function simClick(elem) {
var evt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
var canceled = !elem.dispatchEvent(evt);
};
function alertUpdate(alert){
try{
//console.log('alert up',alert)
if (alert.classList.length == 0) {
return
}
var dismiss = alert.querySelector('a.dismiss');
simClick(dismiss);
}catch(error){console.log('AU Error',error)}
};
function awaitAlerts(){
try{
var alerts = document.querySelector('span.feedCount');
if (alerts){
//console.log('Alerts Exist');
try{
observerFCP.disconnect();
}catch(error){};
monitorFeedCount(alerts.parentNode);
monitorFeeds();
let alertContainer = document.querySelectorAll('li.feedItem');
alertContainer.forEach(alert => {
if (/.*went live.*/.test(alert.innerText)) {
blacklistCheck(alert);
}
else if (/.*Looks forward to the next update for.*/.test(alert.innerText) && settings.updateRequestDismiss == true) {
alertUpdate(alert)
}
else if (/.*New review for.*/.test(alert.innerText) && settings.reviewDismiss == true) {
alertUpdate(alert)
}
else if (/.*Is now a new follower of yours.*/.test(alert.innerText) && settings.followDismiss == true) {
alertUpdate(alert)
}
else if (/.*Likes \".*\".*/.test(alert.innerText) && settings.likeDismiss == true) {
alertUpdate(alert)
}
else if (/.*PM:.*/.test(alert.innerText)) {
}
});
}
else{
//console.log('Alerts Dont Exist');
var observerFCP = new MutationObserver(awaitFeedCount);
observerFCP.observe(document, {
childList: true,
subtree: true
});
};
function awaitFeedCount(mutations){
//Wait for the feed count, when found stop and start the FC monitor
try{
for (let mutation of mutations) {
let alerts = document.querySelector('span.feedCount')
if (mutation.addedNodes.length > 0){
var elm = mutation.addedNodes[0];
if (elm.tagName == 'SPAN' && elm.classList.contains('feedCount')){
observerFCP.disconnect();
monitorFeedCount(alerts.parentNode);
monitorFeeds();
};
};
};
}
catch(error){
console.log('AFC',error)
};
};
function monitorFeedCount(FC){
//Monitors feed count parent for when alerts appear or disappear.
try{
var observerFC = new MutationObserver(function(mutations){
if (mutations[0].removedNodes.length > 0){
//console.log('Alerts Removed.');
try{
window.FL_Script.alertWatcher.disconnect();
//console.log('AW');
}catch(error){}
try{
window.FL_Script.observerDrop.disconnect();
//console.log('DW');
}catch(error){}
}
else if (mutations[0].addedNodes.length > 0){
//console.log('Alerts Added.',x[0].addedNodes);
monitorFeeds();
}
})
observerFC.observe(FC, {childList:true})
}catch(error){console.log('MFC',error)}
};
function monitorFeeds(){
//Alerts are stored in feeds, this monitors them
function dropdownWatch(mutations){
try{
if (dropdown.length == 1){
//console.log('Dropdown has a single child.')
return
}
for (let mutation of mutations){
if (mutation.addedNodes.length > 0 && mutation.addedNodes[0].tagName == 'LI'){
if (mutation.addedNodes[0].closest('.newAlerts')){return}
let text=mutation.addedNodes[0].innerText
let alert = mutation.addedNodes[0]
if (/.*went live.*/.test(text)) {
blacklistCheck(alert);
}
else if (/.*Looks forward to the next update for.*/.test(text) && settings.updateRequestDismiss == true) {
alertUpdate(alert)
}
else if (/.*New review for.*/.test(text) && settings.reviewDismiss == true) {
alertUpdate(alert)
}
else if (/.*Is now a new follower of yours.*/.test(text) && settings.followDismiss == true) {
alertUpdate(alert)
}
else if (/.*Likes \".*\".*/.test(alert.innerText) && settings.likeDismiss == true) {
alertUpdate(alert)
}
else if (/.*PM:.*/.test(text)) {
}
if (settings.qmSort == true){
window.FL_Script.alertAddToList(alert);
}
}
};
}
catch(error){
console.log('DW',error)
};
};
var dropdown = document.querySelector('#loginMenu').children[1];
//console.log('dropdown',dropdown);
var observerDrop = new MutationObserver(dropdownWatch);
observerDrop.observe(dropdown, {childList:true,subtree:true});
window.FL_Script.observerDrop = observerDrop;
let alertContainer = document.querySelectorAll('li.feedItem');
alertContainer.forEach(alert => {
if (/.*went live.*/.test(alert.innerText)) {
blacklistCheck(alert);
}
else if (/.*Looks forward to the next update for.*/.test(alert.innerText) && settings.updateRequestDismiss == true) {
alertUpdate(alert)
}
else if (/.*New review for.*/.test(alert.innerText) && settings.reviewDismiss == true) {
alertUpdate(alert)
}
else if (/.*Is now a new follower of yours.*/.test(alert.innerText) && settings.followDismiss == true) {
alertUpdate(alert)
}
else if (/.*Likes \".*\".*/.test(alert.innerText) && settings.likeDismiss == true) {
alertUpdate(alert)
}
else if (/.*PM:.*/.test(alert.innerText)) {
}
});
};
}catch(error){console.log('AAlerts',error)}
};
function alertSortByQM(){
if (settings.qmSort != true){
if (document.querySelector('[name="sortQM"]')) {
document.querySelector('[name="sortQM"]').remove();
document.querySelector('.newAlerts').remove();
try{window.FL_Script.OADC.disconnect();}catch(error){};
}
return
};
if (!document.querySelector('[name="sortQM"]')) {
let styleS = `
li#loginMenu div.dropdown-menu div.inner:nth-of-type(2){display:none !important;}
li#loginMenu div.dropdown-menu div.inner.newAlerts{display:block !important;}
`;
let style = document.createElement('style');
style.setAttribute("name", "sortQM");
style.appendChild(document.createTextNode(styleS));
document.getElementsByTagName('head')[0].appendChild(style);
}
function sortLIs(){
try {
var sort_by_name = function (a, b) {
let sorted=a.querySelector('.user').innerText.localeCompare(b.querySelector('.user').innerText);
return sorted;
};
if (window.FL_Script.FLTESTUL.children.length > 1){
var list = Array.from(window.FL_Script.FLTESTUL.children);
list.sort(sort_by_name);
for (var i = 0; i < list.length; i++) {
list[i].parentNode.appendChild(list[i]);
}
}
} catch (error) {
console.log(error);
}
};
function liGen(li){
var newLI = li.cloneNode(true);
newLI.children[0].onclick = function(){
li.children[0].click();
this.closest('li').remove()
};
newLI.children[1].onclick = function(){
li.children[1].click();
this.closest('li').remove()
};
try{
newLI.children[2].onclick = function(){
li.children[2].click();
this.closest('li').remove()
};
}catch(error){
}
return newLI
};
window.FL_Script.alertAddToList = function (alert){
try{
let parentNum = alert.parentNode.getAttribute('num');
document.querySelectorAll('.newAlerts ul')[parentNum].appendChild(new liGen(alert))
sortLIs();
}catch(e){if (e instanceof TypeError){}else{console.log('alertAddToList Error',e)}}
};
let alerts = document.querySelector('li#loginMenu div.dropdown-menu div.inner');
//alerts.style.display = 'none';
var options = {
childList: true,
subtree: true
};
let observerAlerts = new MutationObserver(monitorAlerts);
//observerAlerts.observe(alerts, options);
function monitorAlerts(mutations) {
for (let mutation of mutations) {
try {
if (mutation.removedNodes.length > 0){
console.log('mutie',mutation);
console.log('mutie',mutation.removedNodes[0].innerText);
let text=mutation.removedNodes[0].innerText
Array.from(document.querySelector('.newAlerts').children[ulX].children).forEach(child=>{
if (child.innerText == text){
console.log(child,'xaaaaa');
}
}
)
console.log('mutie',text);
}
} catch (error) {console.log('ERR--',error);};
};
};
window.FL_Script.OADC = observerAlerts;
var newAlerts = document.createElement('div');
newAlerts.classList.add('inner', 'newAlerts');
var ulCount=0;
var ulX;
alerts.querySelectorAll('ul').forEach(ul=>{
ul.setAttribute('num',ulCount);
var newAlertsList = document.createElement('ul');
newAlertsList.classList.add('feedType');
newAlertsList.setAttribute('num',ulCount);
if (ul.innerText.includes('went live')){
window.FL_Script.FLTESTUL = newAlertsList;
ulX=ulCount;
};
if (ul.children.length > 0){
//console.log(ul)
Array.from(ul.children).forEach(li=>{
newAlertsList.append(new liGen(li));
})
}
newAlerts.append(newAlertsList);
ulCount=ulCount+1;
});
alerts.parentNode.appendChild(newAlerts);
sortLIs();
};
function awaitMainMenu() {
try {
var options = {
childList: true,
subtree: true
};
let observerMenu = new MutationObserver(awaitMenu);
observerMenu.observe(document, options);
function awaitMenu(mutations) {
for (let mutation of mutations) {
try {
if (document.querySelector('nav#mainMenu')) {
observerMenu.disconnect();
settingsContainer();
darkCheck();
alertSearch();
};
} catch (error) {};
};
};
} catch (error) {
console.log('Error awaiting main menu', error)
};
};
function alertSearch(){
if (settings.alertFilter != true){
try{
document.querySelector('#innerAlertSearch').remove()
}catch(error){}
return
}
if (document.querySelector('#innerAlertSearch')){return}
var dropdown = document.querySelector('.dropdown-menu.ng-scope.dropdown');
var settingsSearchBox = document.createElement('div');
settingsSearchBox.setAttribute('id', 'innerAlertSearch');
settingsSearchBox.style.width = dropdown.offsetWidth.toString();
settingsSearchBox.style = 'background:#2a2c3b;padding-top:10px;margin-top:0;';
settingsSearchBox.addEventListener("click", function(event) {
event.stopPropagation();
event.preventDefault();
});
var settingsAlertSearchInput = document.createElement('input');
settingsAlertSearchInput.setAttribute("type", "text");
settingsAlertSearchInput.setAttribute("name", "alertSearch");
settingsAlertSearchInput.style = 'margin-bottom:10px;';
settingsAlertSearchInput.setAttribute("placeholder", "Enter a title or QM to search.");
settingsAlertSearchInput.oninput = function(){
let alerts = document.querySelectorAll('.dropdown-menu ul.feedType li.feedItem');
alerts.forEach(x => {
x.style.display = 'table';
})
let search = this.parentNode.querySelector('[name="alertSearch"]').value.toLowerCase();
alerts.forEach(alert => {
let text = alert.firstChild.textContent.toLowerCase().replace('author:')
if (!text.includes(search)) {
alert.style.display = 'none';
} else {}
})
}
var settingsAlertSearch = document.createElement('input');
settingsAlertSearch.setAttribute("type", "button");
settingsAlertSearch.setAttribute("class", "cssBtn");
settingsAlertSearch.value = 'Search';
settingsAlertSearch.style ='font-weight: 700;border:none;';
settingsAlertSearch.onclick = function () {
let alerts = document.querySelectorAll('.dropdown-menu ul.feedType li.feedItem');
alerts.forEach(x => {
x.style.display = 'table';
})
let search = this.parentNode.querySelector('[name="alertSearch"]').value.toLowerCase();
alerts.forEach(alert => {
let text = alert.firstChild.textContent.toLowerCase().replace('author:')
if (!text.includes(search)) {
alert.style.display = 'none';
} else {}
})
}
var settingsAlertSearchClear = document.createElement('input');
settingsAlertSearchClear.setAttribute("type", "button");
settingsAlertSearchClear.setAttribute("class", "cssBtn");
settingsAlertSearchClear.value = 'Clear Search';
settingsAlertSearchClear.style ='font-weight: 700;border:none;float:right;';
settingsAlertSearchClear.onclick = function () {
this.parentNode.querySelector('[name="alertSearch"]').value = '';
let alerts = document.querySelectorAll('.dropdown-menu ul.feedType li.feedItem');
alerts.forEach(x => {
x.style.display = 'table';
})
}
settingsSearchBox.appendChild(settingsAlertSearchInput);
//settingsSearchBox.appendChild(settingsAlertSearch);
settingsSearchBox.appendChild(settingsAlertSearchClear);
dropdown.insertBefore(settingsSearchBox,dropdown.children[1])
};
function elementBlacklisted(element) {
var settingsBlacklisted = document.createElement('div');
settingsBlacklisted.setAttribute('class', 'blacklistEntry');
var settingsBlacklistedText = document.createElement('p');
settingsBlacklistedText.setAttribute('class', 'colors');
settingsBlacklistedText.innerText = element;
settingsBlacklistedText.innerText = settingsBlacklistedText.innerText.replace('___', '\nAuthor: ');
var settingsBlacklistRemove = document.createElement('a');
settingsBlacklistRemove.setAttribute('class', 'blacklistRemove')
settingsBlacklistRemove.innerText = 'Remove'
settingsBlacklistRemove.onclick = function () {
blacklistRemove(element);
this.parentNode.remove();
}
settingsBlacklisted.appendChild(settingsBlacklistedText)
settingsBlacklisted.appendChild(settingsBlacklistRemove)
return settingsBlacklisted
};
function settingsContainer() {
function settingsDisplay() {
try {
if (!document.querySelector('#confDisp')) {
function configDisplay() {
var confDisp = document.createElement('div');
confDisp.setAttribute('id', 'confDisp');
return confDisp
};
function configBox() {
var confBox = document.createElement('div');
confBox.setAttribute('id', 'confBox');
if (window.FL_Script.darkMode == true){
confBox.setAttribute('class', 'dark');}
return confBox
};
//Blacklists start here
//Blacklists start here
//Blacklists start here
//Blacklists start here
//Blacklists start here
function settingsUserBlacklist() {
var settingsTab = document.createElement('div');
settingsTab.setAttribute('class', 'settingsTab');
settingsTab.setAttribute('name', 'Chat');
function chatBlacklistRemove(item) {
if (settings.chatBlacklisted.includes(item)) {
let position = settings.chatBlacklisted.indexOf(item);
settings.chatBlacklisted.splice(position, 1);
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
};
};
function chatBlacklisted(element) {
try {
var chatBlacklisted = document.createElement('div');
chatBlacklisted.setAttribute('class', 'blacklistEntry');
var chatBlacklistedText = document.createElement('p');
chatBlacklistedText.setAttribute('class', 'colors');
chatBlacklistedText.innerText = element;
var settingsUserRemove = document.createElement('a');
settingsUserRemove.setAttribute('class', 'blacklistRemove');
settingsUserRemove.innerText = 'Remove';
settingsUserRemove.onclick = function () {
try {
chatBlacklistRemove(element);
this.parentNode.remove();
} catch (error) {
console.log('Error removing user', error)
}
};
chatBlacklisted.appendChild(chatBlacklistedText);
chatBlacklisted.appendChild(settingsUserRemove);
return chatBlacklisted;
} catch (error) {
console.log('44', error)
}
};
function userAddBlacklist() {
var settingsUserBox = document.createElement('div');
settingsUserBox.setAttribute('id', 'settingsBox');
var settingsUserInput = document.createElement('input');
settingsUserInput.setAttribute("type", "text");
settingsUserInput.setAttribute("class", "settingsInput");
settingsUserInput.setAttribute("placeholder", "Input username here.");
var settingsUserAdd = document.createElement('input');
settingsUserAdd.setAttribute("class", "cssBtn");
settingsUserAdd.setAttribute("type", "button");
settingsUserAdd.value = 'Add User';
settingsUserAdd.onclick = function () {
if (settings.chatBlacklisted.includes(this.parentNode.childNodes[0].value)) {
return;
}
settings.chatBlacklisted.push(this.parentNode.childNodes[0].value);
this.parentNode.parentNode.appendChild(chatBlacklisted(this.parentNode.childNodes[0].value));
this.parentNode.childNodes[0].value = "";
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
removeBlacklisted();
};
settingsUserBox.appendChild(settingsUserInput);
settingsUserBox.appendChild(settingsUserAdd);
return settingsUserBox
};
function maxWordCount(){
var settingsBox = document.createElement('div');
settingsBox.setAttribute('id', 'settingsBox');
var settingsText = document.createElement('div');
settingsText.setAttribute('class', 'entryTitle');
settingsText.innerText = 'Message Max Character Count';
var settingsInput = document.createElement('input');
settingsInput.setAttribute("type", "text");
settingsInput.setAttribute("class", "settingsInput");
settingsInput.setAttribute("placeholder", "Maximum character count per message.");
settingsInput.value = settings.maxWords;
var settingsAdd = document.createElement('input');
settingsAdd.setAttribute("class", "cssBtn");
settingsAdd.setAttribute("type", "button");
settingsAdd.value = 'Set Maximum';
settingsAdd.onclick = function () {
settings.maxWords = this.parentNode.childNodes[0].value
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
};
var borderBottom = document.createElement('div');
borderBottom.setAttribute('class', 'borderBottom');
settingsBox.appendChild(settingsText);
settingsBox.appendChild(settingsInput);
settingsBox.appendChild(settingsAdd);
settingsBox.appendChild(borderBottom);
return settingsBox
};
function wordList(word,array){
try {
var blacklistContainer = document.createElement('div');
blacklistContainer.setAttribute('class', 'blacklistEntry');
var blacklistedText = document.createElement('p');
blacklistedText.setAttribute('class', 'colors');
blacklistedText.innerText = word;
var blacklistRemove = document.createElement('a');
blacklistRemove.setAttribute('class', 'blacklistRemove');
blacklistRemove.innerText = 'Remove';
blacklistRemove.onclick = function () {
try {
if (!settings[array].includes(word)){return}
let index = settings[array].indexOf(word);
settings[array].splice(index, 1);
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
this.parentNode.remove();
} catch (error) {
console.log('Error with wordList removal', error)
}
};
blacklistContainer.appendChild(blacklistedText);
blacklistContainer.appendChild(blacklistRemove);
return blacklistContainer;
} catch (error) {
console.log('Error with wordList', error)
}
};
function wordBlacklist(){
var divOuter = document.createElement('div');
divOuter.setAttribute('class', 'settingsBlacklist');
var info = document.createElement('div');
var title = document.createElement('div');
title.setAttribute('class', 'entryTitle');
title.innerText = 'Word Blacklist';
var description = document.createElement('div');
description.setAttribute('class', 'description');
description.innerText = 'Any messages containing any of these phrases will be deleted. QM/Mod required.';
info.append(title)
info.append(description)
divOuter.append(info)
var input = document.createElement('input');
input.setAttribute("type", "text");
input.setAttribute("class", "settingsInput");
input.setAttribute("placeholder", "Input Phrase Here.");
var inputAdd = document.createElement('input');
inputAdd.setAttribute("class", "cssBtn");
inputAdd.setAttribute("type", "button");
inputAdd.value = 'Add A Phrase To Be Auto-Deleteted';
inputAdd.onclick = function () {
if (settings.deletedString.includes(input.value)) {
return;
}
settings.deletedString.push(input.value);
divBL.appendChild(wordList(input.value,'deletedString'));
input.value = "";
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
};
divOuter.append(input)
divOuter.append(inputAdd)
var divBL = document.createElement('div');
//bannedString + deletedString
settings.deletedString.forEach(element => divBL.appendChild(wordList(element,'deletedString')));
divOuter.appendChild(divBL)
var borderBottom = document.createElement('div');
borderBottom.setAttribute('class', 'borderBottom');
divOuter.appendChild(borderBottom);
return divOuter
};
function wordBanlist(){
var divOuter = document.createElement('div');
divOuter.setAttribute('class', 'settingsBlacklist');
var info = document.createElement('div');
var title = document.createElement('div');
title.setAttribute('class', 'entryTitle');
title.innerText = 'Word Banlist';
var description = document.createElement('div');
description.setAttribute('class', 'description');
description.innerText = 'Any messages containing any of these phrases will be deleted and the user banned. QM/Mod required.';
info.append(title)
info.append(description)
divOuter.append(info)
var input = document.createElement('input');
input.setAttribute("type", "text");
input.setAttribute("class", "settingsInput");
input.setAttribute("placeholder", "Input Phrase Here.");
var inputAdd = document.createElement('input');
inputAdd.setAttribute("class", "cssBtn");
inputAdd.setAttribute("type", "button");
inputAdd.value = 'Add A Phrase To Be Auto-Deleteted.';
inputAdd.onclick = function () {
if (settings.bannedString.includes(input.value)) {
return;
}
settings.bannedString.push(input.value);
divBL.appendChild(wordList(input.value,'bannedString'));
input.value = "";
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
};
divOuter.append(input)
divOuter.append(inputAdd)
var divBL = document.createElement('div');
settings.bannedString.forEach(element => divBL.appendChild(wordList(element,'bannedString')));
divOuter.appendChild(divBL)
var borderBottom = document.createElement('div');
borderBottom.setAttribute('class', 'borderBottom');
divOuter.appendChild(borderBottom);
return divOuter
};
function deleteListedMessages(){
window.FL_Script.deleteListedMessages = function (){
document.querySelector('article.chatLog').querySelectorAll('.logItem').forEach(message => {
let questIDregex = '.*\/stories\/.*\/(.*)\/?';
let questID = document.querySelector('article.threads').getAttribute('threads')//window.location.href.match('.*\/stories\/.*\/(.*)\/?')[1];
let messageID = message.querySelector('.chatMsg').getAttribute('data-id');
settings.bannedString.forEach(string=>{
if (message.innerText.includes(string)){
fetch("https://fiction.live/api/anonkun/ban", {
"credentials": "include",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0",
"Accept": "*/*",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
"body": "blockFor="+messageID+"&blockFrom="+questID,
"method": "POST",
"mode": "cors"
});
fetch("https://fiction.live/api/anonkun/node", {
"credentials": "include",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
"referrer": window.location.href,
"body": "deleteFrom="+questID+"&nid="+messageID,
"method": "DELETE",
"mode": "cors"
});
console.log('Banned & Deleted',message);
//message.remove();
return;
}
});
settings.deletedString.forEach(string=>{
if (message.innerText.includes(string)){
fetch("https://fiction.live/api/anonkun/node", {
"credentials": "include",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
"referrer": window.location.href,
"body": "deleteFrom="+questID+"&nid="+messageID,
"method": "DELETE",
"mode": "cors"
});
console.log('Deleted',message);
//message.remove();
}
});
});};
var divOuter = document.createElement('div');
var info = document.createElement('div');
var title = document.createElement('div');
title.setAttribute('class', 'entryTitle');
title.innerText = 'Run Blacklist';
var description = document.createElement('div');
description.setAttribute('class', 'description');
description.innerText = 'Activate after adding to the lists to purge older messages. QM/Mod required.';
info.append(title)
info.append(description)
divOuter.append(info)
var activate = document.createElement('input');
activate.setAttribute("class", "cssBtn");
activate.setAttribute("type", "button");
activate.value = 'Purge Old Matching Messages';
activate.onclick = function () {
window.FL_Script.deleteListedMessages();
};
divOuter.appendChild(activate);
var borderBottom = document.createElement('div');
borderBottom.setAttribute('class', 'borderBottom');
divOuter.appendChild(borderBottom);
return divOuter
};
var settingsUserBlacklist = document.createElement('div');
settingsUserBlacklist.setAttribute('class', 'settingsBlacklist');
settings.chatBlacklisted = [...new Set(settings.chatBlacklisted)]
settings.chatBlacklisted.forEach(element => settingsUserBlacklist.appendChild(chatBlacklisted(element)));
var settingsUserBlacklistText = document.createElement('div');
settingsUserBlacklistText.setAttribute('class', 'entryTitle');
settingsUserBlacklistText.innerText = 'Chat User Blacklist';
settingsUserBlacklist.prepend(userAddBlacklist());
settingsUserBlacklist.prepend(settingsUserBlacklistText);
settingsTab.appendChild(maxWordCount());
settingsTab.appendChild(wordBlacklist());
settingsTab.appendChild(wordBanlist());
settingsTab.appendChild(deleteListedMessages());
settingsTab.appendChild(settingsUserBlacklist);
return settingsTab;
};
function settingsAuthorsBlacklist() {
var settingsTab = document.createElement('div');
settingsTab.setAttribute('class', 'settingsTab');
settingsTab.setAttribute('name', 'Author');
function authorBlacklistRemove(item) {
if (settings.authorBlacklist.includes(item)) {
let position = settings.authorBlacklist.indexOf(item);
settings.authorBlacklist.splice(position, 1);
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
};
};
function authorBlacklisted(element) {
try {
var authorBlacklisted = document.createElement('div');
authorBlacklisted.setAttribute('class', 'blacklistEntry')
var authorBlacklistedText = document.createElement('p');
authorBlacklistedText.setAttribute('class', 'colors');
authorBlacklistedText.innerText = element;
var settingsAuthorRemove = document.createElement('a');
settingsAuthorRemove.setAttribute('class', 'blacklistRemove');
settingsAuthorRemove.innerText = 'Remove';
settingsAuthorRemove.onclick = function () {
try {
authorBlacklistRemove(element);
this.parentNode.remove();
} catch (error) {
console.log('Error removing author', error)
}
};
authorBlacklisted.appendChild(authorBlacklistedText);
authorBlacklisted.appendChild(settingsAuthorRemove);
return authorBlacklisted;
} catch (error) {
console.log('55', error)
}
};
function authorAddBlacklist() {
var settingsAuthorBox = document.createElement('div');
settingsAuthorBox.setAttribute('id', 'settingsBox');
var settingsAuthorsInput = document.createElement('input');
settingsAuthorsInput.setAttribute("type", "text");
settingsAuthorsInput.setAttribute("class", "settingsInput");
settingsAuthorsInput.setAttribute("placeholder", "Input author here.");
var settingsAuthorsAdd = document.createElement('input');
settingsAuthorsAdd.setAttribute("class", "cssBtn");
settingsAuthorsAdd.setAttribute("type", "button");
settingsAuthorsAdd.value = 'Add Author';
settingsAuthorsAdd.onclick = function () {
if (settings.authorBlacklist.includes(this.parentNode.childNodes[0].value)) {
return;
}
settings.authorBlacklist.push(this.parentNode.childNodes[0].value);
this.parentNode.parentNode.appendChild(authorBlacklisted(this.parentNode.childNodes[0].value));
this.parentNode.childNodes[0].value = "";
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
removeBlacklisted();
};
settingsAuthorBox.appendChild(settingsAuthorsInput);
settingsAuthorBox.appendChild(settingsAuthorsAdd);
return settingsAuthorBox
};
var settingsAuthorsBlacklist = document.createElement('div');
settingsAuthorsBlacklist.setAttribute('class', 'settingsBlacklist');
settings.authorBlacklist = [...new Set(settings.authorBlacklist)]
settings.authorBlacklist.sort().forEach(element => settingsAuthorsBlacklist.appendChild(authorBlacklisted(element)));
var settingsAuthorsBlacklistText = document.createElement('div');
settingsAuthorsBlacklistText.innerText = 'Authors Blacklist';
settingsAuthorsBlacklistText.setAttribute('class', 'entryTitle');
settingsAuthorsBlacklist.prepend(authorAddBlacklist());
settingsAuthorsBlacklist.prepend(settingsAuthorsBlacklistText);
settingsTab.appendChild(settingsAuthorsBlacklist)
return settingsTab;
};
function settingsTagsBlacklist() {
var settingsTab = document.createElement('div');
settingsTab.setAttribute('class', 'settingsTab');
settingsTab.setAttribute('name', 'Tags');
function tagBlacklistRemove(item) {
if (settings.tagBlacklist.includes(item)) {
let position = settings.tagBlacklist.indexOf(item);
settings.tagBlacklist.splice(position, 1);
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
};
};
function tagBlacklisted(element) {
try {
var tagBlacklisted = document.createElement('div');
tagBlacklisted.setAttribute('class', 'blacklistEntry');
var tagBlacklistedText = document.createElement('p');
tagBlacklistedText.setAttribute('class', 'colors');
tagBlacklistedText.innerText = element;
var settingsTagRemove = document.createElement('a');
settingsTagRemove.setAttribute('class', 'blacklistRemove');
settingsTagRemove.innerText = 'Remove';
settingsTagRemove.onclick = function () {
try {
tagBlacklistRemove(element);
this.parentNode.remove();
} catch (error) {
console.log('Error removing tag', error)
}
};
tagBlacklisted.appendChild(tagBlacklistedText);
tagBlacklisted.appendChild(settingsTagRemove);
return tagBlacklisted;
} catch (error) {
console.log('78', error)
}
};
function tagAddBlacklist() {
var settingsTagBox = document.createElement('div');
settingsTagBox.setAttribute('id', 'settingsBox');
var settingsTagsInput = document.createElement('input');
settingsTagsInput.setAttribute("type", "text");
settingsTagsInput.setAttribute("class", "settingsInput");
settingsTagsInput.setAttribute("placeholder", "Input tag here.");
var settingsTagsAdd = document.createElement('input');
settingsTagsAdd.setAttribute("class", "cssBtn");
settingsTagsAdd.setAttribute("type", "button");
settingsTagsAdd.value = 'Add Tag';
settingsTagsAdd.onclick = function () {
if (settings.tagBlacklist.includes(this.parentNode.childNodes[0].value)) {
return;
}
settings.tagBlacklist.push(this.parentNode.childNodes[0].value);
this.parentNode.parentNode.appendChild(tagBlacklisted(this.parentNode.childNodes[0].value));
this.parentNode.childNodes[0].value = "";
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
removeBlacklisted();
};
settingsTagBox.appendChild(settingsTagsInput);
settingsTagBox.appendChild(settingsTagsAdd);
return settingsTagBox
};
var settingsTagsBlacklist = document.createElement('div');
settingsTagsBlacklist.setAttribute('class', 'settingsBlacklist');
settings.tagBlacklist = [...new Set(settings.tagBlacklist)]
settings.tagBlacklist.sort().forEach(element => settingsTagsBlacklist.appendChild(tagBlacklisted(element)));
var settingsTagsBlacklistText = document.createElement('div');
settingsTagsBlacklistText.innerText = 'Tags Blacklist';
settingsTagsBlacklistText.setAttribute('class', 'entryTitle');
settingsTagsBlacklist.prepend(tagAddBlacklist());
settingsTagsBlacklist.prepend(settingsTagsBlacklistText);
settingsTab.appendChild(settingsTagsBlacklist)
return settingsTab;
};
function settingsBlacklist() {
var settingsTab = document.createElement('div');
settingsTab.setAttribute('class', 'settingsTab');
settingsTab.setAttribute('name', 'Alerts');
var settingsAlertBox = document.createElement('div');
settingsAlertBox.setAttribute('id', 'settingsAlertBox');
var settingsAlertAdd = document.createElement('input');
settingsAlertAdd.setAttribute("type", "button");
settingsAlertAdd.setAttribute("class", "cssBtn");
settingsAlertAdd.value = 'Blacklist Current Quest';
settingsAlertAdd.onclick = function () {
try {
let author = document.querySelector('span.author span.name').innerText;
let title = document.querySelector('header.page-title').innerText;
let entry = title + '___' + author;
settings.alertBlacklist.push(entry);
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settingsBlacklist.appendChild(elementBlacklisted(entry));
} catch (error) {
console.log('Something went wrong when trying to blacklist this quest.', error);
}
};
var settingsBlacklist = document.createElement('div');
settingsBlacklist.setAttribute('class', 'settingsBlacklist');
settings.alertBlacklist = [...new Set(settings.alertBlacklist)]
settings.alertBlacklist.forEach(element => settingsBlacklist.appendChild(elementBlacklisted(element)));
var settingsBlacklistText = document.createElement('div');
settingsBlacklistText.innerText = 'Alert Blacklist';
settingsBlacklistText.setAttribute('class', 'entryTitle');
var settingsSearchBox = document.createElement('div');
settingsSearchBox.setAttribute('id', 'settingsBox');
var settingsAlertSearchInput = document.createElement('input');
settingsAlertSearchInput.setAttribute("type", "text");
settingsAlertSearchInput.setAttribute("class", "settingsInput");
settingsAlertSearchInput.setAttribute("name", "alertSearch");
settingsAlertSearchInput.setAttribute("placeholder", "Enter a title or QM to search.");
var settingsAlertSearch = document.createElement('input');
settingsAlertSearch.setAttribute("type", "button");
settingsAlertSearch.setAttribute("class", "cssBtn");
settingsAlertSearch.value = 'Search';
settingsAlertSearch.onclick = function () {
this.closest('.settingsBlacklist').querySelectorAll('.blacklistEntry').forEach(x => {
x.style.display = 'initial';
})
let search = this.parentNode.querySelector('[name="alertSearch"]').value.toLowerCase();
let xx = this.closest('.settingsBlacklist').querySelectorAll('.blacklistEntry');
xx.forEach(x => {
let text = x.firstChild.textContent.toLowerCase().replace('author:')
if (!text.includes(search)) {
x.style.display = 'none';
} else {}
})
}
var settingsAlertSearchClear = document.createElement('input');
settingsAlertSearchClear.setAttribute("type", "button");
settingsAlertSearchClear.setAttribute("class", "cssBtn");
settingsAlertSearchClear.value = 'Clear Search';
settingsAlertSearchClear.onclick = function () {
this.parentNode.querySelector('[name="alertSearch"]').value = '';
this.closest('.settingsBlacklist').querySelectorAll('.blacklistEntry').forEach(x => {
x.style.display = 'initial';
})
}
settingsSearchBox.appendChild(settingsAlertSearchInput);
settingsSearchBox.appendChild(settingsAlertSearch);
settingsSearchBox.appendChild(settingsAlertSearchClear);
settingsAlertBox.appendChild(settingsSearchBox);
settingsAlertBox.appendChild(settingsAlertAdd);
settingsBlacklist.prepend(settingsAlertBox);
settingsBlacklist.prepend(settingsBlacklistText);
settingsTab.appendChild(settingsBlacklist)
return settingsTab;
};
function settingsStyle() {
function genStyle(styleAttribute, styleText) {
var settingsStyleEntryText = document.createElement('p');
settingsStyleEntryText.setAttribute('class', 'styleTitle');
settingsStyleEntryText.innerText = styleText;
var settingsStylePicker = document.createElement('input');
settingsStylePicker.setAttribute('class', 'colorPick');
settingsStylePicker.setAttribute('type', 'color');
settingsStylePicker.onchange = function () {
this.parentNode.querySelector('.colorSet').value = this.value
};
var settingsStyleInput = document.createElement('input');
settingsStyleInput.setAttribute('class', 'colorSet');
settingsStyleInput.setAttribute('type', 'text');
if ([styleAttribute]in settings.customCSS[0]) {
settingsStyleInput.value = settings.customCSS[0][styleAttribute]
settingsStylePicker.value = settings.customCSS[0][styleAttribute]
};
var settingsStyleEntry = document.createElement('div');
settingsStyleEntry.setAttribute('class', 'styleEntry');
settingsStyleEntry.setAttribute('name', styleAttribute);
settingsStyleEntry.appendChild(settingsStyleEntryText);
settingsStyleEntry.appendChild(settingsStyleInput);
settingsStyleEntry.appendChild(settingsStylePicker);
return settingsStyleEntry;
};
var settingsStyle = document.createElement('div');
settingsStyle.setAttribute('class', 'settingsTab');
settingsStyle.setAttribute('name', 'Site Style');
var settingsStyleText = document.createElement('div');
settingsStyleText.setAttribute('class', 'entryTitle');
settingsStyleText.innerText = 'Custom Site Style - Beta';
var settingsStyleTextBox = new genStyle('color', 'Text Color');
var settingsStyleBackgroundBox = new genStyle('background', 'Background Color');
var settingsStyleSave = document.createElement('input');
settingsStyleSave.setAttribute("type", "button");
settingsStyleSave.setAttribute('class', 'cssBtn');
settingsStyleSave.setAttribute("class", "cssBtn");
settingsStyleSave.onclick = function () {
try{
try{
document.querySelectorAll('.styleEntry').forEach(
x => {
let name = x.getAttribute("name");
let value = x.querySelector('.colorSet').value;
if (value !== undefined) {
settings.customCSS[0][name] = value;
}
});
}catch(error){}
try{
for (var key in settings.customCSS[0]) {
if (settings.customCSS[0].hasOwnProperty(key)) {
console.log(key, settings.customCSS[0][key]);
}
}
}catch(error){
}
localStorage.setItem('FL_Settings', JSON.stringify(settings));
let styleS = `*{color:${settings.customCSS[0].color}!important;background:${settings.customCSS[0].background} !important;}`;
let style = document.createElement('style');
style.setAttribute("name", "styleSheet");
if (document.querySelector('[name="styleSheet"]')) {
document.querySelector('[name="styleSheet"]').remove();
style.appendChild(document.createTextNode(styleS));
} else {
style.appendChild(document.createTextNode(styleS));
}
document.getElementsByTagName('head')[0].appendChild(style);
}catch(error){
}
};
settingsStyleSave.value = 'Apply Styling';
//External CSS Stuff
function settingsStyleEx(){
function applyCSS(index,cssFile){
var style = document.createElement('link');
let check = document.querySelector(`link[name="${index}"]`)
if (check){check.remove()}
style.setAttribute('name','eCSS'+index);
style.setAttribute('rel','stylesheet');
style.setAttribute('type','text/css');
style.href = cssFile
style.appendChild(document.createTextNode(style));
document.getElementsByTagName('head')[0].appendChild(style);
};
var settingsStyleEx = document.createElement('div');
settingsStyleEx.setAttribute('class', 'settingsStyleEx');
var settingsStyleExText = document.createElement('div');
settingsStyleExText.setAttribute('class', 'entryTitle');
settingsStyleExText.innerText = 'External Style Sheets';
var settingsStyleExDesc = document.createElement('p');
settingsStyleExDesc.style = 'margin:0px;font-size:12px;'
settingsStyleExDesc.innerText = 'Paste links to CSS files below to have them applied, in order, to the page. Or use one of the buttons below this text to apply pre-configured CSS files.';
var settingsStyleExAddDark = document.createElement('input');
settingsStyleExAddDark.setAttribute('type', 'button');
settingsStyleExAddDark.classList.add('class', 'ExternalLink','cssBtn');
settingsStyleExAddDark.value = 'Add old site CSS, dark mode.';
settingsStyleExAddDark.style = 'display:inline-block;';
settingsStyleExAddDark.onclick = function(){
try{
settingsStyleEx.insertBefore(new externalStyleLink('https://tyranical.github.io/style-dark.css'),settingsStyleEx.childNodes[settingsStyleEx.childNodes.length-1]);
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
}catch(error){console.log('settingsStyleError DDD')}
};
var settingsStyleExAddLight = document.createElement('input');
settingsStyleExAddLight.setAttribute('type', 'button');
settingsStyleExAddLight.classList.add('class', 'ExternalLink','cssBtn');
settingsStyleExAddLight.value = 'Add old site CSS, light mode.';
settingsStyleExAddLight.style = 'display:inline-block;';
settingsStyleExAddLight.onclick = function(){
try{
settingsStyleEx.insertBefore(new externalStyleLink('https://tyranical.github.io/style.css'),settingsStyleEx.childNodes[settingsStyleEx.childNodes.length-1]);
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
}catch(error){console.log('settingsStyleError LLL')}
};
function externalStyleLink(ival,initial){
try{
var settingsStyleExCon = document.createElement('div');
settingsStyleExCon.classList.add('eCSSRow');
var settingsStyleExLink = document.createElement('input');
settingsStyleExLink.setAttribute('type', 'text');
settingsStyleExLink.classList.add('ExternalLink','eCSS')
settingsStyleExLink.setAttribute('placeholder', 'Place a link to a CSS file to have it applied to the page.');
if (!ival){
settingsStyleExLink.value = '';
}
else {
settingsStyleExLink.value = ival;
if (!initial){
if (settings.externalCSS.includes(ival)){return;};
settings.externalCSS.push(ival);
applyCSS(settings.externalCSS.indexOf(ival),ival);
}
}
settingsStyleExLink.onchange = function(){
try{
let all_eCSS = document.querySelectorAll('.eCSS');
if (all_eCSS.length > 1){
all_eCSS.forEach(eCSS=>{
var current = this;
if (eCSS == this){return}
if (eCSS.value == this.value){
current.value='Duplicate found and removed.';
setTimeout(function(){
if (current.value == 'Duplicate found and removed.'){
current.value = '';
}
},5000);
}
})
};
if (/.*\.css/.test(this.value)){
let i = Array.from(settingsStyleEx.querySelectorAll('.eCSS')).indexOf(this);
if (!settings.externalCSS[i]){
settings.externalCSS.push(this.value);
applyCSS(i.toString(),this.value);
}else{
settings.externalCSS[i] = this.value;
applyCSS(i.toString(),this.value);
}
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
}
}catch(error){}
};
var settingsStyleExLinkAdd = document.createElement('input');
settingsStyleExLinkAdd.setAttribute('type', 'button');
settingsStyleExLinkAdd.classList.add('class', 'ExternalLink','cssBtn');
settingsStyleExLinkAdd.value = 'Add new Link';
settingsStyleExLinkAdd.style = 'display:inline-block;';
settingsStyleExLinkAdd.onclick = function(){settingsStyleEx.appendChild(new externalStyleLink)};
var settingsStyleExLinkRem = document.createElement('input');
settingsStyleExLinkRem.setAttribute('type', 'button');
settingsStyleExLinkRem.classList.add('class', 'ExternalLink','cssBtn');
settingsStyleExLinkRem.value = 'Remove This Link';
settingsStyleExLinkRem.style = 'display:inline-block;';
settingsStyleExLinkRem.onclick = function(){
//Select the current external css link
//Get the position of said css link in the array
//Remove the css, the link in the array and the UI elements
let i = Array.from(document.querySelectorAll('.eCSS')).indexOf(this.parentNode.children[0]);
settings.externalCSS.splice(i, 1);
try{
document.querySelector(`link[name="${'eCSS'+i}"]`).remove()
}catch(error){console.log('cssRem',error)}
let rows = document.querySelectorAll('.eCSSRow').length;
if (rows == 1)(this.parentNode.children[0].value='')
else{this.parentNode.remove()};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
};
settingsStyleExCon.appendChild(settingsStyleExLink);
settingsStyleExCon.appendChild(settingsStyleExLinkAdd);
settingsStyleExCon.appendChild(settingsStyleExLinkRem);
return settingsStyleExCon;
}catch(error){}
};
settingsStyleExText.appendChild(settingsStyleExDesc);
settingsStyleExText.appendChild(settingsStyleExAddDark);
settingsStyleExText.appendChild(settingsStyleExAddLight);
settingsStyleEx.appendChild(settingsStyleExText);
if (settings.externalCSS){
settings.externalCSS.forEach(css=>{
try{
let i = settings.externalCSS.indexOf(css);
var eCSS = new externalStyleLink(css,true);
settingsStyleEx.appendChild(eCSS);
applyCSS(i,css);
}catch(error){console.log('Error going over externalCSS',error)}
})}
settingsStyleEx.appendChild(new externalStyleLink());
var settingsStyleEntries = document.createElement('div');
settingsStyleEntries.setAttribute('id', 'styleEntries');
settingsStyleEntries.appendChild(settingsStyleTextBox);
settingsStyleEntries.appendChild(settingsStyleBackgroundBox);
settingsStyle.appendChild(settingsStyleText);
settingsStyle.appendChild(settingsStyleEntries);
settingsStyle.appendChild(settingsStyleSave);
return settingsStyleEx;
};
//Complicated CSS Stuff
var settingsExternalStyles = document.createElement('input');
settingsExternalStyles.setAttribute("type", "button");
settingsExternalStyles.setAttribute('class', 'cssBtn');
settingsExternalStyles.value = 'Toggle CSS Input';
var settingsStyleToggle = document.createElement('input');
settingsStyleToggle.setAttribute("type", "button");
settingsStyleToggle.setAttribute('class', 'cssBtn');
settingsStyleToggle.value = 'Toggle CSS Input';
settingsStyleToggle.onclick = function () {
let styleInput = document.querySelector('#styleInput');
let styleSaveCSS = document.querySelector('#styleSaveCSS');
if (styleInput.style.display != 'none') {
styleInput.style.display = 'none';
styleSaveCSS.style.display = 'none';
} else {
styleInput.style.display = 'initial';
styleSaveCSS.style.display = 'initial';
}
};
var settingsStyleBoxSave = document.createElement('input');
settingsStyleBoxSave.setAttribute("type", "button");
settingsStyleBoxSave.setAttribute('id', 'styleSaveCSS');
settingsStyleBoxSave.setAttribute('class', 'cssBtn');
settingsStyleBoxSave.value = 'Save CSS Input';
settingsStyleBoxSave.style.display = 'none';
settingsStyleBoxSave.onclick = function () {
let styleS = document.querySelector('#styleInput').value
if (styleS !== undefined) {
settings.customCSS[1] = styleS;
}
localStorage.setItem('FL_Settings', JSON.stringify(settings));
let style = document.createElement('style');
style.setAttribute("name", "styleSheet");
if (document.querySelector('[name="styleSheet"]')) {
document.querySelector('[name="styleSheet"]').remove();
style.appendChild(document.createTextNode(styleS));
} else {
style.appendChild(document.createTextNode(styleS));
}
document.getElementsByTagName('head')[0].appendChild(style);
};
var settingsStyleClear = document.createElement('input');
settingsStyleClear.setAttribute("type", "button");
settingsStyleClear.setAttribute('class', 'cssBtn');
settingsStyleClear.value = 'Reset Style Settings';
settingsStyleClear.onclick = function () {
try{
document.querySelector('[name="styleSheet"]').remove();
document.querySelectorAll('.colorPick').forEach(x => {
x.value = ''
});
document.querySelectorAll('.colorSet').forEach(x => {
x.value = ''
});
document.querySelector('#styleInput').value = '';
settings.customCSS = [{}, ``];
localStorage.setItem('FL_Settings', JSON.stringify(settings));
}catch(error){}
};
var settingsStyleBox = document.createElement('textarea');
settingsStyleBox.setAttribute('id', 'styleInput');
settingsStyleBox.setAttribute('placeholder', 'Add any more complicated CSS here.');
settingsStyleBox.setAttribute("cols", "50");
settingsStyleBox.setAttribute("rows", "50");
settingsStyleBox.style.display = 'none';
if (settings.customCSS[1] !== ``) {
settingsStyleBox.value = settings.customCSS[1];
}
settingsStyle.appendChild(new settingsStyleEx);
settingsStyle.appendChild(settingsStyleToggle);
settingsStyle.appendChild(settingsStyleBoxSave);
settingsStyle.appendChild(settingsStyleClear);
settingsStyle.appendChild(settingsStyleBox);
try {
if (settings.customCSS[0] != {}) {
let A=''
let B=''
if (settings.customCSS[0].color != undefined){A=`color:${settings.customCSS[0].color}!important;`}
if (settings.customCSS[0].background != undefined){B=`background:${settings.customCSS[0].background} !important;}`}
var styleS = `*{${A}${B}}`;
if (styleS!='*{}'){
var style = document.createElement('style');
style.setAttribute("name", "styleSheet");
if (document.querySelector('[name="styleSheet"]')) {
document.querySelector('[name="styleSheet"]').remove();
style.setAttribute("name", "styleSheet");
style.appendChild(document.createTextNode(styleS));
} else {
style.appendChild(document.createTextNode(styleS));
}
document.getElementsByTagName('head')[0].appendChild(style);
}
};
} catch (error) {
console.log(error)
}
try {
if (settings.customCSS[1] != ``) {
var style2 = document.createElement('style');
var styleS2 = settings.customCSS[1]
if (document.querySelector('[name="styleSheet"]')) {
document.querySelector('[name="styleSheet"]').remove();
style2.setAttribute("name", "styleSheet");
style2.appendChild(document.createTextNode(styleS2));
}
else {
style2.setAttribute("name", "styleSheet");
style2.appendChild(document.createTextNode(styleS2));
}
document.getElementsByTagName('head')[0].appendChild(style2);
}
} catch (error) {
console.log('customcss',error)
}
return settingsStyle;
}
//Toggles for features start here
//Toggles for features start here
//Toggles for features start here
//Toggles for features start here
//Toggles for features start here
function settingsNamefagToggle() {
if (settings.removeUsernames != true){return;}
try{
let authorList = document.querySelectorAll('span.author.ng-scope');
let authors = []
authorList.forEach(element => authors.push(element.querySelector('span').innerText))
let names = document.querySelectorAll('div.user span')
document.querySelectorAll('div.user a img').forEach(x=>{x.remove()})
names.forEach(name => {
let txt = name.innerText;
if (!authors.includes(txt)){
name.innerText = 'anon';
}
})
}catch(error){
console.log('anonForce',error)
}
};
function settingsAnonToggle() {
function toggleAnonStatus() {
var x = 1
try {
try {
var username = localStorage.getItem('username');
var refURL = "https://fiction.live/user/" + username;
var profile = window.ty.currentUser.profile;
profile.asAnon = settings.anonToggle;
} catch (error) {
console.log('Toggle Anon Prep', error);
x = 2;
};
if (x = 1) {
fetch("https://fiction.live/api/user", {
"credentials": "include",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Language": "en-GB,en;q=0.5",
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest"
},
"referrer": refURL,
"body": JSON.stringify(profile),
"method": "PUT",
"mode": "cors"
});
};
} catch (error) {
console.log('Toggle Anon Set', error);
};
};
var settingsAnonToggle = document.createElement('div');
settingsAnonToggle.setAttribute('class', 'settingsToggle');
var settingsAnonToggleText = document.createElement('div');
settingsAnonToggleText.innerText = 'Toggle Anon status.';
var settingsAnonToggleCheckbox = document.createElement('input');
settingsAnonToggleCheckbox.setAttribute("type", "checkbox");
settingsAnonToggleCheckbox.setAttribute("class", "toggleCheck");
if (settings.anonToggle == true) {
settingsAnonToggleCheckbox.checked = true;
};
settingsAnonToggleCheckbox.addEventListener('change', (event) => {
if (event.target.checked) {
settings.anonToggle = true;
toggleAnonStatus();
} else {
settings.anonToggle = false;
toggleAnonStatus();
};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
});
settingsAnonToggle.appendChild(settingsAnonToggleText);
settingsAnonToggle.appendChild(settingsAnonToggleCheckbox);
return settingsAnonToggle
};
function settingsLiveRestore() {
var settingsLiveRestore = document.createElement('div');
settingsLiveRestore.setAttribute('class', 'settingsToggle');
var settingsLiveRestoreText = document.createElement('div');
settingsLiveRestoreText.innerText = 'Restore live timer to nav bar.';
var settingsLiveRestoreCheckbox = document.createElement('input');
settingsLiveRestoreCheckbox.setAttribute("type", "checkbox");
settingsLiveRestoreCheckbox.setAttribute("class", "toggleCheck");
if (settings.liveRestore == true) {
settingsLiveRestoreCheckbox.checked = true;
};
settingsLiveRestoreCheckbox.addEventListener('change', (event) => {
if (event.target.checked) {
settings.liveRestore = true;
let canvas = document.querySelector('header[class="next-live ng-scope"]');
if (canvas){
liveRestore()
}
} else {
settings.liveRestore = false;
};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
});
settingsLiveRestore.appendChild(settingsLiveRestoreText);
settingsLiveRestore.appendChild(settingsLiveRestoreCheckbox);
return settingsLiveRestore
};
function settingsQuestBlock() {
try{
let styleS = `li[class="userControls ng-scope"] > a{display:none !important;} li[class="userControls ng-scope"]{width:100px;}`;
let style = document.createElement('style');
style.setAttribute("name", "QBSS");
if (settings.questBlock == true) {
//let formItem = document.querySelector('div.formItem');
//if (formItem) {
// formItem.parentNode.remove();
//};
style.appendChild(document.createTextNode(styleS));
document.getElementsByTagName('head')[0].appendChild(style);
}
else{
if (document.querySelector('[name="QBSS"]')) {
document.querySelector('[name="QBSS"]').remove();
style.appendChild(document.createTextNode(styleS));
}
}
}catch(error){
console.log('settingsQuestBlock',error);
}
};
function settingsLiveLight() {
var settingsLiveLight = document.createElement('div');
settingsLiveLight.setAttribute('class', 'settingsToggle');
var settingsLiveLightText = document.createElement('div');
settingsLiveLightText.innerText = 'Light mode live timer.';
var settingsLiveLightCheckbox = document.createElement('input');
settingsLiveLightCheckbox.setAttribute("type", "checkbox");
settingsLiveLightCheckbox.setAttribute("class", "toggleCheck");
if (settings.liveLight == true) {
settingsLiveLightCheckbox.checked = true;
};
settingsLiveLightCheckbox.addEventListener('change', (event) => {
let myLive = document.querySelector('#liveBox')
if (event.target.checked) {
settings.liveLight = true;
} else {
settings.liveLight = false;
};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
});
settingsLiveLight.appendChild(settingsLiveLightText);
settingsLiveLight.appendChild(settingsLiveLightCheckbox);
return settingsLiveLight
};
function settingsAuthorHighlight() {
var settingsAuthorHighlight = document.createElement('div');
settingsAuthorHighlight.setAttribute('class', 'settingsToggle');
var settingsAuthorHighlightText = document.createElement('div');
settingsAuthorHighlightText.innerText = 'Highlight author(s) in chat.';
var settingsAuthorHighlightCheckbox = document.createElement('input');
settingsAuthorHighlightCheckbox.setAttribute("type", "checkbox");
settingsAuthorHighlightCheckbox.setAttribute("class", "toggleCheck");
if (settings.authorHighlight == true) {
settingsAuthorHighlightCheckbox.checked = true;
};
settingsAuthorHighlightCheckbox.addEventListener('change', (event) => {
if (event.target.checked) {
settings.authorHighlight = true;
try{
let authorList = document.querySelectorAll('span.author.ng-scope');
let authors = []
authorList.forEach(element => authors.push(element.querySelector('span.name').innerText))
var currentColor = settings.highlightColor;
if (settings.highlightLightToggle == true) {
currentColor = settings.highlightLight;
}
document.querySelectorAll('div.user span.name').forEach(name => {
if (authors.includes(name.innerText)){
name.closest('.logItem').style.background = currentColor
}
})
}catch(error){}
} else {
settings.authorHighlight = false;
};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
});
settingsAuthorHighlight.appendChild(settingsAuthorHighlightText);
settingsAuthorHighlight.appendChild(settingsAuthorHighlightCheckbox);
return settingsAuthorHighlight
};
function settingsLightHighlight() {
var settingsLightHighlight = document.createElement('div');
settingsLightHighlight.setAttribute('class', 'settingsToggle');
var settingsLightHighlightText = document.createElement('div');
settingsLightHighlightText.innerText = 'Light mode highlighting.';
var settingsLightHighlightCheckbox = document.createElement('input');
settingsLightHighlightCheckbox.setAttribute("type", "checkbox");
settingsLightHighlightCheckbox.setAttribute("class", "toggleCheck");
if (settings.highlightLightToggle == true) {
settingsLightHighlightCheckbox.checked = true;
};
settingsLightHighlightCheckbox.addEventListener('change', (event) => {
if (event.target.checked) {
settings.highlightLightToggle = true;
try{
let authorList = document.querySelectorAll('span.author.ng-scope');
let authors = []
authorList.forEach(element => authors.push(element.querySelector('span.name').innerText))
var currentColor = settings.highlightColor;
if (settings.highlightLightToggle == true) {
currentColor = settings.highlightLight;
}
document.querySelectorAll('div.user span.name').forEach(name => {
if (authors.includes(name.innerText)){
name.closest('.logItem').style.background = currentColor
}
})
}catch(error){}
} else {
settings.highlightLightToggle = false;
};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
});
settingsLightHighlight.appendChild(settingsLightHighlightText);
settingsLightHighlight.appendChild(settingsLightHighlightCheckbox);
return settingsLightHighlight
};
function settingsNSFWToggle() {
var settingsNSFWToggle = document.createElement('div');
settingsNSFWToggle.setAttribute('class', 'settingsToggle');
var settingsNSFWToggleText = document.createElement('div');
settingsNSFWToggleText.innerText = 'Remove NSFW covers from quests.';
var settingsNSFWToggleCheckbox = document.createElement('input');
settingsNSFWToggleCheckbox.setAttribute("type", "checkbox");
settingsNSFWToggleCheckbox.setAttribute("class", "toggleCheck");
if (settings.removeNSFW == true) {
settingsNSFWToggleCheckbox.checked = true;
};
settingsNSFWToggleCheckbox.addEventListener('change', (event) => {
if (event.target.checked) {
settings.removeNSFW = true;
removeNSFW();
} else {
settings.removeNSFW = false;
};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
});
settingsNSFWToggle.appendChild(settingsNSFWToggleText);
settingsNSFWToggle.appendChild(settingsNSFWToggleCheckbox);
return settingsNSFWToggle
};
function dismissAlertUpdateRequest() {
try {
if (settings.updateRequestDismiss == true) {
let alertContainer = document.querySelectorAll('li.feedItem');
alertContainer.forEach(alert => {
if (/.*Looks forward to the next update for.*/.test(alert.innerText)) {
alertUpdate(alert);
};
});
}
} catch (error) {
console.log('Error with removing update request', error);
};
};
function dismissAlertReview() {
try {
if (settings.reviewDismiss == true) {
let alertContainer = document.querySelectorAll('li.feedItem');
alertContainer.forEach(alert => {
if (/.*New review for.*/.test(alert.innerText)) {
alertUpdate(alert);
};
});
}
} catch (error) {
console.log('Error with removing review alert', error);
};
};
function dismissAlertFollow() {
try {
if (settings.followDismiss == true) {
let alertContainer = document.querySelectorAll('li.feedItem');
alertContainer.forEach(alert => {
if (/.*Is now a new follower of yours.*/.test(alert.innerText)) {
alertUpdate(alert);
};
});
}
} catch (error) {
console.log('Error with removing follow alert', error);
};
};
function dismissAlertLike() {
try {
if (settings.likeDismiss == true) {
let alertContainer = document.querySelectorAll('li.feedItem');
alertContainer.forEach(alert => {
if (/.*Likes \".*\".*/.test(alert.innerText)) {
alertUpdate(alert);
};
});
}
} catch (error) {
console.log('Error with removing follow alert', error);
};
};
function settingsAkunPlusToggle() {
var settingsAkunPlusToggle = document.createElement('div');
settingsAkunPlusToggle.setAttribute('class', 'settingsToggle');
var settingsAkunPlusToggleText = document.createElement('div');
var settingsAkunPlusToggleBtn = document.createElement('input');
settingsAkunPlusToggleBtn.setAttribute("type", "button");
settingsAkunPlusToggleBtn.setAttribute("class", "toggleBtn");
if (settings.akunPlus == 'Ignore') {
settingsAkunPlusToggleText.innerText = '(Chat) Ignore Akun Premium';
settingsAkunPlusToggleBtn.value = 'Remove';
} else if (settings.akunPlus == 'Remove') {
settingsAkunPlusToggleText.innerText = '(Chat) Remove Akun Premium';
settingsAkunPlusToggleBtn.value = 'Global';
} else {
settingsAkunPlusToggleText.innerText = '(Chat) Global Akun Premium';
settingsAkunPlusToggleBtn.value = 'Ignore';
};
settingsAkunPlusToggleBtn.onclick = function () {
try {
if (settings.akunPlus == 'Ignore') {
this.parentNode.childNodes[0].innerText = '(Chat) Remove Akun Premium';
this.value = 'Global';
settings.akunPlus = 'Remove';
} else if (settings.akunPlus == 'Remove') {
this.parentNode.childNodes[0].innerText = '(Chat) Global Akun Premium';
this.value = 'Ignore';
settings.akunPlus = 'Global';
} else {
this.parentNode.childNodes[0].innerText = '(Chat) Ignore Akun Premium';
this.value = 'Remove';
settings.akunPlus = 'Ignore';
};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
} catch (error) {
console.log('Error changin akunPlus', error);
};
};
settingsAkunPlusToggle.appendChild(settingsAkunPlusToggleText);
settingsAkunPlusToggle.appendChild(settingsAkunPlusToggleBtn);
return settingsAkunPlusToggle
};
function settingsNewThemeChangeToggle() {
var settingsToggle = document.createElement('div');
settingsToggle.setAttribute('class', 'settingsToggle');
var settingsText = document.createElement('div');
settingsText.innerText = 'Change themes without page reload.';
var settingsCheckbox = document.createElement('input');
settingsCheckbox.setAttribute("type", "checkbox");
settingsCheckbox.setAttribute("class", "toggleCheck");
if (settings.useThemeChange == true) {
settingsCheckbox.checked = true;
};
settingsCheckbox.addEventListener('change', (event) => {
if (event.target.checked) {
settings.useThemeChange = true;
try{
newThemeChange();
}catch(error){console.log(error)}
} else {
settings.useThemeChange = false;
};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
});
settingsToggle.appendChild(settingsText);
settingsToggle.appendChild(settingsCheckbox);
return settingsToggle
};
function settingsImageLinkToggle() {
var settingsToggle = document.createElement('div');
settingsToggle.setAttribute('class', 'settingsToggle');
var settingsText = document.createElement('div');
settingsText.innerText = 'Display off-site image poster in chat input.';
var settingsCheckbox = document.createElement('input');
settingsCheckbox.setAttribute("type", "checkbox");
settingsCheckbox.setAttribute("class", "toggleCheck");
if (settings.imageLink == true) {
settingsCheckbox.checked = true;
};
settingsCheckbox.addEventListener('change', (event) => {
if (event.target.checked) {
settings.imageLink = true;
imageLinkButton();
} else {
settings.imageLink = false;
};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
});
settingsToggle.appendChild(settingsText);
settingsToggle.appendChild(settingsCheckbox);
return settingsToggle
};
//Toggle Template/Example
function settingsToggle(text, toggled, desc, func) {
if (!func){func = function(){}}
try{
var settingsToggle = document.createElement('div');
settingsToggle.setAttribute('class', 'settingsToggle');
var settingsText = document.createElement('div');
settingsText.innerText = text;
var settingsCheckbox = document.createElement('input');
settingsCheckbox.setAttribute("type", "checkbox");
settingsCheckbox.setAttribute("class", "toggleCheck");
if (settings[toggled] == true) {
settingsCheckbox.checked = true;
};
settingsCheckbox.addEventListener('change', (event) => {
if (event.target.checked) {
settings[toggled] = true;
} else {
settings[toggled] = false;
};
localStorage.setItem('FL_Settings', JSON.stringify(settings));
settings = JSON.parse(localStorage.getItem('FL_Settings'));
func();
});
settingsToggle.appendChild(settingsText);
settingsToggle.appendChild(settingsCheckbox);
if (desc){
settingsToggle.appendChild(new tooltipGen(desc));
}
func();
return settingsToggle;
}
catch(error){
console.log('Error, does',toggled, 'exist?')
}
};
function settingsActual() {
var settingsActual = document.createElement('div');
settingsActual.setAttribute('class', 'settingsTab');
settingsActual.setAttribute('name', 'General');
settingsActual.style.display = 'initial';
var settingsActualText = document.createElement('div');
settingsActualText.innerText = 'General Script Settings';
settingsActualText.setAttribute('class', 'entryTitle');
//Settings Checkboxes
settingsActual.appendChild(new settingsToggle('Automatically dismiss quest update request alerts.','updateRequestDismiss','Dismisses update request alerts as soon as possible.',dismissAlertUpdateRequest));
settingsActual.appendChild(new settingsToggle('Automatically dismiss review alerts.','reviewDismiss','Dismisses review alerts as soon as possible.',dismissAlertReview));
settingsActual.appendChild(new settingsToggle('Automatically dismiss follow alerts.','followDismiss','Dismisses user follow alerts as soon as possible.',dismissAlertFollow));
settingsActual.appendChild(new settingsToggle('Automatically dismiss like alerts.','likeDismiss','Dismisses user like alerts as soon as possible.',dismissAlertLike));
settingsActual.appendChild(settingsNSFWToggle());
settingsActual.appendChild(settingsLiveRestore());
//Hidden because of dark mode detection
//settingsActual.appendChild(settingsLiveLight());
settingsActual.appendChild(new settingsToggle('Toggle creation of dice buttons.','diceButton','Creates a button that rolls a dice, if the QM creates a post containing a roll.'));
settingsActual.appendChild(new settingsToggle('Remove blank topics.','removeBlankTopics'));
settingsActual.appendChild(new settingsToggle('Hides "Post Your Thoughts" form.','removeTopicForm','Hides the topic creation form, "Post Your Thoughts", in the Alerts tab.',deleteTopicCreate));
settingsActual.appendChild(new settingsToggle('Hide quests with blacklisted tags.','questRemove','Any quests with a tag in the blacklist will be removed from results.'));
settingsActual.appendChild(new settingsToggle('Hide tagged on author pages.','removeTaggedAuthor','Hide quests with blacklisted tags on author pages.'));
settingsActual.appendChild(new settingsToggle('Hide quests with blacklisted authors.','questAuthorRemove'));
settingsActual.appendChild(new settingsToggle('Enable alert filtering.','alertFilter','Lets you search alerts for a phrase, like QM or quest name.',alertSearch));
settingsActual.appendChild(new settingsToggle('Order alerts by QM name.','qmSort','Orders all story alerts alphabetically by QM name.',alertSortByQM));
settingsActual.appendChild(new settingsToggle('(Chromium) Attempt to fix the line spacing issue.','spaceFix','Fixes the chrome-based browser only spacing issue when you create a new line using Shift+Enter.'));
settingsActual.appendChild(new settingsToggle('Hide "+ New Story" button.','questBlock','Hides the new story button.',settingsQuestBlock));
settingsActual.appendChild(settingsNewThemeChangeToggle());
var settingsText = document.createElement('div');
settingsText.innerText = 'Chat Settings';
settingsText.setAttribute('class', 'entryTitle');
settingsActual.appendChild(settingsText);
settingsActual.appendChild(settingsAnonToggle());
settingsActual.appendChild(new settingsToggle('Toggle Auto Roller.','autoRoller','Automatically duplicate dice rolls.'));
settingsActual.appendChild(settingsAuthorHighlight());
//Hidden because of dark mode detection
//settingsActual.appendChild(settingsLightHighlight());
settingsActual.appendChild(new settingsToggle('Make everyone anon.','removeUsernames','Change all usernames to anon and remove icons.',settingsNamefagToggle));
settingsActual.appendChild(new settingsToggle('Attempt to reveal anon usernames in chat.','userReveal'));
settingsActual.appendChild(new settingsToggle('Enable the delete button on your messages.','unpublishBTN','Allows quick message deletion.'));
settingsActual.appendChild(new settingsToggle('Hide blacklisted users in chat.','chatBlacklist','Messages from blacklisted users will be hidden to you.'));
settingsActual.appendChild(new settingsToggle('Remove replies to blacklisted users.','chatBlacklistReplies','Replies to messages from blacklisted users will be hidden to you.'));
settingsActual.appendChild(settingsAkunPlusToggle());
settingsActual.appendChild(new settingsToggle('Resize images in chat.','imageResize','Automatically resizes images posted to chat to make them larger.'));
settingsActual.appendChild(new settingsToggle('Make text links functional.','functionalLinks','Turns text links into clickable links.'));
settingsActual.appendChild(new settingsToggle('Make video links functional.','functionalVideos','Turns supported video links into playable videos in chat.'));
settingsActual.appendChild(new settingsToggle('Allow message editing in chat.','messageEdit','Allows you to edit messages in chat.'));
settingsActual.appendChild(new settingsToggle('Toggle in-chat text options.','textStyle','Allows you to modify your messages with bold, italic, underlined amd strike-through text.'));
settingsActual.appendChild(new settingsToggle('Enable automatic chat hide.','autoHide','Hide chat when you open a quest.'));
settingsActual.appendChild(settingsImageLinkToggle());
settingsActual.appendChild(new settingsToggle('Enable spam auto delete.','spamRemoval','Deletes any messages over a set length that appear in chat. Change the length under the \'Chat\' tab.'));
settingsActual.appendChild(new settingsToggle('Enable auto-delete and ban phrases.','messageBlacklist','Enables the \'Purge Messages\' button, to manually trigger the list check and removal of matches.',
purgeButtonAdd));
settingsActual.appendChild(new settingsToggle('Remove user icons that are gifs.','gifDisable'));
settingsActual.appendChild(new settingsToggle('Enable SauceNao buttons on images.','imgSourceBtn','Hovering over an image will create a button to find the image source.'));
//settingsActual.appendChild(new settingsToggle('test',));
settingsActual.prepend(settingsActualText);
return settingsActual
}
var settingsTop = document.createElement('div');
settingsTop.setAttribute('id', 'scriptTitle');
var scriptVersion = GM_info.script.version;
var settingsTopText = document.createElement('h1');
settingsTopText.innerText = 'Script Config - Script Version '+scriptVersion;
settingsTop.appendChild(settingsTopText);
try {
var settingsSelect = document.createElement('div');
settingsSelect.setAttribute("class", "settingsSelect");
var settingsTabs = ['General', 'Tags', 'Chat', 'Alerts', 'Author', 'Site Style'];
let tabC = 0;
function createTab(tab) {
let settingsSelectBTN = document.createElement('input');
settingsSelectBTN.setAttribute("type", "button");
settingsSelectBTN.setAttribute("class", "settingsSelectBTN");
settingsSelectBTN.value = String(tab);
if (tabC == 0) {
settingsSelectBTN.style.backgroundColor = '#4b4f6b';
settingsSelectBTN.disabled = true;
tabC = 1;
var settingTab = document.querySelector(`.settingsTab[name="${String(tab)}"]`)
}
settingsSelectBTN.onclick = function () {
let len = document.querySelectorAll('input.settingsSelectBTN');
for (let i = 0; i < len.length; i++) {
if (len[i].disabled == true) {
len[i].disabled = false;
len[i].style.backgroundColor = '#373952';
}
};
this.disabled = true;
this.style.backgroundColor = '#4b4f6b';
try {
var settingTab = document.querySelector(`.settingsTab[name="${String(tab)}"]`)
if (settingTab) {
var tabs = document.querySelectorAll(`div.settingsTab`)
for (let i = 0; i < tabs.length; i++) {
tabs[i].style.display = 'none';
};
settingTab.style.display = 'initial'
}
} catch (error) {
console.log(error);
};
};
let settingsSelectDiv = document.createElement('div');
settingsSelectDiv.setAttribute('class', 'settingsSelectDiv');
settingsSelectDiv.style.width = String(100 / settingsTabs.length) + '%';
settingsSelectDiv.appendChild(settingsSelectBTN);
settingsSelect.appendChild(settingsSelectDiv);
}
settingsTabs.forEach(tab => createTab(tab));
} catch (error) {
console.log(error);
}
var settingsExit = document.createElement('a');
settingsExit.setAttribute('class', 'blacklistRemove');
settingsExit.innerText = 'Exit'
settingsExit.onclick = function () {
document.querySelector('#confDisp').style.display = 'none'
};
function contact() {
var contactLeft = document.createElement('div');
contactLeft.setAttribute('class', 'contactL');
var contactContainer = document.createElement('div');
contactContainer.setAttribute('id', 'reportDiv');
contactContainer.innerText = 'Report any issues you encounter to me through either of the links below, though the quest is preferred.';
var contactAkun = document.createElement('a');
contactAkun.innerText = 'Akun Script Quest';
contactAkun.href = 'https://fiction.live/stories/Fiction-live-Merged-Script/2pqyotSpKTcPF9dz8';
contactAkun.rel = "noopener noreferrer";
contactAkun.target = "_blank";
var contactGreasyfork = document.createElement('a');
contactGreasyfork.innerText = 'Greasyfork Page';
contactGreasyfork.href = 'https://greasyfork.org/en/scripts/418607-fiction-live-merged';
contactGreasyfork.rel = "noopener noreferrer";
contactGreasyfork.target = "_blank";
var contactRight = document.createElement('div');
contactRight.setAttribute('class', 'contactR');
function download(data) {
var file = new Blob([data], {type: '.txt'});
if (window.navigator.msSaveOrOpenBlob){// IE10+
window.navigator.msSaveOrOpenBlob(file, 'FictionLiveMerged-Settings');
}
else { // Others
var a = document.createElement("a"),
url = URL.createObjectURL(file);
a.href = url;
a.download = 'FictionLiveMerged-Settings.txt';
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
}
var exportSettings = document.createElement('a');
exportSettings.setAttribute("class", "exportSettings");
exportSettings.innerText='Export settings to file.'
exportSettings.onclick = function(){download(localStorage.getItem('FL_Settings'))};
var importSettings = document.createElement('a');
importSettings.setAttribute("class", "exportSettings");
importSettings.innerText='Import settings from file.';
importSettings.onclick = function(){
this.parentNode.querySelector('#fileImport').click();
};
var resetSettings = document.createElement('a');
resetSettings.setAttribute("class", "exportSettings");
resetSettings.innerText='Reset settings.'
resetSettings.onclick = function(){
if (confirm('Reset all script settings to the defaults?') == true){
localStorage.setItem('FL_Settings', JSON.stringify(defaultSettings));
location.reload();
}
};
var importContainer = document.createElement('div');
var importFile = document.createElement('input');
importFile.setAttribute("id", "fileImport");
importFile.setAttribute("type", "file");
importFile.setAttribute("name", "files[]");
importFile.setAttribute("accept", ".txt");
importFile.style = 'display:none !important; visibility:hidden !important;'
importFile.onchange = function(){
var files = event.target.files; // FileList object
//console.log(files[0]);
//return;
var reader = new FileReader();
if(files && files[0]) {
reader.onload = function (e) {
let data = e.target.result;
localStorage.setItem('FL_Settings', data);
return;
//displayContents(output);
};//end onload()
reader.readAsText(files[0]);
location.reload();
}
};
importContainer.appendChild(importSettings)
importContainer.appendChild(importFile)
var contact = document.createElement('div');
contact.setAttribute('class', 'contactMain');
contactContainer.appendChild(document.createElement('br'));
contactContainer.appendChild(contactAkun);
contactContainer.appendChild(document.createElement('br'));
contactContainer.appendChild(contactGreasyfork);
contactLeft.appendChild(contactContainer);
contactRight.appendChild(exportSettings);
contactRight.appendChild(importContainer);
contactRight.appendChild(resetSettings);
contact.appendChild(contactLeft);
contact.appendChild(contactRight);
return contact;
};
settingsTop.appendChild(settingsExit)
var confDisp = configDisplay();
var confBox = configBox();
confBox.appendChild(settingsTop);
confBox.appendChild(settingsSelect);
confBox.appendChild(settingsActual());
confBox.appendChild(settingsTagsBlacklist());
confBox.appendChild(settingsUserBlacklist());
confBox.appendChild(settingsAuthorsBlacklist());
confBox.appendChild(settingsStyle());
confBox.appendChild(settingsBlacklist());
confBox.appendChild(contact());
confDisp.appendChild(confBox);
document.querySelector('body').prepend(confDisp);
}
} catch (error) {
console.log('Settings Display Error', error);
};
};
function settingsOpen() {
var myLive = document.createElement('li');
myLive.setAttribute('id', 'confScript');
var configOpen = document.createElement('a');
configOpen.innerText = 'Config';
configOpen.onclick = function () {
document.querySelector('#confDisp').style.display = 'block'
};
myLive.appendChild(configOpen);
return myLive
};
function settingsInsert() {
try {
let mainMenu = document.querySelector('nav#mainMenu');
settingsDisplay()
if (!(mainMenu.querySelector('#confScript'))) {
mainMenu.childNodes[2].appendChild(settingsOpen());
}
} catch (error) {
console.log('Errors inserting Settings', error)
};
};
settingsInsert()
};
pageCheck();
awaitAlerts()
awaitMainMenu();
function fixSpacing(){
function KeyPress(e) {
if (settings.spaceFix != true ){return}
var evtobj = window.event? event : e
if (evtobj.keyCode == 13 && evtobj.shiftKey) {
if (Array.from(document.querySelectorAll('div.fieldEditor')).includes(document.activeElement)){
//THIS WORKS
if (window.getSelection) {
var selection = window.getSelection(),
range = selection.getRangeAt(0),
br = document.createElement("br"),
textNode = document.createTextNode("\u00a0"); //Passing " " directly will not end up being shown correctly
range.deleteContents();//required or not?
range.insertNode(br);
range.collapse(false);
range.insertNode(textNode);
range.selectNodeContents(textNode);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('delete');
return false;
}
}
}
}
document.onkeydown = KeyPress;
}
fixSpacing();
//Source - https://github.com/proxy-m/real-visibility
Element.prototype.isReallyNear = function(otherEl) {
let el = this;
if (!el || !otherEl) {
return null;
}
return el.contains(otherEl) || otherEl.contains(el);
};
Element.prototype.isReallyVisible = function() {
let el = this;
let debug = false;
if (!document.body.contains(el)) {
return null;
}
if (document.hidden===true) {
return false;
} else if (document.hidden!==false) {
console.warn("NOT FATAL WARNING: Page Visibility API is not supported by your browser.");
}
let rectPos = el.getBoundingClientRect();
if (debug) {
console.debug("Bounding of: ", el, rectPos);
}
let result = 0;
if (el.isReallyNear(document.elementFromPoint(rectPos.left, rectPos.top))) {
result++;
}
if (el.isReallyNear(document.elementFromPoint(rectPos.left, rectPos.bottom - 1))) {
result++;
}
if (el.isReallyNear(document.elementFromPoint(rectPos.right - 1, rectPos.top))) {
result++;
}
if (el.isReallyNear(document.elementFromPoint(rectPos.right - 1, rectPos.bottom - 1))) {
result++;
}
let info;
let r = true;
if (result == 4) {
info = 'visible';
} else if (result === 0) {
info = 'hidden';
r = false;
} else {
info = 'partially visible';
}
if (debug) {
console.debug(info, el);
}
return r;
};
}catch(error){console.log('Entire Script Error.')}
})();