Merge branch 'master' into feature/socks-support
This commit is contained in:
commit
d106889127
@ -2,7 +2,7 @@
|
||||
root: true
|
||||
|
||||
parserOptions:
|
||||
ecmaVersion: 2018
|
||||
ecmaVersion: 2020
|
||||
|
||||
env:
|
||||
es6: true
|
||||
|
2
.github/ISSUE_TEMPLATE/Bug_Report.md
vendored
2
.github/ISSUE_TEMPLATE/Bug_Report.md
vendored
@ -4,7 +4,7 @@ about: Create a bug report
|
||||
labels: "Type: Bug"
|
||||
---
|
||||
|
||||
<!-- Have a question? Join #thelounge on freenode -->
|
||||
<!-- Have a question? Join #thelounge on Libera.Chat -->
|
||||
|
||||
- _Node version:_
|
||||
- _Browser version:_
|
||||
|
2
.github/ISSUE_TEMPLATE/Feature_Request.md
vendored
2
.github/ISSUE_TEMPLATE/Feature_Request.md
vendored
@ -4,7 +4,7 @@ about: Request a new feature
|
||||
labels: "Type: Feature"
|
||||
---
|
||||
|
||||
<!-- Have a question? Join #thelounge on freenode. -->
|
||||
<!-- Have a question? Join #thelounge on Libera.Chat. -->
|
||||
<!-- Make sure to check the existing issues prior to submitting your suggestion. -->
|
||||
|
||||
### Feature Description
|
||||
|
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -13,4 +13,4 @@ contact_links:
|
||||
|
||||
- name: General support
|
||||
url: https://demo.thelounge.chat/?join=%23thelounge
|
||||
about: "Join #thelounge on Freenode to ask a question before creating an issue"
|
||||
about: "Join #thelounge on Libera.Chat to ask a question before creating an issue"
|
||||
|
2
.github/SUPPORT.md
vendored
2
.github/SUPPORT.md
vendored
@ -6,6 +6,6 @@ need help, you have a few options:
|
||||
- Check out [existing questions on Stack Overflow](https://stackoverflow.com/questions/tagged/thelounge)
|
||||
to see if yours has been answered before. If not, feel free to [ask for a new question](https://stackoverflow.com/questions/ask?tags=thelounge)
|
||||
(using `thelounge` tag so that other people can easily find it).
|
||||
- Find us on the Freenode channel `#thelounge`. You might not get an answer
|
||||
- Find us on the Libera.Chat channel `#thelounge`. You might not get an answer
|
||||
right away, but this channel is full of nice people who will be happy to
|
||||
help you.
|
||||
|
15
CHANGELOG.md
15
CHANGELOG.md
@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
<!-- New entries go after this line -->
|
||||
|
||||
## v4.3.0-pre.2 - 2021-06-07 [Pre-release]
|
||||
|
||||
[See the full changelog](https://github.com/thelounge/thelounge/compare/v4.3.0-pre.1...v4.3.0-pre.2)
|
||||
|
||||
This is a pre-release for v4.3.0 to offer latest changes without having to wait for a stable release.
|
||||
At this stage, features may still be added or modified until the first release candidate for this version gets released.
|
||||
|
||||
Please refer to the commit list given above for a complete list of changes, or wait for the stable release to get a thoroughly prepared change log entry.
|
||||
|
||||
As with all pre-releases, this version requires explicit use of the `next` tag to be installed:
|
||||
|
||||
```sh
|
||||
yarn global add thelounge@next
|
||||
```
|
||||
|
||||
## v4.3.0-pre.1 - 2021-03-02 [Pre-release]
|
||||
|
||||
[See the full changelog](https://github.com/thelounge/thelounge/compare/v4.2.0...v4.3.0-pre.1)
|
||||
|
@ -20,8 +20,8 @@
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://demo.thelounge.chat/"><img
|
||||
alt="#thelounge IRC channel on freenode"
|
||||
src="https://img.shields.io/badge/freenode-%23thelounge-415364.svg?colorA=ff9e18"></a>
|
||||
alt="#thelounge IRC channel on Libera.Chat"
|
||||
src="https://img.shields.io/badge/Libera.Chat-%23thelounge-415364.svg?colorA=ff9e18"></a>
|
||||
<a href="https://yarn.pm/thelounge"><img
|
||||
alt="npm version"
|
||||
src="https://img.shields.io/npm/v/thelounge.svg?colorA=333a41&maxAge=3600"></a>
|
||||
|
@ -4,6 +4,6 @@
|
||||
- Contact us privately first, in a
|
||||
[responsible disclosure](https://en.wikipedia.org/wiki/Responsible_disclosure)
|
||||
manner.
|
||||
- On IRC, send a private message to any voiced user on our Freenode channel,
|
||||
- On IRC, send a private message to any voiced user on our Libera.Chat channel,
|
||||
`#thelounge`.
|
||||
- By email, send us your report at <security@thelounge.chat>.
|
||||
|
@ -51,6 +51,7 @@ export default {
|
||||
Mousetrap.bind("esc", this.escapeKey);
|
||||
Mousetrap.bind("alt+u", this.toggleUserList);
|
||||
Mousetrap.bind("alt+s", this.toggleSidebar);
|
||||
Mousetrap.bind("alt+m", this.toggleMentions);
|
||||
|
||||
// Make a single throttled resize listener available to all components
|
||||
this.debouncedResize = throttle(() => {
|
||||
@ -72,6 +73,7 @@ export default {
|
||||
Mousetrap.unbind("esc", this.escapeKey);
|
||||
Mousetrap.unbind("alt+u", this.toggleUserList);
|
||||
Mousetrap.unbind("alt+s", this.toggleSidebar);
|
||||
Mousetrap.unbind("alt+m", this.toggleMentions);
|
||||
|
||||
window.removeEventListener("resize", this.debouncedResize);
|
||||
clearTimeout(this.dayChangeTimeout);
|
||||
@ -98,6 +100,11 @@ export default {
|
||||
|
||||
return false;
|
||||
},
|
||||
toggleMentions() {
|
||||
if (this.$store.state.networks.length !== 0) {
|
||||
eventbus.emit("mentions:toggle");
|
||||
}
|
||||
},
|
||||
msUntilNextDay() {
|
||||
// Compute how many milliseconds are remaining until the next day starts
|
||||
const today = new Date();
|
||||
|
@ -183,6 +183,10 @@ export default {
|
||||
},
|
||||
setInputSize() {
|
||||
this.$nextTick(() => {
|
||||
if (!this.$refs.input) {
|
||||
return;
|
||||
}
|
||||
|
||||
const style = window.getComputedStyle(this.$refs.input);
|
||||
const lineHeight = parseFloat(style.lineHeight, 10) || 1;
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
<input
|
||||
ref="searchInputField"
|
||||
v-model="searchInput"
|
||||
type="text"
|
||||
type="search"
|
||||
name="search"
|
||||
class="input"
|
||||
placeholder="Search messages…"
|
||||
@ -104,6 +104,10 @@ export default {
|
||||
mounted() {
|
||||
this.searchInput = this.$route.query.q;
|
||||
this.searchOpened = this.onSearchPage;
|
||||
|
||||
if (!this.searchInput && this.searchOpened) {
|
||||
this.$refs.searchInputField.focus();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closeSearch() {
|
||||
|
@ -6,17 +6,20 @@
|
||||
>username to <b>{{ message.new_ident }}</b></span
|
||||
>
|
||||
<span v-if="message.new_host"
|
||||
>hostname to <i class="hostmask">{{ message.new_host }}</i></span
|
||||
>
|
||||
>hostname to
|
||||
<i class="hostmask"><ParsedMessage :network="network" :text="message.new_host" /></i
|
||||
></span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ParsedMessage from "../ParsedMessage.vue";
|
||||
import Username from "../Username.vue";
|
||||
|
||||
export default {
|
||||
name: "MessageTypeChangeHost",
|
||||
components: {
|
||||
ParsedMessage,
|
||||
Username,
|
||||
},
|
||||
props: {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<span class="content">
|
||||
<Username :user="message.from" />
|
||||
<i class="hostmask"> ({{ message.hostmask }})</i>
|
||||
<i class="hostmask"> (<ParsedMessage :network="network" :text="message.hostmask" />)</i>
|
||||
<template v-if="message.account">
|
||||
<i class="account"> [{{ message.account }}]</i>
|
||||
</template>
|
||||
@ -13,11 +13,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ParsedMessage from "../ParsedMessage.vue";
|
||||
import Username from "../Username.vue";
|
||||
|
||||
export default {
|
||||
name: "MessageTypeJoin",
|
||||
components: {
|
||||
ParsedMessage,
|
||||
Username,
|
||||
},
|
||||
props: {
|
||||
|
@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<span class="content">
|
||||
<Username :user="message.from" />
|
||||
<i class="hostmask"> ({{ message.hostmask }})</i> has left the channel
|
||||
<i class="hostmask"> (<ParsedMessage :network="network" :text="message.hostmask" />)</i> has
|
||||
left the channel
|
||||
<i v-if="message.text" class="part-reason"
|
||||
>(<ParsedMessage :network="network" :message="message" />)</i
|
||||
>
|
||||
|
@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<span class="content">
|
||||
<Username :user="message.from" />
|
||||
<i class="hostmask"> ({{ message.hostmask }})</i> has quit
|
||||
<i class="hostmask"> (<ParsedMessage :network="network" :text="message.hostmask" />)</i> has
|
||||
quit
|
||||
<i v-if="message.text" class="quit-reason"
|
||||
>(<ParsedMessage :network="network" :message="message" />)</i
|
||||
>
|
||||
|
@ -12,7 +12,12 @@
|
||||
</template>
|
||||
|
||||
<dt>Host mask:</dt>
|
||||
<dd class="hostmask">{{ message.whois.ident }}@{{ message.whois.hostname }}</dd>
|
||||
<dd class="hostmask">
|
||||
<ParsedMessage
|
||||
:network="network"
|
||||
:text="message.whois.ident + '@' + message.whois.hostname"
|
||||
/>
|
||||
</dd>
|
||||
|
||||
<template v-if="message.whois.actual_hostname">
|
||||
<dt>Actual host:</dt>
|
||||
|
@ -9,7 +9,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="ban in channel.data" :key="ban.hostmask">
|
||||
<td class="hostmask">{{ ban.hostmask }}</td>
|
||||
<td class="hostmask"><ParsedMessage :network="network" :text="ban.hostmask" /></td>
|
||||
<td class="banned_by">{{ ban.banned_by }}</td>
|
||||
<td class="banned_at">{{ localetime(ban.banned_at) }}</td>
|
||||
</tr>
|
||||
@ -18,10 +18,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ParsedMessage from "../ParsedMessage.vue";
|
||||
import localetime from "../../js/helpers/localetime";
|
||||
|
||||
export default {
|
||||
name: "ListBans",
|
||||
components: {
|
||||
ParsedMessage,
|
||||
},
|
||||
props: {
|
||||
network: Object,
|
||||
channel: Object,
|
||||
|
@ -8,7 +8,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="user in channel.data" :key="user.hostmask">
|
||||
<td class="hostmask">{{ user.hostmask }}</td>
|
||||
<td class="hostmask"><ParsedMessage :network="network" :text="user.hostmask" /></td>
|
||||
<td class="when">{{ localetime(user.when) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -16,10 +16,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ParsedMessage from "../ParsedMessage.vue";
|
||||
import localetime from "../../js/helpers/localetime";
|
||||
|
||||
export default {
|
||||
name: "ListIgnored",
|
||||
components: {
|
||||
ParsedMessage,
|
||||
},
|
||||
props: {
|
||||
network: Object,
|
||||
channel: Object,
|
||||
|
@ -9,7 +9,9 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="invite in channel.data" :key="invite.hostmask">
|
||||
<td class="hostmask">{{ invite.hostmask }}</td>
|
||||
<td class="hostmask">
|
||||
<ParsedMessage :network="network" :text="invite.hostmask" />
|
||||
</td>
|
||||
<td class="invitened_by">{{ invite.invited_by }}</td>
|
||||
<td class="invitened_at">{{ localetime(invite.invited_at) }}</td>
|
||||
</tr>
|
||||
@ -18,10 +20,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ParsedMessage from "../ParsedMessage.vue";
|
||||
import localetime from "../../js/helpers/localetime";
|
||||
|
||||
export default {
|
||||
name: "ListInvites",
|
||||
components: {
|
||||
ParsedMessage,
|
||||
},
|
||||
props: {
|
||||
network: Object,
|
||||
channel: Object,
|
||||
|
@ -189,6 +189,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="help-item">
|
||||
<div class="subject">
|
||||
<span v-if="!isApple"><kbd>Alt</kbd> <kbd>M</kbd></span>
|
||||
<span v-else><kbd>⌥</kbd> <kbd>M</kbd></span>
|
||||
</div>
|
||||
<div class="description">
|
||||
<p>Toggle recent mentions popup.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="help-item">
|
||||
<div class="subject">
|
||||
<span><kbd>Esc</kbd></span>
|
||||
@ -673,6 +683,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="help-item">
|
||||
<div class="subject">
|
||||
<code>/search query</code>
|
||||
</div>
|
||||
<div class="description">
|
||||
<p>Search for messages in the current channel / user</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="help-item">
|
||||
<div class="subject">
|
||||
<code>/topic [newtopic]</code>
|
||||
|
@ -1195,7 +1195,6 @@ textarea.input {
|
||||
}
|
||||
|
||||
#chat .show-more {
|
||||
margin-top: 50px;
|
||||
padding: 10px;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 0;
|
||||
@ -1508,8 +1507,11 @@ textarea.input {
|
||||
}
|
||||
|
||||
#chat .msg[data-type="notice"] .time,
|
||||
#chat .msg[data-type="wallops"] .time,
|
||||
#chat .msg[data-type="notice"] .content,
|
||||
#chat .msg[data-type="notice"] .user {
|
||||
#chat .msg[data-type="wallops"] .content,
|
||||
#chat .msg[data-type="notice"] .user,
|
||||
#chat .msg[data-type="wallops"] .user {
|
||||
color: #0074d9;
|
||||
}
|
||||
|
||||
@ -1517,6 +1519,10 @@ textarea.input {
|
||||
content: "Notice: ";
|
||||
}
|
||||
|
||||
#chat .msg[data-type="wallops"] .from .user::before {
|
||||
content: "Wallops: ";
|
||||
}
|
||||
|
||||
#chat .msg[data-type="error"],
|
||||
#chat .msg[data-type="error"] .from {
|
||||
color: #e74c3c;
|
||||
|
20
client/js/commands/search.js
Normal file
20
client/js/commands/search.js
Normal file
@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
|
||||
import store from "../store";
|
||||
import {router} from "../router";
|
||||
|
||||
function input(args) {
|
||||
router.push({
|
||||
name: "SearchResults",
|
||||
params: {
|
||||
id: store.state.activeChannel.channel.id,
|
||||
},
|
||||
query: {
|
||||
q: args.join(" "),
|
||||
},
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export default {input};
|
@ -6,17 +6,24 @@ import socket from "../socket";
|
||||
import store from "../store";
|
||||
|
||||
socket.on("more", function (data) {
|
||||
const channel = store.getters.findChannel(data.chan);
|
||||
const channel = store.getters.findChannel(data.chan)?.channel;
|
||||
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
channel.channel.moreHistoryAvailable =
|
||||
data.totalMessages > channel.channel.messages.length + data.messages.length;
|
||||
channel.channel.messages.unshift(...data.messages);
|
||||
channel.inputHistory = channel.inputHistory.concat(
|
||||
data.messages
|
||||
.filter((m) => m.self && m.text && m.type === "message")
|
||||
.map((m) => m.text)
|
||||
.reverse()
|
||||
.slice(null, 100 - channel.inputHistory.length)
|
||||
);
|
||||
channel.moreHistoryAvailable =
|
||||
data.totalMessages > channel.messages.length + data.messages.length;
|
||||
channel.messages.unshift(...data.messages);
|
||||
|
||||
Vue.nextTick(() => {
|
||||
channel.channel.historyLoading = false;
|
||||
channel.historyLoading = false;
|
||||
});
|
||||
});
|
||||
|
@ -190,7 +190,14 @@ const store = new Vuex.Store({
|
||||
// TODO: This should be a mutation
|
||||
channel.pendingMessage = "";
|
||||
channel.inputHistoryPosition = 0;
|
||||
channel.inputHistory = [""];
|
||||
|
||||
channel.inputHistory = [""].concat(
|
||||
channel.messages
|
||||
.filter((m) => m.self && m.text && m.type === "message")
|
||||
.map((m) => m.text)
|
||||
.reverse()
|
||||
.slice(null, 99)
|
||||
);
|
||||
channel.historyLoading = false;
|
||||
channel.scrolledToBottom = true;
|
||||
channel.editTopic = false;
|
||||
|
@ -231,12 +231,12 @@ module.exports = {
|
||||
// - `join`: Comma-separated list of channels to auto-join once connected.
|
||||
//
|
||||
// This value is set to connect to the official channel of The Lounge on
|
||||
// Freenode by default:
|
||||
// Libera.Chat by default:
|
||||
//
|
||||
// ```js
|
||||
// defaults: {
|
||||
// name: "Freenode",
|
||||
// host: "chat.freenode.net",
|
||||
// name: "Libera.Chat",
|
||||
// host: "irc.libera.chat",
|
||||
// port: 6697,
|
||||
// password: "",
|
||||
// tls: true,
|
||||
@ -248,8 +248,8 @@ module.exports = {
|
||||
// }
|
||||
// ```
|
||||
defaults: {
|
||||
name: "Freenode",
|
||||
host: "chat.freenode.net",
|
||||
name: "Libera.Chat",
|
||||
host: "irc.libera.chat",
|
||||
port: 6697,
|
||||
password: "",
|
||||
tls: true,
|
||||
|
16
package.json
16
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "thelounge",
|
||||
"description": "The self-hosted Web IRC client",
|
||||
"version": "4.3.0-pre.1",
|
||||
"version": "4.3.0-pre.2",
|
||||
"preferGlobal": true,
|
||||
"bin": {
|
||||
"thelounge": "index.js"
|
||||
@ -43,18 +43,18 @@
|
||||
"bcryptjs": "2.4.3",
|
||||
"busboy": "0.3.1",
|
||||
"chalk": "4.1.1",
|
||||
"cheerio": "1.0.0-rc.5",
|
||||
"cheerio": "1.0.0-rc.10",
|
||||
"commander": "7.2.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"express": "4.17.1",
|
||||
"file-type": "16.2.0",
|
||||
"filenamify": "4.2.0",
|
||||
"got": "11.8.1",
|
||||
"irc-framework": "github:mstrodl/irc-framework#feature/fix-socks",
|
||||
"irc-framework": "4.11.0",
|
||||
"is-utf8": "0.2.1",
|
||||
"ldapjs": "2.2.3",
|
||||
"linkify-it": "3.0.2",
|
||||
"lodash": "4.17.20",
|
||||
"lodash": "4.17.21",
|
||||
"mime-types": "2.1.28",
|
||||
"node-forge": "0.10.0",
|
||||
"package-json": "6.5.0",
|
||||
@ -73,8 +73,8 @@
|
||||
"sqlite3": "5.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.14.0",
|
||||
"@babel/preset-env": "7.14.0",
|
||||
"@babel/core": "7.14.6",
|
||||
"@babel/preset-env": "7.14.7",
|
||||
"@fortawesome/fontawesome-free": "5.15.3",
|
||||
"@vue/server-test-utils": "1.1.3",
|
||||
"@vue/test-utils": "1.1.3",
|
||||
@ -83,8 +83,8 @@
|
||||
"chai": "4.3.4",
|
||||
"copy-webpack-plugin": "7.0.0",
|
||||
"css-loader": "5.1.1",
|
||||
"cssnano": "4.1.10",
|
||||
"dayjs": "1.10.4",
|
||||
"cssnano": "4.1.11",
|
||||
"dayjs": "1.10.5",
|
||||
"emoji-regex": "9.2.1",
|
||||
"eslint": "7.23.0",
|
||||
"eslint-config-prettier": "6.15.0",
|
||||
|
@ -34,7 +34,7 @@ try {
|
||||
createPackagesFolder();
|
||||
|
||||
// Merge config key-values passed as CLI options into the main config
|
||||
Helper.mergeConfig(Helper.config, program.config);
|
||||
Helper.mergeConfig(Helper.config, program.opts().config);
|
||||
|
||||
require("./start");
|
||||
|
||||
|
@ -13,6 +13,8 @@ program
|
||||
.on("--help", Utils.extraHelp)
|
||||
.action(function (packageName) {
|
||||
const fs = require("fs");
|
||||
const fspromises = fs.promises;
|
||||
const path = require("path");
|
||||
const packageJson = require("package-json");
|
||||
|
||||
if (!fs.existsSync(Helper.getConfigPath())) {
|
||||
@ -21,22 +23,31 @@ program
|
||||
}
|
||||
|
||||
log.info("Retrieving information about the package...");
|
||||
let readFile = null;
|
||||
let isLocalFile = false;
|
||||
|
||||
if (packageName.startsWith("file:")) {
|
||||
isLocalFile = true;
|
||||
readFile = fspromises
|
||||
.readFile(path.join(packageName.substr("file:".length), "package.json"), "utf-8")
|
||||
.then((data) => JSON.parse(data));
|
||||
} else {
|
||||
const split = packageName.split("@");
|
||||
packageName = split[0];
|
||||
const packageVersion = split[1] || "latest";
|
||||
|
||||
packageJson(packageName, {
|
||||
readFile = packageJson(packageName, {
|
||||
fullMetadata: true,
|
||||
version: packageVersion,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
readFile
|
||||
.then((json) => {
|
||||
const humanVersion = isLocalFile ? packageName : `${json.name} v${json.version}`;
|
||||
|
||||
if (!("thelounge" in json)) {
|
||||
log.error(
|
||||
`${colors.red(
|
||||
json.name + " v" + json.version
|
||||
)} does not have The Lounge metadata.`
|
||||
);
|
||||
log.error(`${colors.red(humanVersion)} does not have The Lounge metadata.`);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
@ -47,7 +58,7 @@ program
|
||||
) {
|
||||
log.error(
|
||||
`${colors.red(
|
||||
json.name + " v" + json.version
|
||||
humanVersion
|
||||
)} does not support The Lounge v${Helper.getVersionNumber()}. Supported version(s): ${
|
||||
json.thelounge.supports
|
||||
}`
|
||||
@ -56,20 +67,23 @@ program
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
log.info(`Installing ${colors.green(json.name + " v" + json.version)}...`);
|
||||
|
||||
return Utils.executeYarnCommand("add", "--exact", `${json.name}@${json.version}`)
|
||||
log.info(`Installing ${colors.green(humanVersion)}...`);
|
||||
const yarnVersion = isLocalFile ? packageName : `${json.name}@${json.version}`;
|
||||
return Utils.executeYarnCommand("add", "--exact", yarnVersion)
|
||||
.then(() => {
|
||||
log.info(
|
||||
`${colors.green(
|
||||
json.name + " v" + json.version
|
||||
)} has been successfully installed.`
|
||||
);
|
||||
log.info(`${colors.green(humanVersion)} has been successfully installed.`);
|
||||
|
||||
if (isLocalFile) {
|
||||
// yarn v1 is buggy if a local filepath is used and doesn't update
|
||||
// the lockfile properly. We need to run an install in that case
|
||||
// even though that's supposed to be done by the add subcommand
|
||||
return Utils.executeYarnCommand("install").catch((err) => {
|
||||
throw `Failed to update lockfile after package install ${err}`;
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((code) => {
|
||||
throw `Failed to install ${colors.green(
|
||||
json.name + " v" + json.version
|
||||
)}. Exit code: ${code}`;
|
||||
throw `Failed to install ${colors.red(humanVersion)}. Exit code: ${code}`;
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
|
@ -79,6 +79,7 @@ Msg.Type = {
|
||||
WHOIS: "whois",
|
||||
RAW: "raw",
|
||||
PLUGIN: "plugin",
|
||||
WALLOPS: "wallops",
|
||||
};
|
||||
|
||||
module.exports = Msg;
|
||||
|
@ -1,4 +1,4 @@
|
||||
const clientSideCommands = ["/collapse", "/expand"];
|
||||
const clientSideCommands = ["/collapse", "/expand", "/search"];
|
||||
|
||||
const passThroughCommands = [
|
||||
"/as",
|
||||
|
@ -222,6 +222,7 @@ function parse(msg, chan, preview, res, client) {
|
||||
case "image/gif":
|
||||
case "image/jpg":
|
||||
case "image/jpeg":
|
||||
case "image/jxl":
|
||||
case "image/webp":
|
||||
case "image/avif":
|
||||
if (!Helper.config.prefetchStorage && Helper.config.disableMediaPreview) {
|
||||
|
@ -33,7 +33,7 @@ module.exports = function (irc, network) {
|
||||
|
||||
irc.on("wallops", function (data) {
|
||||
data.from_server = true;
|
||||
data.type = Msg.Type.NOTICE;
|
||||
data.type = Msg.Type.WALLOPS;
|
||||
handleMessage(data);
|
||||
});
|
||||
|
||||
@ -51,8 +51,13 @@ module.exports = function (irc, network) {
|
||||
return Helper.compareHostmask(entry, data);
|
||||
});
|
||||
|
||||
// Server messages go to server window, no questions asked
|
||||
if (data.from_server) {
|
||||
// Server messages that aren't targeted at a channel go to the server window
|
||||
if (
|
||||
data.from_server &&
|
||||
(!data.target ||
|
||||
!network.getChannel(data.target) ||
|
||||
network.getChannel(data.target).type !== Chan.Type.CHANNEL)
|
||||
) {
|
||||
chan = network.channels[0];
|
||||
from = chan.getUser(data.nick);
|
||||
} else {
|
||||
|
@ -29,6 +29,7 @@ const inlineContentDispositionTypes = {
|
||||
"image/png": "image.png",
|
||||
"image/webp": "image.webp",
|
||||
"image/avif": "image.avif",
|
||||
"image/jxl": "image.jxl",
|
||||
"text/plain": "text.txt",
|
||||
"video/mp4": "video.mp4",
|
||||
"video/ogg": "video.ogv",
|
||||
|
@ -55,8 +55,8 @@ describe("cleanIrcMessage", function () {
|
||||
expected: "bold bold",
|
||||
},
|
||||
{
|
||||
input: "\x02irc\x0f://\x1dfreenode.net\x0f/\x034,8thelounge",
|
||||
expected: "irc://freenode.net/thelounge",
|
||||
input: "\x02irc\x0f://\x1dirc.example.com\x0f/\x034,8thelounge",
|
||||
expected: "irc://irc.example.com/thelounge",
|
||||
},
|
||||
{
|
||||
input: "\x02#\x038,9thelounge",
|
||||
|
@ -8,12 +8,12 @@ const {
|
||||
|
||||
describe("findLinks", () => {
|
||||
it("should find url", () => {
|
||||
const input = "irc://freenode.net/thelounge";
|
||||
const input = "irc://irc.example.com/thelounge";
|
||||
const expected = [
|
||||
{
|
||||
start: 0,
|
||||
end: 28,
|
||||
link: "irc://freenode.net/thelounge",
|
||||
end: 31,
|
||||
link: "irc://irc.example.com/thelounge",
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -63,10 +63,10 @@ describe("IRC formatted message parser", () => {
|
||||
it("should find urls", async () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "irc://freenode.net/thelounge",
|
||||
input: "irc://irc.example.com/thelounge",
|
||||
expected:
|
||||
'<a href="irc://freenode.net/thelounge" dir="auto" target="_blank" rel="noopener">' +
|
||||
"irc://freenode.net/thelounge" +
|
||||
'<a href="irc://irc.example.com/thelounge" dir="auto" target="_blank" rel="noopener">' +
|
||||
"irc://irc.example.com/thelounge" +
|
||||
"</a>",
|
||||
},
|
||||
{
|
||||
@ -416,12 +416,12 @@ describe("IRC formatted message parser", () => {
|
||||
it("should go bonkers like mirc", async () => {
|
||||
const testCases = [
|
||||
{
|
||||
input: "\x02irc\x0f://\x1dfreenode.net\x0f/\x034,8thelounge",
|
||||
input: "\x02irc\x0f://\x1dirc.example.com\x0f/\x034,8thelounge",
|
||||
expected:
|
||||
'<a href="irc://freenode.net/thelounge" dir="auto" target="_blank" rel="noopener">' +
|
||||
'<a href="irc://irc.example.com/thelounge" dir="auto" target="_blank" rel="noopener">' +
|
||||
'<span class="irc-bold">irc</span>' +
|
||||
"://" +
|
||||
'<span class="irc-italic">freenode.net</span>' +
|
||||
'<span class="irc-italic">irc.example.com</span>' +
|
||||
"/" +
|
||||
'<span class="irc-fg4 irc-bg8">thelounge</span>' +
|
||||
"</a>",
|
||||
|
2
test/fixtures/.thelounge/config.js
vendored
2
test/fixtures/.thelounge/config.js
vendored
@ -2,6 +2,8 @@
|
||||
|
||||
var config = require("../../../defaults/config.js");
|
||||
|
||||
config.defaults.name = "Example IRC Server";
|
||||
config.defaults.host = "irc.example.com";
|
||||
config.public = true;
|
||||
config.prefetch = true;
|
||||
config.host = config.bind = "127.0.0.1";
|
||||
|
@ -95,7 +95,7 @@ describe("Network", function () {
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
expect(network.validate()).to.be.true;
|
||||
expect(network.host).to.equal("chat.freenode.net");
|
||||
expect(network.host).to.equal("irc.example.com");
|
||||
expect(network.port).to.equal(6697);
|
||||
expect(network.tls).to.be.true;
|
||||
expect(network.rejectUnauthorized).to.be.true;
|
||||
@ -107,7 +107,7 @@ describe("Network", function () {
|
||||
host: "some.fake.tld",
|
||||
});
|
||||
expect(network2.validate()).to.be.true;
|
||||
expect(network2.host).to.equal("chat.freenode.net");
|
||||
expect(network2.host).to.equal("irc.example.com");
|
||||
|
||||
Helper.config.lockNetwork = false;
|
||||
});
|
||||
@ -269,7 +269,7 @@ describe("Network", function () {
|
||||
// Lobby and initial channel
|
||||
expect(network.channels.length).to.equal(2);
|
||||
|
||||
const newChan = new Chan({name: "#freenode"});
|
||||
const newChan = new Chan({name: "#foo"});
|
||||
network.addChannel(newChan);
|
||||
|
||||
expect(network.channels.length).to.equal(3);
|
||||
@ -282,13 +282,13 @@ describe("Network", function () {
|
||||
|
||||
const network = new Network({
|
||||
channels: [chan1, chan2, chan3],
|
||||
name: "freenode",
|
||||
name: "foo",
|
||||
});
|
||||
|
||||
const newChan = new Chan({name: "#freenode"});
|
||||
const newChan = new Chan({name: "#foo"});
|
||||
network.addChannel(newChan);
|
||||
|
||||
expect(network.channels[0].name).to.equal("freenode");
|
||||
expect(network.channels[0].name).to.equal("foo");
|
||||
expect(network.channels[1]).to.equal(chan1);
|
||||
expect(network.channels[2]).to.equal(newChan);
|
||||
expect(network.channels[3]).to.equal(chan2);
|
||||
@ -303,7 +303,7 @@ describe("Network", function () {
|
||||
channels: [chan1, chan2],
|
||||
});
|
||||
|
||||
const newChan = new Chan({name: "#freenode"});
|
||||
const newChan = new Chan({name: "#foo"});
|
||||
network.addChannel(newChan);
|
||||
|
||||
expect(network.channels[1]).to.equal(chan1);
|
||||
@ -397,7 +397,7 @@ describe("Network", function () {
|
||||
channels: [banlist, chan1, user1],
|
||||
});
|
||||
|
||||
const newChan = new Chan({name: "#freenode"});
|
||||
const newChan = new Chan({name: "#foo"});
|
||||
network.addChannel(newChan);
|
||||
|
||||
expect(network.channels[1]).to.equal(newChan);
|
||||
@ -408,7 +408,7 @@ describe("Network", function () {
|
||||
|
||||
it("should never add something in front of the lobby", function () {
|
||||
const network = new Network({
|
||||
name: "freenode",
|
||||
name: "foo",
|
||||
channels: [],
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user