Update mods
This commit is contained in:
parent
8e0ca4b8a9
commit
98dc169e46
|
@ -1,14 +1,17 @@
|
||||||
function ColorDetector (image) {
|
/* global PleromaMod */
|
||||||
this.color = { r: 0, g: 0, b: 0 };
|
|
||||||
this.image = image;
|
|
||||||
}
|
|
||||||
[
|
|
||||||
function componentToHex (c) {
|
|
||||||
var hex = Math.max(Math.min(c, 255), 0).toString(16);
|
|
||||||
return hex.length === 1 ? "0" + hex : hex;
|
|
||||||
},
|
|
||||||
|
|
||||||
function getHexColor (offset) {
|
class ColorDetector {
|
||||||
|
constructor (image) {
|
||||||
|
this.color = { r: 0, g: 0, b: 0 };
|
||||||
|
this.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentToHex (c) {
|
||||||
|
const hex = Math.max(Math.min(c, 255), 0).toString(16);
|
||||||
|
return hex.length === 1 ? "0" + hex : hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
getHexColor (offset) {
|
||||||
if (!offset) {
|
if (!offset) {
|
||||||
offset = { r: 0, g: 0, b: 0 };
|
offset = { r: 0, g: 0, b: 0 };
|
||||||
}
|
}
|
||||||
|
@ -16,40 +19,39 @@ function ColorDetector (image) {
|
||||||
this.componentToHex(this.color.r + offset.r) +
|
this.componentToHex(this.color.r + offset.r) +
|
||||||
this.componentToHex(this.color.g + offset.g) +
|
this.componentToHex(this.color.g + offset.g) +
|
||||||
this.componentToHex(this.color.b + offset.b);
|
this.componentToHex(this.color.b + offset.b);
|
||||||
},
|
}
|
||||||
|
|
||||||
function detect () {
|
detect () {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
let blockSize = 5;
|
const blockSize = 5;
|
||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement("canvas");
|
||||||
const context = canvas.getContext && canvas.getContext("2d");
|
const context = canvas.getContext && canvas.getContext("2d");
|
||||||
let data; let width; let height;
|
|
||||||
let i = -4;
|
|
||||||
let rgb = { r: 0, g: 0, b: 0 };
|
|
||||||
let length;
|
|
||||||
let count = 0;
|
|
||||||
if (!context) {
|
if (!context) {
|
||||||
console.warn("can't get context of avatar");
|
console.warn("can't get context of avatar");
|
||||||
resolve(this.color);
|
resolve(this.color);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
height = canvas.height = this.image.naturalHeight || this.image.offsetHeight || this.image.height;
|
const height = canvas.height = this.image.naturalHeight || this.image.offsetHeight || this.image.height;
|
||||||
width = canvas.width = this.image.naturalWidth || this.image.offsetWidth || this.image.width;
|
const width = canvas.width = this.image.naturalWidth || this.image.offsetWidth || this.image.width;
|
||||||
|
|
||||||
context.drawImage(this.image, 0, 0);
|
context.drawImage(this.image, 0, 0);
|
||||||
|
|
||||||
|
let data;
|
||||||
try {
|
try {
|
||||||
data = context.getImageData(0, 0, width, height);
|
data = context.getImageData(0, 0, width, height);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("can't get image data");
|
console.error("can't get avatar image data");
|
||||||
console.error(e);
|
console.error(e);
|
||||||
resolve(this.color);
|
resolve(this.color);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
length = data.data.length;
|
let i = -4;
|
||||||
|
let count = 0;
|
||||||
|
const length = data.data.length;
|
||||||
|
const rgb = { r: 0, g: 0, b: 0 };
|
||||||
while ((i += blockSize * 4) < length) {
|
while ((i += blockSize * 4) < length) {
|
||||||
++count;
|
++count;
|
||||||
rgb.r += data.data[i];
|
rgb.r += data.data[i];
|
||||||
|
@ -64,103 +66,96 @@ function ColorDetector (image) {
|
||||||
resolve(this.color);
|
resolve(this.color);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
].forEach((fn) => { ColorDetector.prototype[fn.name] = fn; });
|
|
||||||
|
|
||||||
function PleromaCat (handle, type) {
|
|
||||||
this.type = type || "cat";
|
|
||||||
this.handle = handle;
|
|
||||||
this.colors = {
|
|
||||||
backgroundColor: "#000000",
|
|
||||||
borderColor: "#000000"
|
|
||||||
};
|
|
||||||
this.config = {
|
|
||||||
"nya": {
|
|
||||||
enabled: true,
|
|
||||||
matcher: "(^|\s|>)な+(\s|<|$)", // eslint-disable-line no-useless-escape
|
|
||||||
replacer: {
|
|
||||||
source: "な",
|
|
||||||
dest: "にゃ"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.loadConfig();
|
|
||||||
}
|
}
|
||||||
[
|
|
||||||
function loadConfig () {
|
class PleromaCat {
|
||||||
const json = PleromaModCatify.config;
|
constructor (handle, type, config) {
|
||||||
|
config = config || {};
|
||||||
|
this.type = type || "cat";
|
||||||
|
this.handle = handle;
|
||||||
|
this.colors = {
|
||||||
|
backgroundColor: "#000000",
|
||||||
|
borderColor: "#000000"
|
||||||
|
};
|
||||||
|
|
||||||
|
this.config = {
|
||||||
|
"nya": {
|
||||||
|
enabled: false,
|
||||||
|
replacer: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.loadConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadConfig (json) {
|
||||||
if (!json.nya) {
|
if (!json.nya) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.config.nya.enabled = json.nya.enabled;
|
this.config.nya.enabled = json.nya.enabled;
|
||||||
if (this.config.nya.enabled) {
|
if (this.config.nya.enabled) {
|
||||||
this.config.nya.matcher = json.nya.matcher || this.config.nya.matcher;
|
this.config.nya.matcher = json.nya.matcher || this.config.nya.matcher;
|
||||||
this.config.nya.replacer.source = json.nya.replacer.source || this.config.nya.replacer.source;
|
this.config.nya.replacer.source = json.nya.replacer.source || this.config.nya.replacer.source;
|
||||||
this.config.nya.replacer.dest = json.nya.replacer.dest || this.config.nya.replacer.dest;
|
this.config.nya.replacer.dest = json.nya.replacer.dest || this.config.nya.replacer.dest;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
function getClassName () {
|
getClassName () {
|
||||||
return "USER____" + this.handle.replace(/@/g, "_AT_").replace(/\./g, "_");
|
return "USER____" + this.handle.replace(/@/g, "_AT_").replace(/\./g, "_");
|
||||||
},
|
}
|
||||||
|
|
||||||
function makeCat (element) {
|
makeCat (element) {
|
||||||
if (!element) {
|
element = element || document;
|
||||||
element = document;
|
|
||||||
}
|
|
||||||
if (element.querySelectorAll) {
|
if (element.querySelectorAll) {
|
||||||
var posts = element.querySelectorAll("." + this.getClassName());
|
const posts = element.querySelectorAll("." + this.getClassName());
|
||||||
this.makeCatByClassName("user-info");
|
this.makeCatByClassName("user-info");
|
||||||
this.makeCatByClassName("basic-user-card", "basic-user-card-screen-name");
|
this.makeCatByClassName("basic-user-card");
|
||||||
for (const currentPost of posts) {
|
posts.forEach((currentPost) => {
|
||||||
this.makeCatByElement(currentPost);
|
this.makeCatByElement(currentPost);
|
||||||
this.nyaByPost(currentPost);
|
this.nyaByPost(currentPost);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
function makeCatByClassName (className, usernameClass) {
|
makeCatByClassName (className, usernameClass) {
|
||||||
if (!className) {
|
className = className || "user-info";
|
||||||
className = "user-info";
|
usernameClass = usernameClass || "user-screen-name";
|
||||||
}
|
const userInfos = document.querySelectorAll("." + className);
|
||||||
if (!usernameClass) {
|
userInfos.forEach((userInfo) => {
|
||||||
usernameClass = "user-screen-name";
|
if (userInfo.querySelector && !/cat$/.test(userInfo.innerText)) {
|
||||||
}
|
const handle = userInfo.querySelector("." + usernameClass);
|
||||||
const userinfos = document.querySelectorAll("." + className);
|
|
||||||
for (const infoIndex in userinfos) {
|
|
||||||
if (userinfos[infoIndex].querySelector && !/cat$/.test(userinfos[infoIndex].innerText)) {
|
|
||||||
const handle = userinfos[infoIndex].querySelector("." + usernameClass);
|
|
||||||
const regexHandle = new RegExp(this.handle, "i");
|
const regexHandle = new RegExp(this.handle, "i");
|
||||||
if (handle) {
|
if (handle) {
|
||||||
if (regexHandle.test(handle.innerText)) {
|
if (regexHandle.test(handle.innerText)) {
|
||||||
this.makeCatByElement(userinfos[infoIndex]);
|
this.makeCatByElement(userInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
function makeCatByElement (element) {
|
makeCatByElement (element) {
|
||||||
if (element.querySelectorAll) {
|
if (element.querySelectorAll) {
|
||||||
element.classList.add("catified");
|
element.classList.add("catified");
|
||||||
element.classList.add(this.type);
|
element.classList.add(this.type);
|
||||||
const avatars = element.querySelectorAll(".Avatar");
|
const avatars = element.querySelectorAll(".Avatar");
|
||||||
for (const avatarIndex in avatars) {
|
avatars.forEach((avatar) => {
|
||||||
const currentAvatar = avatars[avatarIndex];
|
if (avatar.style) {
|
||||||
if (currentAvatar.style) {
|
|
||||||
if (this.colors.borderColor === "#000000") {
|
if (this.colors.borderColor === "#000000") {
|
||||||
this.detectColors(currentAvatar);
|
this.detectColors(avatar);
|
||||||
}
|
}
|
||||||
currentAvatar.style.backgroundColor = this.colors.backgroundColor;
|
avatar.style.backgroundColor = this.colors.backgroundColor;
|
||||||
currentAvatar.style.borderColor = this.colors.borderColor;
|
avatar.style.borderColor = this.colors.borderColor;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
function nyaByPost (element) {
|
nyaByPost (element) {
|
||||||
if (element.querySelectorAll && this.config.nya.enabled && element.classList.contains("cat")) {
|
if (element.querySelectorAll && this.config.nya.enabled && element.classList.contains("cat")) {
|
||||||
const contents = element.querySelectorAll(".status-content");
|
const contents = element.querySelectorAll(".StatusContent");
|
||||||
for (const content of contents) {
|
contents.forEach((content) => {
|
||||||
if (content.innerHTML) {
|
if (content.innerHTML) {
|
||||||
const regex = new RegExp(this.config.nya.matcher, "g");
|
const regex = new RegExp(this.config.nya.matcher, "g");
|
||||||
let match;
|
let match;
|
||||||
|
@ -173,69 +168,75 @@ function PleromaCat (handle, type) {
|
||||||
content.innerHTML = content.innerHTML.replace(source, dest);
|
content.innerHTML = content.innerHTML.replace(source, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
function detectColors (avatarElement) {
|
detectColors (avatar) {
|
||||||
const images = avatarElement.querySelectorAll("img");
|
const images = avatar.querySelectorAll("img");
|
||||||
for (const imageIndex in images) {
|
images.forEach((image) => {
|
||||||
images[imageIndex].crossOrigin = "anonymous";
|
image.crossOrigin = "anonymous";
|
||||||
const colorAvatar = () => {
|
const colorAvatar = () => {
|
||||||
const detector = new ColorDetector(images[imageIndex]);
|
const detector = new ColorDetector(image);
|
||||||
detector.detect().then((color) => {
|
detector.detect().then((color) => {
|
||||||
this.colors.backgroundColor = detector.getHexColor();
|
this.colors.backgroundColor = detector.getHexColor();
|
||||||
this.colors.borderColor = detector.getHexColor({ r: -40, g: -40, b: -40 });
|
this.colors.borderColor = detector.getHexColor({ r: -40, g: -40, b: -40 });
|
||||||
avatarElement.style.backgroundColor = this.colors.backgroundColor;
|
avatar.style.backgroundColor = this.colors.backgroundColor;
|
||||||
avatarElement.style.borderColor = this.colors.borderColor;
|
avatar.style.borderColor = this.colors.borderColor;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
if (images[imageIndex].complete) {
|
|
||||||
|
if (image.complete) {
|
||||||
colorAvatar();
|
colorAvatar();
|
||||||
} else {
|
} else {
|
||||||
images[imageIndex].onload = colorAvatar;
|
image.onload = colorAvatar;
|
||||||
}
|
}
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
].forEach((fn) => { PleromaCat.prototype[fn.name] = fn; });
|
}
|
||||||
|
|
||||||
function PleromaModCatify () {
|
class PleromaModCatify extends PleromaMod {
|
||||||
this.animals = {};
|
constructor () {
|
||||||
this.config = {
|
super("pleroma-mod-catify");
|
||||||
stylesheet: "style.css",
|
this.animals = {};
|
||||||
triggers: {
|
this.config = {
|
||||||
cat: {
|
includes: {
|
||||||
displayName: [
|
css: [
|
||||||
"🐱",
|
"style.css"
|
||||||
"😺",
|
|
||||||
"🐈",
|
|
||||||
"😼",
|
|
||||||
"😹",
|
|
||||||
"にゃ",
|
|
||||||
"cat",
|
|
||||||
"mew",
|
|
||||||
"meow",
|
|
||||||
"nya",
|
|
||||||
"miaou",
|
|
||||||
"kitten",
|
|
||||||
"kitn",
|
|
||||||
"ktn",
|
|
||||||
"kadse",
|
|
||||||
"catte"
|
|
||||||
],
|
|
||||||
instances: [
|
|
||||||
"misskey.io"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
bear: {
|
triggers: {
|
||||||
displayName: [
|
cat: {
|
||||||
"🐻"
|
displayName: [
|
||||||
],
|
"🐱",
|
||||||
instances: []
|
"😺",
|
||||||
},
|
"🐈",
|
||||||
rabbit: {
|
"😼",
|
||||||
displayName: [
|
"😹",
|
||||||
|
"にゃ",
|
||||||
|
"cat",
|
||||||
|
"mew",
|
||||||
|
"meow",
|
||||||
|
"nya",
|
||||||
|
"miaou",
|
||||||
|
"kitten",
|
||||||
|
"kitn",
|
||||||
|
"ktn",
|
||||||
|
"kadse",
|
||||||
|
"catte"
|
||||||
|
],
|
||||||
|
instances: [
|
||||||
|
"misskey.io"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
bear: {
|
||||||
|
displayName: [
|
||||||
|
"🐻"
|
||||||
|
],
|
||||||
|
instances: []
|
||||||
|
},
|
||||||
|
rabbit: {
|
||||||
|
displayName: [
|
||||||
"🐰",
|
"🐰",
|
||||||
"🐇",
|
"🐇",
|
||||||
"rabbit",
|
"rabbit",
|
||||||
|
@ -243,65 +244,98 @@ function PleromaModCatify () {
|
||||||
"hase",
|
"hase",
|
||||||
"häschen",
|
"häschen",
|
||||||
"kaninchen"
|
"kaninchen"
|
||||||
],
|
],
|
||||||
instances: []
|
instances: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filter: [
|
nya: {
|
||||||
"user-info",
|
enabled: false
|
||||||
"timeline",
|
},
|
||||||
"Conversation",
|
filter: [
|
||||||
"panel-body",
|
"user-info",
|
||||||
"main",
|
"timeline",
|
||||||
"active",
|
"Conversation",
|
||||||
"status-body"
|
"panel-body",
|
||||||
]
|
"main",
|
||||||
};
|
"active",
|
||||||
|
"status-body"
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
this.loadConfig();
|
onSettingInit (key, ul, li) {
|
||||||
}
|
if (key === "nya") {
|
||||||
[
|
const label = document.createElement("label");
|
||||||
function loadConfig () {
|
label.classList.add("checkbox");
|
||||||
window.fetch(PleromaModLoader.getModDir() + "pleroma-mod-catify/config.json").then((response) => {
|
|
||||||
if (response.ok) {
|
|
||||||
response.json().then((json) => {
|
|
||||||
PleromaModCatify.config = json;
|
|
||||||
for (const type in json.triggers) {
|
|
||||||
this.config.triggers[type] = {};
|
|
||||||
this.config.triggers[type].displayName = json.triggers[type].displayName || [];
|
|
||||||
this.config.triggers[type].instances = json.triggers[type].instances || [];
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error("can't parse catify config");
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.warn("can't load catify config");
|
|
||||||
console.warn(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
function onMutation (mutation, observer) {
|
const input = document.createElement("input");
|
||||||
if (mutation.target.classList.contains("user-info")) {
|
input.setAttribute("type", "checkbox");
|
||||||
mutation.target.classList.remove("catified");
|
input.checked = this.config.nya.enabled;
|
||||||
for (const type in this.config.triggers) {
|
input.addEventListener("change", (event) => {
|
||||||
mutation.target.classList.remove(type);
|
if (event.target.checked) {
|
||||||
}
|
this.config.nya.enabled = true;
|
||||||
|
} else {
|
||||||
|
this.config.nya.enabled = false;
|
||||||
|
}
|
||||||
|
this.saveConfig();
|
||||||
|
});
|
||||||
|
label.appendChild(input);
|
||||||
|
|
||||||
|
const fakeCheckbox = document.createElement("i");
|
||||||
|
fakeCheckbox.classList.add("checkbox-indicator");
|
||||||
|
label.appendChild(fakeCheckbox);
|
||||||
|
|
||||||
|
const text = document.createElement("span");
|
||||||
|
text.classList.add("label");
|
||||||
|
text.innerText = "enable nyanification of posts";
|
||||||
|
label.appendChild(text);
|
||||||
|
|
||||||
|
li.appendChild(label);
|
||||||
|
ul.appendChild(li);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onConfigLoad () {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.fetchJson("config.json").then((json) => {
|
||||||
|
resolve(json);
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error("can't parse catify config");
|
||||||
|
console.error(error);
|
||||||
|
resolve({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMutation (mutation, observer) {
|
||||||
|
const component = PleromaModLoader.getVueComponent(mutation.target);
|
||||||
|
if (component) {
|
||||||
|
this.isCat(component.user);
|
||||||
|
}
|
||||||
|
mutation.addedNodes.forEach((node) => {
|
||||||
|
const nodeComp = PleromaModLoader.getVueComponent(node);
|
||||||
|
if (nodeComp) {
|
||||||
|
if (nodeComp.user) {
|
||||||
|
this.isCat(nodeComp.user);
|
||||||
|
}
|
||||||
|
if (nodeComp.status) {
|
||||||
|
this.isCat(nodeComp.status.user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
this.detectCats();
|
this.detectCats();
|
||||||
for (const element of mutation.addedNodes) {
|
for (const element of mutation.addedNodes) {
|
||||||
this.catify(element);
|
this.catify(element);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
function onReady () {
|
onRun () {
|
||||||
this.areYouACat();
|
this.areYouACat();
|
||||||
this.detectCats();
|
this.detectCats();
|
||||||
this.catify();
|
this.catify();
|
||||||
},
|
}
|
||||||
|
|
||||||
function onDestroy () {
|
onDestroy () {
|
||||||
const allCats = document.querySelectorAll(".catified");
|
const allCats = document.querySelectorAll(".catified");
|
||||||
for (const cat of allCats) {
|
for (const cat of allCats) {
|
||||||
cat.classList.remove("catified");
|
cat.classList.remove("catified");
|
||||||
|
@ -309,81 +343,83 @@ function PleromaModCatify () {
|
||||||
cat.classList.remove(type);
|
cat.classList.remove(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
function run () {
|
addCat (handle, type) {
|
||||||
PleromaModLoader.includeModCss("pleroma-mod-catify/" + this.config.stylesheet);
|
|
||||||
},
|
|
||||||
|
|
||||||
function addCat (handle, type) {
|
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
type = "cat";
|
type = "cat";
|
||||||
}
|
}
|
||||||
handle = handle.trim();
|
handle = handle.trim();
|
||||||
if (!this.animals[handle]) {
|
if (!this.animals[handle]) {
|
||||||
this.animals[handle] = new PleromaCat(handle, type);
|
this.animals[handle] = new PleromaCat(handle, type, this.config);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
function areYouACat () {
|
isCat (user) {
|
||||||
const profile = document.querySelector(".user-card");
|
if (!user) {
|
||||||
for (const type in this.config.triggers) {
|
return false;
|
||||||
|
}
|
||||||
|
let result = false;
|
||||||
|
Object.keys(this.config.triggers).forEach((type) => {
|
||||||
const pattern = this.config.triggers[type].displayName.join("|");
|
const pattern = this.config.triggers[type].displayName.join("|");
|
||||||
const regex = new RegExp(pattern, "i");
|
const regex = new RegExp(pattern, "i");
|
||||||
if (profile) {
|
if (regex.test(user.name)) {
|
||||||
const username = profile.querySelector(".user-name");
|
this.addCat(user.screen_name, type);
|
||||||
if (username) {
|
result = true;
|
||||||
if (regex.test(username.innerText)) {
|
return;
|
||||||
const accountName = profile.querySelector(".user-screen-name");
|
|
||||||
if (accountName) {
|
|
||||||
this.addCat(accountName.innerText.substring(1), type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if (regex.test(user.screen_name)) {
|
||||||
},
|
this.addCat(user.screen_name, type);
|
||||||
|
result = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
user.fields.forEach((field) => {
|
||||||
|
if (regex.test(field.name) || regex.test(field.value)) {
|
||||||
|
this.addCat(user.screen_name, type);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function detectCatsByClassName (classname, usernameClass, accountnameClass) {
|
areYouACat () {
|
||||||
|
const profile = document.querySelector(".user-card");
|
||||||
|
const cmp = PleromaModLoader.getVueComponent(profile);
|
||||||
|
if (cmp) {
|
||||||
|
this.isCat(cmp.user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
detectCatsByClassName (classname) {
|
||||||
classname = classname || "status-container";
|
classname = classname || "status-container";
|
||||||
usernameClass = usernameClass || "status-username";
|
const hits = document.querySelectorAll("." + classname);
|
||||||
accountnameClass = accountnameClass || "account-name";
|
hits.forEach((hit) => {
|
||||||
const nameAndAccountNames = document.querySelectorAll("." + classname);
|
if (hit.classList.contains("catified")) {
|
||||||
for (const type in this.config.triggers) {
|
return;
|
||||||
const regexName = new RegExp(this.config.triggers[type].displayName.join("|"), "i");
|
}
|
||||||
const regexInstance = new RegExp(this.config.triggers[type].instances.join("|"), "i");
|
const cmp = PleromaModLoader.getVueComponent(hit);
|
||||||
for (const currentAccount of nameAndAccountNames) {
|
if (cmp) {
|
||||||
if (currentAccount.querySelector) {
|
if (cmp.user) {
|
||||||
let isCat = false;
|
this.isCat(cmp.user);
|
||||||
const username = currentAccount.querySelector("." + usernameClass);
|
}
|
||||||
if (username && this.config.triggers[type].displayName.length > 0) {
|
if (cmp.status) {
|
||||||
isCat = regexName.test(username.innerText);
|
this.isCat(cmp.status.user);
|
||||||
}
|
|
||||||
const account = currentAccount.querySelector("." + accountnameClass);
|
|
||||||
if (account) {
|
|
||||||
const handle = account.innerText;
|
|
||||||
if (this.config.triggers[type].instances.length > 0) {
|
|
||||||
isCat = isCat || regexInstance.test(handle);
|
|
||||||
}
|
|
||||||
if (isCat) {
|
|
||||||
this.addCat(handle, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
function detectCats () {
|
detectCats () {
|
||||||
this.detectCatsByClassName("status-container");
|
this.detectCatsByClassName("status-container");
|
||||||
this.detectCatsByClassName("basic-user-card", "basic-user-card-user-name-value", "basic-user-card-screen-name");
|
this.detectCatsByClassName("basic-user-card");
|
||||||
},
|
}
|
||||||
|
|
||||||
function catify (element) {
|
catify (element) {
|
||||||
for (const catKey in this.animals) {
|
for (const catKey in this.animals) {
|
||||||
this.animals[catKey].makeCat(element);
|
this.animals[catKey].makeCat(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
].forEach((fn) => { PleromaModCatify.prototype[fn.name] = fn; });
|
}
|
||||||
|
|
||||||
PleromaModLoader.registerMod(PleromaModCatify);
|
PleromaModLoader.registerMod(PleromaModCatify);
|
||||||
|
|
|
@ -1,80 +1,78 @@
|
||||||
function PleromaModLoader () {
|
class PleromaModLoader {
|
||||||
this.config = {
|
constructor () {
|
||||||
"modDirectory": "/instance/pleroma-mods/",
|
this.config = {
|
||||||
"mods": []
|
"modDirectory": "/instance/pleroma-mods/",
|
||||||
};
|
"mods": []
|
||||||
this.loadConfig();
|
};
|
||||||
this.loadedMods = {};
|
this.loadConfig();
|
||||||
this.classes = {};
|
this.loadedMods = {};
|
||||||
}
|
this.classes = {};
|
||||||
[
|
}
|
||||||
function loadMods () {
|
|
||||||
for (const mod of this.config.mods) {
|
|
||||||
const modObject = new PleromaMod(mod);
|
|
||||||
modObject.enabled = true;
|
|
||||||
if (localStorage.getItem("pleroma_mod_" + mod + "_enabled") === "false") {
|
|
||||||
modObject.enabled = false;
|
|
||||||
}
|
|
||||||
localStorage.setItem("pleroma_mod_" + mod + "_enabled", modObject.enabled);
|
|
||||||
modObject.include();
|
|
||||||
this.loadedMods[mod] = modObject;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
function loadConfig () {
|
loadMods () {
|
||||||
window.fetch("/instance/pleroma-mod-config.json").then((response) => {
|
this.config.mods.forEach((mod) => {
|
||||||
if (response.ok) {
|
this.loadMod(mod);
|
||||||
response.json().then((json) => {
|
|
||||||
for (const key in json) {
|
|
||||||
this.config[key] = json[key];
|
|
||||||
}
|
|
||||||
this.loadMods();
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error("can't parse loader config");
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.warn("can't load mod loader config");
|
|
||||||
console.warn(error);
|
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
function registerClass (className, object) {
|
loadMod (modName) {
|
||||||
|
return PleromaModLoader.includeScript(
|
||||||
|
this.config.modDirectory + "pleroma-mod-" + modName + "/mod.js"
|
||||||
|
).then(() => {
|
||||||
|
this.loadedMods[modName] = new this.classes[PleromaModLoader.getClassName(modName)]();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadConfig () {
|
||||||
|
window.fetch("/instance/pleroma-mod-config.json").then((response) => {
|
||||||
|
return response.json();
|
||||||
|
}).then((json) => {
|
||||||
|
Object.keys(json).forEach((key) => {
|
||||||
|
this.config[key] = json[key];
|
||||||
|
});
|
||||||
|
this.loadMods();
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error("can't load loader config");
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
registerClass (className, object) {
|
||||||
this.classes[className] = object;
|
this.classes[className] = object;
|
||||||
},
|
}
|
||||||
|
|
||||||
function waitUntilReady () {
|
waitUntilReady () {
|
||||||
const postPanel = document.getElementsByClassName("post-status-form");
|
const postPanel = document.querySelector(".status-container");
|
||||||
const loginPanel = document.getElementsByClassName("login-form");
|
const loginPanel = document.querySelector(".login-form");
|
||||||
if (postPanel.length > 0 || loginPanel.length > 0) {
|
if (postPanel || loginPanel) {
|
||||||
for (var modName in this.loadedMods) {
|
Object.keys(this.loadedMods).forEach((modName) => {
|
||||||
const settings = document.querySelector(".settings div[label]:first-child");
|
const settings = document.querySelector(".settings-modal div[label]:first-child");
|
||||||
if (settings) {
|
if (settings) {
|
||||||
if (!settings.querySelector(".mod-settings")) {
|
if (!settings.querySelector(".mod-settings")) {
|
||||||
this.appendModSettings(settings);
|
this.appendModSettings(settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = this.loadedMods[modName];
|
const mod = this.loadedMods[modName];
|
||||||
if (mod.enabled && mod.instance) {
|
if (mod.isEnabled) {
|
||||||
if (mod.instance.onReady) {
|
mod.ready();
|
||||||
mod.instance.onReady();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
this.createObserver();
|
this.createObserver();
|
||||||
} else {
|
} else {
|
||||||
|
console.warn("not ready, trying again in 1s");
|
||||||
window.setTimeout(() => { this.waitUntilReady(); }, 1000);
|
window.setTimeout(() => { this.waitUntilReady(); }, 1000);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
function createCheckbox (label, mod) {
|
createCheckbox (label, mod) {
|
||||||
const labelElement = document.createElement("label");
|
const labelElement = document.createElement("label");
|
||||||
labelElement.classList.add("checkbox");
|
labelElement.classList.add("checkbox");
|
||||||
|
|
||||||
const input = document.createElement("input");
|
const input = document.createElement("input");
|
||||||
input.setAttribute("type", "checkbox");
|
input.setAttribute("type", "checkbox");
|
||||||
input.checked = mod.enabled;
|
input.checked = mod.isEnabled;
|
||||||
input.addEventListener("change", (event) => {
|
input.addEventListener("change", (event) => {
|
||||||
if (event.target.checked) {
|
if (event.target.checked) {
|
||||||
mod.enable();
|
mod.enable();
|
||||||
|
@ -91,41 +89,51 @@ function PleromaModLoader () {
|
||||||
const text = document.createElement("span");
|
const text = document.createElement("span");
|
||||||
text.classList.add("label");
|
text.classList.add("label");
|
||||||
text.innerText = label;
|
text.innerText = label;
|
||||||
|
|
||||||
labelElement.appendChild(text);
|
labelElement.appendChild(text);
|
||||||
|
|
||||||
return labelElement;
|
return labelElement;
|
||||||
},
|
}
|
||||||
|
|
||||||
function appendModSettings (element) {
|
appendModSettings (element) {
|
||||||
const container = document.createElement("div");
|
const container = document.createElement("div");
|
||||||
container.classList.add("setting-item");
|
container.classList.add("setting-item");
|
||||||
container.classList.add("mod-settings");
|
container.classList.add("mod-settings");
|
||||||
|
|
||||||
const title = document.createElement("h2");
|
const title = document.createElement("h2");
|
||||||
title.innerText = "Mods";
|
title.innerText = "Pleroma Mods";
|
||||||
container.appendChild(title);
|
container.appendChild(title);
|
||||||
|
|
||||||
const optionList = document.createElement("ul");
|
const optionList = document.createElement("ul");
|
||||||
optionList.classList.add("setting-list");
|
optionList.classList.add("setting-list");
|
||||||
|
|
||||||
const modNames = Object.keys(this.loadedMods).sort();
|
Object.keys(this.loadedMods).sort().forEach((modName) => {
|
||||||
for (const mod of modNames) {
|
|
||||||
const li = document.createElement("li");
|
const li = document.createElement("li");
|
||||||
|
|
||||||
const enable = this.createCheckbox("enable " + mod, this.loadedMods[mod]);
|
const enable = this.createCheckbox("enable " + modName, this.loadedMods[modName]);
|
||||||
|
|
||||||
li.appendChild(enable);
|
li.appendChild(enable);
|
||||||
|
|
||||||
|
const ulConfig = document.createElement("ul");
|
||||||
|
ulConfig.classList.add("setting-list");
|
||||||
|
|
||||||
|
Object.keys(this.loadedMods[modName].config).forEach((key) => {
|
||||||
|
if (key === "includes" || key === "filter") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadedMods[modName].onSettingInit(key, ulConfig, document.createElement("li"));
|
||||||
|
});
|
||||||
|
|
||||||
|
li.appendChild(ulConfig);
|
||||||
|
|
||||||
optionList.appendChild(li);
|
optionList.appendChild(li);
|
||||||
}
|
});
|
||||||
|
|
||||||
container.appendChild(optionList);
|
container.appendChild(optionList);
|
||||||
|
|
||||||
element.appendChild(container);
|
element.appendChild(container);
|
||||||
},
|
}
|
||||||
|
|
||||||
function createObserver () {
|
createObserver () {
|
||||||
this.containers = {
|
this.containers = {
|
||||||
main: document.querySelector(".main"),
|
main: document.querySelector(".main"),
|
||||||
notifications: document.querySelector(".notifications"),
|
notifications: document.querySelector(".notifications"),
|
||||||
|
@ -133,33 +141,26 @@ function PleromaModLoader () {
|
||||||
settingsModal: document.querySelector(".settings-modal")
|
settingsModal: document.querySelector(".settings-modal")
|
||||||
};
|
};
|
||||||
|
|
||||||
const observerConfig = { subtree: true, childList: true };
|
const observerConfig = {
|
||||||
|
subtree: true,
|
||||||
|
childList: true
|
||||||
|
};
|
||||||
|
|
||||||
this.observer = new MutationObserver((mutations, observer) => {
|
this.observer = new MutationObserver((mutations, observer) => {
|
||||||
if (
|
const modal = document.querySelector(".settings-modal div[label]:first-child");
|
||||||
mutations.length > 0 &&
|
if (modal && !modal.querySelector(".mod-settings")) {
|
||||||
mutations[0].addedNodes.length > 0 &&
|
this.appendModSettings(modal);
|
||||||
mutations[0].addedNodes[0].classList &&
|
|
||||||
mutations[0].addedNodes[0].classList.contains("settings_tab-switcher")
|
|
||||||
) {
|
|
||||||
this.appendModSettings(mutations[0].addedNodes[0].querySelector("div[label]:first-child"));
|
|
||||||
}
|
}
|
||||||
for (var modName in this.loadedMods) {
|
|
||||||
const mod = this.loadedMods[modName];
|
Object.values(this.loadedMods).forEach((mod) => {
|
||||||
if (mod.instance && mod.enabled) {
|
if (mod.isEnabled) {
|
||||||
if (mod.instance.onMutation) {
|
mutations.forEach((mutation) => {
|
||||||
for (const mutation of mutations) {
|
mod.mutate(mutation, observer);
|
||||||
let filter = null;
|
});
|
||||||
if (mod.instance.config.filter) {
|
|
||||||
filter = new RegExp(mod.instance.config.filter.join("|"));
|
|
||||||
}
|
|
||||||
if (!filter || filter.test(mutation.target.className)) {
|
|
||||||
mod.instance.onMutation(mutation, observer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.observer.observe(this.containers.main, observerConfig);
|
this.observer.observe(this.containers.main, observerConfig);
|
||||||
if (this.containers.notifications) {
|
if (this.containers.notifications) {
|
||||||
this.observer.observe(this.containers.notifications, observerConfig);
|
this.observer.observe(this.containers.notifications, observerConfig);
|
||||||
|
@ -171,155 +172,306 @@ function PleromaModLoader () {
|
||||||
this.observer.observe(this.containers.settingsModal, observerConfig);
|
this.observer.observe(this.containers.settingsModal, observerConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
].forEach((fn) => { PleromaModLoader.prototype[fn.name] = fn; });
|
|
||||||
[
|
static registerMod (mod) {
|
||||||
function registerMod (mod) {
|
|
||||||
window.__pleromaModLoader.registerClass(mod.name, mod);
|
window.__pleromaModLoader.registerClass(mod.name, mod);
|
||||||
},
|
}
|
||||||
|
|
||||||
function includeModScript (src) {
|
static includeScript (src) {
|
||||||
return PleromaModLoader.includeScript(window.__pleromaModLoader.config.modDirectory + src);
|
console.log("include " + src);
|
||||||
},
|
|
||||||
|
|
||||||
function includeModCss (src) {
|
|
||||||
return PleromaModLoader.includeCss(window.__pleromaModLoader.config.modDirectory + src);
|
|
||||||
},
|
|
||||||
|
|
||||||
function excludeModScript (src) {
|
|
||||||
return PleromaModLoader.excludeScript(window.__pleromaModLoader.config.modDirectory + src);
|
|
||||||
},
|
|
||||||
|
|
||||||
function excludeModCss (src) {
|
|
||||||
return PleromaModLoader.excludeCss(window.__pleromaModLoader.config.modDirectory + src);
|
|
||||||
},
|
|
||||||
|
|
||||||
function includeScript (src) {
|
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const body = document.getElementsByTagName("body")[0];
|
|
||||||
const script = document.createElement("script");
|
const script = document.createElement("script");
|
||||||
script.setAttribute("src", src);
|
script.setAttribute("src", src);
|
||||||
script.setAttribute("type", "text/javascript");
|
script.setAttribute("type", "text/javascript");
|
||||||
script.onload = () => { resolve(); };
|
script.onload = () => {
|
||||||
body.appendChild(script);
|
resolve();
|
||||||
|
};
|
||||||
|
document.querySelector("body").appendChild(script);
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
function getVueScope (element) {
|
static includeCss (src) {
|
||||||
|
console.log("include " + src);
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const link = document.createElement("link");
|
||||||
|
link.setAttribute("href", src);
|
||||||
|
link.setAttribute("rel", "stylesheet");
|
||||||
|
link.setAttribute("type", "text/css");
|
||||||
|
link.onload = () => {
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
document.querySelector("head").appendChild(link);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static excludeScript (src) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const script = document.querySelector("script[src=\"" + src + "\"]");
|
||||||
|
if (script) {
|
||||||
|
script.remove();
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static excludeCss (src) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const link = document.querySelector("link[href=\"" + src + "\"]");
|
||||||
|
if (link) {
|
||||||
|
link.remove();
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static getVueScope (element) {
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (element.__vue__) {
|
if (element.__vue__) {
|
||||||
|
console.warn("old vue version, please update pleroma-fe");
|
||||||
return element.__vue__;
|
return element.__vue__;
|
||||||
}
|
}
|
||||||
|
if (element._vnode) {
|
||||||
|
return element._vnode;
|
||||||
|
}
|
||||||
|
if (element.__vnode) {
|
||||||
|
return element.__vnode;
|
||||||
|
}
|
||||||
if (element.parentNode) {
|
if (element.parentNode) {
|
||||||
return PleromaModLoader.getVueScope(element.parentNode);
|
return PleromaModLoader.getVueScope(element.parentNode);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
}
|
||||||
|
|
||||||
function getRootVueScope () {
|
static getVueComponent (element) {
|
||||||
return document.querySelector("#app").__vue__;
|
if (!element) {
|
||||||
},
|
return null;
|
||||||
|
}
|
||||||
|
if (element.__vnode && element.__vnode.component) {
|
||||||
|
return element.__vnode.component;
|
||||||
|
}
|
||||||
|
if (element.__vueParentComponent) {
|
||||||
|
return element.__vueParentComponent.ctx;
|
||||||
|
}
|
||||||
|
if (element.__vueComponent__) {
|
||||||
|
return element.__vueComponent__;
|
||||||
|
}
|
||||||
|
if (element.parentNode) {
|
||||||
|
return PleromaModLoader.getVueComponent(element.parentNode);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function includeCss (src) {
|
static getRootVueScope () {
|
||||||
return new Promise((resolve) => {
|
return PleromaModLoader.getVueScope(document.querySelector("#app"));
|
||||||
const head = document.getElementsByTagName("head")[0];
|
}
|
||||||
const link = document.createElement("link");
|
|
||||||
link.setAttribute("href", src);
|
|
||||||
link.setAttribute("rel", "stylesheet");
|
|
||||||
link.setAttribute("type", "text/css");
|
|
||||||
link.onload = () => { resolve(); };
|
|
||||||
head.appendChild(link);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
function excludeScript (src) {
|
static getToken () {
|
||||||
return new Promise((resolve) => {
|
return PleromaModLoader.getRootVueScope().appContext.provides.store.getters.getUserToken();
|
||||||
const script = document.querySelector('script[src="' + src + '"]');
|
}
|
||||||
if(script) {
|
|
||||||
script.remove();
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
function excludeCss (src) {
|
static getModDir () {
|
||||||
return new Promise((resolve) => {
|
|
||||||
const link = document.querySelector('link[href="' + src + '"]');
|
|
||||||
if(link) {
|
|
||||||
link.remove();
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
function getToken () {
|
|
||||||
return PleromaModLoader.getRootVueScope().$store._vm.getUserToken();
|
|
||||||
},
|
|
||||||
|
|
||||||
function getModDir () {
|
|
||||||
return window.__pleromaModLoader.config.modDirectory;
|
return window.__pleromaModLoader.config.modDirectory;
|
||||||
}
|
}
|
||||||
].forEach((fn) => { PleromaModLoader[fn.name] = fn; });
|
|
||||||
|
|
||||||
function PleromaMod (name) {
|
static getClassName (name) {
|
||||||
this.name = name;
|
|
||||||
this.instance = null;
|
|
||||||
this.enabled = localStorage.getItem("pleroma_mod_" + this.name + "_enabled") !== "false";
|
|
||||||
}
|
|
||||||
[
|
|
||||||
function getClassName () {
|
|
||||||
let className = "PleromaMod";
|
let className = "PleromaMod";
|
||||||
const nameParts = this.name.split("-");
|
name.split("-").forEach((namePart) => {
|
||||||
for (const namePart of nameParts) {
|
|
||||||
className += namePart.substring(0, 1).toUpperCase();
|
className += namePart.substring(0, 1).toUpperCase();
|
||||||
className += namePart.substring(1);
|
className += namePart.substring(1);
|
||||||
}
|
|
||||||
return className;
|
|
||||||
},
|
|
||||||
|
|
||||||
function enable () {
|
|
||||||
this.enabled = true;
|
|
||||||
this.modLoaded();
|
|
||||||
if (this.instance.onReady) {
|
|
||||||
this.instance.onReady();
|
|
||||||
}
|
|
||||||
localStorage.setItem("pleroma_mod_" + this.name + "_enabled", this.enabled);
|
|
||||||
},
|
|
||||||
|
|
||||||
function disable () {
|
|
||||||
this.enabled = false;
|
|
||||||
if (this.instance.onDestroy) {
|
|
||||||
this.instance.onDestroy();
|
|
||||||
}
|
|
||||||
console.log(this.name + " unloaded");
|
|
||||||
this.instance = null;
|
|
||||||
localStorage.setItem("pleroma_mod_" + this.name + "_enabled", this.enabled);
|
|
||||||
},
|
|
||||||
|
|
||||||
function include () {
|
|
||||||
console.log("loading " + this.name);
|
|
||||||
PleromaModLoader.includeScript(
|
|
||||||
PleromaModLoader.getModDir() + "pleroma-mod-" + this.name + "/mod.js"
|
|
||||||
).then(() => {
|
|
||||||
if (this.enabled) {
|
|
||||||
this.modLoaded();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
function modLoaded () {
|
static api (method, path, params) {
|
||||||
console.log(this.name + " loaded");
|
return new Promise((resolve, reject) => {
|
||||||
this.instance = new window.__pleromaModLoader.classes[this.getClassName()]();
|
const token = PleromaModLoader.getToken();
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.responseType = "json";
|
||||||
|
xhr.open(method, path);
|
||||||
|
xhr.setRequestHeader("Content-Type", "application/json");
|
||||||
|
xhr.setRequestHeader("Authorization", "Bearer " + token);
|
||||||
|
xhr.onreadstatechange = () => {
|
||||||
|
if (xhr.readyState === 4) {
|
||||||
|
if (xhr.status !== 200) {
|
||||||
|
reject(new Error({
|
||||||
|
status: xhr.status,
|
||||||
|
response: xhr.response,
|
||||||
|
xhr: xhr
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onload = () => {
|
||||||
|
resolve(xhr.response);
|
||||||
|
};
|
||||||
|
xhr.send(JSON.stringify(params));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PleromaMod { // eslint-disable-line no-unused-vars
|
||||||
|
constructor (name) {
|
||||||
|
this.name = name;
|
||||||
|
this.config = {};
|
||||||
|
this.isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isEnabled () {
|
||||||
|
return localStorage.getItem("pleroma_mod_" + this.name + "_enabled") !== "false" || true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getClassName () {
|
||||||
|
return PleromaModLoader.getClassName(this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
getModDir () {
|
||||||
|
return PleromaModLoader.getModDir() + this.name + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
ready () {
|
||||||
|
this.onReady();
|
||||||
this.run();
|
this.run();
|
||||||
},
|
}
|
||||||
|
|
||||||
function run () {
|
destroy () {
|
||||||
if (this.instance) {
|
this.isRunning = false;
|
||||||
this.instance.run();
|
if (this.config.includes) {
|
||||||
|
const styles = this.config.includes.css || [];
|
||||||
|
const scripts = this.config.includes.js || [];
|
||||||
|
|
||||||
|
Promise.all(styles.map((style) => {
|
||||||
|
return this.excludeCss(style);
|
||||||
|
}).concat(scripts.map((script) => {
|
||||||
|
return this.excludeScript(script);
|
||||||
|
}))).then(() => {
|
||||||
|
this.onDestroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
run () {
|
||||||
|
if (this.config.includes) {
|
||||||
|
const styles = this.config.includes.css || [];
|
||||||
|
const scripts = this.config.includes.js || [];
|
||||||
|
|
||||||
|
Promise.all(styles.map((style) => {
|
||||||
|
return this.includeCss(style);
|
||||||
|
}).concat(scripts.map((script) => {
|
||||||
|
return this.includeScript(script);
|
||||||
|
})).concat([
|
||||||
|
this.loadConfig(),
|
||||||
|
this.onCreate()
|
||||||
|
])).then(() => {
|
||||||
|
this.isRunning = true;
|
||||||
|
this.onRun();
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isRunning = true;
|
||||||
|
this.onRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
mutate (mutation, observer) {
|
||||||
|
if (this.isRunning) {
|
||||||
|
this.onMutation(mutation, observer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
].forEach((fn) => { PleromaMod.prototype[fn.name] = fn; });
|
|
||||||
|
saveConfig () {
|
||||||
|
const storedConfig = {};
|
||||||
|
Object.keys(this.config).filter((key) => {
|
||||||
|
return key !== "includes" && key !== "filter";
|
||||||
|
}).forEach((key) => {
|
||||||
|
storedConfig[key] = this.config[key];
|
||||||
|
});
|
||||||
|
localStorage.setItem(this.name + "_config", JSON.stringify(storedConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeConfig (newConfig) {
|
||||||
|
Object.keys(newConfig).forEach((key) => {
|
||||||
|
this.config[key] = JSON.parse(JSON.stringify(newConfig[key]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadConfig () {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
// TODO: use structuredClone when its more supported
|
||||||
|
this.defaultConfig = JSON.parse(JSON.stringify(this.config));
|
||||||
|
|
||||||
|
const storedConfig = JSON.parse(localStorage.getItem(this.name + "_config"));
|
||||||
|
|
||||||
|
this.onConfigLoad().then((json) => {
|
||||||
|
this.mergeConfig(json);
|
||||||
|
if (storedConfig) {
|
||||||
|
this.mergeConfig(storedConfig);
|
||||||
|
}
|
||||||
|
this.saveConfig();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onReady () {}
|
||||||
|
onCreate () {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onDestroy () {}
|
||||||
|
onRun () {}
|
||||||
|
onMutation (mutation, observer) {}
|
||||||
|
onConfigLoad () {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
resolve({});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onSettingInit (key, ul, li) {}
|
||||||
|
|
||||||
|
includeCss (src) {
|
||||||
|
return PleromaModLoader.includeCss(PleromaModLoader.getModDir() + this.name + "/" + src);
|
||||||
|
}
|
||||||
|
|
||||||
|
includeScript (src) {
|
||||||
|
return PleromaModLoader.includeScript(PleromaModLoader.getModDir() + this.name + "/" + src);
|
||||||
|
}
|
||||||
|
|
||||||
|
excludeCss (src) {
|
||||||
|
return PleromaModLoader.excludeCss(PleromaModLoader.getModDir() + this.name + "/" + src);
|
||||||
|
}
|
||||||
|
|
||||||
|
excludeScript (src) {
|
||||||
|
return PleromaModLoader.excludeScript(PleromaModLoader.getModDir() + this.name + "/" + src);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchJson (src) {
|
||||||
|
console.log("loading " + src);
|
||||||
|
return window.fetch(PleromaModLoader.getModDir() + this.name + "/" + src).then((response) => {
|
||||||
|
return response.json();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
api (method, path, params) {
|
||||||
|
return PleromaModLoader.api(method, path, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
enable () {
|
||||||
|
this.ready();
|
||||||
|
localStorage.setItem("pleroma_mod_" + this.name + "_enabled", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
disable () {
|
||||||
|
this.destroy();
|
||||||
|
localStorage.setItem("pleroma_mod_" + this.name + "_enabled", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window.__pleromaModLoader = new PleromaModLoader();
|
window.__pleromaModLoader = new PleromaModLoader();
|
||||||
window.__pleromaModLoader.waitUntilReady();
|
window.__pleromaModLoader.waitUntilReady();
|
||||||
|
|
Loading…
Reference in New Issue