mirror of
https://github.com/plantroon/mx-puppet-xmpp.git
synced 2024-11-14 15:31:40 +00:00
update stuffs, user profile updates should work now
This commit is contained in:
parent
416df718bd
commit
dc333129da
17
package-lock.json
generated
17
package-lock.json
generated
@ -2511,6 +2511,11 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz",
|
||||
"integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4="
|
||||
},
|
||||
"lodash.toarray": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
|
||||
"integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE="
|
||||
},
|
||||
"logform": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz",
|
||||
@ -2863,6 +2868,14 @@
|
||||
"semver": "^5.4.1"
|
||||
}
|
||||
},
|
||||
"node-emoji": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz",
|
||||
"integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==",
|
||||
"requires": {
|
||||
"lodash.toarray": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node-html-parser": {
|
||||
"version": "1.2.13",
|
||||
"resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-1.2.13.tgz",
|
||||
@ -3606,8 +3619,8 @@
|
||||
}
|
||||
},
|
||||
"skype-http": {
|
||||
"version": "git://github.com/Sorunome/skype-http.git#10555125f46307bbff93a8c4779889f4100669d2",
|
||||
"from": "git://github.com/Sorunome/skype-http.git#10555125f46307bbff93a8c4779889f4100669d2",
|
||||
"version": "git://github.com/Sorunome/skype-http.git#e8a92f8bc4929443bbba9755b6dd1ce90026bf4e",
|
||||
"from": "git://github.com/Sorunome/skype-http.git#e8a92f8bc4929443bbba9755b6dd1ce90026bf4e",
|
||||
"requires": {
|
||||
"@types/cheerio": "^0.22.12",
|
||||
"@types/escape-html": "0.0.20",
|
||||
|
@ -11,6 +11,7 @@
|
||||
},
|
||||
"author": "Sorunome",
|
||||
"dependencies": {
|
||||
"cheerio": "^1.0.0-rc.3",
|
||||
"command-line-args": "^5.1.1",
|
||||
"command-line-usage": "^5.0.5",
|
||||
"decode-html": "^2.0.0",
|
||||
@ -18,8 +19,9 @@
|
||||
"events": "^3.0.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"mx-puppet-bridge": "0.0.35-1",
|
||||
"node-emoji": "^1.10.0",
|
||||
"node-html-parser": "^1.2.13",
|
||||
"skype-http": "git://github.com/Sorunome/skype-http#10555125f46307bbff93a8c4779889f4100669d2",
|
||||
"skype-http": "git://github.com/Sorunome/skype-http#e8a92f8bc4929443bbba9755b6dd1ce90026bf4e",
|
||||
"tslint": "^5.17.0",
|
||||
"typescript": "^3.7.4"
|
||||
},
|
||||
|
169
src/client.ts
169
src/client.ts
@ -20,13 +20,18 @@ import { Context as SkypeContext } from "skype-http/dist/lib/interfaces/api/cont
|
||||
|
||||
const log = new Log("SkypePuppet:client");
|
||||
|
||||
// tslint:disable no-magic-numbers
|
||||
const ID_TIMEOUT = 60000;
|
||||
const CONTACTS_DELTA_INTERVAL = 5 * 60 * 1000;
|
||||
// tslint:enable no-magic-numbers
|
||||
|
||||
export class Client extends EventEmitter {
|
||||
public contacts: Map<string, SkypeContact | null> = new Map();
|
||||
public conversations: Map<string, skypeHttp.Conversation | null> = new Map();
|
||||
private api: skypeHttp.Api;
|
||||
private handledIds: ExpireSet<string>;
|
||||
private lastContactsDate: Date = new Date();
|
||||
private contactsInterval: NodeJS.Timeout | null = null;
|
||||
constructor(
|
||||
private loginUsername: string,
|
||||
private password: string,
|
||||
@ -46,7 +51,7 @@ export class Client extends EventEmitter {
|
||||
|
||||
public async connect() {
|
||||
let connectedWithAuth = false;
|
||||
if (this.state && false) {
|
||||
if (this.state) {
|
||||
try {
|
||||
this.api = await skypeHttp.connect({ state: this.state, verbose: true });
|
||||
connectedWithAuth = true;
|
||||
@ -71,63 +76,52 @@ export class Client extends EventEmitter {
|
||||
connectedWithAuth = false;
|
||||
}
|
||||
|
||||
this.api.on("event", (evt: skypeHttp.events.EventMessage) => {
|
||||
if (!evt || !evt.resource) {
|
||||
return;
|
||||
}
|
||||
const resource = evt.resource;
|
||||
if (this.handledIds.has(resource.id)) {
|
||||
return;
|
||||
}
|
||||
this.handledIds.add(resource.id);
|
||||
log.debug(`Got new event of type ${resource.type}`);
|
||||
const [type, subtype] = resource.type.split("/");
|
||||
switch (type) {
|
||||
case "Text":
|
||||
this.emit("text", resource);
|
||||
break;
|
||||
case "RichText":
|
||||
if (subtype === "Location") {
|
||||
this.emit("location", resource);
|
||||
} else if (subtype) {
|
||||
this.emit("file", resource);
|
||||
} else {
|
||||
this.emit("richText", resource);
|
||||
}
|
||||
break;
|
||||
case "Control":
|
||||
if (subtype === "Typing" || subtype === "ClearTyping") {
|
||||
this.emit("typing", resource, subtype === "Typing");
|
||||
}
|
||||
break;
|
||||
case "ThreadActivity":
|
||||
if (subtype === "MemberConsumptionHorizonUpdate") {
|
||||
this.emit("presence", resource);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
this.api.on("error", (err: Error) => {
|
||||
log.error("An error occured", err);
|
||||
this.emit("error", err);
|
||||
});
|
||||
|
||||
const contacts = await this.api.getContacts();
|
||||
for (const contact of contacts) {
|
||||
this.contacts.set(contact.mri, contact);
|
||||
}
|
||||
const conversations = await this.api.getConversations();
|
||||
for (const conversation of conversations) {
|
||||
this.conversations.set(conversation.id, conversation);
|
||||
}
|
||||
await this.startupApi();
|
||||
|
||||
await this.api.listen();
|
||||
await this.api.setStatus("Online");
|
||||
if (connectedWithAuth) {
|
||||
let resolved = false;
|
||||
return new Promise((resolve, reject) => {
|
||||
const TIMEOUT_SUCCESS = 5000;
|
||||
setTimeout(() => {
|
||||
if (resolved) {
|
||||
return;
|
||||
}
|
||||
resolved = true;
|
||||
resolve();
|
||||
}, TIMEOUT_SUCCESS);
|
||||
this.api.once("error", async () => {
|
||||
if (resolved) {
|
||||
return;
|
||||
}
|
||||
resolved = true;
|
||||
// alright, re-try as normal user
|
||||
try {
|
||||
await this.api.stopListening();
|
||||
this.api = await skypeHttp.connect({
|
||||
credentials: {
|
||||
username: this.loginUsername,
|
||||
password: this.password,
|
||||
},
|
||||
verbose: true,
|
||||
});
|
||||
await this.startupApi();
|
||||
resolve();
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async disconnect() {
|
||||
await this.api.stopListening();
|
||||
if (this.contactsInterval) {
|
||||
clearInterval(this.contactsInterval);
|
||||
this.contactsInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
public async getContact(id: string): Promise<SkypeContact | null> {
|
||||
@ -193,7 +187,7 @@ export class Client extends EventEmitter {
|
||||
}
|
||||
|
||||
public async downloadFile(url: string): Promise<Buffer> {
|
||||
if (!url.includes("/views/imgpsh_fullsize_anim")) {
|
||||
if (!url.includes("/views/")) {
|
||||
url = url + "/views/imgpsh_fullsize_anim";
|
||||
}
|
||||
return await Util.DownloadFile(url, {
|
||||
@ -238,4 +232,75 @@ export class Client extends EventEmitter {
|
||||
): Promise<skypeHttp.Api.SendMessageResult> {
|
||||
return await this.api.sendImage(opts, conversationId);
|
||||
}
|
||||
|
||||
private async startupApi() {
|
||||
this.api.on("event", (evt: skypeHttp.events.EventMessage) => {
|
||||
if (!evt || !evt.resource) {
|
||||
return;
|
||||
}
|
||||
const resource = evt.resource;
|
||||
log.debug(`Got new event of type ${resource.type}`);
|
||||
log.silly(evt);
|
||||
const [type, subtype] = resource.type.split("/");
|
||||
switch (type) {
|
||||
case "RichText":
|
||||
if (evt.resourceType === "NewMessage") {
|
||||
if (resource.native.skypeeditedid || this.handledIds.has(resource.id)) {
|
||||
break;
|
||||
}
|
||||
this.handledIds.add(resource.id);
|
||||
if (subtype === "Location") {
|
||||
this.emit("location", resource);
|
||||
} else if (subtype) {
|
||||
this.emit("file", resource);
|
||||
} else {
|
||||
this.emit("text", resource);
|
||||
}
|
||||
} else if (evt.resourceType === "MessageUpdate") {
|
||||
this.emit("edit", resource);
|
||||
}
|
||||
break;
|
||||
case "Control":
|
||||
if (subtype === "Typing" || subtype === "ClearTyping") {
|
||||
this.emit("typing", resource, subtype === "Typing");
|
||||
}
|
||||
break;
|
||||
case "ThreadActivity":
|
||||
if (subtype === "MemberConsumptionHorizonUpdate") {
|
||||
this.emit("presence", resource);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
this.api.on("error", (err: Error) => {
|
||||
log.error("An error occured", err);
|
||||
this.emit("error", err);
|
||||
});
|
||||
|
||||
const contacts = await this.api.getContacts();
|
||||
for (const contact of contacts) {
|
||||
this.contacts.set(contact.mri, contact);
|
||||
}
|
||||
this.lastContactsDate = new Date();
|
||||
const conversations = await this.api.getConversations();
|
||||
for (const conversation of conversations) {
|
||||
this.conversations.set(conversation.id, conversation);
|
||||
}
|
||||
|
||||
if (this.contactsInterval) {
|
||||
clearInterval(this.contactsInterval);
|
||||
this.contactsInterval = null;
|
||||
}
|
||||
this.contactsInterval = setInterval(this.updateContacts.bind(this), CONTACTS_DELTA_INTERVAL);
|
||||
}
|
||||
|
||||
private async updateContacts() {
|
||||
const contacts = await this.api.getContacts(true);
|
||||
for (const contact of contacts) {
|
||||
this.contacts.set(contact.mri, contact);
|
||||
this.emit("updateContact", contact);
|
||||
}
|
||||
this.lastContactsDate = new Date();
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ export class MatrixMessageParser {
|
||||
}
|
||||
|
||||
private walkChildNodes(node: Parser.Node): string {
|
||||
return node.childNodes.map((node) => this.walkNode(node)).join("");
|
||||
return node.childNodes.map((n) => this.walkNode(n)).join("");
|
||||
}
|
||||
|
||||
private escape(s: string): string {
|
||||
|
114
src/skype.ts
114
src/skype.ts
@ -23,6 +23,7 @@ import * as decodeHtml from "decode-html";
|
||||
import * as escapeHtml from "escape-html";
|
||||
import { MatrixMessageParser } from "./matrixmessageparser";
|
||||
import { SkypeMessageParser } from "./skypemessageparser";
|
||||
import * as cheerio from "cheerio";
|
||||
|
||||
const log = new Log("SkypePuppet:skype");
|
||||
|
||||
@ -104,7 +105,7 @@ export class Skype {
|
||||
return {
|
||||
user: this.getUserParams(puppetId, contact),
|
||||
room: this.getRoomParams(puppetId, conversation),
|
||||
eventId: (resource as any).clientId || resource.native.clientmessageid || resource.id, // tslint:disable-line no-any
|
||||
eventId: resource.id, // tslint:disable-line no-any
|
||||
};
|
||||
}
|
||||
|
||||
@ -125,16 +126,16 @@ export class Skype {
|
||||
const client = p.client;
|
||||
client.on("text", async (resource: skypeHttp.resources.TextResource) => {
|
||||
try {
|
||||
await this.handleSkypeText(puppetId, resource, false);
|
||||
await this.handleSkypeText(puppetId, resource);
|
||||
} catch (err) {
|
||||
log.error("Error while handling text event", err);
|
||||
}
|
||||
});
|
||||
client.on("richText", async (resource: skypeHttp.resources.RichTextResource) => {
|
||||
client.on("edit", async (resource: skypeHttp.resources.RichTextResource) => {
|
||||
try {
|
||||
await this.handleSkypeText(puppetId, resource, true);
|
||||
await this.handleSkypeEdit(puppetId, resource);
|
||||
} catch (err) {
|
||||
log.error("Error while handling richText event", err);
|
||||
log.error("Error while handling edit event", err);
|
||||
}
|
||||
});
|
||||
client.on("location", async (resource: skypeHttp.resources.RichTextLocationResource) => {
|
||||
@ -165,6 +166,14 @@ export class Skype {
|
||||
log.error("Error while handling presence event", err);
|
||||
}
|
||||
});
|
||||
client.on("updateContact", async (contact: SkypeContact) => {
|
||||
try {
|
||||
const remoteUser = this.getUserParams(puppetId, contact);
|
||||
await this.puppet.updateUser(remoteUser);
|
||||
} catch (err) {
|
||||
log.error("Error while handling updateContact event", err);
|
||||
}
|
||||
});
|
||||
const MINUTE = 60000;
|
||||
client.on("error", async (err: Error) => {
|
||||
await this.puppet.sendStatusMessage(puppetId, "Error: " + err);
|
||||
@ -324,9 +333,8 @@ export class Skype {
|
||||
const dedupeKey = `${room.puppetId};${room.roomId}`;
|
||||
this.messageDeduplicator.lock(dedupeKey, p.client.username, msg);
|
||||
const ret = await p.client.sendMessage(conversation.id, msg);
|
||||
const dedupeId = ret && ret.clientMessageId;
|
||||
const eventId = ret && ret.MessageId;
|
||||
this.messageDeduplicator.unlock(dedupeKey, p.client.username, dedupeId);
|
||||
this.messageDeduplicator.unlock(dedupeKey, p.client.username, eventId);
|
||||
if (eventId) {
|
||||
await this.puppet.eventSync.insert(room.puppetId, data.eventId!, eventId);
|
||||
}
|
||||
@ -412,9 +420,8 @@ export class Skype {
|
||||
const dedupeKey = `${room.puppetId};${room.roomId}`;
|
||||
this.messageDeduplicator.lock(dedupeKey, p.client.username, `file:${data.filename}`);
|
||||
const ret = await p.client[method](conversation.id, opts);
|
||||
const dedupeId = ret && ret.clientMessageId;
|
||||
const eventId = ret && ret.MessageId;
|
||||
this.messageDeduplicator.unlock(dedupeKey, p.client.username, dedupeId);
|
||||
this.messageDeduplicator.unlock(dedupeKey, p.client.username, eventId);
|
||||
if (eventId) {
|
||||
await this.puppet.eventSync.insert(room.puppetId, data.eventId!, eventId);
|
||||
}
|
||||
@ -423,12 +430,12 @@ export class Skype {
|
||||
private async handleSkypeText(
|
||||
puppetId: number,
|
||||
resource: skypeHttp.resources.TextResource | skypeHttp.resources.RichTextResource,
|
||||
rich: boolean,
|
||||
) {
|
||||
const p = this.puppets[puppetId];
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
const rich = resource.native.messagetype.startsWith("RichText");
|
||||
log.info("Got new skype message");
|
||||
log.silly(resource);
|
||||
const params = await this.getSendParams(puppetId, resource);
|
||||
@ -438,7 +445,66 @@ export class Skype {
|
||||
}
|
||||
let msg = resource.content;
|
||||
let emote = false;
|
||||
if (resource.native && resource.native.skypeemoteoffset) {
|
||||
if (resource.native.skypeemoteoffset) {
|
||||
emote = true;
|
||||
msg = msg.substr(Number(resource.native.skypeemoteoffset));
|
||||
}
|
||||
const dedupeKey = `${puppetId};${params.room.roomId}`;
|
||||
if (rich && msg.trim().startsWith("<URIObject") && msg.trim().endsWith("</URIObject>")) {
|
||||
// okay, we might have a sticker or something...
|
||||
const $ = cheerio.load(msg);
|
||||
const obj = $("URIObject");
|
||||
let uri = obj.attr("uri");
|
||||
const filename = $(obj.find("OriginalName")).attr("v");
|
||||
if (uri) {
|
||||
if (await this.messageDeduplicator.dedupe(dedupeKey, params.user.userId, params.eventId, `file:${filename}`)) {
|
||||
log.silly("file message dedupe");
|
||||
return;
|
||||
}
|
||||
uri += "/views/thumblarge";
|
||||
uri = uri.replace("static.asm.skype.com", "static-asm.secure.skypeassets.com");
|
||||
const buffer = await p.client.downloadFile(uri);
|
||||
await this.puppet.sendFileDetect(params, buffer, filename);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (await this.messageDeduplicator.dedupe(dedupeKey, params.user.userId, params.eventId, msg)) {
|
||||
log.silly("normal message dedupe");
|
||||
return;
|
||||
}
|
||||
let sendMsg: IMessageEvent;
|
||||
if (rich) {
|
||||
sendMsg = this.skypeMessageParser.parse(msg);
|
||||
} else {
|
||||
sendMsg = {
|
||||
body: msg,
|
||||
};
|
||||
}
|
||||
if (emote) {
|
||||
sendMsg.emote = true;
|
||||
}
|
||||
await this.puppet.sendMessage(params, sendMsg);
|
||||
}
|
||||
|
||||
private async handleSkypeEdit(
|
||||
puppetId: number,
|
||||
resource: skypeHttp.resources.TextResource | skypeHttp.resources.RichTextResource,
|
||||
) {
|
||||
const p = this.puppets[puppetId];
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
const rich = resource.native.messagetype.startsWith("RichText");
|
||||
log.info("Got new skype edit");
|
||||
log.silly(resource);
|
||||
const params = await this.getSendParams(puppetId, resource);
|
||||
if (!params) {
|
||||
log.warn("Couldn't generate params");
|
||||
return;
|
||||
}
|
||||
let msg = resource.content;
|
||||
let emote = false;
|
||||
if (resource.native.skypeemoteoffset) {
|
||||
emote = true;
|
||||
msg = msg.substr(Number(resource.native.skypeemoteoffset));
|
||||
}
|
||||
@ -458,17 +524,13 @@ export class Skype {
|
||||
if (emote) {
|
||||
sendMsg.emote = true;
|
||||
}
|
||||
if (resource.native && resource.native.skypeeditedid) {
|
||||
if (resource.content) {
|
||||
await this.puppet.sendEdit(params, resource.native.skypeeditedid, sendMsg);
|
||||
} else if (p.deletedMessages.has(resource.native.skypeeditedid)) {
|
||||
log.silly("normal message redact dedupe");
|
||||
return;
|
||||
} else {
|
||||
await this.puppet.sendRedact(params, resource.native.skypeeditedid);
|
||||
}
|
||||
if (resource.content) {
|
||||
await this.puppet.sendEdit(params, resource.id, sendMsg);
|
||||
} else if (p.deletedMessages.has(resource.id)) {
|
||||
log.silly("normal message redact dedupe");
|
||||
return;
|
||||
} else {
|
||||
await this.puppet.sendMessage(params, sendMsg);
|
||||
await this.puppet.sendRedact(params, resource.id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -490,14 +552,6 @@ export class Skype {
|
||||
log.silly("file message dedupe");
|
||||
return;
|
||||
}
|
||||
if (resource.native && resource.native.skypeeditedid && !resource.uri) {
|
||||
if (p.deletedMessages.has(resource.native.skypeeditedid)) {
|
||||
log.silly("file message redact dedupe");
|
||||
return;
|
||||
}
|
||||
await this.puppet.sendRedact(params, resource.native.skypeeditedid);
|
||||
return;
|
||||
}
|
||||
const buffer = await p.client.downloadFile(resource.uri);
|
||||
await this.puppet.sendFileDetect(params, buffer, filename);
|
||||
}
|
||||
@ -519,7 +573,7 @@ export class Skype {
|
||||
|
||||
private async handleSkypePresence(puppetId: number, resource: skypeHttp.resources.Resource) {
|
||||
const p = this.puppets[puppetId];
|
||||
if (!p || !resource.native) {
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
log.info("Got new skype presence event");
|
||||
|
@ -15,6 +15,7 @@ import * as Parser from "node-html-parser";
|
||||
import * as decodeHtml from "decode-html";
|
||||
import * as escapeHtml from "escape-html";
|
||||
import { IMessageEvent } from "mx-puppet-bridge";
|
||||
import * as emoji from "node-emoji";
|
||||
|
||||
export class SkypeMessageParser {
|
||||
public parse(msg: string): IMessageEvent {
|
||||
@ -26,7 +27,13 @@ export class SkypeMessageParser {
|
||||
}
|
||||
|
||||
private walkChildNodes(node: Parser.Node): IMessageEvent {
|
||||
return node.childNodes.map((node) => this.walkNode(node)).reduce((acc, curr) => {
|
||||
if (!node.childNodes.length) {
|
||||
return {
|
||||
body: "",
|
||||
formattedBody: "",
|
||||
};
|
||||
}
|
||||
return node.childNodes.map((n) => this.walkNode(n)).reduce((acc, curr) => {
|
||||
return {
|
||||
body: acc.body + curr.body,
|
||||
formattedBody: acc.formattedBody! + curr.formattedBody!,
|
||||
@ -83,7 +90,82 @@ export class SkypeMessageParser {
|
||||
formattedBody: `<a href="${escapeHtml(href)}">${child.formattedBody}</a>`,
|
||||
};
|
||||
}
|
||||
case "ss": {
|
||||
// skype emoji
|
||||
const type = nodeHtml.attributes.type;
|
||||
let emojiType = {
|
||||
smile: "slightly_smiling_face",
|
||||
sad: "slightly_frowning_face",
|
||||
laugh: "grin",
|
||||
cool: "sunglasses",
|
||||
hearteyes: "heart_eyes",
|
||||
stareyes: "star-struck",
|
||||
like: "thumbsup",
|
||||
cwl: "rolling_on_the_floor_laughing",
|
||||
xd: "laughing",
|
||||
happyface: "smiley",
|
||||
happyeyes: "smile",
|
||||
// hysterical: "", TODO: find
|
||||
sweatgrinning: "sweat_smile",
|
||||
// smileeyes: "", TODO: find
|
||||
blankface: "no_mouth",
|
||||
surprised: "astonished",
|
||||
upsidedownface: "upside_down_face",
|
||||
loudlycrying: "sob",
|
||||
shivering: "🥶",
|
||||
speechless: "😐️",
|
||||
tongueout: "stuck_out_tongue",
|
||||
winktongueout: "stuck_out_tongue_winking_eye",
|
||||
inlove: "🥰",
|
||||
// wonder: "", TODO: find
|
||||
// dull: "", TODO: find
|
||||
yawn: "🥱",
|
||||
puke: "face_vomiting",
|
||||
// doh: "", TODO: find
|
||||
angryface: "angry",
|
||||
angry: "rage",
|
||||
// wasntme: "", TODO: find
|
||||
// worry: "", TODO: find
|
||||
screamingfear: "scream",
|
||||
// veryconfused: "", TODO: find
|
||||
// mmm: "", TODO: find
|
||||
nerdy: "nerd_face",
|
||||
loveearth: "🌍️",
|
||||
// rainbowsmile: "", TODO: find
|
||||
// lipssealed: "", TODO: find
|
||||
devil: "smiling_imp",
|
||||
// envy: "", TODO: find
|
||||
// makeup: "", TODO: find
|
||||
think: "thinking_face",
|
||||
rofl: "rolling_on_the_floor_laughing",
|
||||
}[type];
|
||||
const haveEmojiType = Boolean(emojiType);
|
||||
if (!emojiType) {
|
||||
emojiType = type;
|
||||
}
|
||||
let e = emoji.get(emojiType);
|
||||
if (e === `:${emojiType}:`) {
|
||||
e = emoji.get(emojiType + "_face");
|
||||
}
|
||||
if (!e.startsWith(":")) {
|
||||
return {
|
||||
body: e,
|
||||
formattedBody: e,
|
||||
};
|
||||
}
|
||||
if (haveEmojiType) {
|
||||
return {
|
||||
body: emojiType,
|
||||
formattedBody: emojiType,
|
||||
};
|
||||
}
|
||||
return {
|
||||
body: `(${type})`,
|
||||
formattedBody: `(${escapeHtml(type)})`,
|
||||
};
|
||||
}
|
||||
case "e_m":
|
||||
// empty edit tag
|
||||
return {
|
||||
body: "",
|
||||
formattedBody: "",
|
||||
|
Loading…
Reference in New Issue
Block a user