mirror of
https://github.com/thelounge/thelounge.git
synced 2024-06-04 23:02:18 +02:00
feat(irc framework): support (client) tags
It is now possible to receive, send and process client tags in general using the IRC framework. This is useful for many client-oriented IRCv3 features: typing, reacts, replies, channel contexts, etc.
This commit is contained in:
parent
9f05a75c39
commit
ac5eb004fe
|
@ -35,6 +35,7 @@
|
|||
"../server/models/user.ts",
|
||||
"../server/models/msg.ts",
|
||||
"../server/models/prefix.ts",
|
||||
"../server/models/client-tags.ts",
|
||||
"./js/helpers/fullnamemap.json",
|
||||
"./js/helpers/simplemap.json",
|
||||
"../webpack.config.ts",
|
||||
|
|
36
server/models/client-tags.ts
Normal file
36
server/models/client-tags.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import _ from "lodash";
|
||||
|
||||
export enum ClientTagKey {
|
||||
// https://ircv3.net/specs/client-tags/reply
|
||||
DRAFT_REPLY = "draft/reply",
|
||||
// https://ircv3.net/specs/client-tags/react
|
||||
DRAFT_REACT = "draft/react",
|
||||
// https://ircv3.net/specs/client-tags/channel-context
|
||||
DRAFT_CHANNEL_CONTEXT = "draft/channel-context",
|
||||
|
||||
// https://ircv3.net/specs/client-tags/typing.html
|
||||
TYPING = "typing",
|
||||
}
|
||||
|
||||
export class ClientTags {
|
||||
reaction?: string;
|
||||
repliedTo?: string;
|
||||
channelContext?: string;
|
||||
rawTags: Record<string, string>;
|
||||
|
||||
public constructor(rawClientTags: Record<string, string>) {
|
||||
this.rawTags = rawClientTags;
|
||||
|
||||
this.reaction = this.get(ClientTagKey.DRAFT_REACT);
|
||||
this.repliedTo = this.get(ClientTagKey.DRAFT_REPLY);
|
||||
this.channelContext = this.get(ClientTagKey.DRAFT_CHANNEL_CONTEXT);
|
||||
}
|
||||
|
||||
public get(key: string): string | undefined {
|
||||
return this.rawTags[`+${key}`];
|
||||
}
|
||||
|
||||
public has(key: string): boolean {
|
||||
return Object.prototype.hasOwnProperty.call(this.rawTags, `+${key}`);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import _ from "lodash";
|
||||
import {LinkPreview} from "../plugins/irc-events/link";
|
||||
import User from "./user";
|
||||
import {ClientTags} from "./client-tags";
|
||||
|
||||
export type UserInMessage = Partial<User> & {
|
||||
mode: string;
|
||||
|
@ -18,6 +19,7 @@ export enum MessageType {
|
|||
LOGIN = "login",
|
||||
LOGOUT = "logout",
|
||||
MESSAGE = "message",
|
||||
TAGMSG = "tagmsg",
|
||||
MODE = "mode",
|
||||
MODE_CHANNEL = "mode_channel",
|
||||
MODE_USER = "mode_user", // RPL_UMODEIS
|
||||
|
@ -61,6 +63,8 @@ class Msg {
|
|||
gecos!: string;
|
||||
account!: boolean;
|
||||
|
||||
client_tags!: ClientTags;
|
||||
|
||||
// these are all just for error:
|
||||
error!: string;
|
||||
nick!: string;
|
||||
|
@ -94,6 +98,7 @@ class Msg {
|
|||
text: "",
|
||||
type: MessageType.MESSAGE,
|
||||
self: false,
|
||||
client_tags: {},
|
||||
});
|
||||
|
||||
if (this.time) {
|
||||
|
|
|
@ -16,6 +16,7 @@ function getTarget(cmd: string, args: string[], chan: Chan) {
|
|||
|
||||
const input: PluginInputHandler = function (network, chan, cmd, args) {
|
||||
let targetName = getTarget(cmd, args, chan);
|
||||
const tags = {};
|
||||
|
||||
if (cmd === "query") {
|
||||
if (!targetName) {
|
||||
|
@ -91,7 +92,7 @@ const input: PluginInputHandler = function (network, chan, cmd, args) {
|
|||
return true;
|
||||
}
|
||||
|
||||
network.irc.say(targetName, msg);
|
||||
network.irc.say(targetName, msg, tags);
|
||||
|
||||
// If the IRCd does not support echo-message, simulate the message
|
||||
// being sent back to us.
|
||||
|
|
|
@ -5,6 +5,7 @@ import Helper from "../../helper";
|
|||
import {IrcEventHandler} from "../../client";
|
||||
import Chan, {ChanType} from "../../models/chan";
|
||||
import User from "../../models/user";
|
||||
import {ClientTags} from "../../models/client-tags";
|
||||
|
||||
const nickRegExp = /(?:\x03[0-9]{1,2}(?:,[0-9]{1,2})?)?([\w[\]\\`^{|}-]+)/g;
|
||||
|
||||
|
@ -26,6 +27,11 @@ export default <IrcEventHandler>function (irc, network) {
|
|||
handleMessage(data);
|
||||
});
|
||||
|
||||
irc.on("tagmsg", function (data) {
|
||||
data.type = MessageType.TAGMSG;
|
||||
handleMessage(data);
|
||||
});
|
||||
|
||||
irc.on("privmsg", function (data) {
|
||||
data.type = MessageType.MESSAGE;
|
||||
handleMessage(data);
|
||||
|
@ -44,6 +50,7 @@ export default <IrcEventHandler>function (irc, network) {
|
|||
target: string;
|
||||
type: MessageType;
|
||||
time: number;
|
||||
tags: Record<string, string>;
|
||||
text?: string;
|
||||
from_server?: boolean;
|
||||
message: string;
|
||||
|
@ -131,14 +138,20 @@ export default <IrcEventHandler>function (irc, network) {
|
|||
from: from,
|
||||
highlight: highlight,
|
||||
users: [],
|
||||
client_tags: new ClientTags(data.tags),
|
||||
});
|
||||
|
||||
if (showInActive) {
|
||||
msg.showInActive = true;
|
||||
}
|
||||
|
||||
// remove IRC formatting for custom highlight testing
|
||||
const cleanMessage = cleanIrcMessage(data.message);
|
||||
// Not all messages have bodies.
|
||||
let cleanMessage = data.message;
|
||||
|
||||
if (data.message) {
|
||||
// remove IRC formatting for custom highlight testing
|
||||
cleanMessage = cleanIrcMessage(data.message);
|
||||
}
|
||||
|
||||
// Self messages in channels are never highlighted
|
||||
// Non-self messages are highlighted as soon as the nick is detected
|
||||
|
@ -174,10 +187,19 @@ export default <IrcEventHandler>function (irc, network) {
|
|||
LinkPrefetch(client, chan, msg, cleanMessage);
|
||||
}
|
||||
|
||||
if (!data.message) {
|
||||
return;
|
||||
}
|
||||
|
||||
chan.pushMessage(client, msg, !msg.self);
|
||||
|
||||
// Do not send notifications if the channel is muted or for messages older than 15 minutes (znc buffer for example)
|
||||
if (!chan.muted && msg.highlight && (!data.time || data.time > Date.now() - 900000)) {
|
||||
if (
|
||||
!chan.muted &&
|
||||
msg.highlight &&
|
||||
(!data.time || data.time > Date.now() - 900000) &&
|
||||
msg.type !== MessageType.TAGMSG
|
||||
) {
|
||||
let title = chan.name;
|
||||
let body = cleanMessage;
|
||||
|
||||
|
|
13
server/types/modules/irc-framework.d.ts
vendored
13
server/types/modules/irc-framework.d.ts
vendored
|
@ -174,11 +174,18 @@ declare module "irc-framework" {
|
|||
|
||||
changeNick(nick: string): void;
|
||||
|
||||
sendMessage(commandName: string, target: string, message: string): string[];
|
||||
sendMessage(
|
||||
commandName: string,
|
||||
target: string,
|
||||
message: string,
|
||||
tags: Record<string, string> = {}
|
||||
): string[];
|
||||
|
||||
say(target: string, message: string): string[];
|
||||
say(target: string, message: string, tags: Record<string, string> = {}): string[];
|
||||
|
||||
notice(target: string, message: string): string[];
|
||||
notice(target: string, message: string, tags: Record<string, string> = {}): string[];
|
||||
|
||||
tagmsg(target: string, tags: Record<string, string> = {}): string[];
|
||||
|
||||
join(channel: string, key?: string): void;
|
||||
|
||||
|
|
Loading…
Reference in a new issue