progress moving types out of types/

This commit is contained in:
Max Leiter 2022-05-04 15:41:57 -07:00
parent aa2e5b6834
commit 6de13b6ff8
No known key found for this signature in database
GPG key ID: A3512F2F2F17EBDA
99 changed files with 668 additions and 640 deletions

View file

@ -1,3 +1,5 @@
import Chan from "../src/models/chan";
declare module "*.vue" {
import Vue from "vue";
export default Vue;

View file

@ -5,7 +5,8 @@
"../src/types/models/channel.d.ts",
"js/helpers/simplemap.json",
"js/helpers/fullnamemap.json",
"../package.json"
"../package.json",
"./types.d.ts"
],
"compilerOptions": {
// "paths": {

View file

@ -13,15 +13,15 @@
"homepage": "https://thelounge.chat/",
"scripts": {
"build:client": "webpack",
"build:server": "tsc -p src/tsconfig.json index.ts",
"build:server": "tsc -p src/tsconfig.json src/index.ts",
"coverage": "run-s test:* && nyc --nycrc-path=test/.nycrc-report.json report",
"dev": "ts-node --project tsconfig.json index.ts start --dev",
"dev": "ts-node --project src/tsconfig.json src/index.ts start --dev",
"format:prettier": "prettier --write \"**/*.*\"",
"lint:check-eslint": "eslint-config-prettier .eslintrc.cjs",
"lint:eslint": "eslint . --ext .js,.vue --report-unused-disable-directives --color",
"lint:prettier": "prettier --list-different \"**/*.*\"",
"lint:stylelint": "stylelint --color \"client/**/*.css\"",
"start": "ts-node index start",
"start": "ts-node src/index start",
"test": "run-p --aggregate-output --continue-on-error lint:* test:*",
"test:mocha": "webpack --mode=development && nyc --nycrc-path=test/.nycrc-mocha.json mocha --colors --config=test/.mocharc.yml",
"watch": "webpack --watch"
@ -101,6 +101,7 @@
"@types/ua-parser-js": "0.7.36",
"@types/uuid": "8.3.4",
"@types/web-push": "3.3.2",
"@types/webpack-env": "1.16.4",
"@types/ws": "8.5.3",
"@typescript-eslint/eslint-plugin": "5.22.0",
"@typescript-eslint/parser": "5.22.0",

View file

@ -8,8 +8,8 @@ import crypto from "crypto";
import colors from "chalk";
import log from "./log";
import Chan from "./models/chan";
import Msg from "./models/msg";
import Chan, {ChanType} from "./models/chan";
import Msg, {MessageType, UserInMessage} from "./models/msg";
import Config from "./config";
import constants from "../client/js/constants";
@ -17,7 +17,7 @@ import inputs from "./plugins/inputs";
import PublicClient from "./plugins/packages/publicClient";
import SqliteMessageStorage from "./plugins/messageStorage/sqlite";
import TextFileMessageStorage from "./plugins/messageStorage/text";
import Network from "./models/network";
import Network, {NetworkWithIrcFramework} from "./models/network";
import ClientManager from "./clientManager";
import {MessageStorage} from "./types/plugins/messageStorage";
@ -48,6 +48,46 @@ const events = [
"welcome",
"whois",
];
type ClientPushSubscription = {
endpoint: string;
keys: {
p256dh: string;
auth: string;
};
};
type ClientConfig = {
log: boolean;
password: string;
sessions: {
[token: string]: {
lastUse: number;
ip: string;
agent: string;
pushSubscription?: ClientPushSubscription;
};
};
clientSettings: {
[key: string]: any;
};
browser?: {
language?: string;
ip?: string;
hostname?: string;
isSecure?: boolean;
};
};
type Mention = {
chanId: number;
msgId: number;
type: MessageType;
time: number;
text: string;
from: UserInMessage;
};
class Client {
awayMessage!: string;
lastActiveChannel!: number;
@ -272,12 +312,11 @@ class Client {
networks: [network.getFilteredClone(this.lastActiveChannel, -1)],
});
// @ts-ignore it complains because validate expects this to be NetworkWith
if (!network.validate(client)) {
if (!(network as NetworkWithIrcFramework).validate(client)) {
return;
}
network.createIrcFramework(client);
(network as NetworkWithIrcFramework).createIrcFramework(client);
events.forEach(async (plugin) => {
(await import(`./plugins/irc-events/${plugin}`)).default.apply(client, [
@ -413,6 +452,11 @@ class Client {
if (inputs.userInputs.has(cmd)) {
const plugin = inputs.userInputs.get(cmd);
if (!plugin) {
// should be a no-op
throw new Error(`Plugin ${cmd} not found`);
}
if (typeof plugin.input === "function" && (connected || plugin.allowDisconnected)) {
connected = true;
plugin.input.apply(client, [target.network, target.chan, cmd, args]);
@ -785,3 +829,10 @@ class Client {
}
export default Client;
// TODO: this should exist elsewhere?
export type IrcEventHandler = (
this: Client,
irc: NetworkWithIrcFramework["irc"],
network: NetworkWithIrcFramework
) => void;

View file

@ -7,7 +7,97 @@ import _ from "lodash";
import colors from "chalk";
import log from "./log";
import Helper from "./helper";
import {Config as ConfigType} from "./types/config";
// TODO: Type this
export type WebIRC = {
[key: string]: any;
};
type Https = {
enable: boolean;
key: string;
certificate: string;
ca: string;
};
type FileUpload = {
enable: boolean;
maxFileSize: number;
baseUrl?: string;
};
export type Defaults = {
name: string;
host: string;
port: number;
password: string;
tls: boolean;
rejectUnauthorized: boolean;
nick: string;
username: string;
realname: string;
join: string;
leaveMessage: string;
};
type Identd = {
enable: boolean;
port: number;
};
type SearchDN = {
rootDN: string;
rootPassword: string;
filter: string;
base: string;
scope: string;
};
type Ldap = {
enable: boolean;
url: string;
tlsOptions: any;
primaryKey: string;
searchDN: SearchDN;
baseDN?: string;
};
type TlsOptions = any;
type Debug = {
ircFramework: boolean;
raw: boolean;
};
export type ConfigType = {
public: boolean;
host: string | undefined;
port: number;
bind: string | undefined;
reverseProxy: boolean;
maxHistory: number;
https: Https;
theme: string;
prefetch: boolean;
disableMediaPreview: boolean;
prefetchStorage: boolean;
prefetchMaxImageSize: number;
prefetchMaxSearchSize: number;
prefetchTimeout: number;
fileUpload: FileUpload;
transports: string[];
leaveMessage: string;
defaults: Defaults;
lockNetwork: boolean;
messageStorage: string[];
useHexIp: boolean;
webirc?: WebIRC;
identd: Identd;
oidentd?: string;
ldap: Ldap;
debug: Debug;
themeColor: string;
};
class Config {
values = require(path.resolve(

View file

@ -8,7 +8,12 @@ import fs from "fs";
import net from "net";
import bcrypt from "bcryptjs";
import crypto from "crypto";
import {Hostmask} from "./types/helper";
export type Hostmask = {
nick: string;
ident: string;
hostname: string;
};
const Helper = {
expandHome,

2
src/index.d.ts vendored
View file

@ -1 +1 @@
// / <reference path="types/index.d.ts" />
import "./types";

View file

@ -7,7 +7,7 @@ process.chdir(__dirname);
// Perform node version check before loading any other files or modules
// Doing this check as soon as possible allows us to
// avoid ES6 parser errors or other issues
import pkg from "./package.json";
import pkg from "../package.json";
import {satisfies} from "semver";
if (!satisfies(process.version, pkg.engines.node)) {
@ -33,4 +33,4 @@ if (dns.setDefaultResultOrder) {
dns.setDefaultResultOrder("verbatim");
}
import "./src/command-line";
import "./command-line";

View file

@ -4,12 +4,37 @@ import _ from "lodash";
import log from "../log";
import Config from "../config";
import User from "./user";
import Msg from "./msg";
import Msg, {MessageType} from "./msg";
import storage from "../plugins/storage";
import Client from "../client";
import Network from "./network";
import Prefix from "./prefix";
export enum ChanType {
CHANNEL = "channel",
LOBBY = "lobby",
QUERY = "query",
SPECIAL = "special",
}
export enum SpecialChanType {
BANLIST = "list_bans",
INVITELIST = "list_invites",
CHANNELLIST = "list_channels",
IGNORELIST = "list_ignored",
}
export enum ChanState {
PARTED = 0,
JOINED = 1,
}
// eslint-disable-next-line no-use-before-define
export type FilteredChannel = Chan & {
users: [];
totalMessages: number;
};
class Chan {
// TODO: don't force existence, figure out how to make TS infer it.
id!: number;
@ -298,3 +323,5 @@ function requestZncPlayback(channel, network, from) {
}
export default Chan;
export type Channel = Chan;

View file

@ -1,6 +1,48 @@
"use strict";
import _ from "lodash";
import User from "./user";
export type UserInMessage = Partial<User> & {
mode: string;
};
export type MessagePreview = {
shown: boolean;
link: string;
body: string;
};
export enum MessageType {
UNHANDLED = "unhandled",
ACTION = "action",
AWAY = "away",
BACK = "back",
ERROR = "error",
INVITE = "invite",
JOIN = "join",
KICK = "kick",
LOGIN = "login",
LOGOUT = "logout",
MESSAGE = "message",
MODE = "mode",
MODE_CHANNEL = "mode_channel",
MODE_USER = "mode_user", // RPL_UMODEIS
MONOSPACE_BLOCK = "monospace_block",
NICK = "nick",
NOTICE = "notice",
PART = "part",
QUIT = "quit",
CTCP = "ctcp",
CTCP_REQUEST = "ctcp_request",
CHGHOST = "chghost",
TOPIC = "topic",
TOPIC_SET_BY = "topic_set_by",
WHOIS = "whois",
RAW = "raw",
PLUGIN = "plugin",
WALLOPS = "wallops",
}
class Msg {
from!: UserInMessage;
@ -95,3 +137,5 @@ class Msg {
}
export default Msg;
export type Message = Msg;

View file

@ -2,14 +2,14 @@
import _ from "lodash";
import {v4 as uuidv4} from "uuid";
import IrcFramework from "irc-framework";
import Chan from "./chan";
import Msg from "./msg";
import IrcFramework, {Client as IRCClient} from "irc-framework";
import Chan, {Channel, ChanType} from "./chan";
import Msg, {MessageType} from "./msg";
import Prefix from "./prefix";
import Helper from "../helper";
import Config from "../config";
import Helper, {Hostmask} from "../helper";
import Config, {WebIRC} from "../config";
import STSPolicies from "../plugins/sts";
import ClientCertificate from "../plugins/clientCertificate";
import ClientCertificate, {ClientCertificateType} from "../plugins/clientCertificate";
import Client from "../client";
/**
@ -22,6 +22,53 @@ const fieldsForClient = {
serverOptions: true,
};
type NetworkIrcOptions = {
host: string;
port: number;
password: string;
nick: string;
username: string;
gecos: string;
tls: boolean;
rejectUnauthorized: boolean;
webirc: WebIRC;
client_certificate: ClientCertificateType | null;
socks?: {
host: string;
port: number;
user: string;
pass: string;
};
sasl_mechanism?: string;
account?:
| {
account: string;
password: string;
}
| Record<string, never>;
};
type NetworkStatus = {
connected: boolean;
secure: boolean;
};
export type IgnoreListItem = Hostmask & {
when?: number;
};
type IgnoreList = IgnoreListItem[];
type NonNullableIRCWithOptions = NonNullable<IRCClient & {options: NetworkIrcOptions}>;
// eslint-disable-next-line no-use-before-define
export type NetworkWithIrcFramework = Network & {
// eslint-disable-next-line no-use-before-define
irc: NonNullable<Network["irc"]> & {
options: NonNullableIRCWithOptions;
};
};
class Network {
nick!: string;
name!: string;
@ -223,7 +270,7 @@ class Network {
return true;
}
createIrcFramework(this: Network, client: Client) {
createIrcFramework(this: NetworkWithIrcFramework, client: Client) {
this.irc = new IrcFramework.Client({
version: false, // We handle it ourselves
outgoing_addr: Config.values.bind,
@ -237,7 +284,6 @@ class Network {
auto_reconnect_max_retries: 30,
});
// @ts-ignore TODO: `this` should now be a NetworkWithIrcFramework
this.setIrcFrameworkOptions(client);
this.irc.requestCap([

View file

@ -1,5 +1,12 @@
"use strict";
type PrefixSymbol = string;
type PrefixObject = {
symbol: PrefixSymbol;
mode: string;
};
class Prefix {
prefix: PrefixObject[];
modeToSymbol: {[mode: string]: string};

View file

@ -1,8 +1,18 @@
"use strict";
import colors from "chalk";
import Client from "../client";
import ClientManager from "../clientManager";
import log from "../log";
export type AuthHandler = (
manager: ClientManager,
client: Client,
user: string,
password: string,
callback: (success: boolean) => void
) => void;
// The order defines priority: the first available plugin is used.
// Always keep 'local' auth plugin at the end of the list; it should always be enabled.
const plugins = [import("./auth/ldap"), import("./auth/local")];

View file

@ -1,10 +1,10 @@
"use strict";
import ldap, {SearchOptions} from "ldapjs";
import colors from "chalk";
import log from "../../log";
import Config from "../../config";
import ldap, {SearchOptions} from "ldapjs";
import colors from "chalk";
import {AuthHandler} from "types/plugins/auth";
import type {AuthHandler} from "../auth";
function ldapAuthCommon(
user: string,
@ -191,9 +191,8 @@ function advancedLdapLoadUsers(users: string[], callbackLoadUser) {
}
res.on("searchEntry", function (entry) {
// @ts-ignore
// TODO
const user = entry.attributes[0]._vals[0].toString();
// TODO: was _vals.
const user = entry.attributes[0].vals[0].toString();
if (remainingUsers.has(user)) {
remainingUsers.delete(user);

View file

@ -3,7 +3,7 @@
import colors from "chalk";
import log from "../../log";
import Helper from "../../helper";
import {AuthHandler} from "../../types/plugins/auth";
import type {AuthHandler} from "../auth";
const localAuth: AuthHandler = (manager, client, user, password, callback) => {
// If no user is found, or if the client has not provided a password,

View file

@ -12,7 +12,12 @@ export default {
remove,
};
function get(uuid: string): ClientCertificate | null {
export type ClientCertificateType = {
private_key: string;
certificate: string;
};
function get(uuid: string): ClientCertificateType | null {
if (Config.values.public) {
return null;
}
@ -28,7 +33,7 @@ function get(uuid: string): ClientCertificate | null {
return {
private_key: fs.readFileSync(paths.privateKeyPath, "utf-8"),
certificate: fs.readFileSync(paths.certificatePath, "utf-8"),
} as ClientCertificate;
} as ClientCertificateType;
} catch (e: any) {
log.error("Unable to get certificate", e);
}
@ -121,7 +126,7 @@ function generate() {
const pem = {
private_key: pki.privateKeyToPem(keys.privateKey),
certificate: pki.certificateToPem(cert),
} as ClientCertificate;
} as ClientCertificateType;
return pem;
}

View file

@ -1,6 +1,6 @@
"use strict";
import log from "../log";
import webpack from "webpack";
import webpackDevMiddleware from "webpack-dev-middleware";
export default (app) => {
log.debug("Starting server in development mode");
@ -16,12 +16,12 @@ export default (app) => {
const compiler = webpack(webpackConfig);
app.use(
require("webpack-dev-middleware")(compiler, {
webpackDevMiddleware(compiler, {
index: "/",
publicPath: webpackConfig.output.publicPath,
})
).use(
require("webpack-hot-middleware")(compiler, {
webpackDevMiddleware(compiler, {
path: "/storage/__webpack_hmr",
})
);

View file

@ -1,6 +1,8 @@
"use strict";
import Msg from "../../models/msg";
import {PluginInputHandler} from "./index";
import Msg, {MessageType} from "../../models/msg";
import {ChanType} from "../../models/chan";
const commands = ["slap", "me"];

View file

@ -1,6 +1,7 @@
"use strict";
const commands = ["away", "back"];
import {PluginInputHandler} from "./index";
const input: PluginInputHandler = function (network, chan, cmd, args) {
let reason = "";

View file

@ -1,6 +1,8 @@
"use strict";
import Msg from "../../models/msg";
import {ChanType} from "../../models/chan";
import Msg, {MessageType} from "../../models/msg";
import {PluginInputHandler} from "./index";
const commands = ["ban", "unban", "banlist", "kickban"];

View file

@ -1,6 +1,7 @@
"use strict";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import {PluginInputHandler} from "./index";
const commands = ["connect", "server"];
const allowDisconnected = true;

View file

@ -1,6 +1,7 @@
"use strict";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import {PluginInputHandler} from "./index";
const commands = ["ctcp"];

View file

@ -1,4 +1,5 @@
"use strict";
import {PluginInputHandler} from "./index";
const commands = ["disconnect"];
const allowDisconnected = true;

View file

@ -1,7 +1,10 @@
"use strict";
import Msg from "../../models/msg";
import Helper from "helper";
import Msg, {MessageType} from "../../models/msg";
import Helper from "../../helper";
import {PluginInputHandler} from "./index";
import {IgnoreListItem} from "../../models/network";
import {ChanType, SpecialChanType} from "../../models/chan";
const commands = ["ignore", "unignore", "ignorelist"];

View file

@ -1,5 +1,20 @@
import Chan from "../../models/chan";
import Network from "../../models/network";
import Client from "../../client";
import Chan, {Channel} from "../../models/chan";
import Network, {NetworkWithIrcFramework} from "../../models/network";
export type PluginInputHandler = (
this: Client,
network: NetworkWithIrcFramework,
chan: Channel,
cmd: string,
args: string[]
) => void;
type Plugin = {
commands: string[];
input: (network: Network, chan: Chan, cmd: string, args: string[]) => void;
allowDisconnected?: boolean | undefined;
};
const clientSideCommands = ["/collapse", "/expand", "/search"];
@ -16,7 +31,8 @@ const passThroughCommands = [
"/rs",
];
const userInputs = [
const userInputs = new Map<string, Plugin>();
const builtInInputs = [
"action",
"away",
"ban",
@ -39,8 +55,10 @@ const userInputs = [
"topic",
"whois",
"mute",
].reduce(function (plugins, name) {
const plugin = import(`./${name}`).then(
];
for (const input of builtInInputs) {
import(`./${input}`).then(
(plugin: {
default: {
commands: string[];
@ -48,11 +66,26 @@ const userInputs = [
allowDisconnected?: boolean;
};
}) => {
plugin.default.commands.forEach((command: string) => plugins.set(command, plugin));
plugin.default.commands.forEach((command: string) =>
userInputs.set(command, plugin.default)
);
}
);
return plugins;
}, new Map());
}
// .reduce(async function (plugins, name) {
// return import(`./${name}`).then(
// (plugin: {
// default: {
// commands: string[];
// input: (network: Network, chan: Chan, cmd: string, args: string[]) => void;
// allowDisconnected?: boolean;
// };
// }) => {
// plugin.default.commands.forEach((command: string) => plugins.set(command, plugin));
// }
// );
// }, Promise.resolve(new Map()));
const pluginCommands = new Map();

View file

@ -1,9 +1,8 @@
"use strict";
import Network from "../../models/network";
import Chan from "../../models/chan";
import Msg from "../../models/msg";
import {PluginInputHandler} from "./index";
import Msg, {MessageType} from "../../models/msg";
import {ChanType} from "../../models/chan";
const commands = ["invite", "invitelist"];

View file

@ -1,6 +1,7 @@
"use strict";
import Msg from "../../models/msg";
import {PluginInputHandler} from "./index";
import Msg, {MessageType} from "../../models/msg";
import {ChanType} from "../../models/chan";
const commands = ["kick"];

View file

@ -1,4 +1,5 @@
"use strict";
import {PluginInputHandler} from "./index";
const commands = ["kill"];

View file

@ -1,4 +1,5 @@
"use strict";
import {PluginInputHandler} from "./index";
const commands = ["list"];

View file

@ -1,6 +1,8 @@
"use strict";
import {PluginInputHandler} from "./index";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import {ChanType} from "../../models/chan";
const commands = ["mode", "umode", "op", "deop", "hop", "dehop", "voice", "devoice"];

View file

@ -1,8 +1,7 @@
"use strict";
import Network from "../../models/network";
import Msg from "../../models/msg";
import {PluginInputHandler} from "./index";
import Msg, {MessageType} from "../../models/msg";
import {ChanType} from "../../models/chan";
const commands = ["query", "msg", "say"];

View file

@ -1,8 +1,9 @@
"use strict";
import Chan from "../../models/chan";
import Network from "../../models/network";
import {PluginInputHandler} from "./index";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import Client from "../../client";

View file

@ -1,6 +1,7 @@
"use strict";
import {PluginInputHandler} from "./index";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
const commands = ["nick"];
const allowDisconnected = true;

View file

@ -1,4 +1,5 @@
"use strict";
import {PluginInputHandler} from "./index";
const commands = ["notice"];

View file

@ -1,7 +1,9 @@
"use strict";
import {PluginInputHandler} from "./index";
import Msg from "../../models/msg";
import Config from "config";
import Msg, {MessageType} from "../../models/msg";
import Config from "../../config";
import {ChanType, ChanState} from "../../models/chan";
const commands = ["close", "leave", "part"];
const allowDisconnected = true;

View file

@ -1,7 +1,7 @@
"use strict";
import _ from "lodash";
import {PluginInputHandler} from "./index";
import ClientCertificate from "../clientCertificate";
const commands = ["quit"];

View file

@ -1,4 +1,5 @@
"use strict";
import {PluginInputHandler} from "./index";
const commands = ["raw", "send", "quote"];

View file

@ -1,6 +1,8 @@
"use strict";
import {PluginInputHandler} from "./index";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import {ChanType} from "../../models/chan";
const commands = ["cycle", "rejoin"];

View file

@ -1,6 +1,8 @@
"use strict";
import {PluginInputHandler} from "./index";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import {ChanType} from "../../models/chan";
const commands = ["topic"];

View file

@ -1,4 +1,5 @@
"use strict";
import {PluginInputHandler} from "./index";
const commands = ["whois"];

View file

@ -1,6 +1,7 @@
"use strict";
import Msg from "../../models/msg";
import {IrcEventHandler} from "../../client";
import {ChanType} from "../../models/chan";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,4 +1,5 @@
"use strict";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import STSPolicies from "../sts";

View file

@ -1,6 +1,7 @@
"use strict";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,10 +1,13 @@
"use strict";
import _ from "lodash";
import {IrcEventHandler} from "../../client";
import log from "../../log";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import Helper from "../../helper";
import Config from "../../config";
import {ChanType, ChanState} from "../../models/chan";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,10 +1,9 @@
"use strict";
import Network from "../../models/network";
import _ from "lodash";
import {IrcEventHandler} from "../../client";
import Helper from "../../helper";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import User from "../../models/user";
import pkg from "../../../package.json";

View file

@ -1,8 +1,8 @@
"use strict";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import Config from "../../config";
import Network from "../../models/network";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,8 +1,7 @@
"use strict";
import Network from "../../models/network";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import {IrcEventHandler} from "../../client";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,6 +1,7 @@
"use strict";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import {IrcEventHandler} from "../../client";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,8 +1,8 @@
"use strict";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,14 +1,11 @@
"use strict";
import {ChanState} from "../../types/models/channel";
import {Network} from "../../types/models/network";
import Chan from "../../models/chan";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import User from "../../models/user";
import type {IrcEventHandler} from "../../client";
import {ChanState} from "../../models/chan";
module.exports = function (irc: Network["irc"], network: Network) {
export default <IrcEventHandler>function (irc, network) {
const client = this;
irc.on("join", function (data) {

View file

@ -1,6 +1,9 @@
"use strict";
import {IrcEventHandler} from "../../client";
import {ChanState} from "../../models/chan";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import User from "../../models/user";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -9,15 +9,25 @@ import log from "../../log";
import Config from "../../config";
import {findLinksWithSchema} from "../../../client/js/helpers/ircmessageparser/findLinks";
import storage from "../storage";
import Client from "../../client";
import Client, {IrcEventHandler} from "../../client";
import Chan from "../../models/chan";
import Msg from "../../models/msg";
import {Preview} from "../../types/plugins/preview";
const currentFetchPromises = new Map();
const imageTypeRegex = /^image\/.+/;
const mediaTypeRegex = /^(audio|video)\/.+/;
type Preview = {
type: string;
head: string;
body: string;
thumb: string;
size: number;
link: string; // Send original matched link to the client
shown: boolean | null;
error: undefined | any;
message: undefined | string;
};
export default function (client: Client, chan: Chan, msg: Msg, cleanText: string) {
if (!Config.values.prefetch) {
return;
@ -136,7 +146,7 @@ function parseHtml(preview, res, client: Client) {
});
}
function parseHtmlMedia($: cheerio.CheerioAPI, preview, client) {
function parseHtmlMedia($: cheerio.Root, preview, client) {
return new Promise((resolve, reject) => {
if (Config.values.disableMediaPreview) {
reject();

View file

@ -1,8 +1,8 @@
"use strict";
import Msg from "../../models/msg";
import {IrcEventHandler} from "../../client";
import Chan from "../../models/chan";
import Chan, {ChanType, SpecialChanType} from "../../models/chan";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,10 +1,11 @@
"use strict";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
import LinkPrefetch from "./link";
import cleanIrcMessage from "../../../client/js/helpers/ircmessageparser/cleanIrcMessage";
import Helper from "../../helper";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import {ChanType} from "../../models/chan";
const nickRegExp = /(?:\x03[0-9]{1,2}(?:,[0-9]{1,2})?)?([\w[\]\\`^{|}-]+)/g;
@ -204,7 +205,7 @@ export default <IrcEventHandler>function (irc, network) {
chanId: chan.id,
msgId: msg.id,
type: msg.type,
time: msg.time,
time: msg.time.getTime(),
text: msg.text,
from: msg.from,
});

View file

@ -1,9 +1,9 @@
"use strict";
import _ from "lodash";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,9 +1,9 @@
"use strict";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import {SpecialChanType, ChanType} from "../../models/chan";
import Chan from "../../models/chan";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,8 +1,8 @@
"use strict";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,6 +1,6 @@
"use strict";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,8 +1,8 @@
"use strict";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,13 +1,17 @@
"use strict";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;
irc.on("part", function (data) {
if (!data.channel) {
return;
}
const chan = network.getChannel(data.channel);
if (typeof chan === "undefined") {

View file

@ -1,8 +1,8 @@
"use strict";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,8 +1,8 @@
"use strict";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,6 +1,7 @@
"use strict";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,8 +1,8 @@
"use strict";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -1,4 +1,5 @@
"use strict";
import {IrcEventHandler} from "../../client";
import Msg from "../../models/msg";

View file

@ -1,8 +1,9 @@
"use strict";
import Network from "../../models/network";
import {IrcEventHandler} from "../../client";
import {ChanType} from "../../models/chan";
import Msg from "../../models/msg";
import Msg, {MessageType} from "../../models/msg";
export default <IrcEventHandler>function (irc, network) {
const client = this;

View file

@ -6,10 +6,11 @@ import log from "../../log";
import path from "path";
import fs from "fs";
import Config from "../../config";
import Msg from "../../models/msg";
import Msg, {Message} from "../../models/msg";
import Client from "../../client";
import Chan from "../../models/chan";
import Chan, {Channel} from "../../models/chan";
import type {SqliteMessageStorage as ISqliteMessageStorage} from "../../types/plugins/messageStorage";
import Network from "../../models/network";
// TODO; type
let sqlite3: any;

View file

@ -7,6 +7,9 @@ import log from "../../log";
import Config from "../../config";
import {MessageStorage} from "../../types/plugins/messageStorage";
import Client from "../../client";
import Channel from "../../models/chan";
import {Message, MessageType} from "../../models/msg";
import Network from "../../models/network";
class TextFileMessageStorage implements MessageStorage {
client: Client;

View file

@ -14,6 +14,14 @@ import fs from "fs";
import Utils from "../../command-line/utils";
import Client from "../../client";
type PackageInfo = {
packageName: string;
thelounge?: {supports: any};
version: string;
type?: string;
files?: string[];
};
const stylesheets: string[] = [];
const files: string[] = [];

View file

@ -1,6 +1,6 @@
import Client from "../../client";
import Chan from "../../models/chan";
import Msg from "../../models/msg";
import Msg, {MessageType, UserInMessage} from "../../models/msg";
export default class PublicClient {
private client: Client;
@ -16,7 +16,7 @@ export default class PublicClient {
* @param {String} command - IRC command to run, this is in the same format that a client would send to the server (eg: JOIN #test)
* @param {String} targetId - The id of the channel to simulate the command coming from. Replies will go to this channel if appropriate
*/
runAsUser(command, targetId) {
runAsUser(command: string, targetId: string) {
this.client.inputLine({target: targetId, text: command});
}
@ -34,7 +34,7 @@ export default class PublicClient {
* @param {String} event - Name of the event, must be something the browser will recognise
* @param {Object} data - Body of the event, can be anything, but will need to be properly interpreted by the client
*/
sendToBrowser(event, data) {
sendToBrowser(event: string, data) {
this.client.emit(event, data);
}
@ -42,7 +42,7 @@ export default class PublicClient {
*
* @param {Number} chanId
*/
getChannel(chanId) {
getChannel(chanId: number) {
return this.client.find(chanId);
}

View file

@ -6,7 +6,24 @@ import _ from "lodash";
import Config from "../../config";
const themes = new Map();
type Module = {
type: string;
name: string;
};
type ThemeModule = Module & {
themeColor: string;
css: string;
};
export type ThemeForClient = {
displayName: string;
filename?: string;
name: string;
themeColor: string | null;
};
const themes = new Map<string, ThemeForClient>();
export default {
addTheme,

View file

@ -5,7 +5,15 @@ import fs from "fs";
import path from "path";
import log from "../log";
import Config from "../config";
import type {PolicyMap, PolicyOption} from "../types/plugins/sts";
type PolicyOption = {
port: number;
duration: number;
expires: number;
host: string;
};
type PolicyMap = Map<string, Omit<PolicyOption, "host">>;
class STSPolicies {
stsFile: string;

View file

@ -16,24 +16,50 @@ import Client from "./client";
import ClientManager from "./clientManager";
import Uploader from "./plugins/uploader";
import Helper from "./helper";
import Config from "./config";
import Config, {ConfigType, Defaults} from "./config";
import Identification from "./identification";
import changelog from "./plugins/changelog";
import inputs from "./plugins/inputs";
import Auth from "./plugins/auth";
import themes from "./plugins/packages/themes";
import themes, {ThemeForClient} from "./plugins/packages/themes";
themes.loadLocalThemes();
import packages from "./plugins/packages/index";
import type {
ClientConfiguration,
Defaults,
IndexTemplateConfiguration,
ServerConfiguration,
} from "./types/config";
import {NetworkWithIrcFramework} from "./models/network";
import {ChanType} from "./models/chan";
import type {ServerOptions} from "./types/server";
type ServerOptions = {
dev: boolean;
};
type ServerConfiguration = ConfigType & {
stylesheets: string[];
};
type IndexTemplateConfiguration = ServerConfiguration & {
cacheBust: string;
};
type ClientConfiguration = Pick<
ConfigType,
"public" | "lockNetwork" | "useHexIp" | "prefetch" | "defaults"
> & {
fileUpload: boolean;
ldapEnabled: boolean;
isUpdateAvailable: boolean;
applicationServerKey: string;
version: string;
gitCommit: string | null;
defaultTheme: string;
themes: ThemeForClient[];
defaults: Defaults & {
sasl?: string;
saslAccount?: string;
saslPassword?: string;
};
fileUploadMaxFileSize?: number;
};
// A random number that will force clients to reload the page if it differs
const serverHash = Math.floor(Date.now() * Math.random());
@ -59,7 +85,7 @@ export default async function (
const app = express();
if (options.dev) {
(await import("./plugins/dev-server.js")).default(app);
(await import("./plugins/dev-server")).default(app);
}
app.set("env", "production")
@ -85,7 +111,7 @@ export default async function (
const themeName = req.params.theme;
const theme = themes.getByName(themeName);
if (theme === undefined) {
if (theme === undefined || theme.filename === undefined) {
return res.status(404).send("Not found");
}

View file

@ -6,10 +6,13 @@
"../client/js/helpers/ircmessageparser/findLinks.ts",
"../client/js/helpers/ircmessageparser/cleanIrcMessage.ts"
],
"ts-node": {
"files": true
},
// TODO: these should be imported from the base config,
// but ts-node doesn't seem to care.
"include": ["**/*"],
"typeRoots": ["./src/types/"],
// "include": ["**/*"],
// "typeRoots": ["./types/"],
"compilerOptions": {
"types": ["node"],

38
src/types/client.d.ts vendored
View file

@ -1,38 +0,0 @@
type ClientConfig = {
log: boolean;
password: string;
sessions: {
[token: string]: {
lastUse: number;
ip: string;
agent: string;
pushSubscription?: ClientPushSubscription;
};
};
clientSettings: {
[key: string]: any;
};
browser?: {
language?: string;
ip?: string;
hostname?: string;
isSecure?: boolean;
};
};
type ClientPushSubscription = {
endpoint: string;
keys: {
p256dh: string;
auth: string;
};
};
type Mention = {
chanId: number;
msgId: number;
type: MessageType;
time: number;
text: string;
from: UserInMessage;
};

118
src/types/config.d.ts vendored
View file

@ -1,118 +0,0 @@
type Config = {
public: boolean;
host: string | undefined;
port: number;
bind: string | undefined;
reverseProxy: boolean;
maxHistory: number;
https: Https;
theme: string;
prefetch: boolean;
disableMediaPreview: boolean;
prefetchStorage: boolean;
prefetchMaxImageSize: number;
prefetchMaxSearchSize: number;
prefetchTimeout: number;
fileUpload: FileUpload;
transports: string[];
leaveMessage: string;
defaults: Defaults;
lockNetwork: boolean;
messageStorage: string[];
useHexIp: boolean;
webirc?: WebIRC;
identd: Identd;
oidentd?: string;
ldap: Ldap;
debug: Debug;
themeColor: string;
};
type ClientConfiguration = Pick<
Config,
"public" | "lockNetwork" | "useHexIp" | "prefetch" | "defaults"
> & {
fileUpload: boolean;
ldapEnabled: boolean;
isUpdateAvailable: boolean;
applicationServerKey: string;
version: string;
gitCommit: string | null;
defaultTheme: string;
themes: ThemeForClient[];
defaults: Defaults & {
sasl?: string;
saslAccount?: string;
saslPassword?: string;
};
fileUploadMaxFileSize?: number;
};
type ServerConfiguration = Config & {
stylesheets: string[];
};
type IndexTemplateConfiguration = ServerConfiguration & {
cacheBust: string;
};
// TODO: Type this
type WebIRC = {
[key: string]: any;
};
type Https = {
enable: boolean;
key: string;
certificate: string;
ca: string;
};
export type FileUpload = {
enable: boolean;
maxFileSize: number;
baseUrl?: string;
};
export type Defaults = {
name: string;
host: string;
port: number;
password: string;
tls: boolean;
rejectUnauthorized: boolean;
nick: string;
username: string;
realname: string;
join: string;
leaveMessage: string;
};
export type Identd = {
enable: boolean;
port: number;
};
export type Ldap = {
enable: boolean;
url: string;
tlsOptions: any;
primaryKey: string;
searchDN: SearchDN;
baseDN?: string;
};
export type TlsOptions = any;
export type SearchDN = {
rootDN: string;
rootPassword: string;
filter: string;
base: string;
scope: string;
};
export type Debug = {
ircFramework: boolean;
raw: boolean;
};

View file

@ -1,5 +0,0 @@
export type Hostmask = {
nick: string;
ident: string;
hostname: string;
};

View file

@ -1,6 +1,2 @@
// / <reference path="models/index.d.ts" />
// / <reference path="plugins/index.d.ts" />
// / <reference path="config.d.ts" />
// / <reference path="helper.d.ts" />
// / <reference path="server.d.ts" />
// / <reference path="client.d.ts" />
import "./modules";
import "./plugins";

View file

@ -1,29 +0,0 @@
import Chan from "../../models/chan";
declare global {
export type Channel = Chan;
export type FilteredChannel = Chan & {
users: [];
totalMessages: number;
};
export enum ChanType {
CHANNEL = "channel",
LOBBY = "lobby",
QUERY = "query",
SPECIAL = "special",
}
export enum SpecialChanType {
BANLIST = "list_bans",
INVITELIST = "list_invites",
CHANNELLIST = "list_channels",
IGNORELIST = "list_ignored",
}
export enum ChanState {
PARTED = 0,
JOINED = 1,
}
}

View file

@ -1,5 +0,0 @@
// / <reference path="channel.d.ts" />
// / <reference path="prefix.d.ts" />
// / <reference path="message.d.ts" />
// / <reference path="user.d.ts" />
// / <reference path="network.d.ts" />

View file

@ -1,46 +0,0 @@
import Msg from "../../models/msg";
declare global {
type Message = Msg;
type UserInMessage = Partial<User> & {
mode: string;
};
type MessagePreview = {
shown: boolean;
link: string;
body: string;
};
export enum MessageType {
UNHANDLED = "unhandled",
ACTION = "action",
AWAY = "away",
BACK = "back",
ERROR = "error",
INVITE = "invite",
JOIN = "join",
KICK = "kick",
LOGIN = "login",
LOGOUT = "logout",
MESSAGE = "message",
MODE = "mode",
MODE_CHANNEL = "mode_channel",
MODE_USER = "mode_user", // RPL_UMODEIS
MONOSPACE_BLOCK = "monospace_block",
NICK = "nick",
NOTICE = "notice",
PART = "part",
QUIT = "quit",
CTCP = "ctcp",
CTCP_REQUEST = "ctcp_request",
CHGHOST = "chghost",
TOPIC = "topic",
TOPIC_SET_BY = "topic_set_by",
WHOIS = "whois",
RAW = "raw",
PLUGIN = "plugin",
WALLOPS = "wallops",
}
}

View file

@ -1,51 +0,0 @@
import NetworkClass from "../../models/network";
import {Client as IRCClient} from "irc-framework";
import {WebIRC} from "../config";
declare global {
export type Network = NetworkClass;
type NetworkIrcOptions = {
host: string;
port: number;
password: string;
nick: string;
username: string;
gecos: string;
tls: boolean;
rejectUnauthorized: boolean;
webirc: WebIRC;
client_certificate: ClientCertificate | null;
socks?: {
host: string;
port: number;
user: string;
pass: string;
};
sasl_mechanism?: string;
account?:
| {
account: string;
password: string;
}
| {};
};
type NonNullableIRCWithOptions = NonNullable<IRCClient & {options: NetworkIrcOptions}>;
type NetworkWithIrcFramework = Network & {
irc: NonNullable<Network["irc"]> & {
options: NonNullableIRCWithOptions;
};
};
type NetworkStatus = {
connected: boolean;
secure: boolean;
};
type IgnoreListItem = Hostmask & {
when?: number;
};
type IgnoreList = IgnoreListItem[];
}

View file

@ -1,6 +0,0 @@
type PrefixSymbol = string;
type PrefixObject = {
symbol: PrefixSymbol;
mode: string;
};

View file

@ -1,4 +0,0 @@
import UserClass from "models/user";
declare global {
export type User = UserClass;
}

View file

@ -19,6 +19,83 @@ declare module "irc-framework" {
end: () => void;
};
export interface MessageEventArgs {
account?: any;
group?: any;
hostname: string;
ident: string;
message: string;
nick: string;
reply: (message: string) => void;
tags: {[key: string]: string};
target: string;
time?: any;
type: "privmsg" | "action"; // TODO
}
export interface JoinEventArgs {
// todo: is that wrong?
account: boolean;
channel: string;
gecos: string;
hostname: string;
ident: string;
nick: string;
time?: any;
}
export interface KickEventArgs {
kicked: string;
nick: string;
ident: string;
hostname: string;
channel: string;
message: string;
time: number;
}
export interface RawEventArgs {
from_server: boolean;
line: string;
}
export interface RegisteredEventArgs {
nick: string;
}
export interface QuitEventArgs {
hostname: string;
ident: string;
message: string;
nick: string;
time?: any;
channel?: string;
kicked?: string;
}
interface Mode {
mode: string;
param: string;
}
export interface ModeEventArgs {
modes: Mode[];
nick: string;
raw_modes: string;
raw_params: string[];
target: string;
time?: any;
}
export interface ServerOptionsEventArgs {
options: any;
cap: any;
}
export interface NickInvalidEventArgs {
nick: string;
reason: string;
}
export interface NickInUseEventArgs {
nick: string;
reason: string;
}
export interface IrcErrorEventArgs {
error: string;
channel: string;
reason: string;
}
export class Client extends EventEmitter {
constructor(options: ClientConstructorParameters);
@ -176,11 +253,11 @@ declare module "irc-framework" {
on(eventType: "mode", cb: (event: ModeEventArgs) => any): this;
on(eventType: "socket close", cb: (event: {}) => any): this;
on(eventType: "socket close", cb: (event: Record<string, unknown>) => any): this;
on(eventType: "socket connected", cb: (event: {}) => any): this;
on(eventType: "socket connected", cb: (event: Record<string, unknown>) => any): this;
on(eventType: "raw socket connected", cb: (event: {}) => any): this;
on(eventType: "raw socket connected", cb: (event: Record<string, unknown>) => any): this;
on(eventType: "server options", cb: (event: ServerOptionsEventArgs) => any): this;
@ -217,83 +294,7 @@ declare module "irc-framework" {
type: string;
}
export interface MessageEventArgs {
account?: any;
group?: any;
hostname: string;
ident: string;
message: string;
nick: string;
reply: (message: string) => void;
tags: {[key: string]: string};
target: string;
time?: any;
type: "privmsg" | "action"; // TODO
}
export interface JoinEventArgs {
// todo: is that wrong?
account: boolean;
channel: string;
gecos: string;
hostname: string;
ident: string;
nick: string;
time?: any;
}
export interface KickEventArgs {
kicked: string;
nick: string;
ident: string;
hostname: string;
channel: string;
message: string;
time: number;
}
export interface RawEventArgs {
from_server: boolean;
line: string;
}
export interface RegisteredEventArgs {
nick: string;
}
export interface QuitEventArgs {
hostname: string;
ident: string;
message: string;
nick: string;
time?: any;
channel?: string;
kicked?: string;
}
interface Mode {
mode: string;
param: string;
}
export interface ModeEventArgs {
modes: Mode[];
nick: string;
raw_modes: string;
raw_params: string[];
target: string;
time?: any;
}
export interface ServerOptionsEventArgs {
options: any;
cap: any;
}
export interface NickInvalidEventArgs {
nick: string;
reason: string;
}
export interface NickInUseEventArgs {
nick: string;
reason: string;
}
export interface IrcErrorEventArgs {
error: string;
channel: string;
reason: string;
}
// interface IrcUser {
// /**The current nick you are currently using.*/
// nick: string;

View file

@ -1,2 +0,0 @@
// / <reference path="themes.d.ts" />
// / <reference path="packages.d.ts" />

View file

@ -1,7 +0,0 @@
type PackageInfo = {
packageName: string;
thelounge?: {supports: any};
version: string;
type?: string;
files?: string[];
};

View file

@ -1,17 +0,0 @@
// TODO: move to index.d.ts when more types are added
type Module = {
type: string;
name: string;
};
type ThemeModule = Module & {
themeColor: string;
css: string;
};
type ThemeForClient = {
displayName: string;
filename?: string;
name: string;
themeColor: string | null;
};

View file

@ -1,10 +0,0 @@
import Client from "../../client";
import ClientManager from "../../clientManager";
type AuthHandler = (
manager: ClientManager,
client: Client,
user: string,
password: string,
callback: (success: boolean) => void
) => void;

View file

@ -1,4 +0,0 @@
type ClientCertificate = {
private_key: string;
certificate: string;
};

View file

@ -1,7 +1 @@
// / <reference path="sts.d.ts" />
// / <reference path="messageStorage/index.d.ts" />
// / <reference path="clientCertificate.d.ts" />
// / <reference path="preview.d.ts" />
// / <reference path="inputs/index.d.ts" />
// / <reference path="irc-events/index.d.ts" />
// / <reference path="auth/index.d.ts" />
import "./messageStorage";

View file

@ -1,11 +0,0 @@
import Client from "../../../client";
declare global {
type PluginInputHandler = (
this: Client,
network: NetworkWithIrcFramework,
chan: Channel,
cmd: string,
args: string[]
) => void;
}

View file

@ -1,9 +0,0 @@
import Client from "../../client";
declare global {
type IrcEventHandler = (
this: Client,
irc: NetworkWithIrcFramework["irc"],
network: NetworkWithIrcFramework
) => void;
}

View file

@ -1,13 +0,0 @@
import Msg from "../../models/msg";
type Preview = {
type: string;
head: string;
body: string;
thumb: string;
size: number;
link: string; // Send original matched link to the client
shown: boolean | null;
error: undefined | any;
message: undefined | string;
};

View file

@ -1,8 +0,0 @@
type PolicyOption = {
port: number;
duration: number;
expires: number;
host: string;
};
export type PolicyMap = Map<string, Omit<PolicyOption, "host">>;

View file

@ -1,3 +0,0 @@
export type ServerOptions = {
dev: boolean;
};

View file

@ -1,5 +0,0 @@
type RequiredNotNull<T> = {
[P in keyof T]: NonNullable<T[P]>;
};
type Ensure<T, K extends keyof T> = T & RequiredNotNull<Pick<T, K>>;

View file

@ -1,18 +1,6 @@
{
"extends": "./tsconfig.base.json",
"files": ["index.ts", "./src/index.d.ts", "./webpack.config.ts", "./src/helper.ts"],
"compilerOptions": {
"types": ["node"],
"paths": {
"@src/*": ["src/*"],
"@client/*": ["client/*"]
}
},
"ts-node": {
"files": true
},
"exclude": ["./node_modules"],
"include": ["./src/**/*"],
"files": ["./webpack.config.ts", "./babel.config.cjs", "./src/helper.ts"],
"references": [
{
"path": "./src"

View file

@ -1665,6 +1665,11 @@
dependencies:
"@types/node" "*"
"@types/webpack-env@1.16.4":
version "1.16.4"
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.16.4.tgz#1f4969042bf76d7ef7b5914f59b3b60073f4e1f4"
integrity sha512-llS8qveOUX3wxHnSykP5hlYFFuMfJ9p5JvIyCiBgp7WTfl6K5ZcyHj8r8JsN/J6QODkAsRRCLIcTuOCu8etkUw==
"@types/ws@8.5.3":
version "8.5.3"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d"