mirror of
https://github.com/thelounge/thelounge.git
synced 2024-05-19 06:36:46 +02:00
Create channels table in sqlite, and store channels in it
This commit is contained in:
parent
2a11c07ba9
commit
d7ed8a38a3
119
src/client.js
119
src/client.js
|
@ -141,10 +141,23 @@ function Client(manager, name, config = {}) {
|
|||
}
|
||||
}
|
||||
|
||||
Client.prototype.createChannel = function (attr) {
|
||||
Client.prototype.createChannel = function (attr, network) {
|
||||
const chan = new Chan(attr);
|
||||
chan.id = this.idChan++;
|
||||
|
||||
if (!chan.isLoggable() || !network) {
|
||||
return chan;
|
||||
}
|
||||
|
||||
const messageStorage = this.messageStorage.find((s) => s.canProvideMessages());
|
||||
|
||||
if (messageStorage) {
|
||||
messageStorage
|
||||
.getChannelId(network, chan)
|
||||
.then((id) => (chan.idStorage = id))
|
||||
.catch((err) => log.error(`Failed to get storage channel id: ${err}`));
|
||||
}
|
||||
|
||||
return chan;
|
||||
};
|
||||
|
||||
|
@ -177,54 +190,6 @@ Client.prototype.find = function (channelId) {
|
|||
|
||||
Client.prototype.connect = function (args, isStartup = false) {
|
||||
const client = this;
|
||||
let channels = [];
|
||||
|
||||
// Get channel id for lobby before creating other channels for nicer ids
|
||||
const lobbyChannelId = client.idChan++;
|
||||
|
||||
if (args.channels) {
|
||||
let badName = false;
|
||||
|
||||
args.channels.forEach((chan) => {
|
||||
if (!chan.name) {
|
||||
badName = true;
|
||||
return;
|
||||
}
|
||||
|
||||
channels.push(
|
||||
client.createChannel({
|
||||
name: chan.name,
|
||||
key: chan.key || "",
|
||||
type: chan.type,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
if (badName && client.name) {
|
||||
log.warn(
|
||||
"User '" +
|
||||
client.name +
|
||||
"' on network '" +
|
||||
args.name +
|
||||
"' has an invalid channel which has been ignored"
|
||||
);
|
||||
}
|
||||
// `join` is kept for backwards compatibility when updating from versions <2.0
|
||||
// also used by the "connect" window
|
||||
} else if (args.join) {
|
||||
channels = args.join
|
||||
.replace(/,/g, " ")
|
||||
.split(/\s+/g)
|
||||
.map((chan) => {
|
||||
if (!chan.match(/^[#&!+]/)) {
|
||||
chan = `#${chan}`;
|
||||
}
|
||||
|
||||
return client.createChannel({
|
||||
name: chan,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const network = new Network({
|
||||
uuid: args.uuid,
|
||||
|
@ -244,12 +209,60 @@ Client.prototype.connect = function (args, isStartup = false) {
|
|||
saslAccount: String(args.saslAccount || ""),
|
||||
saslPassword: String(args.saslPassword || ""),
|
||||
commands: args.commands || [],
|
||||
channels: channels,
|
||||
ignoreList: args.ignoreList ? args.ignoreList : [],
|
||||
});
|
||||
|
||||
// Set network lobby channel id
|
||||
network.channels[0].id = lobbyChannelId;
|
||||
if (args.channels) {
|
||||
let badName = false;
|
||||
|
||||
args.channels.forEach((chan) => {
|
||||
if (!chan.name) {
|
||||
badName = true;
|
||||
return;
|
||||
}
|
||||
|
||||
network.channels.push(
|
||||
client.createChannel(
|
||||
{
|
||||
name: chan.name,
|
||||
key: chan.key || "",
|
||||
type: chan.type,
|
||||
},
|
||||
network
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
if (badName && client.name) {
|
||||
log.warn(
|
||||
"User '" +
|
||||
client.name +
|
||||
"' on network '" +
|
||||
args.name +
|
||||
"' has an invalid channel which has been ignored"
|
||||
);
|
||||
}
|
||||
} else if (args.join) {
|
||||
// `join` is kept for backwards compatibility when updating from versions <2.0
|
||||
// also used by the "connect" window
|
||||
args.join
|
||||
.replace(/,/g, " ")
|
||||
.split(/\s+/g)
|
||||
.forEach((chan) => {
|
||||
if (!chan.match(/^[#&!+]/)) {
|
||||
chan = `#${chan}`;
|
||||
}
|
||||
|
||||
network.channels.push(
|
||||
client.createChannel(
|
||||
{
|
||||
name: chan,
|
||||
},
|
||||
network
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
client.networks.push(network);
|
||||
client.emit("network", {
|
||||
|
@ -281,7 +294,7 @@ Client.prototype.connect = function (args, isStartup = false) {
|
|||
|
||||
if (!isStartup) {
|
||||
client.save();
|
||||
channels.forEach((channel) => channel.loadMessages(client, network));
|
||||
network.channels.forEach((channel) => channel.loadMessages(client, network));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ Chan.State = {
|
|||
function Chan(attr) {
|
||||
_.defaults(this, attr, {
|
||||
id: 0,
|
||||
idStorage: 0,
|
||||
messages: [],
|
||||
name: "",
|
||||
key: "",
|
||||
|
@ -192,7 +193,7 @@ Chan.prototype.getFilteredClone = function (lastActiveChannel, lastMessage) {
|
|||
}
|
||||
|
||||
newChannel.totalMessages = this[prop].length;
|
||||
} else {
|
||||
} else if (prop !== "idStorage") {
|
||||
newChannel[prop] = this[prop];
|
||||
}
|
||||
|
||||
|
|
|
@ -118,12 +118,15 @@ exports.input = function (network, chan, cmd, args) {
|
|||
let newChan = network.getChannel(chanName);
|
||||
|
||||
if (typeof newChan === "undefined") {
|
||||
newChan = client.createChannel({
|
||||
type: Chan.Type.SPECIAL,
|
||||
special: Chan.SpecialType.IGNORELIST,
|
||||
name: chanName,
|
||||
data: ignored,
|
||||
});
|
||||
newChan = client.createChannel(
|
||||
{
|
||||
type: Chan.Type.SPECIAL,
|
||||
special: Chan.SpecialType.IGNORELIST,
|
||||
name: chanName,
|
||||
data: ignored,
|
||||
},
|
||||
network
|
||||
);
|
||||
client.emit("join", {
|
||||
network: network.uuid,
|
||||
chan: newChan.getFilteredClone(true),
|
||||
|
|
|
@ -63,10 +63,13 @@ exports.input = function (network, chan, cmd, args) {
|
|||
}
|
||||
}
|
||||
|
||||
const newChan = this.createChannel({
|
||||
type: Chan.Type.QUERY,
|
||||
name: targetName,
|
||||
});
|
||||
const newChan = this.createChannel(
|
||||
{
|
||||
type: Chan.Type.QUERY,
|
||||
name: targetName,
|
||||
},
|
||||
network
|
||||
);
|
||||
|
||||
this.emit("join", {
|
||||
network: network.uuid,
|
||||
|
|
|
@ -11,10 +11,13 @@ module.exports = function (irc, network) {
|
|||
let chan = network.getChannel(data.channel);
|
||||
|
||||
if (typeof chan === "undefined") {
|
||||
chan = client.createChannel({
|
||||
name: data.channel,
|
||||
state: Chan.State.JOINED,
|
||||
});
|
||||
chan = client.createChannel(
|
||||
{
|
||||
name: data.channel,
|
||||
state: Chan.State.JOINED,
|
||||
},
|
||||
network
|
||||
);
|
||||
|
||||
client.emit("join", {
|
||||
network: network.uuid,
|
||||
|
|
|
@ -34,12 +34,15 @@ module.exports = function (irc, network) {
|
|||
let chan = network.getChannel("Channel List");
|
||||
|
||||
if (typeof chan === "undefined") {
|
||||
chan = client.createChannel({
|
||||
type: Chan.Type.SPECIAL,
|
||||
special: Chan.SpecialType.CHANNELLIST,
|
||||
name: "Channel List",
|
||||
data: msg,
|
||||
});
|
||||
chan = client.createChannel(
|
||||
{
|
||||
type: Chan.Type.SPECIAL,
|
||||
special: Chan.SpecialType.CHANNELLIST,
|
||||
name: "Channel List",
|
||||
data: msg,
|
||||
},
|
||||
network
|
||||
);
|
||||
|
||||
client.emit("join", {
|
||||
network: network.uuid,
|
||||
|
|
|
@ -75,10 +75,13 @@ module.exports = function (irc, network) {
|
|||
showInActive = true;
|
||||
chan = network.channels[0];
|
||||
} else {
|
||||
chan = client.createChannel({
|
||||
type: Chan.Type.QUERY,
|
||||
name: target,
|
||||
});
|
||||
chan = client.createChannel(
|
||||
{
|
||||
type: Chan.Type.QUERY,
|
||||
name: target,
|
||||
},
|
||||
network
|
||||
);
|
||||
|
||||
client.emit("join", {
|
||||
network: network.uuid,
|
||||
|
|
|
@ -50,12 +50,15 @@ module.exports = function (irc, network) {
|
|||
let chan = network.getChannel(chanName);
|
||||
|
||||
if (typeof chan === "undefined") {
|
||||
chan = client.createChannel({
|
||||
type: Chan.Type.SPECIAL,
|
||||
special: type,
|
||||
name: chanName,
|
||||
data: data,
|
||||
});
|
||||
chan = client.createChannel(
|
||||
{
|
||||
type: Chan.Type.SPECIAL,
|
||||
special: type,
|
||||
name: chanName,
|
||||
data: data,
|
||||
},
|
||||
network
|
||||
);
|
||||
client.emit("join", {
|
||||
network: network.uuid,
|
||||
chan: chan.getFilteredClone(true),
|
||||
|
|
|
@ -22,10 +22,13 @@ module.exports = function (irc, network) {
|
|||
if (data.error) {
|
||||
chan = network.channels[0];
|
||||
} else {
|
||||
chan = client.createChannel({
|
||||
type: Chan.Type.QUERY,
|
||||
name: data.nick,
|
||||
});
|
||||
chan = client.createChannel(
|
||||
{
|
||||
type: Chan.Type.QUERY,
|
||||
name: data.nick,
|
||||
},
|
||||
network
|
||||
);
|
||||
|
||||
client.emit("join", {
|
||||
shouldOpen: true,
|
||||
|
|
|
@ -21,9 +21,12 @@ try {
|
|||
const currentSchemaVersion = 1520239200;
|
||||
|
||||
const schema = [
|
||||
// Schema version #1
|
||||
// Tables
|
||||
"CREATE TABLE IF NOT EXISTS options (name TEXT, value TEXT, CONSTRAINT name_unique UNIQUE (name))",
|
||||
"CREATE TABLE IF NOT EXISTS channels (channel_id INTEGER PRIMARY KEY, network TEXT, channel TEXT, CONSTRAINT unique_channel UNIQUE (network, channel))",
|
||||
"CREATE TABLE IF NOT EXISTS messages (network TEXT, channel TEXT, time INTEGER, type TEXT, msg TEXT)",
|
||||
|
||||
// Indexes
|
||||
"CREATE INDEX IF NOT EXISTS network_channel ON messages (network, channel)",
|
||||
"CREATE INDEX IF NOT EXISTS time ON messages (time)",
|
||||
];
|
||||
|
@ -116,6 +119,13 @@ class MessageStorage {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new message in specified channel
|
||||
*
|
||||
* @param Network network - Network object where the channel is
|
||||
* @param Chan channel - Channel object
|
||||
* @param Msg msg - Message object to store
|
||||
*/
|
||||
index(network, channel, msg) {
|
||||
if (!this.isEnabled) {
|
||||
return;
|
||||
|
@ -144,6 +154,12 @@ class MessageStorage {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete stored all stored messages in a channel
|
||||
*
|
||||
* @param Network network - Network object where the channel is
|
||||
* @param Chan channel - Channel object
|
||||
*/
|
||||
deleteChannel(network, channel) {
|
||||
if (!this.isEnabled) {
|
||||
return;
|
||||
|
@ -158,6 +174,51 @@ class MessageStorage {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stored channel id, creates one if does not exist.
|
||||
*
|
||||
* @param Network network - Network object where the channel is
|
||||
* @param Chan channel - Channel object
|
||||
*/
|
||||
getChannelId(network, channel) {
|
||||
if (!this.isEnabled) {
|
||||
return Promise.resolve(0);
|
||||
}
|
||||
|
||||
const channelName = channel.name.toLowerCase();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.database.serialize(() =>
|
||||
this.database.get(
|
||||
"SELECT channel_id FROM channels WHERE network = ? AND channel = ?",
|
||||
[network.uuid, channelName],
|
||||
(err, row) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
if (row) {
|
||||
return resolve(row.channel_id);
|
||||
}
|
||||
|
||||
// This channel was not found, create it and "recursively" call getChannelId again
|
||||
this.database.run(
|
||||
"INSERT INTO channels (network, channel) VALUES (?, ?)",
|
||||
[network.uuid, channelName],
|
||||
(err2) => {
|
||||
if (err2) {
|
||||
return reject(err2);
|
||||
}
|
||||
|
||||
this.getChannelId(network, channel).then(resolve).catch(reject);
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load messages for given channel on a given network and resolve a promise with loaded messages.
|
||||
*
|
||||
|
|
|
@ -18,9 +18,10 @@ module.exports = class PublicClient {
|
|||
/**
|
||||
*
|
||||
* @param {Object} attributes
|
||||
* @param {Network} network
|
||||
*/
|
||||
createChannel(attributes) {
|
||||
return this.client.createChannel(attributes);
|
||||
createChannel(attributes, network) {
|
||||
return this.client.createChannel(attributes, network);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -66,6 +66,12 @@ describe("SQLite Message Storage", function () {
|
|||
sql:
|
||||
"CREATE TABLE options (name TEXT, value TEXT, CONSTRAINT name_unique UNIQUE (name))",
|
||||
},
|
||||
{
|
||||
name: "channels",
|
||||
tbl_name: "channels",
|
||||
sql:
|
||||
"CREATE TABLE channels (channel_id INTEGER PRIMARY KEY, network TEXT, channel TEXT, CONSTRAINT unique_channel UNIQUE (network, channel))",
|
||||
},
|
||||
{
|
||||
name: "messages",
|
||||
tbl_name: "messages",
|
||||
|
@ -80,6 +86,37 @@ describe("SQLite Message Storage", function () {
|
|||
);
|
||||
});
|
||||
|
||||
it("should create channel id if not exists", function (done) {
|
||||
const network = {
|
||||
uuid: "network-uuid",
|
||||
};
|
||||
|
||||
store
|
||||
.getChannelId(network, {
|
||||
name: "#This-Is-Channel-One",
|
||||
})
|
||||
.then((id) => {
|
||||
expect(id).to.equal(1);
|
||||
|
||||
store
|
||||
.getChannelId(network, {
|
||||
name: "#this-is-channel-ONE",
|
||||
})
|
||||
.then((id2) => {
|
||||
expect(id2).to.equal(1);
|
||||
|
||||
store
|
||||
.getChannelId(network, {
|
||||
name: "#this-is-channel-two",
|
||||
})
|
||||
.then((id3) => {
|
||||
expect(id3).to.equal(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should insert schema version to options table", function (done) {
|
||||
store.database.serialize(() =>
|
||||
store.database.get(
|
||||
|
|
Loading…
Reference in a new issue